VolumetricFog.cpp 43 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320
  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 "environment/VolumetricFog.h"
  23. #include "windowManager/platformWindowMgr.h"
  24. #include "gfx/gfxTransformSaver.h"
  25. #include "renderInstance/renderPassManager.h"
  26. #include "math/mathIO.h"
  27. #include "materials/shaderData.h"
  28. #include "math/util/matrixSet.h"
  29. #include "core/resourceManager.h"
  30. #include "core/stream/bitStream.h"
  31. #include "T3D/gameBase/gameConnection.h"
  32. #include "T3D/shapeBase.h"
  33. #include "ts/tsShapeInstance.h"
  34. #include "console/engineAPI.h"
  35. #include "gui/core/guiCanvas.h"
  36. #include "VolumetricFogRTManager.h"
  37. #include "lighting/lightInfo.h"
  38. #include "lighting/lightManager.h"
  39. #define COLBOX_SCALE Point3F(1.02f, 1.02f, 1.02f)
  40. IMPLEMENT_CO_NETOBJECT_V1(VolumetricFog);
  41. ConsoleDocClass(VolumetricFog,
  42. "@brief Volumetric Fog Object class. Main class defining the Volumetric\n"
  43. "Fog objects in the scene. Used in conjunction with the VolumetricFogRTManager\n"
  44. "class which is responsible for the required rendertargets.\n\n"
  45. "Methods (exposed to script):\n"
  46. " setFogColorF(color) Changes the overall fog color (color.rgba range 0.0 - 1.0).\n;"
  47. " setFogColor(color) Changes the overall fog color color.rgba range 0 - 255).\n;"
  48. " setFogDensity(density) Changes the overall fog density.\n"
  49. " setFogModulation(strength, speed1, speed2) changes the strength\n"
  50. " and the speeds of the 2 animation layers.\n\n"
  51. "Callbacks:\n"
  52. "onEnterFog triggered whenever the controlobject (Player or Camera) enters the Fog.\n"
  53. " (current Fog object and the controlobject are exposed to script.\n"
  54. "onLeaveFog triggered whenever the controlobject (Player or Camera) left the Fog.\n"
  55. " (current Fog object and the controlobject are exposed to script.\n\n"
  56. "@tsexample\n"
  57. " new VolumetricFog()\n"
  58. " {\n"
  59. " shapeName = \"art/environment/FogRCube.dts\";\n"
  60. " fogColor = \"200 200 200 128\";\n"
  61. " fogDensity = \"0.2\";\n"
  62. " ignoreWater = \"0\";\n"
  63. " MinSize = \"250\";\n"
  64. " FadeSize = \"750\";\n"
  65. " texture = \"art/environment/FogMod_heavy.dds\";\n"
  66. " tiles = \"1.5\";\n"
  67. " modStrength = \"0.2\";\n"
  68. " PrimSpeed = \"-0.01 0.04\";\n"
  69. " SecSpeed = \"0.02 -0.02\";\n"
  70. " position = \"748.644 656.371 65.3506\"; \n"
  71. " rotation = \"0 0 1 20.354\";\n"
  72. " scale = \"40 30 6\";\n"
  73. " };\n"
  74. "@endtsexample\n"
  75. );
  76. IMPLEMENT_CALLBACK(VolumetricFog, onEnterFog, void, (SimObjectId obj), (obj),
  77. "@brief Called when an object enters the volume of the Fog instance.\n\n"
  78. "@param obj the controlobject entering the fog.");
  79. IMPLEMENT_CALLBACK(VolumetricFog, onLeaveFog, void, (SimObjectId obj), (obj),
  80. "@brief Called when an object left the volume of the Fog instance.\n\n"
  81. "@param obj the controlobject leaving the fog.");
  82. VolumetricFog::VolumetricFog()
  83. {
  84. AssertFatal(VFRTM != NULL, "VolumetricFog Fatal Error: No Manager found");
  85. if (!VFRTM->IsInitialized())
  86. VFRTM->Init();
  87. mNetFlags.set(Ghostable | ScopeAlways);
  88. mTypeMask |= EnvironmentObjectType | StaticObjectType;
  89. mPrepassTarget = NULL;
  90. mDepthBufferTarget = NULL;
  91. mFrontBufferTarget = NULL;
  92. z_buf = NULL;
  93. mTexture = NULL;
  94. mIsVBDirty = false;
  95. mIsPBDirty = false;
  96. mFogColor.set(200, 200, 200, 255);
  97. mFogDensity = 0.3f;
  98. mIgnoreWater = false;
  99. mReflect = false;
  100. mCamInFog = false;
  101. mResizing = false;
  102. mFogReflStrength = 20.0;
  103. mUseGlow = false;
  104. mGlowStrength = 0.3f;
  105. mGlowing = 0;
  106. mModifLightRays = false;
  107. mLightRayMod = 1.0f;
  108. mOldLightRayStrength = 0.1f;
  109. mShapeName = "";
  110. mShapeLoaded = false;
  111. mMinDisplaySize = 10.0f;
  112. mFadeSize = 0.0f;
  113. mCurDetailLevel = 0;
  114. mNumDetailLevels = 0;
  115. det_size.clear();
  116. mTextureName = "";
  117. mIsTextured = false;
  118. mStrength = 0.5f;
  119. mTexTiles = 1.0f;
  120. mSpeed1.set(0.5f, 0.0f);
  121. mSpeed2.set(0.1f, 0.1f);
  122. }
  123. VolumetricFog::~VolumetricFog()
  124. {
  125. if (isClientObject())
  126. return;
  127. for (S32 i = 0; i < det_size.size(); i++)
  128. {
  129. if (det_size[i].indices != NULL)
  130. delete(det_size[i].indices);
  131. if (det_size[i].piArray != NULL)
  132. delete(det_size[i].piArray);
  133. if (det_size[i].verts != NULL)
  134. delete(det_size[i].verts);
  135. }
  136. det_size.clear();
  137. if (z_buf.isValid())
  138. SAFE_DELETE(z_buf);
  139. if (!mTexture.isNull())
  140. mTexture.free();
  141. }
  142. void VolumetricFog::initPersistFields()
  143. {
  144. addGroup("VolumetricFogData");
  145. addField("shapeName", TypeShapeFilename, Offset(mShapeName, VolumetricFog),
  146. "Path and filename of the model file (.DTS, .DAE) to use for this Volume.");
  147. addField("FogColor", TypeColorI, Offset(mFogColor, VolumetricFog),
  148. "Fog color RGBA (Alpha is ignored)");
  149. addField("FogDensity", TypeF32, Offset(mFogDensity, VolumetricFog),
  150. "Overal fog density value (0 disables the fog).");
  151. addField("IgnoreWater", TypeBool, Offset(mIgnoreWater, VolumetricFog),
  152. "Set to true if volumetric fog should continue while submerged.");
  153. addField("MinSize", TypeF32, Offset(mMinDisplaySize, VolumetricFog),
  154. "Min size (in pixels) for fog to be rendered.");
  155. addField("FadeSize", TypeF32, Offset(mFadeSize, VolumetricFog),
  156. "Object size in pixels at which the FX-fading kicks in (0 disables fading).");
  157. endGroup("VolumetricFogData");
  158. addGroup("VolumetricFogModulation");
  159. addField("texture", TypeImageFilename, Offset(mTextureName, VolumetricFog),
  160. "A texture which contains Fogdensity modulator in the red channel and color with 1-green channel. No texture disables modulation.");
  161. addField("tiles", TypeF32, Offset(mTexTiles, VolumetricFog),
  162. "How many times the texture is mapped to the object.");
  163. addField("modStrength", TypeF32, Offset(mStrength, VolumetricFog),
  164. "Overall strength of the density modulation (0 disables modulation).");
  165. addField("PrimSpeed", TypePoint2F, Offset(mSpeed1, VolumetricFog),
  166. "Overall primary speed of the density modulation (x-speed(u) y-speed(v))");
  167. addField("SecSpeed", TypePoint2F, Offset(mSpeed2, VolumetricFog),
  168. "Overall secundary speed of the density modulation (x-speed(u) y-speed(v))");
  169. endGroup("VolumetricFogModulation");
  170. addGroup("Reflections");
  171. addField("Reflectable", TypeBool, Offset(mReflect, VolumetricFog),
  172. "Set to true if volumetric fog should be reflected.");
  173. addField("ReflectStrength", TypeF32, Offset(mFogReflStrength, VolumetricFog),
  174. "Strength of the reflections (0 disables the fog).");
  175. endGroup("Reflections");
  176. addGroup("PostFX");
  177. addField("useGlow", TypeBool, Offset(mUseGlow, VolumetricFog),
  178. "Set to true if volumetric fog should use glow PostFX.");
  179. addField("glowStrength", TypeF32, Offset(mGlowStrength, VolumetricFog),
  180. "Overall strength of the glow PostFX.");
  181. addField("modLightRay", TypeBool, Offset(mModifLightRays, VolumetricFog),
  182. "Set to true if volumetric fog should modify the brightness of the Lightrays.");
  183. addField("lightRayMod", TypeF32, Offset(mLightRayMod, VolumetricFog),
  184. "Modifier for LightRay PostFX when inside Fog.");
  185. endGroup("PostFX");
  186. Parent::initPersistFields();
  187. }
  188. void VolumetricFog::inspectPostApply()
  189. {
  190. Parent::inspectPostApply();
  191. mSpeed.set(mSpeed1.x, mSpeed1.y, mSpeed2.x, mSpeed2.y);
  192. setMaskBits(VolumetricFogMask | FogColorMask | FogDensityMask | FogModulationMask | FogPostFXMask | FogShapeMask);
  193. }
  194. bool VolumetricFog::onAdd()
  195. {
  196. if (!Parent::onAdd())
  197. return false;
  198. if (!VFRTM->IsInitialized())
  199. {
  200. Con::errorf("No VolumetricFogRTManager present!!");
  201. return false;
  202. }
  203. resetWorldBox();
  204. mShapeLoaded = LoadShape();
  205. setRenderTransform(mObjToWorld);
  206. addToScene();
  207. ColBox.set(getTransform(), (mObjBox.getExtents() * getScale() * COLBOX_SCALE));
  208. mObjSize = mWorldBox.getGreatestDiagonalLength();
  209. mObjScale = getScale();
  210. mTexTiles = mAbs(mTexTiles);
  211. mSpeed.set(mSpeed1.x, mSpeed1.y, mSpeed2.x, mSpeed2.y);
  212. mInvScale = (1.0f / getMax(getMax(mObjScale.x, mObjScale.y), mObjScale.z));
  213. if (isClientObject())
  214. {
  215. conn = GameConnection::getConnectionToServer();
  216. if (!conn)
  217. {
  218. Con::errorf("VolumetricFog::onAdd - No Serverconnection");
  219. return false;
  220. }
  221. glowFX = static_cast<PostEffect*>(Sim::findObject("VolFogGlowPostFx"));
  222. mOldLightRayStrength = Con::getFloatVariable("$LightRayPostFX::brightScalar",1.0f);
  223. GuiCanvas* cv = dynamic_cast<GuiCanvas*>(Sim::findObject("Canvas"));
  224. if (cv == NULL)
  225. {
  226. Con::errorf("VolumetricFog::onAdd - Canvas not found!!");
  227. return false;
  228. }
  229. mPlatformWindow = cv->getPlatformWindow();
  230. VolumetricFogRTManager::getVolumetricFogRTMResizeSignal().notify(this, &VolumetricFog::handleResize);
  231. GuiCanvas::getCanvasSizeChangeSignal().notify(this, &VolumetricFog::handleCanvasResize);
  232. InitTexture();
  233. return setupRenderer();
  234. }
  235. VFRTM->IncFogObjects();
  236. return true;
  237. }
  238. void VolumetricFog::onRemove()
  239. {
  240. if (isClientObject())
  241. {
  242. if (isTicking())
  243. {
  244. setProcessTick(false);
  245. if (mGlowing != 0)
  246. {
  247. mGlowing = 0;
  248. glowFX->disable();
  249. }
  250. _leaveFog(static_cast<ShapeBase*>(conn->getControlObject()));
  251. }
  252. VolumetricFogRTManager::getVolumetricFogRTMResizeSignal().remove(this, &VolumetricFog::handleResize);
  253. GuiCanvas::getCanvasSizeChangeSignal().remove(this, &VolumetricFog::handleCanvasResize);
  254. }
  255. removeFromScene();
  256. VFRTM->DecFogObjects();
  257. Parent::onRemove();
  258. }
  259. void VolumetricFog::handleCanvasResize(GuiCanvas* canvas)
  260. {
  261. UpdateBuffers(0,true);
  262. }
  263. void VolumetricFog::handleResize(VolumetricFogRTManager *RTM, bool resize)
  264. {
  265. if (resize)
  266. {
  267. mResizing = true;
  268. RTM->FogAnswered();
  269. }
  270. else
  271. mResizing = false;
  272. if (mIsTextured)
  273. {
  274. F32 width = (F32)mPlatformWindow->getClientExtent().x;
  275. F32 height = (F32)mPlatformWindow->getClientExtent().y;
  276. mTexScale.x = 2.0f - ((F32)mTexture.getWidth() / width);
  277. mTexScale.y = 2.0f - ((F32)mTexture.getHeight() / height);
  278. }
  279. UpdateBuffers(0,true);
  280. }
  281. //-----------------------------------------------------------------------------
  282. // Loadshape extracted from TSMesh and TSShapeInstance
  283. //-----------------------------------------------------------------------------
  284. bool VolumetricFog::LoadShape()
  285. {
  286. GFXPrimitiveType GFXdrawTypes[] = { GFXTriangleList, GFXTriangleStrip };
  287. if (!mShapeName || mShapeName[0] == '\0')
  288. {
  289. Con::errorf("VolumetricFog::LoadShape() - No shape name! Volumetric Fog will not be rendered!");
  290. return false;
  291. }
  292. // Load shape, server side only reads bounds and radius
  293. Resource<TSShape> mShape;
  294. mShape = ResourceManager::get().load(mShapeName);
  295. if (bool(mShape) == false)
  296. {
  297. Con::errorf("VolumetricFog::LoadShape() - Unable to load shape: %s", mShapeName);
  298. return false;
  299. }
  300. mObjBox = mShape->bounds;
  301. mRadius = mShape->radius;
  302. resetWorldBox();
  303. if (!isClientObject())
  304. return false;
  305. TSShapeInstance *mShapeInstance = new TSShapeInstance(mShape, false);
  306. meshes mesh_detail;
  307. for (S32 i = 0; i < det_size.size(); i++)
  308. {
  309. if (det_size[i].indices != NULL)
  310. delete(det_size[i].indices);
  311. if (det_size[i].piArray != NULL)
  312. delete(det_size[i].piArray);
  313. if (det_size[i].verts != NULL)
  314. delete(det_size[i].verts);
  315. }
  316. det_size.clear();
  317. // browsing model for detail levels
  318. for (U32 i = 0; i < mShape->details.size(); i++)
  319. {
  320. const TSDetail *detail = &mShape->details[i];
  321. mesh_detail.det_size = detail->size;
  322. mesh_detail.sub_shape = detail->subShapeNum;
  323. mesh_detail.obj_det = detail->objectDetailNum;
  324. mesh_detail.verts = NULL;
  325. mesh_detail.piArray = NULL;
  326. mesh_detail.indices = NULL;
  327. if (detail->size >= 0.0f && detail->subShapeNum >= 0)
  328. det_size.push_back(mesh_detail);
  329. }
  330. for (U32 i = 0; i < det_size.size(); i++)
  331. {
  332. const S32 ss = det_size[i].sub_shape;
  333. if (ss >= 0)
  334. {
  335. const S32 start = mShape->subShapeFirstObject[ss];
  336. const S32 end = start + mShape->subShapeNumObjects[ss];
  337. for (S32 j = start; j < end; j++)
  338. {
  339. // Loading shape, only the first mesh for each detail will be used!
  340. TSShapeInstance::MeshObjectInstance *meshObj = &mShapeInstance->mMeshObjects[j];
  341. if (!meshObj)
  342. continue;
  343. TSMesh *mesh = meshObj->getMesh(det_size[i].obj_det);
  344. if (mesh != NULL)
  345. {
  346. const U32 numNrms = mesh->mNumVerts;
  347. GFXVertexPNTT *tmpVerts = NULL;
  348. tmpVerts = new GFXVertexPNTT[numNrms];
  349. mIsVBDirty = true;
  350. for (U32 k = 0; k < numNrms; k++)
  351. {
  352. const TSMesh::__TSMeshVertexBase &vd = mesh->mVertexData.getBase(k);
  353. Point3F norm = vd.normal();
  354. Point3F vert = vd.vert();
  355. Point2F uv = vd.tvert();
  356. tmpVerts[k].point = vert;
  357. tmpVerts[k].texCoord = uv;
  358. tmpVerts[k].normal = norm;
  359. }
  360. det_size[i].verts = tmpVerts;
  361. det_size[i].num_verts = numNrms;
  362. det_size[i].piArray = new Vector<GFXPrimitive>();
  363. GFXPrimitive pInfo;
  364. det_size[i].indices = new Vector<U32>();
  365. for (U32 k = 0; k < mesh->indices.size(); k++)
  366. det_size[i].indices->push_back(mesh->indices[k]);
  367. U32 primitivesSize = mesh->primitives.size();
  368. for (U32 k = 0; k < primitivesSize; k++)
  369. {
  370. const TSDrawPrimitive & draw = mesh->primitives[k];
  371. GFXPrimitiveType drawType = GFXdrawTypes[draw.matIndex >> 30];
  372. switch (drawType)
  373. {
  374. case GFXTriangleList:
  375. pInfo.type = drawType;
  376. pInfo.numPrimitives = draw.numElements / 3;
  377. pInfo.startIndex = draw.start;
  378. // Use the first index to determine which 16-bit address space we are operating in
  379. pInfo.startVertex = mesh->indices[draw.start] & 0xFFFF0000;
  380. pInfo.minIndex = pInfo.startVertex;
  381. pInfo.numVertices = getMin((U32)0x10000, mesh->mNumVerts - pInfo.startVertex);
  382. break;
  383. case GFXTriangleStrip:
  384. pInfo.type = drawType;
  385. pInfo.numPrimitives = draw.numElements - 2;
  386. pInfo.startIndex = draw.start;
  387. // Use the first index to determine which 16-bit address space we are operating in
  388. pInfo.startVertex = mesh->indices[draw.start] & 0xFFFF0000;
  389. pInfo.minIndex = pInfo.startVertex;
  390. pInfo.numVertices = getMin((U32)0x10000, mesh->mNumVerts - pInfo.startVertex);
  391. break;
  392. default:
  393. Con::errorf("VolumetricFog::LoadShape Unknown drawtype!?!");
  394. return false;
  395. break;
  396. }
  397. det_size[i].piArray->push_back(pInfo);
  398. j = end;
  399. }
  400. }
  401. else
  402. {
  403. Con::errorf("VolumetricFog::LoadShape Error loading mesh from shape!");
  404. delete mShapeInstance;
  405. return false;
  406. }
  407. mIsVBDirty = true;
  408. mIsPBDirty = true;
  409. }
  410. }
  411. }
  412. mNumDetailLevels = det_size.size();
  413. mCurDetailLevel = 0;
  414. UpdateBuffers(mCurDetailLevel);
  415. delete mShapeInstance;
  416. return true;
  417. }
  418. //-----------------------------------------------------------------------------
  419. // UpdateBuffers called whenever detaillevel changes (LOD)
  420. //-----------------------------------------------------------------------------
  421. bool VolumetricFog::UpdateBuffers(U32 dl, bool force)
  422. {
  423. if (mVB.isNull() || mIsVBDirty || dl != mCurDetailLevel || force)
  424. {
  425. mVB.set(GFX, det_size[dl].num_verts, GFXBufferTypeDynamic);
  426. mIsVBDirty = false;
  427. }
  428. GFXVertexPNTT *vertPtr = mVB.lock();
  429. if (!vertPtr)
  430. {
  431. mVB.unlock();
  432. return false;
  433. }
  434. dMemcpy(vertPtr, det_size[dl].verts, sizeof (GFXVertexPNTT)* det_size[dl].num_verts);
  435. mVB.unlock();
  436. if (mIsPBDirty || mPB.isNull() || dl != mCurDetailLevel || force)
  437. {
  438. #ifdef TORQUE_DEBUG
  439. mPB.set(GFX, det_size[dl].indices->size(), det_size[dl].piArray->size(), GFXBufferTypeDynamic, avar("%s() - VolFogPrimBuffer (line %d)", __FUNCTION__, __LINE__));
  440. #else
  441. mPB.set(GFX, det_size[dl].indices->size(), det_size[dl].piArray->size(), GFXBufferTypeDynamic);
  442. #endif
  443. U16 *ibIndices = NULL;
  444. GFXPrimitive *piInput = NULL;
  445. mPB.lock(&ibIndices, &piInput);
  446. dCopyArray(ibIndices, det_size[dl].indices->address(), det_size[dl].indices->size());
  447. dMemcpy(piInput, det_size[dl].piArray->address(), det_size[dl].piArray->size() * sizeof(GFXPrimitive));
  448. mPB.unlock();
  449. mIsPBDirty = false;
  450. }
  451. mCurDetailLevel = dl;
  452. return true;
  453. }
  454. U32 VolumetricFog::packUpdate(NetConnection *con, U32 mask, BitStream *stream)
  455. {
  456. U32 retMask = Parent::packUpdate(con, mask, stream);
  457. if (stream->writeFlag(mask & FogColorMask))
  458. stream->write(mFogColor);
  459. if (stream->writeFlag(mask & FogDensityMask))
  460. stream->write(mFogDensity);
  461. if (stream->writeFlag(mask & FogModulationMask))
  462. {
  463. stream->write(mTextureName);
  464. mTexTiles = mFabs(mTexTiles);
  465. stream->write(mTexTiles);
  466. stream->write(mStrength);
  467. mathWrite(*stream, mSpeed);
  468. }
  469. if (stream->writeFlag(mask & FogPostFXMask))
  470. {
  471. stream->writeFlag(mUseGlow);
  472. stream->write(mGlowStrength);
  473. stream->writeFlag(mModifLightRays);
  474. stream->write(mLightRayMod);
  475. }
  476. if (stream->writeFlag(mask & VolumetricFogMask))
  477. {
  478. stream->writeFlag(mIgnoreWater);
  479. stream->writeFlag(mReflect);
  480. stream->write(mFogReflStrength);
  481. stream->writeFlag(mResizing);
  482. stream->write(mMinDisplaySize);
  483. stream->write(mFadeSize);
  484. }
  485. if (stream->writeFlag(mask & FogShapeMask))
  486. {
  487. stream->writeString(mShapeName);
  488. mathWrite(*stream, getTransform());
  489. mathWrite(*stream, getScale());
  490. if (!mShapeName || mShapeName[0] == '\0')
  491. return retMask;
  492. Resource<TSShape> mShape;
  493. mShape = ResourceManager::get().load(mShapeName);
  494. if (bool(mShape) == false)
  495. return retMask;
  496. mObjBox = mShape->bounds;
  497. mRadius = mShape->radius;
  498. resetWorldBox();
  499. mObjSize = mWorldBox.getGreatestDiagonalLength();
  500. mObjScale = getScale();
  501. mInvScale = (1.0f / getMax(getMax(mObjScale.x, mObjScale.y), mObjScale.z));
  502. }
  503. return retMask;
  504. }
  505. void VolumetricFog::unpackUpdate(NetConnection *con, BitStream *stream)
  506. {
  507. Parent::unpackUpdate(con, stream);
  508. MatrixF mat;
  509. VectorF scale;
  510. VectorF mOldScale = getScale();
  511. String oldTextureName = mTextureName;
  512. StringTableEntry oldShape = mShapeName;
  513. if (stream->readFlag())// Fog color
  514. stream->read(&mFogColor);
  515. if (stream->readFlag())// Fog Density
  516. {
  517. stream->read(&mFogDensity);
  518. if (isTicking())
  519. {
  520. char buf[20];
  521. dSprintf(buf, sizeof(buf), "%3.7f", mFogDensity);
  522. Con::setVariable("$VolumetricFog::density", buf);
  523. }
  524. }
  525. if (stream->readFlag())// Fog Modulation
  526. {
  527. stream->read(&mTextureName);
  528. stream->read(&mTexTiles);
  529. mTexTiles = mFabs(mTexTiles);
  530. stream->read(&mStrength);
  531. mathRead(*stream, &mSpeed);
  532. mSpeed1.set(mSpeed.x, mSpeed.y);
  533. mSpeed2.set(mSpeed.z, mSpeed.w);
  534. if (isProperlyAdded())
  535. {
  536. if (oldTextureName != mTextureName)
  537. InitTexture();
  538. if (oldTextureName.isNotEmpty() && mTextureName.isEmpty())
  539. {
  540. mIsTextured = false;
  541. mTexture.free();
  542. }
  543. }
  544. }
  545. if (stream->readFlag())//Fog PostFX
  546. {
  547. mUseGlow = stream->readFlag();
  548. stream->read(&mGlowStrength);
  549. mModifLightRays = stream->readFlag();
  550. stream->read(&mLightRayMod);
  551. if (isTicking())
  552. {
  553. char buf[20];
  554. dSprintf(buf, sizeof(buf), "%3.7f", mGlowStrength);
  555. Con::setVariable("$VolFogGlowPostFx::glowStrength", buf);
  556. if (mUseGlow && !glowFX->isEnabled())
  557. glowFX->enable();
  558. if (!mUseGlow && glowFX->isEnabled())
  559. glowFX->disable();
  560. if (mModifLightRays)
  561. {
  562. char buf[20];
  563. dSprintf(buf, sizeof(buf), "%3.7f", mOldLightRayStrength * mLightRayMod);
  564. Con::setVariable("$LightRayPostFX::brightScalar", buf);
  565. }
  566. if (!mModifLightRays)
  567. {
  568. char buf[20];
  569. dSprintf(buf, sizeof(buf), "%3.7f", mOldLightRayStrength);
  570. Con::setVariable("$LightRayPostFX::brightScalar", buf);
  571. }
  572. }
  573. }
  574. if (stream->readFlag())//Volumetric Fog
  575. {
  576. mIgnoreWater = stream->readFlag();
  577. mReflect = stream->readFlag();
  578. stream->read(&mFogReflStrength);
  579. mResizing = stream->readFlag();
  580. stream->read(&mMinDisplaySize);
  581. stream->read(&mFadeSize);
  582. }
  583. if (stream->readFlag())//Fog shape
  584. {
  585. mShapeName = stream->readSTString();
  586. mathRead(*stream, &mat);
  587. mathRead(*stream, &scale);
  588. if (strcmp(oldShape, mShapeName) != 0)
  589. {
  590. mIsVBDirty = true;
  591. mShapeLoaded = LoadShape();
  592. }
  593. setScale(scale);
  594. setTransform(mat);
  595. ColBox.set(getTransform(), (mObjBox.getExtents() * getScale() * COLBOX_SCALE));
  596. mObjSize = mWorldBox.getGreatestDiagonalLength();
  597. mObjScale = getScale();
  598. mInvScale = (1.0f / getMax(getMax(mObjScale.x, mObjScale.y), mObjScale.z));
  599. }
  600. }
  601. void VolumetricFog::processTick(const Move* move)
  602. {
  603. Parent::processTick(move);
  604. mCounter++;
  605. if ( mGlowing==1 && mCurGlow < mGlowStrength )
  606. {
  607. mCurGlow += (mGlowStrength / 10.0);
  608. char buf[20];
  609. dSprintf(buf, sizeof(buf), "%3.7f", mCurGlow);
  610. Con::setVariable("$VolFogGlowPostFx::glowStrength", buf);
  611. }
  612. else if ( mGlowing == 2 && mCurGlow > 0.0f )
  613. {
  614. mCurGlow -= (mGlowStrength / 5.0f);
  615. if (mCurGlow <= 0.0f)
  616. {
  617. glowFX->disable();
  618. mGlowing = 0;
  619. setProcessTick(false);
  620. return;
  621. }
  622. else
  623. {
  624. char buf[20];
  625. dSprintf(buf, sizeof(buf), "%3.7f", mCurGlow);
  626. Con::setVariable("$VolFogGlowPostFx::glowStrength", buf);
  627. }
  628. }
  629. if (mCounter == 3)
  630. {
  631. ShapeBase* control = static_cast<ShapeBase*>(conn->getControlObject());
  632. MatrixF xfm;
  633. control->getRenderEyeTransform(&xfm);
  634. Point3F pos = xfm.getPosition();
  635. if (!ColBox.isContained(pos))
  636. _leaveFog(control);
  637. mCounter = 0;
  638. }
  639. }
  640. void VolumetricFog::_enterFog(ShapeBase *control)
  641. {
  642. if (mUseGlow)
  643. {
  644. if (glowFX)
  645. {
  646. mCurGlow = 0.0f;
  647. Con::setVariable("$VolFogGlowPostFx::glowStrength", "0.0");
  648. glowFX->enable();
  649. mGlowing = 1;
  650. }
  651. }
  652. if (mModifLightRays)
  653. {
  654. char buf[20];
  655. dSprintf(buf, sizeof(buf), "%3.7f", mOldLightRayStrength * mLightRayMod);
  656. Con::setVariable("$LightRayPostFX::brightScalar", buf);
  657. }
  658. mCounter = 0;
  659. char buf[20];
  660. dSprintf(buf, sizeof(buf), "%3.7f", mFogDensity);
  661. Con::setVariable("$VolumetricFog::density", buf);
  662. setProcessTick(true);
  663. if (control)
  664. onEnterFog_callback(control->getId());
  665. }
  666. void VolumetricFog::_leaveFog(ShapeBase *control)
  667. {
  668. mCamInFog = false;
  669. Con::setVariable("$VolumetricFog::density", "0.0");
  670. if (mModifLightRays)
  671. {
  672. char buf[20];
  673. dSprintf(buf, sizeof(buf), "%3.7f", mOldLightRayStrength);
  674. Con::setVariable("$LightRayPostFX::brightScalar", buf);
  675. }
  676. if (mUseGlow)
  677. {
  678. if (glowFX && mGlowing != 2)
  679. {
  680. mCurGlow = mGlowStrength;
  681. mGlowing = 2;
  682. if (control)
  683. onLeaveFog_callback(control->getId());
  684. }
  685. }
  686. else
  687. {
  688. setProcessTick(false);
  689. if (control)
  690. onLeaveFog_callback(control->getId());
  691. }
  692. }
  693. //-----------------------------------------------------------------------------
  694. // Setting up the renderers
  695. //-----------------------------------------------------------------------------
  696. bool VolumetricFog::setupRenderer()
  697. {
  698. // Search for the prepass rendertarget and shadermacros.
  699. mPrepassTarget = NamedTexTarget::find("prepass");
  700. if (!mPrepassTarget.isValid())
  701. {
  702. Con::errorf("VolumetricFog::setupRenderer - could not find PrepassTarget");
  703. return false;
  704. }
  705. Vector<GFXShaderMacro> macros;
  706. if (mPrepassTarget)
  707. mPrepassTarget->getShaderMacros(&macros);
  708. // Search the depth and frontbuffers which are created by the VolumetricFogRTManager
  709. mDepthBufferTarget = NamedTexTarget::find("volfogdepth");
  710. if (!mDepthBufferTarget.isValid())
  711. {
  712. Con::errorf("VolumetricFog::setupRenderer - could not find depthbuffer");
  713. return false;
  714. }
  715. mFrontBufferTarget = NamedTexTarget::find("volfogfront");
  716. if (!mFrontBufferTarget.isValid())
  717. {
  718. Con::errorf("VolumetricFog::setupRenderer - could not find frontbuffer");
  719. return false;
  720. }
  721. // Find and setup the prepass Shader
  722. ShaderData *shaderData;
  723. mPrePassShader = Sim::findObject("VolumetricFogPrePassShader", shaderData) ?
  724. shaderData->getShader() : NULL;
  725. if (!mPrePassShader)
  726. {
  727. Con::errorf("VolumetricFog::setupRenderer - could not find VolumetricFogPrePassShader");
  728. return false;
  729. }
  730. // Create ShaderConstBuffer and Handles
  731. mPPShaderConsts = mPrePassShader->allocConstBuffer();
  732. if (mPPShaderConsts.isNull())
  733. {
  734. Con::errorf("VolumetricFog::setupRenderer - could not allocate ShaderConstants 1.");
  735. return false;
  736. }
  737. mPPModelViewProjSC = mPrePassShader->getShaderConstHandle("$modelView");
  738. // Find and setup the VolumetricFog Shader
  739. shaderData = NULL;
  740. mShader = Sim::findObject("VolumetricFogShader", shaderData) ?
  741. shaderData->getShader(macros) : NULL;
  742. if (!mShader)
  743. {
  744. Con::errorf("VolumetricFog::setupRenderer - could not find VolumetricFogShader");
  745. return false;
  746. }
  747. // Create ShaderConstBuffer and Handles
  748. mShaderConsts = mShader->allocConstBuffer();
  749. if (mShaderConsts.isNull())
  750. {
  751. Con::errorf("VolumetricFog::setupRenderer - could not allocate ShaderConstants 2.");
  752. return false;
  753. }
  754. mModelViewProjSC = mShader->getShaderConstHandle("$modelView");
  755. mFadeSizeSC = mShader->getShaderConstHandle("$fadesize");
  756. mFogColorSC = mShader->getShaderConstHandle("$fogColor");
  757. mFogDensitySC = mShader->getShaderConstHandle("$fogDensity");
  758. mPreBias = mShader->getShaderConstHandle("$preBias");
  759. mAccumTime = mShader->getShaderConstHandle("$accumTime");
  760. mIsTexturedSC = mShader->getShaderConstHandle("$textured");
  761. mTexTilesSC = mShader->getShaderConstHandle("$numtiles");
  762. mModStrengthSC = mShader->getShaderConstHandle("$modstrength");
  763. mModSpeedSC = mShader->getShaderConstHandle("$modspeed");
  764. mViewPointSC = mShader->getShaderConstHandle("$viewpoint");
  765. mTexScaleSC = mShader->getShaderConstHandle("$texscale");
  766. mAmbientColorSC = mShader->getShaderConstHandle("$ambientColor");
  767. // Find and setup the reflection Shader
  768. shaderData = NULL;
  769. mReflectionShader = Sim::findObject("VolumetricFogReflectionShader", shaderData) ?
  770. shaderData->getShader() : NULL;
  771. if (!mReflectionShader)
  772. {
  773. Con::errorf("VolumetricFog::setupRenderer - could not find VolumetricFogReflectionShader");
  774. return false;
  775. }
  776. mReflShaderConsts = mReflectionShader->allocConstBuffer();
  777. if (mReflShaderConsts.isNull())
  778. {
  779. Con::errorf("VolumetricFog::setupRenderer - could not allocate ShaderConstants for VolumetricFogReflectionShader.");
  780. return false;
  781. }
  782. mReflModelViewProjSC = mReflectionShader->getShaderConstHandle("$modelView");
  783. mReflFogColorSC = mReflectionShader->getShaderConstHandle("$fogColor");
  784. mReflFogDensitySC = mReflectionShader->getShaderConstHandle("$fogDensity");
  785. mReflFogStrengthSC = mReflectionShader->getShaderConstHandle("$reflStrength");
  786. // Create the prepass StateBlock
  787. desc_preD.setCullMode(GFXCullCW);
  788. desc_preD.setBlend(true);
  789. desc_preD.setZReadWrite(false, false);
  790. desc_preD.stencilEnable = false;
  791. desc_preF.setCullMode(GFXCullCCW);
  792. desc_preF.setBlend(true);
  793. desc_preF.setZReadWrite(true, false);
  794. desc_preF.stencilEnable = false;
  795. // Create the VolumetricFog StateBlock
  796. descD.setCullMode(GFXCullCW);
  797. descD.setBlend(true);
  798. descD.setZReadWrite(false, false);// desc.setZReadWrite(true, false);
  799. // prepassBuffer sampler
  800. descD.samplersDefined = true;
  801. descD.samplers[0].addressModeU = GFXAddressClamp;
  802. descD.samplers[0].addressModeV = GFXAddressClamp;
  803. descD.samplers[0].addressModeW = GFXAddressClamp;
  804. descD.samplers[0].magFilter = GFXTextureFilterLinear;
  805. descD.samplers[0].minFilter = GFXTextureFilterLinear;
  806. descD.samplers[0].mipFilter = GFXTextureFilterLinear;
  807. descD.samplers[0].textureColorOp = GFXTOPDisable;
  808. // DepthBuffer sampler
  809. descD.samplers[1].addressModeU = GFXAddressClamp;
  810. descD.samplers[1].addressModeV = GFXAddressClamp;
  811. descD.samplers[1].addressModeW = GFXAddressClamp;
  812. descD.samplers[1].magFilter = GFXTextureFilterLinear;
  813. descD.samplers[1].minFilter = GFXTextureFilterLinear;
  814. descD.samplers[1].mipFilter = GFXTextureFilterLinear;
  815. descD.samplers[1].textureColorOp = GFXTOPModulate;
  816. // FrontBuffer sampler
  817. descD.samplers[2].addressModeU = GFXAddressClamp;
  818. descD.samplers[2].addressModeV = GFXAddressClamp;
  819. descD.samplers[2].addressModeW = GFXAddressClamp;
  820. descD.samplers[2].magFilter = GFXTextureFilterLinear;
  821. descD.samplers[2].minFilter = GFXTextureFilterLinear;
  822. descD.samplers[2].mipFilter = GFXTextureFilterLinear;
  823. descD.samplers[2].textureColorOp = GFXTOPModulate;
  824. // animated density modifier map sampler
  825. descD.samplers[3].addressModeU = GFXAddressWrap;
  826. descD.samplers[3].addressModeV = GFXAddressWrap;
  827. descD.samplers[3].addressModeW = GFXAddressWrap;
  828. descD.samplers[3].magFilter = GFXTextureFilterLinear;
  829. descD.samplers[3].minFilter = GFXTextureFilterLinear;
  830. descD.samplers[3].mipFilter = GFXTextureFilterLinear;
  831. descD.samplers[3].textureColorOp = GFXTOPModulate;
  832. dMemcpy(&descF, &descD, sizeof(GFXStateBlockDesc));
  833. descF.setCullMode(GFXCullCCW);
  834. descF.setBlend(true);
  835. descF.setZReadWrite(true, false);
  836. desc_refl.setCullMode(GFXCullCCW);
  837. desc_refl.setBlend(true);
  838. desc_refl.setZReadWrite(true, false);
  839. mStateblock_preD = GFX->createStateBlock(desc_preD);
  840. mStateblock_preF = GFX->createStateBlock(desc_preF);
  841. mStateblockD = GFX->createStateBlock(descD);
  842. mStateblockF = GFX->createStateBlock(descF);
  843. mStateblock_refl = GFX->createStateBlock(desc_refl);
  844. // Create Rendertarget
  845. z_buf = GFX->allocRenderToTextureTarget();
  846. if (z_buf == NULL)
  847. {
  848. Con::errorf("VolumetricFog::setupRenderer - Could not create Render Target");
  849. return false;
  850. }
  851. return true;
  852. }
  853. void VolumetricFog::prepRenderImage(SceneRenderState *state)
  854. {
  855. if (!mShapeLoaded || mFogDensity <= 0.0f || mResizing)
  856. return;
  857. if (!state->isDiffusePass())
  858. {
  859. if (!state->isReflectPass())
  860. return;
  861. }
  862. PROFILE_SCOPE(VolumetricFog_prepRenderImage);
  863. // Time critical therefore static_cast
  864. ShapeBase* control = static_cast<ShapeBase*>(conn->getControlObject());
  865. if (control->getWaterCoverage() >= 0.9f && !mIgnoreWater)
  866. return;
  867. camPos = state->getCameraPosition();
  868. F32 dist = (camPos - getBoxCenter()).len();
  869. F32 scaleFactor = dist * mInvScale;
  870. if (scaleFactor <= 0.0f)
  871. {
  872. if (mCurDetailLevel != 0)
  873. UpdateBuffers(0);
  874. }
  875. const F32 pixelScale = state->getViewport().extent.y / 300.0f;
  876. mPixelSize = (mRadius / scaleFactor) * state->getWorldToScreenScale().y * pixelScale;
  877. if (mPixelSize < mMinDisplaySize)
  878. return;
  879. if (mNumDetailLevels > 1)
  880. {
  881. if ((det_size[mCurDetailLevel].det_size > mPixelSize) && (mCurDetailLevel < mNumDetailLevels - 1))
  882. UpdateBuffers(mCurDetailLevel + 1);
  883. else if (mCurDetailLevel > 0)
  884. {
  885. if (mPixelSize >= det_size[mCurDetailLevel - 1].det_size)
  886. UpdateBuffers(mCurDetailLevel - 1);
  887. }
  888. }
  889. if (state->isReflectPass() && mReflect)
  890. {
  891. ObjectRenderInst *ri = state->getRenderPass()->allocInst<ObjectRenderInst>();
  892. ri->renderDelegate.bind(this, &VolumetricFog::reflect_render);
  893. ri->type = RenderPassManager::RIT_VolumetricFog;
  894. ri->translucentSort = true;
  895. ri->sortDistSq = getRenderWorldBox().getSqDistanceToPoint(camPos);
  896. if (dist < 1.0f)
  897. ri->defaultKey = 1;
  898. else
  899. ri->defaultKey = U32(dist);
  900. state->getRenderPass()->addInst(ri);
  901. return;
  902. }
  903. else if (state->isDiffusePass())
  904. {
  905. viewDist = state->getFarPlane();
  906. mFOV = state->getCameraFrustum().getFov() / M_PI_F;
  907. Point3F mEyeVec = state->getVectorEye() * viewDist;
  908. mViewPoint.x = ((mAtan2(mEyeVec.x, mEyeVec.y) / M_PI_F) + 1.0f) * mTexTiles;
  909. mViewPoint.y = (0.5f - (mAsin(mEyeVec.z) / M_PI_F)) * mTexTiles;
  910. bool isInside = ColBox.isContained(camPos);
  911. if (isInside && !mCamInFog)
  912. {
  913. mCamInFog = true;
  914. _enterFog(control);
  915. }
  916. else if (!isInside && mCamInFog)
  917. mCamInFog = false;
  918. ObjectRenderInst *ri = state->getRenderPass()->allocInst<ObjectRenderInst>();
  919. ri->renderDelegate.bind(this, &VolumetricFog::render);
  920. ri->type = RenderPassManager::RIT_VolumetricFog;
  921. ri->translucentSort = true;
  922. ri->sortDistSq = getRenderWorldBox().getSqDistanceToPoint(camPos);
  923. if (dist < 1.0f)
  924. ri->defaultKey = 1;
  925. else
  926. ri->defaultKey = U32(dist);
  927. state->getRenderPass()->addInst(ri);
  928. return;
  929. }
  930. return;
  931. }
  932. void VolumetricFog::render(ObjectRenderInst *ri, SceneRenderState *state, BaseMatInstance *overrideMat)
  933. {
  934. if (overrideMat || !mShapeLoaded || !isClientObject() || mResizing)
  935. return;
  936. PROFILE_SCOPE(VolumetricFog_Render);
  937. GFXTransformSaver saver;
  938. GFX->setVertexBuffer(mVB);
  939. GFX->setPrimitiveBuffer(mPB);
  940. MatrixF mat = getRenderTransform();
  941. mat.scale(mObjScale);
  942. GFX->multWorld(mat);
  943. GFX->setShader(mPrePassShader);
  944. GFX->setShaderConstBuffer(mPPShaderConsts);
  945. GFX->setStateBlock(mStateblock_preD);
  946. // Set all the shader consts...
  947. MatrixF xform(GFX->getProjectionMatrix());
  948. xform *= GFX->getViewMatrix();
  949. xform *= GFX->getWorldMatrix();
  950. mPPShaderConsts->setSafe(mPPModelViewProjSC, xform);
  951. const ColorF &sunlight = state->getAmbientLightColor();
  952. Point3F ambientColor(sunlight.red, sunlight.green, sunlight.blue);
  953. mShaderConsts->setSafe(mAmbientColorSC, ambientColor);
  954. GFXTextureObject *mDepthBuffer = mDepthBufferTarget ? mDepthBufferTarget->getTexture(0) : NULL;
  955. GFXTextureObject *mFrontBuffer = mFrontBufferTarget ? mFrontBufferTarget->getTexture(0) : NULL;
  956. GFX->pushActiveRenderTarget();
  957. //render backside to target mDepthBuffer
  958. z_buf->attachTexture(GFXTextureTarget::DepthStencil, GFXTextureTarget::sDefaultDepthStencil);
  959. z_buf->attachTexture(GFXTextureTarget::Color0, mDepthBuffer);
  960. GFX->setActiveRenderTarget(z_buf);
  961. GFX->clear(GFXClearStencil | GFXClearTarget , ColorI(0,0,0,0), 1.0f, 0);
  962. GFX->drawPrimitive(0);
  963. z_buf->resolve();
  964. //render frontside to target mFrontBuffer
  965. z_buf->attachTexture(GFXTextureTarget::DepthStencil, GFXTextureTarget::sDefaultDepthStencil);
  966. z_buf->attachTexture(GFXTextureTarget::Color0, mFrontBuffer);
  967. GFX->clear(GFXClearStencil | GFXClearTarget, ColorI(0, 0, 0, 0), 1.0f, 0);
  968. GFX->setStateBlock(mStateblock_preF);
  969. GFX->drawPrimitive(0);
  970. z_buf->resolve();
  971. GFX->popActiveRenderTarget();
  972. z_buf->attachTexture(GFXTextureTarget::Color0, NULL);
  973. //render Volumetric Fog
  974. GFX->setShader(mShader);
  975. GFX->setShaderConstBuffer(mShaderConsts);
  976. mShaderConsts->setSafe(mModelViewProjSC, xform);
  977. if (mFadeSize > 0.0f)
  978. mShaderConsts->setSafe(mFadeSizeSC, mClampF(mPixelSize / mFadeSize, 0.0f, 1.0f));
  979. else
  980. mShaderConsts->setSafe(mFadeSizeSC, 1.0f);
  981. mShaderConsts->setSafe(mFogColorSC, mFogColor);
  982. mShaderConsts->setSafe(mFogDensitySC, mFogDensity);
  983. mShaderConsts->setSafe(mPreBias, viewDist);
  984. mShaderConsts->setSafe(mAccumTime, (F32)Sim::getCurrentTime() / 1000.0f);
  985. mShaderConsts->setSafe(mModStrengthSC, mStrength);
  986. mShaderConsts->setSafe(mModSpeedSC, mSpeed);
  987. mShaderConsts->setSafe(mViewPointSC, mViewPoint);
  988. mShaderConsts->setSafe(mTexScaleSC, mTexScale * mFOV);
  989. mShaderConsts->setSafe(mTexTilesSC, mTexTiles);
  990. GFXTextureObject *prepasstex = mPrepassTarget ? mPrepassTarget->getTexture(0) : NULL;
  991. GFX->setTexture(0, prepasstex);
  992. GFX->setTexture(1, mDepthBuffer);
  993. GFX->setTexture(2, mFrontBuffer);
  994. if (mIsTextured && mStrength > 0.0f)
  995. {
  996. GFX->setTexture(3, mTexture);
  997. mShaderConsts->setSafe(mIsTexturedSC, 1.0f);
  998. }
  999. else
  1000. mShaderConsts->setSafe(mIsTexturedSC, 0.0f);
  1001. if (mCamInFog)
  1002. {
  1003. /*GFXLockedRect *rect=mDepthBuffer->lock();
  1004. U32 pixoffset = 0;// 1572864 + (512 * 4);
  1005. U8 red = rect->bits[pixoffset];
  1006. U8 green = rect->bits[pixoffset+1];
  1007. U8 blue = rect->bits[pixoffset+2];
  1008. U8 alpha = rect->bits[pixoffset+3];
  1009. mDepthBuffer->unlock();
  1010. S32 lval = ((alpha << 24) + (blue << 16) + (green << 8) + (red));
  1011. F32 fval = ((F32)lval / S32_MAX);
  1012. Con::printf("Color %d %d %d %d %d %f", red, green, blue, alpha, lval, fval);*/
  1013. GFX->setStateBlock(mStateblockD);
  1014. }
  1015. else
  1016. GFX->setStateBlock(mStateblockF);
  1017. GFX->drawPrimitive(0);
  1018. // Ensure these two textures are bound to the pixel shader input on the second run as they are used as pixel shader outputs (render targets).
  1019. GFX->setTexture(1, NULL); //mDepthBuffer
  1020. GFX->setTexture(2, NULL); //mFrontBuffer
  1021. GFX->updateStates(); //update the dirty texture state we set above
  1022. }
  1023. void VolumetricFog::reflect_render(ObjectRenderInst *ri, SceneRenderState *state, BaseMatInstance *overrideMat)
  1024. {
  1025. if (overrideMat || !mShapeLoaded || !isClientObject() || mResizing || (mFogReflStrength==0.0f))
  1026. return;
  1027. GFXTransformSaver saver;
  1028. GFX->setVertexBuffer(mVB);
  1029. GFX->setPrimitiveBuffer(mPB);
  1030. MatrixF mat = getRenderTransform();
  1031. mat.scale(mObjScale);
  1032. GFX->multWorld(mat);
  1033. GFX->setShader(mReflectionShader);
  1034. GFX->setShaderConstBuffer(mReflShaderConsts);
  1035. GFX->setStateBlock(mStateblock_refl);
  1036. // Set all the shader consts...
  1037. MatrixF xform(GFX->getProjectionMatrix());
  1038. xform *= GFX->getViewMatrix();
  1039. xform *= GFX->getWorldMatrix();
  1040. mReflShaderConsts->setSafe(mReflModelViewProjSC, xform);
  1041. mReflShaderConsts->setSafe(mReflFogColorSC, mFogColor);
  1042. mReflShaderConsts->setSafe(mReflFogDensitySC, mFogDensity);
  1043. mReflShaderConsts->setSafe(mReflFogStrengthSC, mFogReflStrength);
  1044. GFX->drawPrimitive(0);
  1045. }
  1046. //-----------------------------------------------------------------------------
  1047. // InitTexture is called whenever a modulation texture is added to the object
  1048. //-----------------------------------------------------------------------------
  1049. void VolumetricFog::InitTexture()
  1050. {
  1051. mIsTextured = false;
  1052. if (mTextureName.isNotEmpty())
  1053. mTexture.set(mTextureName, &GFXDefaultStaticDiffuseProfile, "VolumetricFogMod");
  1054. if (!mTexture.isNull())
  1055. {
  1056. mIsTextured = true;
  1057. F32 width = (F32)mPlatformWindow->getClientExtent().x;
  1058. F32 height = (F32)mPlatformWindow->getClientExtent().y;
  1059. mTexScale.x = 2.0f - ((F32)mTexture.getWidth() / width);
  1060. mTexScale.y = 2.0f - ((F32)mTexture.getHeight() / height);
  1061. }
  1062. }
  1063. void VolumetricFog::setFogColor(ColorF color)
  1064. {
  1065. mFogColor.set(255 * color.red,255 * color.green,255 * color.blue);
  1066. setMaskBits(FogColorMask);
  1067. }
  1068. void VolumetricFog::setFogColor(ColorI color)
  1069. {
  1070. mFogColor = color;
  1071. setMaskBits(FogColorMask);
  1072. }
  1073. void VolumetricFog::setFogDensity(F32 density)
  1074. {
  1075. if (density < 0.0f)
  1076. density = 0.0f;
  1077. mFogDensity = density;
  1078. setMaskBits(FogDensityMask);
  1079. }
  1080. void VolumetricFog::setFogModulation(F32 strength,Point2F speed1,Point2F speed2)
  1081. {
  1082. mStrength = strength;
  1083. mSpeed1 = speed1;
  1084. mSpeed2 = speed2;
  1085. mSpeed.set(speed1.x, speed1.y, speed2.x, speed2.y);
  1086. setMaskBits(FogModulationMask);
  1087. }
  1088. void VolumetricFog::setFogGlow(bool on_off, F32 strength)
  1089. {
  1090. mUseGlow = on_off;
  1091. mGlowStrength = strength;
  1092. setMaskBits(FogPostFXMask);
  1093. }
  1094. void VolumetricFog::setFogLightray(bool on_off, F32 strength)
  1095. {
  1096. mModifLightRays = on_off;
  1097. mLightRayMod = strength;
  1098. setMaskBits(FogPostFXMask);
  1099. }
  1100. bool VolumetricFog::isInsideFog()
  1101. {
  1102. return mCamInFog;
  1103. }
  1104. DefineEngineMethod(VolumetricFog, SetFogColorF, void, (ColorF new_color), ,
  1105. "@brief Changes the color of the fog\n\n."
  1106. "@params new_color the new fog color (rgb 0.0 - 1.0, a is ignored.")
  1107. {
  1108. object->setFogColor(new_color);
  1109. }
  1110. DefineEngineMethod(VolumetricFog, SetFogColor, void, (ColorI new_color), ,
  1111. "@brief Changes the color of the fog\n\n."
  1112. "@params new_color the new fog color (rgb 0-255, a is ignored.")
  1113. {
  1114. object->setFogColor(new_color);
  1115. }
  1116. DefineEngineMethod(VolumetricFog, SetFogDensity, void, (F32 new_density), ,
  1117. "@brief Changes the density of the fog\n\n."
  1118. "@params new_density the new fog density.")
  1119. {
  1120. object->setFogDensity(new_density);
  1121. }
  1122. DefineEngineMethod(VolumetricFog, SetFogModulation, void, (F32 new_strenght, Point2F new_speed1, Point2F new_speed2), ,
  1123. "@brief Changes the modulation of the fog\n\n."
  1124. "@params new_strenght the new strength of the modulation.\n"
  1125. "@params new_speed1 the new speed (x y) of the modulation layer 1.\n"
  1126. "@params new_speed2 the new speed (x y) of the modulation layer 2.\n")
  1127. {
  1128. object->setFogModulation(new_strenght, new_speed1, new_speed2);
  1129. }
  1130. DefineEngineMethod(VolumetricFog, SetFogGlow, void, (bool on_off,F32 strength), ,
  1131. "@brief Changes the glow postfx when inside the fog\n\n."
  1132. "@params on_off set to true to enable glow.\n"
  1133. "@params strength glow strength.\n")
  1134. {
  1135. object->setFogGlow(on_off, strength);
  1136. }
  1137. DefineEngineMethod(VolumetricFog, SetFogLightray, void, (bool on_off, F32 strength), ,
  1138. "@brief Changes the lightrays postfx when inside the fog\n\n."
  1139. "@params on_off set to true to modification of the lightray postfx.\n"
  1140. "@params strength lightray strength.\n")
  1141. {
  1142. object->setFogLightray(on_off, strength);
  1143. }
  1144. DefineEngineMethod(VolumetricFog, isInsideFog, bool, (), ,
  1145. "@brief returns true if control object is inside the fog\n\n.")
  1146. {
  1147. return object->isInsideFog();
  1148. }