VolumetricFog.cpp 43 KB

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