From 5d5e878129be994d435ee4bcf3c513b8a76f8420 Mon Sep 17 00:00:00 2001 From: Azaezel Date: Thu, 23 Oct 2014 20:48:58 -0500 Subject: [PATCH 01/47] dynamic cubemap support for tsStatics engine: implements the capacity for tsstatic objects to allow themselves to use the reflector system in order to display runtime generated cubemaps. script: defines a calibrated reflectordesc that reflects all object types within the space of approximately half stock veiwdistance usage: cubeReflectorDesc = DefaultCubeDesc placed in a given object-insatnces entry that uses a material with a dynamiccubemap = true; flag. immediate purpose: consistency of application of materials. long term impact: tags steps required in order to associate a given runtime generated cubemap with an object-instance. in the future, this is likely to give way to an area-derived cubemap based on the accumulation volume tech developed by Andrew Mac, or a screenspace reflection. --- Engine/source/T3D/tsStatic.cpp | 60 +++++++++++++++++++ Engine/source/T3D/tsStatic.h | 9 +++ .../Full/game/art/datablocks/environment.cs | 12 ++++ 3 files changed, 81 insertions(+) diff --git a/Engine/source/T3D/tsStatic.cpp b/Engine/source/T3D/tsStatic.cpp index 1474bf96d..c7ef76d4f 100644 --- a/Engine/source/T3D/tsStatic.cpp +++ b/Engine/source/T3D/tsStatic.cpp @@ -90,6 +90,9 @@ ConsoleDocClass( TSStatic, ); TSStatic::TSStatic() +: + cubeDescId( 0 ), + reflectorDesc( NULL ) { mNetFlags.set(Ghostable | ScopeAlways); @@ -180,6 +183,11 @@ void TSStatic::initPersistFields() endGroup("Rendering"); + addGroup( "Reflection" ); + addField( "cubeReflectorDesc", TypeRealString, Offset( cubeDescName, TSStatic ), + "References a ReflectorDesc datablock that defines performance and quality properties for dynamic reflections.\n"); + endGroup( "Reflection" ); + addGroup("Collision"); addField( "collisionType", TypeTSMeshType, Offset( mCollisionType, TSStatic ), @@ -279,6 +287,14 @@ bool TSStatic::onAdd() addToScene(); + if ( isClientObject() ) + { + mCubeReflector.unregisterReflector(); + + if ( reflectorDesc ) + mCubeReflector.registerReflector( this, reflectorDesc ); + } + _updateShouldTick(); return true; @@ -337,6 +353,16 @@ bool TSStatic::_createShape() if ( mAmbientThread ) mShapeInstance->setSequence( mAmbientThread, ambientSeq, 0); + // Resolve CubeReflectorDesc. + if ( cubeDescName.isNotEmpty() ) + { + Sim::findObject( cubeDescName, reflectorDesc ); + } + else if( cubeDescId > 0 ) + { + Sim::findObject( cubeDescId, reflectorDesc ); + } + return true; } @@ -402,6 +428,8 @@ void TSStatic::onRemove() mShapeInstance = NULL; mAmbientThread = NULL; + if ( isClientObject() ) + mCubeReflector.unregisterReflector(); Parent::onRemove(); } @@ -504,6 +532,12 @@ void TSStatic::prepRenderImage( SceneRenderState* state ) F32 invScale = (1.0f/getMax(getMax(mObjScale.x,mObjScale.y),mObjScale.z)); + // If we're currently rendering our own reflection we + // don't want to render ourselves into it. + if ( mCubeReflector.isRendering() ) + return; + + if ( mForceDetail == -1 ) mShapeInstance->setDetailFromDistance( state, dist * invScale ); else @@ -520,6 +554,9 @@ void TSStatic::prepRenderImage( SceneRenderState* state ) rdata.setFadeOverride( 1.0f ); rdata.setOriginSort( mUseOriginSort ); + if ( mCubeReflector.isEnabled() ) + rdata.setCubemap( mCubeReflector.getCubemap() ); + // If we have submesh culling enabled then prepare // the object space frustum to pass to the shape. Frustum culler; @@ -544,6 +581,20 @@ void TSStatic::prepRenderImage( SceneRenderState* state ) mat.scale( mObjScale ); GFX->setWorldMatrix( mat ); + if ( state->isDiffusePass() && mCubeReflector.isEnabled() && mCubeReflector.getOcclusionQuery() ) + { + RenderPassManager *pass = state->getRenderPass(); + OccluderRenderInst *ri = pass->allocInst(); + + ri->type = RenderPassManager::RIT_Occluder; + ri->query = mCubeReflector.getOcclusionQuery(); + mObjToWorld.mulP( mObjBox.getCenter(), &ri->position ); + ri->scale.set( mObjBox.getExtents() ); + ri->orientation = pass->allocUniqueXform( mObjToWorld ); + ri->isSphere = false; + state->getRenderPass()->addInst( ri ); + } + mShapeInstance->animate(); mShapeInstance->render( rdata ); @@ -628,6 +679,10 @@ U32 TSStatic::packUpdate(NetConnection *con, U32 mask, BitStream *stream) if ( mLightPlugin ) retMask |= mLightPlugin->packUpdate(this, AdvancedStaticOptionsMask, con, mask, stream); + if( stream->writeFlag( reflectorDesc != NULL ) ) + { + stream->writeRangedU32( reflectorDesc->getId(), DataBlockObjectIdFirst, DataBlockObjectIdLast ); + } return retMask; } @@ -687,6 +742,11 @@ void TSStatic::unpackUpdate(NetConnection *con, BitStream *stream) mLightPlugin->unpackUpdate(this, con, stream); } + if( stream->readFlag() ) + { + cubeDescId = stream->readRangedU32( DataBlockObjectIdFirst, DataBlockObjectIdLast ); + } + if ( isProperlyAdded() ) _updateShouldTick(); } diff --git a/Engine/source/T3D/tsStatic.h b/Engine/source/T3D/tsStatic.h index fe7113294..ac6c50cc1 100644 --- a/Engine/source/T3D/tsStatic.h +++ b/Engine/source/T3D/tsStatic.h @@ -39,6 +39,10 @@ #include "ts/tsShape.h" #endif +#ifndef _REFLECTOR_H_ + #include "scene/reflector.h" +#endif + class TSShapeInstance; class TSThread; class TSStatic; @@ -135,6 +139,11 @@ protected: /// Start or stop processing ticks depending on our state. void _updateShouldTick(); + String cubeDescName; + U32 cubeDescId; + ReflectorDesc *reflectorDesc; + CubeReflector mCubeReflector; + protected: Convex *mConvexList; diff --git a/Templates/Full/game/art/datablocks/environment.cs b/Templates/Full/game/art/datablocks/environment.cs index 386703f67..c9d2b0a51 100644 --- a/Templates/Full/game/art/datablocks/environment.cs +++ b/Templates/Full/game/art/datablocks/environment.cs @@ -84,3 +84,15 @@ datablock LightningData(DefaultStorm) thunderSounds[2] = ThunderCrash3Sound; thunderSounds[3] = ThunderCrash4Sound; }; + +datablock ReflectorDesc( DefaultCubeDesc ) +{ + texSize = 256; + nearDist = 0.1; + farDist = 1000.0; + objectTypeMask = 0xFFFFFFFF; + detailAdjust = 1.0; + priority = 1.0; + maxRateMs = 15; + useOcclusionQuery = true; +}; From b8c750dd56056edf4df47d1540cb103c775af037 Mon Sep 17 00:00:00 2001 From: Azaezel Date: Sun, 11 Jan 2015 17:45:29 -0600 Subject: [PATCH 02/47] extraneous mipmap generation prune OR spits out quite a few pointless mips for non square textures, which can lead to it triggering that AssertFatal(mNumMipLevels <= c_maxMipLevels, "GBitmap::allocateBitmap: too many miplevels"); entry --- Engine/source/gfx/bitmap/gBitmap.cpp | 2 +- Engine/source/gfx/gfxTextureManager.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Engine/source/gfx/bitmap/gBitmap.cpp b/Engine/source/gfx/bitmap/gBitmap.cpp index 151a792ed..78454d5e3 100644 --- a/Engine/source/gfx/bitmap/gBitmap.cpp +++ b/Engine/source/gfx/bitmap/gBitmap.cpp @@ -326,7 +326,7 @@ void GBitmap::allocateBitmap(const U32 in_width, const U32 in_height, const bool mNumMipLevels++; allocPixels += currWidth * currHeight * mBytesPerPixel; - } while (currWidth != 1 || currHeight != 1); + } while (currWidth != 1 && currHeight != 1); } AssertFatal(mNumMipLevels <= c_maxMipLevels, "GBitmap::allocateBitmap: too many miplevels"); diff --git a/Engine/source/gfx/gfxTextureManager.cpp b/Engine/source/gfx/gfxTextureManager.cpp index c997d1d2b..da132d7d2 100644 --- a/Engine/source/gfx/gfxTextureManager.cpp +++ b/Engine/source/gfx/gfxTextureManager.cpp @@ -1098,7 +1098,7 @@ void GFXTextureManager::_validateTexParams( const U32 width, const U32 height, currHeight = 1; inOutNumMips++; - } while ( currWidth != 1 || currHeight != 1 ); + } while ( currWidth != 1 && currHeight != 1 ); } } } From 6b0c6ae8ac79b4841c24f00c6066d04c61e4dda8 Mon Sep 17 00:00:00 2001 From: Azaezel Date: Wed, 24 Jun 2015 14:26:23 -0500 Subject: [PATCH 03/47] adds 3 new horizontal relative gui entries for dealing with swapping elements between 4:3 and 16:9 aspect ratios. "relativeToYL" maintains the initial aspect ratio, keeping the leftmost edge the same, "relativeToYR" also shifts it so the right hand side is shifted over so that edge would match, and "relativeToYC" takes/adds space from both sides --- Engine/source/gui/core/guiControl.cpp | 33 +++++++++++++++++++++++++++ Engine/source/gui/core/guiControl.h | 3 +++ 2 files changed, 36 insertions(+) diff --git a/Engine/source/gui/core/guiControl.cpp b/Engine/source/gui/core/guiControl.cpp index a17e701f3..14a10c517 100644 --- a/Engine/source/gui/core/guiControl.cpp +++ b/Engine/source/gui/core/guiControl.cpp @@ -175,6 +175,9 @@ ImplementEnumType( GuiHorizontalSizing, { GuiControl::horizResizeLeft, "left" }, { GuiControl::horizResizeCenter, "center" }, { GuiControl::horizResizeRelative, "relative" }, + { GuiControl::horizResizeRelativeToYL, "relativeToYL" }, + { GuiControl::horizResizeRelativeToYR, "relativeToYR" }, + { GuiControl::horizResizeRelativeToYC, "relativeToYC" }, { GuiControl::horizResizeWindowRelative, "windowRelative" } EndImplementEnumType; @@ -1366,6 +1369,36 @@ void GuiControl::parentResized(const RectI &oldParentRect, const RectI &newParen newPosition.x = newLeft; newExtent.x = newWidth; } + else if (mHorizSizing == horizResizeRelativeToYL && oldParentRect.extent.x != 0) + { + S32 newLeft = mRoundToNearest((F32(newPosition.x) / F32(oldParentRect.extent.x)) * F32(newParentRect.extent.x)); + S32 newWidth = mRoundToNearest((F32(newExtent.x) / F32(oldParentRect.extent.y)) * F32(newParentRect.extent.y)); + + newPosition.x = newLeft; + newExtent.x = newWidth; + } + else if (mHorizSizing == horizResizeRelativeToYR && oldParentRect.extent.x != 0) + { + S32 newLeft = mRoundToNearest((F32(newPosition.x) / F32(oldParentRect.extent.x)) * F32(newParentRect.extent.x)); + S32 newWidth = mRoundToNearest((F32(newExtent.x) / F32(oldParentRect.extent.y)) * F32(newParentRect.extent.y)); //origional aspect ratio corrected width + S32 rWidth = mRoundToNearest((F32(newExtent.x) / F32(oldParentRect.extent.x)) * F32(newParentRect.extent.x)); //parent aspect ratio relative width + + S32 offset = rWidth - newWidth; // account for change in relative width + newLeft += offset; + newPosition.x = newLeft; + newExtent.x = newWidth; + } + else if (mHorizSizing == horizResizeRelativeToYC && oldParentRect.extent.x != 0) + { + S32 newLeft = mRoundToNearest((F32(newPosition.x) / F32(oldParentRect.extent.x)) * F32(newParentRect.extent.x)); + S32 newWidth = mRoundToNearest((F32(newExtent.x) / F32(oldParentRect.extent.y)) * F32(newParentRect.extent.y)); //origional aspect ratio corrected width + S32 rWidth = mRoundToNearest((F32(newExtent.x) / F32(oldParentRect.extent.x)) * F32(newParentRect.extent.x)); //parent aspect ratio relative width + + S32 offset = rWidth - newWidth; // account for change in relative width + newLeft += offset/2; + newPosition.x = newLeft; + newExtent.x = newWidth; + } if (mVertSizing == vertResizeCenter) newPosition.y = (newParentRect.extent.y - getHeight()) >> 1; diff --git a/Engine/source/gui/core/guiControl.h b/Engine/source/gui/core/guiControl.h index 4240fbad6..fd538c65f 100644 --- a/Engine/source/gui/core/guiControl.h +++ b/Engine/source/gui/core/guiControl.h @@ -121,6 +121,9 @@ class GuiControl : public SimGroup horizResizeLeft, ///< fixed on the right and width horizResizeCenter, horizResizeRelative, ///< resize relative + horizResizeRelativeToYL, ///< resize relative to hieght delta (offset Left) + horizResizeRelativeToYR, ///< resize relative to hieght delta (offset Right) + horizResizeRelativeToYC, ///< resize relative to hieght delta (offset Right) horizResizeWindowRelative ///< resize window relative }; enum vertSizingOptions From 138d34e31cc54a41f4fefae39cbc773365ba982d Mon Sep 17 00:00:00 2001 From: Azaezel Date: Wed, 24 Jun 2015 17:18:36 -0500 Subject: [PATCH 04/47] renames for clarity: relativeToYL changed to aspectLeft ect. also by request, vertsizing options for down the line when mobile is supported.. --- Engine/source/gui/core/guiControl.cpp | 45 +++++++++++++++++++++++---- Engine/source/gui/core/guiControl.h | 9 ++++-- 2 files changed, 45 insertions(+), 9 deletions(-) diff --git a/Engine/source/gui/core/guiControl.cpp b/Engine/source/gui/core/guiControl.cpp index 14a10c517..222560f75 100644 --- a/Engine/source/gui/core/guiControl.cpp +++ b/Engine/source/gui/core/guiControl.cpp @@ -175,9 +175,9 @@ ImplementEnumType( GuiHorizontalSizing, { GuiControl::horizResizeLeft, "left" }, { GuiControl::horizResizeCenter, "center" }, { GuiControl::horizResizeRelative, "relative" }, - { GuiControl::horizResizeRelativeToYL, "relativeToYL" }, - { GuiControl::horizResizeRelativeToYR, "relativeToYR" }, - { GuiControl::horizResizeRelativeToYC, "relativeToYC" }, + { GuiControl::horizResizeAspectLeft, "aspectLeft" }, + { GuiControl::horizResizeAspectRight, "aspectRight" }, + { GuiControl::horizResizeAspectCenter, "aspectCenter" }, { GuiControl::horizResizeWindowRelative, "windowRelative" } EndImplementEnumType; @@ -189,6 +189,9 @@ ImplementEnumType( GuiVerticalSizing, { GuiControl::vertResizeTop, "top" }, { GuiControl::vertResizeCenter, "center" }, { GuiControl::vertResizeRelative, "relative" }, + { GuiControl::vertResizeAspectTop, "aspectTop" }, + { GuiControl::vertResizeAspectBottom, "aspectBottom" }, + { GuiControl::vertResizeAspectCenter, "aspectCenter" }, { GuiControl::vertResizeWindowRelative, "windowRelative" } EndImplementEnumType; @@ -1369,7 +1372,7 @@ void GuiControl::parentResized(const RectI &oldParentRect, const RectI &newParen newPosition.x = newLeft; newExtent.x = newWidth; } - else if (mHorizSizing == horizResizeRelativeToYL && oldParentRect.extent.x != 0) + else if (mHorizSizing == horizResizeAspectLeft && oldParentRect.extent.x != 0) { S32 newLeft = mRoundToNearest((F32(newPosition.x) / F32(oldParentRect.extent.x)) * F32(newParentRect.extent.x)); S32 newWidth = mRoundToNearest((F32(newExtent.x) / F32(oldParentRect.extent.y)) * F32(newParentRect.extent.y)); @@ -1377,7 +1380,7 @@ void GuiControl::parentResized(const RectI &oldParentRect, const RectI &newParen newPosition.x = newLeft; newExtent.x = newWidth; } - else if (mHorizSizing == horizResizeRelativeToYR && oldParentRect.extent.x != 0) + else if (mHorizSizing == horizResizeAspectRight && oldParentRect.extent.x != 0) { S32 newLeft = mRoundToNearest((F32(newPosition.x) / F32(oldParentRect.extent.x)) * F32(newParentRect.extent.x)); S32 newWidth = mRoundToNearest((F32(newExtent.x) / F32(oldParentRect.extent.y)) * F32(newParentRect.extent.y)); //origional aspect ratio corrected width @@ -1388,7 +1391,7 @@ void GuiControl::parentResized(const RectI &oldParentRect, const RectI &newParen newPosition.x = newLeft; newExtent.x = newWidth; } - else if (mHorizSizing == horizResizeRelativeToYC && oldParentRect.extent.x != 0) + else if (mHorizSizing == horizResizeAspectCenter && oldParentRect.extent.x != 0) { S32 newLeft = mRoundToNearest((F32(newPosition.x) / F32(oldParentRect.extent.x)) * F32(newParentRect.extent.x)); S32 newWidth = mRoundToNearest((F32(newExtent.x) / F32(oldParentRect.extent.y)) * F32(newParentRect.extent.y)); //origional aspect ratio corrected width @@ -1414,6 +1417,36 @@ void GuiControl::parentResized(const RectI &oldParentRect, const RectI &newParen newPosition.y = newTop; newExtent.y = newHeight; } + else if (mVertSizing == vertResizeAspectTop && oldParentRect.extent.y != 0) + { + S32 newTop = mRoundToNearest((F32(newPosition.y) / F32(oldParentRect.extent.y)) * F32(newParentRect.extent.y)); + S32 newHeight = mRoundToNearest((F32(newExtent.y) / F32(oldParentRect.extent.x)) * F32(newParentRect.extent.x)); + + newPosition.y = newTop; + newExtent.y = newHeight; + } + else if (mVertSizing == vertResizeAspectBottom && oldParentRect.extent.y != 0) + { + S32 newTop = mRoundToNearest((F32(newPosition.y) / F32(oldParentRect.extent.y)) * F32(newParentRect.extent.y)); + S32 newHeight = mRoundToNearest((F32(newExtent.y) / F32(oldParentRect.extent.x)) * F32(newParentRect.extent.x)); //origional aspect ratio corrected hieght + S32 rHeight = mRoundToNearest((F32(newExtent.y) / F32(oldParentRect.extent.y)) * F32(newParentRect.extent.y)); //parent aspect ratio relative hieght + + S32 offset = rHeight - newHeight; // account for change in relative hieght + newTop += offset; + newPosition.y = newTop; + newExtent.y = newHeight; + } + else if (mVertSizing == vertResizeAspectCenter && oldParentRect.extent.y != 0) + { + S32 newTop = mRoundToNearest((F32(newPosition.y) / F32(oldParentRect.extent.y)) * F32(newParentRect.extent.y)); + S32 newHeight = mRoundToNearest((F32(newExtent.y) / F32(oldParentRect.extent.x)) * F32(newParentRect.extent.x)); //origional aspect ratio corrected hieght + S32 rHeight = mRoundToNearest((F32(newExtent.y) / F32(oldParentRect.extent.y)) * F32(newParentRect.extent.y)); //parent aspect ratio relative hieght + + S32 offset = rHeight - newHeight; // account for change in relative hieght + newTop += offset / 2; + newPosition.y = newTop; + newExtent.y = newHeight; + } // Resizing Re factor [9/18/2006] // Only resize if our minExtent is satisfied with it. diff --git a/Engine/source/gui/core/guiControl.h b/Engine/source/gui/core/guiControl.h index fd538c65f..dc2653ff9 100644 --- a/Engine/source/gui/core/guiControl.h +++ b/Engine/source/gui/core/guiControl.h @@ -121,9 +121,9 @@ class GuiControl : public SimGroup horizResizeLeft, ///< fixed on the right and width horizResizeCenter, horizResizeRelative, ///< resize relative - horizResizeRelativeToYL, ///< resize relative to hieght delta (offset Left) - horizResizeRelativeToYR, ///< resize relative to hieght delta (offset Right) - horizResizeRelativeToYC, ///< resize relative to hieght delta (offset Right) + horizResizeAspectLeft, ///< resize relative to hieght delta (offset Left) + horizResizeAspectRight, ///< resize relative to hieght delta (offset Right) + horizResizeAspectCenter, ///< resize relative to hieght delta (Centered) horizResizeWindowRelative ///< resize window relative }; enum vertSizingOptions @@ -133,6 +133,9 @@ class GuiControl : public SimGroup vertResizeTop, ///< fixed in height and on the bottom vertResizeCenter, vertResizeRelative, ///< resize relative + vertResizeAspectTop, ///< resize relative to width delta (offset Left) + vertResizeAspectBottom, ///< resize relative to width delta (offset Right) + vertResizeAspectCenter, ///< resize relative to width delta Centered) vertResizeWindowRelative ///< resize window relative }; From 005c3c4b367ed7af19a9bd758bd330ac88a95c38 Mon Sep 17 00:00:00 2001 From: Azaezel Date: Wed, 29 Jul 2015 01:41:09 -0500 Subject: [PATCH 05/47] =?UTF-8?q?From=20Du=C5=A1an=20Joci=C4=87:=20additio?= =?UTF-8?q?nal=20debugdraw=20entries.=20DirectionLine,=20OutlinedText,=20C?= =?UTF-8?q?apsule?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Engine/source/gfx/sim/debugDraw.cpp | 110 +++++++++++++++++++++++++++- Engine/source/gfx/sim/debugDraw.h | 7 +- 2 files changed, 114 insertions(+), 3 deletions(-) diff --git a/Engine/source/gfx/sim/debugDraw.cpp b/Engine/source/gfx/sim/debugDraw.cpp index 68b8c835d..b31a6925e 100644 --- a/Engine/source/gfx/sim/debugDraw.cpp +++ b/Engine/source/gfx/sim/debugDraw.cpp @@ -132,6 +132,11 @@ void DebugDrawer::setupStateBlocks() d.setZReadWrite(false); mRenderZOffSB = GFX->createStateBlock(d); + + d.setCullMode(GFXCullCCW); + d.setZReadWrite(true, false); + d.setBlend(true); + mRenderAlpha = GFX->createStateBlock(d); } void DebugDrawer::render() @@ -158,10 +163,13 @@ void DebugDrawer::render() // Set up the state block... GFXStateBlockRef currSB; - if(p->useZ) + if(p->type==DebugPrim::Capsule){ + currSB = mRenderAlpha; + }else if(p->useZ){ currSB = mRenderZOnSB; - else + }else{ currSB = mRenderZOffSB; + } GFX->setStateBlock( currSB ); Point3F d; @@ -180,6 +188,47 @@ void DebugDrawer::render() PrimBuild::end(); break; + case DebugPrim::DirectionLine: + { + const static F32 ARROW_LENGTH = 0.2f, ARROW_RADIUS = 0.035f, CYLINDER_RADIUS = 0.008f; + Point3F &start = p->a, &end = p->b; + Point3F direction = end - start; + F32 length = direction.len(); + if( length>ARROW_LENGTH ){ + //cylinder with arrow on end + direction *= (1.0f/length); + Point3F baseArrow = end - (direction*ARROW_LENGTH); + GFX->getDrawUtil()->drawCone(currSB->getDesc(), baseArrow, end, ARROW_RADIUS, p->color); + GFX->getDrawUtil()->drawCylinder(currSB->getDesc(), start, baseArrow, CYLINDER_RADIUS, p->color); + }else if( length>0 ){ + //short, so just draw arrow + GFX->getDrawUtil()->drawCone(currSB->getDesc(), start, end, ARROW_RADIUS, p->color); + } + } + break; + case DebugPrim::Capsule: + GFX->getDrawUtil()->drawCapsule(currSB->getDesc(), p->a, p->b.x, p->b.y, p->color); + break; + case DebugPrim::OutlinedText: + { + GFXTransformSaver saver; + Point3F result; + if (MathUtils::mProjectWorldToScreen(p->a, &result, GFX->getViewport(), GFX->getWorldMatrix(), GFX->getProjectionMatrix())) + { + GFX->setClipRect(GFX->getViewport()); + Point2I where = Point2I(result.x, result.y); + + GFX->getDrawUtil()->setBitmapModulation(p->color2); + GFX->getDrawUtil()->drawText(mFont, Point2I(where.x-1, where.y), p->mText); + GFX->getDrawUtil()->drawText(mFont, Point2I(where.x+1, where.y), p->mText); + GFX->getDrawUtil()->drawText(mFont, Point2I(where.x, where.y-1), p->mText); + GFX->getDrawUtil()->drawText(mFont, Point2I(where.x, where.y+1), p->mText); + + GFX->getDrawUtil()->setBitmapModulation(p->color); + GFX->getDrawUtil()->drawText(mFont, where, p->mText); + } + } + break; case DebugPrim::Box: d = p->a - p->b; GFX->getDrawUtil()->drawCube(currSB->getDesc(), d * 0.5, (p->a + p->b) * 0.5, p->color); @@ -262,6 +311,63 @@ void DebugDrawer::drawLine(const Point3F &a, const Point3F &b, const ColorF &col mHead = n; } +void DebugDrawer::drawCapsule(const Point3F &a, const F32 &radius, const F32 &height, const ColorF &color) +{ + if(isFrozen || !isDrawing) + return; + + DebugPrim *n = mPrimChunker.alloc(); + + n->useZ = true; + n->dieTime = 0; + n->a = a; + n->b.x = radius; + n->b.y = height; + n->color = color; + n->type = DebugPrim::Capsule; + + n->next = mHead; + mHead = n; + +} + +void DebugDrawer::drawDirectionLine(const Point3F &a, const Point3F &b, const ColorF &color) +{ + if(isFrozen || !isDrawing) + return; + + DebugPrim *n = mPrimChunker.alloc(); + + n->useZ = true; + n->dieTime = 0; + n->a = a; + n->b = b; + n->color = color; + n->type = DebugPrim::DirectionLine; + + n->next = mHead; + mHead = n; +} + +void DebugDrawer::drawOutlinedText(const Point3F& pos, const String& text, const ColorF &color, const ColorF &colorOutline) +{ + if(isFrozen || !isDrawing) + return; + + DebugPrim *n = mPrimChunker.alloc(); + + n->useZ = false; + n->dieTime = 0; + n->a = pos; + n->color = color; + n->color2 = colorOutline; + dStrncpy(n->mText, text.c_str(), 256); + n->type = DebugPrim::OutlinedText; + + n->next = mHead; + mHead = n; +} + void DebugDrawer::drawTri(const Point3F &a, const Point3F &b, const Point3F &c, const ColorF &color) { if(isFrozen || !isDrawing) diff --git a/Engine/source/gfx/sim/debugDraw.h b/Engine/source/gfx/sim/debugDraw.h index b1ab55970..c650417b0 100644 --- a/Engine/source/gfx/sim/debugDraw.h +++ b/Engine/source/gfx/sim/debugDraw.h @@ -161,6 +161,7 @@ private: { /// Color used for this primitive. ColorF color; + ColorF color2; /// Points used to store positional data. Exact semantics determined by type. Point3F a, b, c; @@ -168,7 +169,10 @@ private: Tri, Box, Line, - Text + Text, + DirectionLine, + OutlinedText, + Capsule, } type; ///< Type of the primitive. The meanings of a,b,c are determined by this. SimTime dieTime; ///< Time at which we should remove this from the list. @@ -188,6 +192,7 @@ private: GFXStateBlockRef mRenderZOffSB; GFXStateBlockRef mRenderZOnSB; + GFXStateBlockRef mRenderAlpha; Resource mFont; From 5d91cf90b386759f2d2ede4773139786a8b32a6d Mon Sep 17 00:00:00 2001 From: Hein-Pieter van Braam Date: Tue, 7 Jul 2015 21:11:26 +0200 Subject: [PATCH 06/47] Fix running on Linux / Intel Mesa drivers * Explicitly request a GL 3.2 context * Enable 'experimental' extensions on glew (This appears necessary to get glew to work with explictly set GL versions) --- Engine/source/gfx/gl/sdl/gfxGLDevice.sdl.cpp | 4 ++++ Engine/source/gfx/gl/tGL/tGL.cpp | 1 + Engine/source/platformSDL/sdlPlatformGL.cpp | 4 +--- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/Engine/source/gfx/gl/sdl/gfxGLDevice.sdl.cpp b/Engine/source/gfx/gl/sdl/gfxGLDevice.sdl.cpp index 10e18deb4..74e1773fc 100644 --- a/Engine/source/gfx/gl/sdl/gfxGLDevice.sdl.cpp +++ b/Engine/source/gfx/gl/sdl/gfxGLDevice.sdl.cpp @@ -83,6 +83,10 @@ void GFXGLDevice::enumerateAdapters( Vector &adapterList ) ); SDL_ClearError(); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); + SDL_GLContext tempContext = SDL_GL_CreateContext( tempWindow ); if( !tempContext ) { diff --git a/Engine/source/gfx/gl/tGL/tGL.cpp b/Engine/source/gfx/gl/tGL/tGL.cpp index 94953b487..8d62a7fd1 100644 --- a/Engine/source/gfx/gl/tGL/tGL.cpp +++ b/Engine/source/gfx/gl/tGL/tGL.cpp @@ -29,6 +29,7 @@ namespace GL { void gglPerformBinds() { + glewExperimental = GL_TRUE; GLenum err = glewInit(); AssertFatal(GLEW_OK == err, avar("Error: %s\n", glewGetErrorString(err)) ); } diff --git a/Engine/source/platformSDL/sdlPlatformGL.cpp b/Engine/source/platformSDL/sdlPlatformGL.cpp index 6562f2c80..b71846d8b 100644 --- a/Engine/source/platformSDL/sdlPlatformGL.cpp +++ b/Engine/source/platformSDL/sdlPlatformGL.cpp @@ -13,18 +13,16 @@ namespace PlatformGL return; inited = true; - const U32 majorOGL = 4; + const U32 majorOGL = 3; const U32 minorOGL = 2; U32 debugFlag = 0; #ifdef TORQUE_DEBUG debugFlag |= SDL_GL_CONTEXT_DEBUG_FLAG; #endif -#if 0 // cause problem with glew, no extension load SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, majorOGL); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, minorOGL); SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); -#endif SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, debugFlag); SDL_ClearError(); From 08622e9601da87b2c663042a06ba404e6bc1577a Mon Sep 17 00:00:00 2001 From: Hein-Pieter van Braam Date: Mon, 20 Jul 2015 15:15:04 +0200 Subject: [PATCH 07/47] Use different extension detection mechanism I got this from looking at the code from the glew utility 'glewinfo' on my system it reported the following for GL_ARB_geometry_shader4: OK [MISSING]. This lead me to believe that there are two different ways of determining extensions. The first 'OK' seems to refer to the entrypoint existing while the second one seems to refer to the extension being available. The difference is this: The first OK comes from : GLEW_ARB_geometry_shader4 the global whereas the second 'MISSING' comes from glewGetExtension("GL_ARB_geometry_shader4"). By replacing the gglHasExtension I got the desired result. We may want to implement some caching if we want to keep using GLEW perhaps? Anyway I suggest this merely as a test, I'm not sure if this is a viable long-term solution. --- Engine/source/gfx/gl/tGL/tGL.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Engine/source/gfx/gl/tGL/tGL.h b/Engine/source/gfx/gl/tGL/tGL.h index aa1275ee5..849f49093 100644 --- a/Engine/source/gfx/gl/tGL/tGL.h +++ b/Engine/source/gfx/gl/tGL/tGL.h @@ -24,7 +24,8 @@ #define T_GL_H #include "GL/glew.h" -#define gglHasExtension(EXTENSION) GLEW_##EXTENSION +// Slower but reliably detects extensions +#define gglHasExtension(EXTENSION) glewGetExtension("GL_##EXTENSION") #endif From 320718327f1c77c8ad61b29301dbf949ca63307b Mon Sep 17 00:00:00 2001 From: Hein-Pieter van Braam Date: Mon, 20 Jul 2015 16:27:52 +0200 Subject: [PATCH 08/47] Actually generate a working string for glewGetExtension() I don't know how to 'C' apparently. --- Engine/source/gfx/gl/tGL/tGL.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Engine/source/gfx/gl/tGL/tGL.h b/Engine/source/gfx/gl/tGL/tGL.h index 849f49093..37aefe7f3 100644 --- a/Engine/source/gfx/gl/tGL/tGL.h +++ b/Engine/source/gfx/gl/tGL/tGL.h @@ -25,7 +25,7 @@ #include "GL/glew.h" // Slower but reliably detects extensions -#define gglHasExtension(EXTENSION) glewGetExtension("GL_##EXTENSION") +#define gglHasExtension(EXTENSION) glewGetExtension("GL_" # EXTENSION) #endif From eadd77272d857d9478baaf94833210e9af5498ed Mon Sep 17 00:00:00 2001 From: Hein-Pieter van Braam Date: Thu, 30 Jul 2015 22:16:13 +0200 Subject: [PATCH 09/47] Add @Azaezel's exception for Win32 "This chunk causes issues on the win8.1/non-SDL side." --- Engine/source/gfx/gl/tGL/tGL.h | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Engine/source/gfx/gl/tGL/tGL.h b/Engine/source/gfx/gl/tGL/tGL.h index 37aefe7f3..bb21422b7 100644 --- a/Engine/source/gfx/gl/tGL/tGL.h +++ b/Engine/source/gfx/gl/tGL/tGL.h @@ -24,8 +24,13 @@ #define T_GL_H #include "GL/glew.h" -// Slower but reliably detects extensions +#if defined (TORQUE_OS_WIN) +// This doesn't work on Mesa drivers. +#define gglHasExtension(EXTENSION) GLEW_##EXTENSION +#else +// Slower but reliably detects extensions on Mesa. #define gglHasExtension(EXTENSION) glewGetExtension("GL_" # EXTENSION) +#endif #endif From 4d3db61e941b33cd32253441df9373ce9eaecb66 Mon Sep 17 00:00:00 2001 From: Azaezel Date: Wed, 12 Aug 2015 03:41:49 -0500 Subject: [PATCH 10/47] credit to @MusicMonkey5555 for spotting. asserts for Div/NULLs with mutli-element classes Also includes his magnitude and normalize safe alts --- Engine/source/core/color.h | 1 + Engine/source/math/mPoint2.h | 10 ++++++++++ Engine/source/math/mPoint3.h | 29 ++++++++++++++++++++++++++++- 3 files changed, 39 insertions(+), 1 deletion(-) diff --git a/Engine/source/core/color.h b/Engine/source/core/color.h index b0620fc4f..6378e3579 100644 --- a/Engine/source/core/color.h +++ b/Engine/source/core/color.h @@ -503,6 +503,7 @@ inline ColorI& ColorI::operator*=(const S32 in_mul) inline ColorI& ColorI::operator/=(const S32 in_mul) { + AssertFatal(in_mul != 0.0f, "Error, div by zero..."); red = red / in_mul; green = green / in_mul; blue = blue / in_mul; diff --git a/Engine/source/math/mPoint2.h b/Engine/source/math/mPoint2.h index f814ddbbc..c141400b9 100644 --- a/Engine/source/math/mPoint2.h +++ b/Engine/source/math/mPoint2.h @@ -438,6 +438,7 @@ inline Point2I Point2I::operator/(const Point2I &_vec) const inline Point2I& Point2I::operator/=(const Point2I &_vec) { + AssertFatal(_vec.x != 0 && _vec.y != 0, "Error, div by zero attempted"); x /= _vec.x; y /= _vec.y; return *this; @@ -645,6 +646,7 @@ inline Point2F Point2F::operator/(const Point2F &_vec) const inline Point2F& Point2F::operator/=(const Point2F &_vec) { + AssertFatal(_vec.x != 0 && _vec.y != 0, "Error, div by zero attempted"); x /= _vec.x; y /= _vec.y; return *this; @@ -908,6 +910,14 @@ inline bool mIsNaN( const Point2F &p ) return mIsNaN_F( p.x ) || mIsNaN_F( p.y ); } +/// Return 0 if points are colinear +/// Return positive if p0p1p2 are counter-clockwise +/// Return negative if p0p1p2 are clockwise +inline F64 mCross(const Point2F &p0, const Point2F &p1, const Point2F &pt2) +{ + return (p1.x - p0.x) * (pt2.y - p0.y) - (p1.y - p0.y) * (pt2.x - p0.x); +} + namespace DictHash { diff --git a/Engine/source/math/mPoint3.h b/Engine/source/math/mPoint3.h index 5a85c6cd0..12af91c4b 100644 --- a/Engine/source/math/mPoint3.h +++ b/Engine/source/math/mPoint3.h @@ -233,11 +233,13 @@ class Point3D bool isZero() const; F64 len() const; F64 lenSquared() const; + F64 magnitudeSafe() const; //-------------------------------------- Mathematical mutators public: void neg(); void normalize(); + void normalizeSafe(); void normalize(F64 val); void convolve(const Point3D&); void convolveInverse(const Point3D&); @@ -728,11 +730,13 @@ inline Point3F& Point3F::operator*=(const Point3F &_vec) inline Point3F Point3F::operator/(const Point3F &_vec) const { + AssertFatal(_vec.x != 0.0f && _vec.y != 0.0f && _vec.z != 0.0f, "Error, div by zero attempted"); return Point3F(x / _vec.x, y / _vec.y, z / _vec.z); } inline Point3F& Point3F::operator/=(const Point3F &_vec) { + AssertFatal(_vec.x != 0.0f && _vec.y != 0.0f && _vec.z != 0.0f, "Error, div by zero attempted"); x /= _vec.x; y /= _vec.y; z /= _vec.z; @@ -855,7 +859,8 @@ inline F64 Point3D::lenSquared() const inline F64 Point3D::len() const { - return mSqrtD(x*x + y*y + z*z); + F64 temp = x*x + y*y + z*z; + return (temp > 0.0) ? mSqrtD(temp) : 0.0; } inline void Point3D::normalize() @@ -863,6 +868,28 @@ inline void Point3D::normalize() m_point3D_normalize(*this); } +inline F64 Point3D::magnitudeSafe() const +{ + if( isZero() ) + { + return 0.0; + } + else + { + return len(); + } +} + +inline void Point3D::normalizeSafe() +{ + F64 vmag = magnitudeSafe(); + + if( vmag > POINT_EPSILON ) + { + *this *= F64(1.0 / vmag); + } +} + inline void Point3D::normalize(F64 val) { m_point3D_normalize_f(*this, val); From 3630f97ab14867887acb196283ee3c09fc73efed Mon Sep 17 00:00:00 2001 From: irei1as Date: Tue, 22 Sep 2015 19:37:42 +0200 Subject: [PATCH 11/47] mQuat.h change to fix QuatF::angleBetween The old version doesn't have that 2.0f in the return that seems to be needed. Also added normalizing inside so it can be used for not-normalized quaternions too. --- Engine/source/math/mQuat.h | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/Engine/source/math/mQuat.h b/Engine/source/math/mQuat.h index 2ea1b94c1..c167e4e18 100644 --- a/Engine/source/math/mQuat.h +++ b/Engine/source/math/mQuat.h @@ -227,8 +227,13 @@ inline F32 QuatF::dot( const QuatF &q ) const inline F32 QuatF::angleBetween( const QuatF & q ) { - // angle between to quaternions - return mAcos(x * q.x + y * q.y + z * q.z + w * q.w); + // angle between two quaternions + QuatF base(x,y,z,w); + base=base.normalize(); + QuatF q_norm=q; + q_norm=q_norm.normalize(); + return 2.0f*mAcos(base.dot(q_norm)); } + #endif // _MQUAT_H_ From f128b451702782edbdd6b04664286b2bae79b6f0 Mon Sep 17 00:00:00 2001 From: rextimmy Date: Fri, 25 Sep 2015 22:40:24 +1000 Subject: [PATCH 12/47] Changed order of fmodex library unload. --- Engine/source/sfx/fmod/sfxFMODDevice.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Engine/source/sfx/fmod/sfxFMODDevice.h b/Engine/source/sfx/fmod/sfxFMODDevice.h index f710faa20..fc15041e9 100644 --- a/Engine/source/sfx/fmod/sfxFMODDevice.h +++ b/Engine/source/sfx/fmod/sfxFMODDevice.h @@ -105,8 +105,8 @@ struct FModFNTable } ~FModFNTable() { - eventDllRef = NULL; dllRef = NULL; + eventDllRef = NULL; delete mutex; } From 1733ecc315197cab5b3f2873a619980d36895c61 Mon Sep 17 00:00:00 2001 From: irei1as Date: Tue, 29 Sep 2015 16:13:01 +0200 Subject: [PATCH 13/47] Updated normalize() It seems normalize() already changes the quaternion so the asignation is not needed. --- Engine/source/math/mQuat.h | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/Engine/source/math/mQuat.h b/Engine/source/math/mQuat.h index c167e4e18..628e298ba 100644 --- a/Engine/source/math/mQuat.h +++ b/Engine/source/math/mQuat.h @@ -229,11 +229,10 @@ inline F32 QuatF::angleBetween( const QuatF & q ) { // angle between two quaternions QuatF base(x,y,z,w); - base=base.normalize(); + base.normalize(); QuatF q_norm=q; - q_norm=q_norm.normalize(); + q_norm.normalize(); return 2.0f*mAcos(base.dot(q_norm)); } - #endif // _MQUAT_H_ From 6d6055c8738c96bc5910ba9be720c2ac0e2abdeb Mon Sep 17 00:00:00 2001 From: blackwc Date: Wed, 7 Oct 2015 03:28:48 -0400 Subject: [PATCH 14/47] fullscreen and windowed mode cli fix --- Templates/Empty/game/core/main.cs | 4 ++-- Templates/Empty/game/core/scripts/client/canvas.cs | 3 +++ Templates/Full/game/core/main.cs | 4 ++-- Templates/Full/game/core/scripts/client/canvas.cs | 3 +++ 4 files changed, 10 insertions(+), 4 deletions(-) diff --git a/Templates/Empty/game/core/main.cs b/Templates/Empty/game/core/main.cs index 0baeb9364..f666c948c 100644 --- a/Templates/Empty/game/core/main.cs +++ b/Templates/Empty/game/core/main.cs @@ -141,11 +141,11 @@ function parseArgs() switch$ (%arg) { case "-fullscreen": - setFullScreen(true); + $cliFullscreen = true; $argUsed[%i]++; case "-windowed": - setFullScreen(false); + $cliFullscreen = false; $argUsed[%i]++; case "-openGL": diff --git a/Templates/Empty/game/core/scripts/client/canvas.cs b/Templates/Empty/game/core/scripts/client/canvas.cs index 69dd6da71..b3a906f46 100644 --- a/Templates/Empty/game/core/scripts/client/canvas.cs +++ b/Templates/Empty/game/core/scripts/client/canvas.cs @@ -32,6 +32,9 @@ function configureCanvas() if ($pref::Video::mode $= "") $pref::Video::mode = "800 600 false 32 60 0"; + if($cliFullscreen !$="") + $pref::Video::mode = setWord($pref::Video::mode, $WORD::FULLSCREEN, $cliFullScreen); + %resX = getWord($pref::Video::mode, $WORD::RES_X); %resY = getWord($pref::Video::mode, $WORD::RES_Y); %fs = getWord($pref::Video::mode, $WORD::FULLSCREEN); diff --git a/Templates/Full/game/core/main.cs b/Templates/Full/game/core/main.cs index 0baeb9364..f666c948c 100644 --- a/Templates/Full/game/core/main.cs +++ b/Templates/Full/game/core/main.cs @@ -141,11 +141,11 @@ function parseArgs() switch$ (%arg) { case "-fullscreen": - setFullScreen(true); + $cliFullscreen = true; $argUsed[%i]++; case "-windowed": - setFullScreen(false); + $cliFullscreen = false; $argUsed[%i]++; case "-openGL": diff --git a/Templates/Full/game/core/scripts/client/canvas.cs b/Templates/Full/game/core/scripts/client/canvas.cs index 69dd6da71..b3a906f46 100644 --- a/Templates/Full/game/core/scripts/client/canvas.cs +++ b/Templates/Full/game/core/scripts/client/canvas.cs @@ -32,6 +32,9 @@ function configureCanvas() if ($pref::Video::mode $= "") $pref::Video::mode = "800 600 false 32 60 0"; + if($cliFullscreen !$="") + $pref::Video::mode = setWord($pref::Video::mode, $WORD::FULLSCREEN, $cliFullScreen); + %resX = getWord($pref::Video::mode, $WORD::RES_X); %resY = getWord($pref::Video::mode, $WORD::RES_Y); %fs = getWord($pref::Video::mode, $WORD::FULLSCREEN); From 5239c2f183787e66393391a9b1d6016d29f8dd65 Mon Sep 17 00:00:00 2001 From: blackwc Date: Wed, 7 Oct 2015 04:56:36 -0400 Subject: [PATCH 15/47] fullscreen and windowed mode cli fix update --- Templates/Empty/game/core/scripts/client/canvas.cs | 4 +++- Templates/Full/game/core/scripts/client/canvas.cs | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/Templates/Empty/game/core/scripts/client/canvas.cs b/Templates/Empty/game/core/scripts/client/canvas.cs index b3a906f46..3982b433d 100644 --- a/Templates/Empty/game/core/scripts/client/canvas.cs +++ b/Templates/Empty/game/core/scripts/client/canvas.cs @@ -32,8 +32,10 @@ function configureCanvas() if ($pref::Video::mode $= "") $pref::Video::mode = "800 600 false 32 60 0"; - if($cliFullscreen !$="") + if($cliFullscreen !$="") { $pref::Video::mode = setWord($pref::Video::mode, $WORD::FULLSCREEN, $cliFullScreen); + $cliFullscreen = ""; + } %resX = getWord($pref::Video::mode, $WORD::RES_X); %resY = getWord($pref::Video::mode, $WORD::RES_Y); diff --git a/Templates/Full/game/core/scripts/client/canvas.cs b/Templates/Full/game/core/scripts/client/canvas.cs index b3a906f46..cae9e16b6 100644 --- a/Templates/Full/game/core/scripts/client/canvas.cs +++ b/Templates/Full/game/core/scripts/client/canvas.cs @@ -32,8 +32,10 @@ function configureCanvas() if ($pref::Video::mode $= "") $pref::Video::mode = "800 600 false 32 60 0"; - if($cliFullscreen !$="") + if($cliFullscreen !$= "") { $pref::Video::mode = setWord($pref::Video::mode, $WORD::FULLSCREEN, $cliFullScreen); + $cliFullscreen = ""; + } %resX = getWord($pref::Video::mode, $WORD::RES_X); %resY = getWord($pref::Video::mode, $WORD::RES_Y); From ef5bdc66d33164809f81bde73a31c818a2032457 Mon Sep 17 00:00:00 2001 From: blackwc Date: Sun, 11 Oct 2015 02:34:21 -0400 Subject: [PATCH 16/47] fullscreen and windowed mode cli fix update 2 --- Templates/Empty/game/core/scripts/client/canvas.cs | 14 +++++++------- Templates/Full/game/core/scripts/client/canvas.cs | 14 +++++++------- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/Templates/Empty/game/core/scripts/client/canvas.cs b/Templates/Empty/game/core/scripts/client/canvas.cs index 3982b433d..5c1d377c5 100644 --- a/Templates/Empty/game/core/scripts/client/canvas.cs +++ b/Templates/Empty/game/core/scripts/client/canvas.cs @@ -32,11 +32,6 @@ function configureCanvas() if ($pref::Video::mode $= "") $pref::Video::mode = "800 600 false 32 60 0"; - if($cliFullscreen !$="") { - $pref::Video::mode = setWord($pref::Video::mode, $WORD::FULLSCREEN, $cliFullScreen); - $cliFullscreen = ""; - } - %resX = getWord($pref::Video::mode, $WORD::RES_X); %resY = getWord($pref::Video::mode, $WORD::RES_Y); %fs = getWord($pref::Video::mode, $WORD::FULLSCREEN); @@ -44,9 +39,14 @@ function configureCanvas() %rate = getWord($pref::Video::mode, $WORD::REFRESH); %fsaa = getWord($pref::Video::mode, $WORD::AA); - echo("--------------"); - echo("Attempting to set resolution to \"" @ $pref::Video::mode @ "\""); + if($cliFullscreen !$= "") { + %fs = $cliFullscreen; + $cliFullscreen = ""; + } + echo("--------------"); + echo("Attempting to set resolution to \"" @ %resX SPC %resY SPC %fs SPC %bpp SPC %rate SPC %fsaa @ "\""); + %deskRes = getDesktopResolution(); %deskResX = getWord(%deskRes, $WORD::RES_X); %deskResY = getWord(%deskRes, $WORD::RES_Y); diff --git a/Templates/Full/game/core/scripts/client/canvas.cs b/Templates/Full/game/core/scripts/client/canvas.cs index cae9e16b6..5c1d377c5 100644 --- a/Templates/Full/game/core/scripts/client/canvas.cs +++ b/Templates/Full/game/core/scripts/client/canvas.cs @@ -32,11 +32,6 @@ function configureCanvas() if ($pref::Video::mode $= "") $pref::Video::mode = "800 600 false 32 60 0"; - if($cliFullscreen !$= "") { - $pref::Video::mode = setWord($pref::Video::mode, $WORD::FULLSCREEN, $cliFullScreen); - $cliFullscreen = ""; - } - %resX = getWord($pref::Video::mode, $WORD::RES_X); %resY = getWord($pref::Video::mode, $WORD::RES_Y); %fs = getWord($pref::Video::mode, $WORD::FULLSCREEN); @@ -44,9 +39,14 @@ function configureCanvas() %rate = getWord($pref::Video::mode, $WORD::REFRESH); %fsaa = getWord($pref::Video::mode, $WORD::AA); - echo("--------------"); - echo("Attempting to set resolution to \"" @ $pref::Video::mode @ "\""); + if($cliFullscreen !$= "") { + %fs = $cliFullscreen; + $cliFullscreen = ""; + } + echo("--------------"); + echo("Attempting to set resolution to \"" @ %resX SPC %resY SPC %fs SPC %bpp SPC %rate SPC %fsaa @ "\""); + %deskRes = getDesktopResolution(); %deskResX = getWord(%deskRes, $WORD::RES_X); %deskResY = getWord(%deskRes, $WORD::RES_Y); From b1fccc848c6bd45364b6cb7bbe109a117cb179cd Mon Sep 17 00:00:00 2001 From: Azaezel Date: Sat, 7 Nov 2015 09:04:47 -0600 Subject: [PATCH 17/47] corrects ghosted decal datablock lookup flaw --- Engine/source/T3D/decal/decalData.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/Engine/source/T3D/decal/decalData.cpp b/Engine/source/T3D/decal/decalData.cpp index 67436e991..e517d2897 100644 --- a/Engine/source/T3D/decal/decalData.cpp +++ b/Engine/source/T3D/decal/decalData.cpp @@ -284,6 +284,7 @@ void DecalData::unpackData( BitStream *stream ) Parent::unpackData( stream ); stream->read( &lookupName ); + assignName(lookupName); stream->read( &size ); stream->read( &materialName ); _updateMaterial(); From ce2964d2d019f9e0cb2fcb93d290efd10358bc7f Mon Sep 17 00:00:00 2001 From: Azaezel Date: Wed, 11 Nov 2015 13:52:46 -0600 Subject: [PATCH 18/47] diffuse/albedo texture linearization http://http.developer.nvidia.com/GPUGems3/gpugems3_ch24.html --- .../advanced/advancedLightManager.cpp | 2 +- .../source/materials/materialFeatureTypes.cpp | 1 + .../source/materials/materialFeatureTypes.h | 1 + .../source/shaderGen/GLSL/accuFeatureGLSL.cpp | 2 + .../shaderGen/GLSL/shaderFeatureGLSL.cpp | 43 ++-- .../source/shaderGen/GLSL/shaderFeatureGLSL.h | 5 + .../shaderGen/GLSL/shaderGenGLSLInit.cpp | 1 + .../source/shaderGen/HLSL/accuFeatureHLSL.cpp | 2 + .../shaderGen/HLSL/shaderFeatureHLSL.cpp | 42 ++-- .../source/shaderGen/HLSL/shaderFeatureHLSL.h | 5 + .../shaderGen/HLSL/shaderGenHLSLInit.cpp | 1 + .../source/terrain/glsl/terrFeatureGLSL.cpp | 7 + Engine/source/terrain/glsl/terrFeatureGLSL.h | 3 + .../source/terrain/hlsl/terrFeatureHLSL.cpp | 7 + Engine/source/terrain/hlsl/terrFeatureHLSL.h | 4 + Engine/source/util/imposterCapture.cpp | 1 + Templates/Full/game/art/gui/optionsDlg.gui | 216 ++++++++++++++---- .../Full/game/core/scripts/client/defaults.cs | 4 +- .../core/scripts/client/postFx/GammaPostFX.cs | 6 +- .../game/core/scripts/client/postFx/hdr.cs | 15 +- .../game/core/scripts/client/renderManager.cs | 33 +-- .../Full/game/shaders/common/gl/torque.glsl | 33 +++ .../game/shaders/common/postFx/gammaP.hlsl | 9 +- .../game/shaders/common/postFx/gl/gammaP.glsl | 8 + .../common/postFx/hdr/finalPassCombineP.hlsl | 8 + .../postFx/hdr/gl/finalPassCombineP.glsl | 8 + .../Full/game/shaders/common/torque.hlsl | 32 +++ .../shaders/common/water/gl/waterBasicP.glsl | 1 + .../game/shaders/common/water/gl/waterP.glsl | 1 + .../shaders/common/water/waterBasicP.hlsl | 1 + .../game/shaders/common/water/waterP.hlsl | 1 + 31 files changed, 396 insertions(+), 107 deletions(-) diff --git a/Engine/source/lighting/advanced/advancedLightManager.cpp b/Engine/source/lighting/advanced/advancedLightManager.cpp index ef4446a40..d7db83a6b 100644 --- a/Engine/source/lighting/advanced/advancedLightManager.cpp +++ b/Engine/source/lighting/advanced/advancedLightManager.cpp @@ -105,7 +105,7 @@ void AdvancedLightManager::activate( SceneManager *sceneManager ) // we prefer the floating point format if it works. Vector formats; formats.push_back( GFXFormatR16G16B16A16F ); - formats.push_back( GFXFormatR16G16B16A16 ); + //formats.push_back( GFXFormatR16G16B16A16 ); GFXFormat blendTargetFormat = GFX->selectSupportedFormat( &GFXDefaultRenderTargetProfile, formats, true, diff --git a/Engine/source/materials/materialFeatureTypes.cpp b/Engine/source/materials/materialFeatureTypes.cpp index f7a63815b..9cdc57415 100644 --- a/Engine/source/materials/materialFeatureTypes.cpp +++ b/Engine/source/materials/materialFeatureTypes.cpp @@ -46,6 +46,7 @@ ImplementFeatureType( MFT_AlphaTest, MFG_Texture, 7.0f, true ); ImplementFeatureType( MFT_SpecularMap, MFG_Texture, 8.0f, true ); ImplementFeatureType( MFT_NormalMap, MFG_Texture, 9.0f, true ); ImplementFeatureType( MFT_DetailNormalMap, MFG_Texture, 10.0f, true ); +ImplementFeatureType( MFT_Imposter, U32(-1), -1, true ); ImplementFeatureType( MFT_AccuMap, MFG_PreLighting, 2.0f, true ); diff --git a/Engine/source/materials/materialFeatureTypes.h b/Engine/source/materials/materialFeatureTypes.h index 55b52506c..c302045c2 100644 --- a/Engine/source/materials/materialFeatureTypes.h +++ b/Engine/source/materials/materialFeatureTypes.h @@ -94,6 +94,7 @@ DeclareFeatureType( MFT_OverlayMap ); DeclareFeatureType( MFT_DetailMap ); DeclareFeatureType( MFT_DiffuseColor ); DeclareFeatureType( MFT_DetailNormalMap ); +DeclareFeatureType( MFT_Imposter ); DeclareFeatureType( MFT_AccuMap ); DeclareFeatureType( MFT_AccuScale ); diff --git a/Engine/source/shaderGen/GLSL/accuFeatureGLSL.cpp b/Engine/source/shaderGen/GLSL/accuFeatureGLSL.cpp index c663b93ea..04a280e09 100644 --- a/Engine/source/shaderGen/GLSL/accuFeatureGLSL.cpp +++ b/Engine/source/shaderGen/GLSL/accuFeatureGLSL.cpp @@ -144,6 +144,8 @@ void AccuTexFeatGLSL::processPix(Vector &componentList, // get the accu pixel color meta->addStatement( new GenOp( " @ = tex2D(@, @ * @);\r\n", colorAccuDecl, accuMap, inTex, accuScale ) ); + if (!fd.features[MFT_Imposter]) + meta->addStatement(new GenOp(" @ = toLinear(@);\r\n", accuColor, accuColor)); // scale up normals meta->addStatement( new GenOp( " @.xyz = @.xyz * 2.0 - 0.5;\r\n", bumpNorm, bumpNorm ) ); diff --git a/Engine/source/shaderGen/GLSL/shaderFeatureGLSL.cpp b/Engine/source/shaderGen/GLSL/shaderFeatureGLSL.cpp index 7567b5516..eed42dd68 100644 --- a/Engine/source/shaderGen/GLSL/shaderFeatureGLSL.cpp +++ b/Engine/source/shaderGen/GLSL/shaderFeatureGLSL.cpp @@ -828,6 +828,12 @@ Var* ShaderFeatureGLSL::addOutDetailTexCoord( Vector &compon // Base Texture //**************************************************************************** +DiffuseMapFeatGLSL::DiffuseMapFeatGLSL() +: mTorqueDep("shaders/common/gl/torque.glsl") +{ + addDependency(&mTorqueDep); +} + void DiffuseMapFeatGLSL::processVert( Vector &componentList, const MaterialFeatureData &fd ) { @@ -855,20 +861,23 @@ void DiffuseMapFeatGLSL::processPix( Vector &componentList, diffuseMap->sampler = true; diffuseMap->constNum = Var::getTexUnitNum(); // used as texture unit num here + // create sample color var + Var *diffColor = new Var; + diffColor->setType("vec4"); + diffColor->setName("diffuseColor"); + LangElement *colorDecl = new DecOp( diffColor ); + + MultiLine * meta = new MultiLine; + output = meta; + if ( fd.features[MFT_CubeMap] ) { - MultiLine * meta = new MultiLine; - - // create sample color - Var *diffColor = new Var; - diffColor->setType( "vec4" ); - diffColor->setName( "diffuseColor" ); - LangElement *colorDecl = new DecOp( diffColor ); - meta->addStatement( new GenOp( " @ = tex2D(@, @);\r\n", colorDecl, diffuseMap, inTex ) ); + if (!fd.features[MFT_Imposter]) + meta->addStatement( new GenOp(" @ = toLinear(@);\r\n", diffColor, diffColor) ); meta->addStatement( new GenOp( " @;\r\n", assignColor( diffColor, Material::Mul ) ) ); output = meta; @@ -877,8 +886,6 @@ void DiffuseMapFeatGLSL::processPix( Vector &componentList, { // Handle atlased textures // http://www.infinity-universe.com/Infinity/index.php?option=com_content&task=view&id=65&Itemid=47 - MultiLine * meta = new MultiLine; - output = meta; Var *atlasedTex = new Var; atlasedTex->setName("atlasedTexCoord"); @@ -934,11 +941,6 @@ void DiffuseMapFeatGLSL::processPix( Vector &componentList, // For the rest of the feature... inTex = atlasedTex; - // create sample color var - Var *diffColor = new Var; - diffColor->setType("vec4"); - diffColor->setName("diffuseColor"); - // To dump out UV coords... //#define DEBUG_ATLASED_UV_COORDS #ifdef DEBUG_ATLASED_UV_COORDS @@ -954,21 +956,26 @@ void DiffuseMapFeatGLSL::processPix( Vector &componentList, { meta->addStatement(new GenOp( " @ = tex2Dlod(@, float4(@, 0.0, mipLod));\r\n", new DecOp(diffColor), diffuseMap, inTex)); + if (!fd.features[MFT_Imposter]) + meta->addStatement(new GenOp(" @ = toLinear(@);\r\n", diffColor, diffColor)); } else { meta->addStatement(new GenOp( " @ = tex2D(@, @);\r\n", new DecOp(diffColor), diffuseMap, inTex)); + if (!fd.features[MFT_Imposter]) + meta->addStatement(new GenOp(" @ = toLinear(@);\r\n", diffColor, diffColor)); } meta->addStatement(new GenOp( " @;\r\n", assignColor(diffColor, Material::Mul))); } else { - LangElement *statement = new GenOp( "tex2D(@, @)", diffuseMap, inTex ); - output = new GenOp( " @;\r\n", assignColor( statement, Material::Mul ) ); + meta->addStatement(new GenOp("@ = tex2D(@, @);\r\n", colorDecl, diffuseMap, inTex)); + if (!fd.features[MFT_Imposter]) + meta->addStatement(new GenOp(" @ = toLinear(@);\r\n", diffColor, diffColor)); + meta->addStatement(new GenOp(" @;\r\n", assignColor(diffColor, Material::Mul))); } - } ShaderFeature::Resources DiffuseMapFeatGLSL::getResources( const MaterialFeatureData &fd ) diff --git a/Engine/source/shaderGen/GLSL/shaderFeatureGLSL.h b/Engine/source/shaderGen/GLSL/shaderFeatureGLSL.h index a0e831e93..276183d99 100644 --- a/Engine/source/shaderGen/GLSL/shaderFeatureGLSL.h +++ b/Engine/source/shaderGen/GLSL/shaderFeatureGLSL.h @@ -236,7 +236,12 @@ public: /// Base texture class DiffuseMapFeatGLSL : public ShaderFeatureGLSL { + +protected: + + ShaderIncludeDependency mTorqueDep; public: + DiffuseMapFeatGLSL(); virtual void processVert( Vector &componentList, const MaterialFeatureData &fd ); diff --git a/Engine/source/shaderGen/GLSL/shaderGenGLSLInit.cpp b/Engine/source/shaderGen/GLSL/shaderGenGLSLInit.cpp index 3c4065d44..ef15793a5 100644 --- a/Engine/source/shaderGen/GLSL/shaderGenGLSLInit.cpp +++ b/Engine/source/shaderGen/GLSL/shaderGenGLSLInit.cpp @@ -68,6 +68,7 @@ void _initShaderGenGLSL( ShaderGen *shaderGen ) FEATUREMGR->registerFeature( MFT_IsTranslucent, new NamedFeatureGLSL( "Translucent" ) ); FEATUREMGR->registerFeature( MFT_Visibility, new VisibilityFeatGLSL ); FEATUREMGR->registerFeature( MFT_Fog, new FogFeatGLSL ); + FEATUREMGR->registerFeature( MFT_Imposter, new NamedFeatureGLSL( "Imposter" ) ); FEATUREMGR->registerFeature( MFT_NormalsOut, new NormalsOutFeatGLSL ); diff --git a/Engine/source/shaderGen/HLSL/accuFeatureHLSL.cpp b/Engine/source/shaderGen/HLSL/accuFeatureHLSL.cpp index 63161c258..1e90faa12 100644 --- a/Engine/source/shaderGen/HLSL/accuFeatureHLSL.cpp +++ b/Engine/source/shaderGen/HLSL/accuFeatureHLSL.cpp @@ -141,6 +141,8 @@ void AccuTexFeatHLSL::processPix( Vector &componentList, // get the accu pixel color meta->addStatement( new GenOp( " @ = tex2D(@, @ * @);\r\n", colorAccuDecl, accuMap, inTex, accuScale ) ); + if (!fd.features[MFT_Imposter]) + meta->addStatement(new GenOp(" @ = toLinear(@);\r\n", accuColor, accuColor)); // scale up normals meta->addStatement( new GenOp( " @.xyz = @.xyz * 2.0 - 0.5;\r\n", bumpNorm, bumpNorm ) ); diff --git a/Engine/source/shaderGen/HLSL/shaderFeatureHLSL.cpp b/Engine/source/shaderGen/HLSL/shaderFeatureHLSL.cpp index 8f8b5918a..17cf6333c 100644 --- a/Engine/source/shaderGen/HLSL/shaderFeatureHLSL.cpp +++ b/Engine/source/shaderGen/HLSL/shaderFeatureHLSL.cpp @@ -826,6 +826,12 @@ Var* ShaderFeatureHLSL::addOutDetailTexCoord( Vector &compon // Base Texture //**************************************************************************** +DiffuseMapFeatHLSL::DiffuseMapFeatHLSL() +: mTorqueDep("shaders/common/torque.hlsl") +{ + addDependency(&mTorqueDep); +} + void DiffuseMapFeatHLSL::processVert( Vector &componentList, const MaterialFeatureData &fd ) { @@ -853,30 +859,30 @@ void DiffuseMapFeatHLSL::processPix( Vector &componentList, diffuseMap->sampler = true; diffuseMap->constNum = Var::getTexUnitNum(); // used as texture unit num here + // create sample color + Var *diffColor = new Var; + diffColor->setType("float4"); + diffColor->setName("diffuseColor"); + LangElement *colorDecl = new DecOp(diffColor); + + MultiLine * meta = new MultiLine; + output = meta; + if ( fd.features[MFT_CubeMap] ) { - MultiLine * meta = new MultiLine; - - // create sample color - Var *diffColor = new Var; - diffColor->setType( "float4" ); - diffColor->setName( "diffuseColor" ); - LangElement *colorDecl = new DecOp( diffColor ); - meta->addStatement( new GenOp( " @ = tex2D(@, @);\r\n", colorDecl, diffuseMap, inTex ) ); + if (!fd.features[MFT_Imposter]) + meta->addStatement(new GenOp(" @ = toLinear(@);\r\n", diffColor, diffColor)); meta->addStatement( new GenOp( " @;\r\n", assignColor( diffColor, Material::Mul ) ) ); - output = meta; } else if(fd.features[MFT_DiffuseMapAtlas]) { // Handle atlased textures // http://www.infinity-universe.com/Infinity/index.php?option=com_content&task=view&id=65&Itemid=47 - MultiLine * meta = new MultiLine; - output = meta; Var *atlasedTex = new Var; atlasedTex->setName("atlasedTexCoord"); @@ -932,11 +938,6 @@ void DiffuseMapFeatHLSL::processPix( Vector &componentList, // For the rest of the feature... inTex = atlasedTex; - // create sample color var - Var *diffColor = new Var; - diffColor->setType("float4"); - diffColor->setName("diffuseColor"); - // To dump out UV coords... //#define DEBUG_ATLASED_UV_COORDS #ifdef DEBUG_ATLASED_UV_COORDS @@ -958,15 +959,18 @@ void DiffuseMapFeatHLSL::processPix( Vector &componentList, meta->addStatement(new GenOp( " @ = tex2D(@, @);\r\n", new DecOp(diffColor), diffuseMap, inTex)); } + if (!fd.features[MFT_Imposter]) + meta->addStatement(new GenOp(" @ = toLinear(@);\r\n", diffColor, diffColor)); meta->addStatement(new GenOp( " @;\r\n", assignColor(diffColor, Material::Mul))); } else { - LangElement *statement = new GenOp( "tex2D(@, @)", diffuseMap, inTex ); - output = new GenOp( " @;\r\n", assignColor( statement, Material::Mul ) ); + meta->addStatement(new GenOp("@ = tex2D(@, @);\r\n", colorDecl, diffuseMap, inTex)); + if (!fd.features[MFT_Imposter]) + meta->addStatement(new GenOp(" @ = toLinear(@);\r\n", diffColor, diffColor)); + meta->addStatement(new GenOp(" @;\r\n", assignColor(diffColor, Material::Mul))); } - } ShaderFeature::Resources DiffuseMapFeatHLSL::getResources( const MaterialFeatureData &fd ) diff --git a/Engine/source/shaderGen/HLSL/shaderFeatureHLSL.h b/Engine/source/shaderGen/HLSL/shaderFeatureHLSL.h index 3c2fc821e..4f77c175a 100644 --- a/Engine/source/shaderGen/HLSL/shaderFeatureHLSL.h +++ b/Engine/source/shaderGen/HLSL/shaderFeatureHLSL.h @@ -236,7 +236,12 @@ public: /// Base texture class DiffuseMapFeatHLSL : public ShaderFeatureHLSL { +protected: + + ShaderIncludeDependency mTorqueDep; + public: + DiffuseMapFeatHLSL(); virtual void processVert( Vector &componentList, const MaterialFeatureData &fd ); diff --git a/Engine/source/shaderGen/HLSL/shaderGenHLSLInit.cpp b/Engine/source/shaderGen/HLSL/shaderGenHLSLInit.cpp index c754e1b25..a5c6165e0 100644 --- a/Engine/source/shaderGen/HLSL/shaderGenHLSLInit.cpp +++ b/Engine/source/shaderGen/HLSL/shaderGenHLSLInit.cpp @@ -70,6 +70,7 @@ void _initShaderGenHLSL( ShaderGen *shaderGen ) FEATUREMGR->registerFeature( MFT_GlossMap, new NamedFeatureHLSL( "Gloss Map" ) ); FEATUREMGR->registerFeature( MFT_LightbufferMRT, new NamedFeatureHLSL( "Lightbuffer MRT" ) ); FEATUREMGR->registerFeature( MFT_RenderTarget1_Zero, new RenderTargetZeroHLSL( ShaderFeature::RenderTarget1 ) ); + FEATUREMGR->registerFeature( MFT_Imposter, new NamedFeatureHLSL( "Imposter" ) ); FEATUREMGR->registerFeature( MFT_DiffuseMapAtlas, new NamedFeatureHLSL( "Diffuse Map Atlas" ) ); FEATUREMGR->registerFeature( MFT_NormalMapAtlas, new NamedFeatureHLSL( "Normal Map Atlas" ) ); diff --git a/Engine/source/terrain/glsl/terrFeatureGLSL.cpp b/Engine/source/terrain/glsl/terrFeatureGLSL.cpp index ebe052e00..5f32359a8 100644 --- a/Engine/source/terrain/glsl/terrFeatureGLSL.cpp +++ b/Engine/source/terrain/glsl/terrFeatureGLSL.cpp @@ -64,6 +64,12 @@ MODULE_BEGIN( TerrainFeatGLSL ) MODULE_END; +TerrainFeatGLSL::TerrainFeatGLSL() + : mTorqueDep( "shaders/common/gl/torque.glsl" ) + { + addDependency( &mTorqueDep ); + } + Var* TerrainFeatGLSL::_getUniformVar( const char *name, const char *type, ConstantSortPosition csp ) { Var *theVar = (Var*)LangElement::find( name ); @@ -262,6 +268,7 @@ void TerrainBaseMapFeatGLSL::processPix( Vector &componentLis baseColor->setType( "vec4" ); baseColor->setName( "baseColor" ); meta->addStatement( new GenOp( " @ = tex2D( @, @.xy );\r\n", new DecOp( baseColor ), diffuseMap, texCoord ) ); + meta->addStatement(new GenOp(" @ = toLinear(@);\r\n", baseColor, baseColor)); meta->addStatement( new GenOp( " @;\r\n", assignColor( baseColor, Material::Mul ) ) ); output = meta; diff --git a/Engine/source/terrain/glsl/terrFeatureGLSL.h b/Engine/source/terrain/glsl/terrFeatureGLSL.h index 790a8a342..6cb3a3c0c 100644 --- a/Engine/source/terrain/glsl/terrFeatureGLSL.h +++ b/Engine/source/terrain/glsl/terrFeatureGLSL.h @@ -36,7 +36,10 @@ class TerrainFeatGLSL : public ShaderFeatureGLSL { protected: + ShaderIncludeDependency mTorqueDep; +public: + TerrainFeatGLSL(); Var* _getInDetailCoord(Vector &componentList ); Var* _getInMacroCoord(Vector &componentList ); diff --git a/Engine/source/terrain/hlsl/terrFeatureHLSL.cpp b/Engine/source/terrain/hlsl/terrFeatureHLSL.cpp index 7190d7f82..6ef1c2009 100644 --- a/Engine/source/terrain/hlsl/terrFeatureHLSL.cpp +++ b/Engine/source/terrain/hlsl/terrFeatureHLSL.cpp @@ -64,6 +64,12 @@ MODULE_BEGIN( TerrainFeatHLSL ) MODULE_END; +TerrainFeatHLSL::TerrainFeatHLSL() + : mTorqueDep( "shaders/common/torque.hlsl" ) + { + addDependency( &mTorqueDep ); + } + Var* TerrainFeatHLSL::_getUniformVar( const char *name, const char *type, ConstantSortPosition csp ) { Var *theVar = (Var*)LangElement::find( name ); @@ -262,6 +268,7 @@ void TerrainBaseMapFeatHLSL::processPix( Vector &componentLis baseColor->setType( "float4" ); baseColor->setName( "baseColor" ); meta->addStatement( new GenOp( " @ = tex2D( @, @.xy );\r\n", new DecOp( baseColor ), diffuseMap, texCoord ) ); + meta->addStatement(new GenOp(" @ = toLinear(@);\r\n", baseColor, baseColor)); meta->addStatement( new GenOp( " @;\r\n", assignColor( baseColor, Material::Mul ) ) ); output = meta; diff --git a/Engine/source/terrain/hlsl/terrFeatureHLSL.h b/Engine/source/terrain/hlsl/terrFeatureHLSL.h index 85f75a29e..e6297f3b4 100644 --- a/Engine/source/terrain/hlsl/terrFeatureHLSL.h +++ b/Engine/source/terrain/hlsl/terrFeatureHLSL.h @@ -37,6 +37,10 @@ class TerrainFeatHLSL : public ShaderFeatureHLSL { protected: + ShaderIncludeDependency mTorqueDep; + +public: + TerrainFeatHLSL(); Var* _getInDetailCoord(Vector &componentList ); Var* _getInMacroCoord(Vector &componentList ); diff --git a/Engine/source/util/imposterCapture.cpp b/Engine/source/util/imposterCapture.cpp index fb0786390..f6bcba23f 100644 --- a/Engine/source/util/imposterCapture.cpp +++ b/Engine/source/util/imposterCapture.cpp @@ -136,6 +136,7 @@ void ImposterCaptureMaterialHook::_overrideFeatures( ProcessedMaterial *mat, fd.features.addFeature( MFT_NormalsOut ); fd.features.addFeature( MFT_ForwardShading ); + fd.features.addFeature( MFT_Imposter ); } ImposterCaptureMaterialHook* ImposterCaptureMaterialHook::_getOrCreateHook( BaseMatInstance *inMat ) diff --git a/Templates/Full/game/art/gui/optionsDlg.gui b/Templates/Full/game/art/gui/optionsDlg.gui index fcff1cb95..9f12a272a 100644 --- a/Templates/Full/game/art/gui/optionsDlg.gui +++ b/Templates/Full/game/art/gui/optionsDlg.gui @@ -33,7 +33,7 @@ anchorLeft = "1"; anchorRight = "0"; position = "323 232"; - extent = "377 303"; + extent = "377 355"; minExtent = "8 8"; horizSizing = "center"; vertSizing = "center"; @@ -51,7 +51,7 @@ groupNum = "-1"; buttonType = "PushButton"; useMouseEvents = "0"; - position = "306 271"; + position = "304 319"; extent = "60 23"; minExtent = "8 8"; horizSizing = "right"; @@ -179,47 +179,49 @@ canSave = "1"; canSaveDynamicFields = "0"; }; - - new GuiSliderCtrl(OptMouseSensitivity) { - range = "0.02 2"; - ticks = "10"; - value = "0.75"; - isContainer = "0"; - Profile = "GuiSliderProfile"; - HorizSizing = "right"; - VertSizing = "bottom"; - position = "105 182"; - Extent = "244 18"; - MinExtent = "8 2"; - canSave = "1"; - Visible = "1"; - Command = "OptMouseSetSensitivity(OptMouseSensitivity.value);"; - tooltipprofile = "GuiToolTipProfile"; - hovertime = "1000"; - canSaveDynamicFields = "0"; - }; - new GuiTextCtrl() { - text = "Mouse Sensitivity:"; - maxLength = "255"; - Margin = "0 0 0 0"; - Padding = "0 0 0 0"; - AnchorTop = "1"; - AnchorBottom = "0"; - AnchorLeft = "1"; - AnchorRight = "0"; - isContainer = "0"; - Profile = "GuiTextProfile"; - HorizSizing = "right"; - VertSizing = "bottom"; - position = "15 182"; - Extent = "85 18"; - MinExtent = "8 8"; - canSave = "1"; - Visible = "1"; - tooltipprofile = "GuiToolTipProfile"; - hovertime = "1000"; - canSaveDynamicFields = "0"; - }; + new GuiSliderCtrl(OptMouseSensitivity) { + range = "0.02 2"; + ticks = "10"; + snap = "0"; + value = "1"; + position = "105 182"; + extent = "244 18"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiSliderProfile"; + visible = "1"; + active = "1"; + command = "OptMouseSetSensitivity(OptMouseSensitivity.value);"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiTextCtrl() { + text = "Mouse Sensitivity:"; + maxLength = "255"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "0"; + anchorLeft = "1"; + anchorRight = "0"; + position = "15 182"; + extent = "85 18"; + minExtent = "8 8"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiTextProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; }; new GuiBitmapBorderCtrl() { position = "9 55"; @@ -601,7 +603,7 @@ }; new GuiBitmapBorderCtrl() { position = "9 55"; - extent = "358 210"; + extent = "358 252"; minExtent = "8 8"; horizSizing = "right"; vertSizing = "bottom"; @@ -1252,6 +1254,66 @@ canSave = "1"; canSaveDynamicFields = "0"; }; + new GuiControl() { + position = "0 227"; + extent = "352 15"; + minExtent = "8 2"; + horizSizing = "width"; + vertSizing = "bottom"; + profile = "GuiDefaultProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "1"; + internalName = "GammaSliderContainer"; + canSave = "1"; + canSaveDynamicFields = "0"; + + new GuiSliderCtrl() { + range = "0.5 1.5"; + ticks = "0"; + snap = "0"; + value = "1"; + position = "76 -1"; + extent = "268 15"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiSliderProfile"; + visible = "1"; + active = "1"; + variable = "$pref::Video::Contrast"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiTextCtrl() { + text = "Contrast:"; + maxLength = "255"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "0"; + anchorLeft = "1"; + anchorRight = "0"; + position = "18 -4"; + extent = "105 18"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiTextProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + }; new GuiControl() { position = "0 190"; extent = "352 15"; @@ -1269,10 +1331,10 @@ canSaveDynamicFields = "0"; new GuiSliderCtrl() { - range = "0.001 2.2"; + range = "2.0 2.5"; ticks = "0"; snap = "0"; - value = "1"; + value = "2.2"; position = "76 -1"; extent = "268 15"; minExtent = "8 2"; @@ -1312,6 +1374,66 @@ canSaveDynamicFields = "0"; }; }; + new GuiControl() { + position = "0 208"; + extent = "352 15"; + minExtent = "8 2"; + horizSizing = "width"; + vertSizing = "bottom"; + profile = "GuiDefaultProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "1"; + internalName = "GammaSliderContainer"; + canSave = "1"; + canSaveDynamicFields = "0"; + + new GuiSliderCtrl() { + range = "-0.5 0.5"; + ticks = "0"; + snap = "0"; + value = "0"; + position = "76 -1"; + extent = "268 15"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiSliderProfile"; + visible = "1"; + active = "1"; + variable = "$pref::Video::Brightness"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiTextCtrl() { + text = "Brightness:"; + maxLength = "255"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "0"; + anchorLeft = "1"; + anchorRight = "0"; + position = "6 -3"; + extent = "105 18"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiTextProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + }; }; new GuiControl() { position = "9 55"; @@ -1396,7 +1518,7 @@ groupNum = "-1"; buttonType = "PushButton"; useMouseEvents = "0"; - position = "241 271"; + position = "239 319"; extent = "60 23"; minExtent = "8 8"; horizSizing = "right"; diff --git a/Templates/Full/game/core/scripts/client/defaults.cs b/Templates/Full/game/core/scripts/client/defaults.cs index 0142a9410..d1805d337 100644 --- a/Templates/Full/game/core/scripts/client/defaults.cs +++ b/Templates/Full/game/core/scripts/client/defaults.cs @@ -73,7 +73,9 @@ $pref::Video::disableCubemapping = false; /// $pref::Video::disableParallaxMapping = false; -$pref::Video::Gamma = 1.0; +$pref::Video::Gamma = 2.2; +$pref::Video::Contrast = 1.0; +$pref::Video::Brightness = 0; // Console-friendly defaults if($platform $= "xenon") diff --git a/Templates/Full/game/core/scripts/client/postFx/GammaPostFX.cs b/Templates/Full/game/core/scripts/client/postFx/GammaPostFX.cs index 383a0c8cd..b88f31305 100644 --- a/Templates/Full/game/core/scripts/client/postFx/GammaPostFX.cs +++ b/Templates/Full/game/core/scripts/client/postFx/GammaPostFX.cs @@ -44,7 +44,7 @@ singleton GFXStateBlockData( GammaStateBlock : PFX_DefaultStateBlock ) singleton PostEffect( GammaPostFX ) { isEnabled = true; - allowReflectPass = false; + allowReflectPass = true; renderTime = "PFXBeforeBin"; renderBin = "EditorBin"; @@ -65,6 +65,8 @@ function GammaPostFX::preProcess( %this ) function GammaPostFX::setShaderConsts( %this ) { - %clampedGamma = mClamp( $pref::Video::Gamma, 0.001, 2.2); + %clampedGamma = mClamp( $pref::Video::Gamma, 2.0, 2.5); %this.setShaderConst( "$OneOverGamma", 1 / %clampedGamma ); + %this.setShaderConst( "$Brightness", $pref::Video::Brightness ); + %this.setShaderConst( "$Contrast", $pref::Video::Contrast ); } \ No newline at end of file diff --git a/Templates/Full/game/core/scripts/client/postFx/hdr.cs b/Templates/Full/game/core/scripts/client/postFx/hdr.cs index a5c450799..136a5ca95 100644 --- a/Templates/Full/game/core/scripts/client/postFx/hdr.cs +++ b/Templates/Full/game/core/scripts/client/postFx/hdr.cs @@ -253,8 +253,10 @@ function HDRPostFX::setShaderConsts( %this ) %combinePass.setShaderConst( "$g_fEnableBlueShift", $HDRPostFX::enableBlueShift ); %combinePass.setShaderConst( "$g_fBlueShiftColor", $HDRPostFX::blueShiftColor ); - %clampedGamma = mClamp( $pref::Video::Gamma, 0.001, 2.2); + %clampedGamma = mClamp( $pref::Video::Gamma, 2.0, 2.5); %combinePass.setShaderConst( "$g_fOneOverGamma", 1 / %clampedGamma ); + %combinePass.setShaderConst( "$Brightness", $pref::Video::Brightness ); + %combinePass.setShaderConst( "$Contrast", $pref::Video::Contrast ); %whiteCutoff = ( $HDRPostFX::whiteCutoff * $HDRPostFX::whiteCutoff ) * ( $HDRPostFX::whiteCutoff * $HDRPostFX::whiteCutoff ); @@ -329,7 +331,7 @@ function HDRPostFX::onDisabled( %this ) singleton PostEffect( HDRPostFX ) { isEnabled = false; - allowReflectPass = false; + allowReflectPass = true; // Resolve the HDR before we render any editor stuff // and before we resolve the scene to the backbuffer. @@ -355,6 +357,7 @@ singleton PostEffect( HDRPostFX ) new PostEffect() { + allowReflectPass = true; shader = HDR_DownScale4x4Shader; stateBlock = HDR_DownSampleStateBlock; texture[0] = "$inTex"; @@ -365,6 +368,7 @@ singleton PostEffect( HDRPostFX ) new PostEffect() { + allowReflectPass = true; internalName = "bloomH"; shader = HDR_BloomGaussBlurHShader; @@ -376,6 +380,7 @@ singleton PostEffect( HDRPostFX ) new PostEffect() { + allowReflectPass = true; internalName = "bloomV"; shader = HDR_BloomGaussBlurVShader; @@ -390,6 +395,7 @@ singleton PostEffect( HDRPostFX ) // Now calculate the adapted luminance. new PostEffect() { + allowReflectPass = true; internalName = "adaptLum"; shader = HDR_SampleLumShader; @@ -401,6 +407,7 @@ singleton PostEffect( HDRPostFX ) new PostEffect() { + allowReflectPass = true; shader = HDR_DownSampleLumShader; stateBlock = HDR_DownSampleStateBlock; texture[0] = "$inTex"; @@ -411,6 +418,7 @@ singleton PostEffect( HDRPostFX ) new PostEffect() { + allowReflectPass = true; shader = HDR_DownSampleLumShader; stateBlock = HDR_DownSampleStateBlock; texture[0] = "$inTex"; @@ -421,6 +429,7 @@ singleton PostEffect( HDRPostFX ) new PostEffect() { + allowReflectPass = true; shader = HDR_DownSampleLumShader; stateBlock = HDR_DownSampleStateBlock; texture[0] = "$inTex"; @@ -434,6 +443,7 @@ singleton PostEffect( HDRPostFX ) // one... PostEffect takes care to manage that. new PostEffect() { + allowReflectPass = true; internalName = "finalLum"; shader = HDR_CalcAdaptedLumShader; stateBlock = HDR_DownSampleStateBlock; @@ -450,6 +460,7 @@ singleton PostEffect( HDRPostFX ) // version of the scene. new PostEffect() { + allowReflectPass = true; internalName = "combinePass"; shader = HDR_CombineShader; diff --git a/Templates/Full/game/core/scripts/client/renderManager.cs b/Templates/Full/game/core/scripts/client/renderManager.cs index dcd1628fe..5559fd70a 100644 --- a/Templates/Full/game/core/scripts/client/renderManager.cs +++ b/Templates/Full/game/core/scripts/client/renderManager.cs @@ -33,7 +33,7 @@ function initRenderManager() { enabled = "false"; - format = "GFXFormatR8G8B8A8"; + format = "GFXFormatR16G16B16A16F"; depthFormat = "GFXFormatD24S8"; aaLevel = 0; // -1 = match backbuffer @@ -49,20 +49,21 @@ function initRenderManager() // We really need to fix the sky to render after all the // meshes... but that causes issues in reflections. - DiffuseRenderPassManager.addManager( new RenderObjectMgr() { bintype = "Sky"; renderOrder = 0.1; processAddOrder = 0.1; } ); + DiffuseRenderPassManager.addManager( new RenderObjectMgr(SkyBin) { bintype = "Sky"; renderOrder = 0.1; processAddOrder = 0.1; } ); //DiffuseRenderPassManager.addManager( new RenderVistaMgr() { bintype = "Vista"; renderOrder = 0.15; processAddOrder = 0.15; } ); - DiffuseRenderPassManager.addManager( new RenderObjectMgr() { bintype = "Begin"; renderOrder = 0.2; processAddOrder = 0.2; } ); + DiffuseRenderPassManager.addManager( new RenderObjectMgr(BeginBin) { bintype = "Begin"; renderOrder = 0.2; processAddOrder = 0.2; } ); // Normal mesh rendering. - DiffuseRenderPassManager.addManager( new RenderTerrainMgr() { renderOrder = 0.4; processAddOrder = 0.4; } ); - DiffuseRenderPassManager.addManager( new RenderMeshMgr() { bintype = "Mesh"; renderOrder = 0.5; processAddOrder = 0.5; } ); - DiffuseRenderPassManager.addManager( new RenderImposterMgr() { renderOrder = 0.56; processAddOrder = 0.56; } ); - DiffuseRenderPassManager.addManager( new RenderObjectMgr() { bintype = "Object"; renderOrder = 0.6; processAddOrder = 0.6; } ); - - DiffuseRenderPassManager.addManager( new RenderObjectMgr() { bintype = "Shadow"; renderOrder = 0.7; processAddOrder = 0.7; } ); - DiffuseRenderPassManager.addManager( new RenderMeshMgr() { bintype = "Decal"; renderOrder = 0.8; processAddOrder = 0.8; } ); - DiffuseRenderPassManager.addManager( new RenderOcclusionMgr() { bintype = "Occluder"; renderOrder = 0.9; processAddOrder = 0.9; } ); + DiffuseRenderPassManager.addManager( new RenderTerrainMgr(TerrainBin) { renderOrder = 0.4; processAddOrder = 0.4; } ); + DiffuseRenderPassManager.addManager( new RenderMeshMgr(MeshBin) { bintype = "Mesh"; renderOrder = 0.5; processAddOrder = 0.5; } ); + DiffuseRenderPassManager.addManager( new RenderImposterMgr(ImposterBin) { renderOrder = 0.56; processAddOrder = 0.56; } ); + DiffuseRenderPassManager.addManager( new RenderObjectMgr(ObjectBin) { bintype = "Object"; renderOrder = 0.6; processAddOrder = 0.6; } ); + + DiffuseRenderPassManager.addManager( new RenderObjectMgr(ShadowBin) { bintype = "Shadow"; renderOrder = 0.7; processAddOrder = 0.7; } ); + DiffuseRenderPassManager.addManager( new RenderMeshMgr(DecalRoadBin) { bintype = "DecalRoad"; renderOrder = 0.8; processAddOrder = 0.8; } ); + DiffuseRenderPassManager.addManager( new RenderMeshMgr(DecalBin) { bintype = "Decal"; renderOrder = 0.81; processAddOrder = 0.81; } ); + DiffuseRenderPassManager.addManager( new RenderOcclusionMgr(OccluderBin){ bintype = "Occluder"; renderOrder = 0.9; processAddOrder = 0.9; } ); // We now render translucent objects that should handle // their own fogging and lighting. @@ -70,10 +71,10 @@ function initRenderManager() // Note that the fog effect is triggered before this bin. DiffuseRenderPassManager.addManager( new RenderObjectMgr(ObjTranslucentBin) { bintype = "ObjectTranslucent"; renderOrder = 1.0; processAddOrder = 1.0; } ); - DiffuseRenderPassManager.addManager( new RenderObjectMgr() { bintype = "Water"; renderOrder = 1.2; processAddOrder = 1.2; } ); - DiffuseRenderPassManager.addManager( new RenderObjectMgr() { bintype = "Foliage"; renderOrder = 1.3; processAddOrder = 1.3; } ); - DiffuseRenderPassManager.addManager( new RenderParticleMgr() { renderOrder = 1.35; processAddOrder = 1.35; } ); - DiffuseRenderPassManager.addManager( new RenderTranslucentMgr() { renderOrder = 1.4; processAddOrder = 1.4; } ); + DiffuseRenderPassManager.addManager( new RenderObjectMgr(WaterBin) { bintype = "Water"; renderOrder = 1.2; processAddOrder = 1.2; } ); + DiffuseRenderPassManager.addManager( new RenderObjectMgr(FoliageBin) { bintype = "Foliage"; renderOrder = 1.3; processAddOrder = 1.3; } ); + DiffuseRenderPassManager.addManager( new RenderParticleMgr(ParticleBin) { renderOrder = 1.35; processAddOrder = 1.35; } ); + DiffuseRenderPassManager.addManager( new RenderTranslucentMgr(TranslucentBin){ renderOrder = 1.4; processAddOrder = 1.4; } ); // Note that the GlowPostFx is triggered after this bin. DiffuseRenderPassManager.addManager( new RenderGlowMgr(GlowBin) { renderOrder = 1.5; processAddOrder = 1.5; } ); @@ -83,7 +84,7 @@ function initRenderManager() DiffuseRenderPassManager.addManager( new RenderObjectMgr(EditorBin) { bintype = "Editor"; renderOrder = 1.6; processAddOrder = 1.6; } ); // Resolve format change token last. - DiffuseRenderPassManager.addManager( new RenderPassStateBin() { renderOrder = 1.7; stateToken = AL_FormatToken; } ); + DiffuseRenderPassManager.addManager( new RenderPassStateBin(FinalBin) { renderOrder = 1.7; stateToken = AL_FormatToken; } ); } /// This post effect is used to copy data from the non-MSAA back-buffer to the diff --git a/Templates/Full/game/shaders/common/gl/torque.glsl b/Templates/Full/game/shaders/common/gl/torque.glsl index 9032a57f7..65580cb7b 100644 --- a/Templates/Full/game/shaders/common/gl/torque.glsl +++ b/Templates/Full/game/shaders/common/gl/torque.glsl @@ -284,4 +284,37 @@ void fizzle(vec2 vpos, float visibility) /// @note This macro will only work in the void main() method of a pixel shader. #define assert(condition, color) { if(!any(condition)) { OUT_col = color; return; } } +// Deferred Shading: Material Info Flag Check +bool getFlag(float flags, int num) +{ + float process = round(flags * 255); + float squareNum = pow(2, num); + return (mod(process, pow(2, squareNum)) >= squareNum); +} + +// #define TORQUE_STOCK_GAMMA +#ifdef TORQUE_STOCK_GAMMA +// Sample in linear space. Decodes gamma. +vec4 toLinear(vec4 tex) +{ + return tex; +} +// Encodes gamma. +vec4 toGamma(vec4 tex) +{ + return tex; +} +#else +// Sample in linear space. Decodes gamma. +vec4 toLinear(vec4 tex) +{ + return vec4(pow(abs(tex.rgb), vec3(2.2)), tex.a); +} +// Encodes gamma. +vec4 toGamma(vec4 tex) +{ + return vec4(pow(abs(tex.rgb), vec3(1.0/2.2)), tex.a); +} +#endif // + #endif // _TORQUE_GLSL_ diff --git a/Templates/Full/game/shaders/common/postFx/gammaP.hlsl b/Templates/Full/game/shaders/common/postFx/gammaP.hlsl index dedfe8eb5..20196548b 100644 --- a/Templates/Full/game/shaders/common/postFx/gammaP.hlsl +++ b/Templates/Full/game/shaders/common/postFx/gammaP.hlsl @@ -28,7 +28,8 @@ uniform sampler2D backBuffer : register(S0); uniform sampler1D colorCorrectionTex : register( s1 ); uniform float OneOverGamma; - +uniform float Brightness; +uniform float Contrast; float4 main( PFXVertToPix IN ) : COLOR0 { @@ -42,5 +43,11 @@ float4 main( PFXVertToPix IN ) : COLOR0 // Apply gamma correction color.rgb = pow( abs(color.rgb), OneOverGamma ); + // Apply contrast + color.rgb = ((color.rgb - 0.5f) * Contrast) + 0.5f; + + // Apply brightness + color.rgb += Brightness; + return color; } \ No newline at end of file diff --git a/Templates/Full/game/shaders/common/postFx/gl/gammaP.glsl b/Templates/Full/game/shaders/common/postFx/gl/gammaP.glsl index 414a277d3..1bf5d1b8f 100644 --- a/Templates/Full/game/shaders/common/postFx/gl/gammaP.glsl +++ b/Templates/Full/game/shaders/common/postFx/gl/gammaP.glsl @@ -28,6 +28,8 @@ uniform sampler2D backBuffer; uniform sampler1D colorCorrectionTex; uniform float OneOverGamma; +uniform float Brightness; +uniform float Contrast; in vec2 uv0; @@ -45,5 +47,11 @@ void main() // Apply gamma correction color.rgb = pow( abs(color.rgb), vec3(OneOverGamma) ); + // Apply contrast + color.rgb = ((color.rgb - 0.5f) * Contrast) + 0.5f; + + // Apply brightness + color.rgb += Brightness; + OUT_col = color; } \ No newline at end of file diff --git a/Templates/Full/game/shaders/common/postFx/hdr/finalPassCombineP.hlsl b/Templates/Full/game/shaders/common/postFx/hdr/finalPassCombineP.hlsl index 7ac71bebd..9541f39cb 100644 --- a/Templates/Full/game/shaders/common/postFx/hdr/finalPassCombineP.hlsl +++ b/Templates/Full/game/shaders/common/postFx/hdr/finalPassCombineP.hlsl @@ -41,6 +41,8 @@ uniform float3 g_fBlueShiftColor; uniform float g_fBloomScale; uniform float g_fOneOverGamma; +uniform float Brightness; +uniform float Contrast; float4 main( PFXVertToPix IN ) : COLOR0 @@ -90,6 +92,12 @@ float4 main( PFXVertToPix IN ) : COLOR0 // Apply gamma correction sample.rgb = pow( abs(sample.rgb), g_fOneOverGamma ); + + // Apply contrast + sample.rgb = ((sample.rgb - 0.5f) * Contrast) + 0.5f; + + // Apply brightness + sample.rgb += Brightness; return sample; } diff --git a/Templates/Full/game/shaders/common/postFx/hdr/gl/finalPassCombineP.glsl b/Templates/Full/game/shaders/common/postFx/hdr/gl/finalPassCombineP.glsl index 38762baa5..123c831f3 100644 --- a/Templates/Full/game/shaders/common/postFx/hdr/gl/finalPassCombineP.glsl +++ b/Templates/Full/game/shaders/common/postFx/hdr/gl/finalPassCombineP.glsl @@ -42,6 +42,8 @@ uniform vec3 g_fBlueShiftColor; uniform float g_fBloomScale; uniform float g_fOneOverGamma; +uniform float Brightness; +uniform float Contrast; out vec4 OUT_col; @@ -93,6 +95,12 @@ void main() // Apply gamma correction _sample.rgb = pow( abs(_sample.rgb), vec3(g_fOneOverGamma) ); + + // Apply contrast + _sample.rgb = ((_sample.rgb - 0.5f) * Contrast) + 0.5f; + + // Apply brightness + _sample.rgb += Brightness; OUT_col = _sample; } diff --git a/Templates/Full/game/shaders/common/torque.hlsl b/Templates/Full/game/shaders/common/torque.hlsl index 1d253936b..f50832cb8 100644 --- a/Templates/Full/game/shaders/common/torque.hlsl +++ b/Templates/Full/game/shaders/common/torque.hlsl @@ -277,5 +277,37 @@ void fizzle(float2 vpos, float visibility) clip( visibility - frac( determinant( m ) ) ); } +// Deferred Shading: Material Info Flag Check +bool getFlag(float flags, int num) +{ + int process = round(flags * 255); + int squareNum = pow(2, num); + return (fmod(process, pow(2, squareNum)) >= squareNum); +} + +// #define TORQUE_STOCK_GAMMA +#ifdef TORQUE_STOCK_GAMMA +// Sample in linear space. Decodes gamma. +float4 toLinear(float4 tex) +{ + return tex; +} +// Encodes gamma. +float4 toLinear(float4 tex) +{ + return tex; +} +#else +// Sample in linear space. Decodes gamma. +float4 toLinear(float4 tex) +{ + return float4(pow(abs(tex.rgb), 2.2), tex.a); +} +// Encodes gamma. +float4 toGamma(float4 tex) +{ + return float4(pow(abs(tex.rgb), 1.0/2.2), tex.a); +} +#endif // #endif // _TORQUE_HLSL_ diff --git a/Templates/Full/game/shaders/common/water/gl/waterBasicP.glsl b/Templates/Full/game/shaders/common/water/gl/waterBasicP.glsl index 82c421031..1d5a07c3f 100644 --- a/Templates/Full/game/shaders/common/water/gl/waterBasicP.glsl +++ b/Templates/Full/game/shaders/common/water/gl/waterBasicP.glsl @@ -120,6 +120,7 @@ void main() { // Modulate baseColor by the ambientColor. vec4 waterBaseColor = baseColor * vec4( ambientColor.rgb, 1 ); + waterBaseColor = toLinear(waterBaseColor); // Get the bumpNorm... vec3 bumpNorm = ( texture( bumpMap, IN_rippleTexCoord01.xy ).rgb * 2.0 - 1.0 ) * rippleMagnitude.x; diff --git a/Templates/Full/game/shaders/common/water/gl/waterP.glsl b/Templates/Full/game/shaders/common/water/gl/waterP.glsl index af151020a..15002849f 100644 --- a/Templates/Full/game/shaders/common/water/gl/waterP.glsl +++ b/Templates/Full/game/shaders/common/water/gl/waterP.glsl @@ -324,6 +324,7 @@ void main() // Calculate the water "base" color based on depth. vec4 waterBaseColor = baseColor * texture( depthGradMap, saturate( delta / depthGradMax ) ); + waterBaseColor = toLinear(waterBaseColor); // Modulate baseColor by the ambientColor. waterBaseColor *= vec4( ambientColor.rgb, 1 ); diff --git a/Templates/Full/game/shaders/common/water/waterBasicP.hlsl b/Templates/Full/game/shaders/common/water/waterBasicP.hlsl index d27b28c67..7ae933f6f 100644 --- a/Templates/Full/game/shaders/common/water/waterBasicP.hlsl +++ b/Templates/Full/game/shaders/common/water/waterBasicP.hlsl @@ -117,6 +117,7 @@ float4 main( ConnectData IN ) : COLOR { // Modulate baseColor by the ambientColor. float4 waterBaseColor = baseColor * float4( ambientColor.rgb, 1 ); + waterBaseColor = toLinear(waterBaseColor); // Get the bumpNorm... float3 bumpNorm = ( tex2D( bumpMap, IN.rippleTexCoord01.xy ).rgb * 2.0 - 1.0 ) * rippleMagnitude.x; diff --git a/Templates/Full/game/shaders/common/water/waterP.hlsl b/Templates/Full/game/shaders/common/water/waterP.hlsl index 851fb471f..2b4035755 100644 --- a/Templates/Full/game/shaders/common/water/waterP.hlsl +++ b/Templates/Full/game/shaders/common/water/waterP.hlsl @@ -311,6 +311,7 @@ float4 main( ConnectData IN ) : COLOR // Calculate the water "base" color based on depth. float4 waterBaseColor = baseColor * tex1D( depthGradMap, saturate( delta / depthGradMax ) ); + waterBaseColor = toLinear(waterBaseColor); // Modulate baseColor by the ambientColor. waterBaseColor *= float4( ambientColor.rgb, 1 ); From d3c7edfe4290a6b87182dc9a79f410b684b67093 Mon Sep 17 00:00:00 2001 From: Robert MacGregor Date: Sun, 22 Nov 2015 02:45:25 -0500 Subject: [PATCH 19/47] Fix TinyXML Build errors --- Engine/source/console/consoleObject.h | 110 +++++++++++++------------- 1 file changed, 53 insertions(+), 57 deletions(-) diff --git a/Engine/source/console/consoleObject.h b/Engine/source/console/consoleObject.h index 5e585247e..5f04435aa 100644 --- a/Engine/source/console/consoleObject.h +++ b/Engine/source/console/consoleObject.h @@ -48,7 +48,7 @@ #include "console/simObjectRef.h" #endif #ifndef TINYXML_INCLUDED - #include "tinyXML/tinyxml.h" + #include "tinyxml.h" #endif /// @file @@ -212,7 +212,7 @@ public: /// /// @param conIdPtr Pointer to the static S32 console ID. /// @param conTypeName Console type name. - AbstractClassRep( S32* conIdPtr, const char* typeName ) + AbstractClassRep( S32* conIdPtr, const char* typeName ) : Parent( sizeof( void* ), conIdPtr, typeName ) { VECTOR_SET_ASSOCIATION( mFieldList ); @@ -323,13 +323,13 @@ public: /// Return the namespace that contains the methods of this class. Namespace* getNameSpace() const { return mNamespace; } - + /// Return the AbstractClassRep of the class that this class is derived from. AbstractClassRep* getParentClass() const { return parentClass; } virtual AbstractClassRep* getContainerChildClass(const bool recurse) = 0; virtual WriteCustomTamlSchema getCustomTamlSchema(void) = 0; - + /// Return the size of instances of this class in bytes. S32 getSizeof() const { return mClassSizeof; } @@ -396,7 +396,7 @@ protected: Namespace * mNamespace; /// @} - + public: bool mIsRenderEnabled; @@ -404,23 +404,23 @@ public: bool isRenderEnabled() const { return mIsRenderEnabled; } bool isSelectionEnabled() const { return mIsSelectionEnabled; } - + /// @name Categories /// @{ - + protected: const char* mCategory; const char* mDescription; - + public: /// Return the space separated category path for the class. const char* getCategory() const { return mCategory; } - + /// Return a short description string suitable for displaying in tooltips. const char* getDescription() const { return mDescription; } - + /// @} /// @name Fields @@ -434,16 +434,12 @@ public: /// This is a function pointer typedef to support optional writing for fields. typedef bool(*WriteDataNotify)(void* obj, StringTableEntry pFieldName); - /// Allows the writing of a custom TAML schema. - typedef void(*WriteCustomTamlSchema)(const AbstractClassRep* pClassRep, TiXmlElement* pParentElement); - - /// These are special field type values used to mark /// groups and arrays in the field list. /// @see Field::type /// @see addArray, endArray - /// @see addGroup, endGroup - /// @see addGroup, endGroup + /// @see addGroup, endGroup + /// @see addGroup, endGroup /// @see addDeprecatedField enum ACRFieldTypes { @@ -451,35 +447,35 @@ public: /// types greater or equal to this one are not /// console data types. ARCFirstCustomField = 0xFFFFFFFB, - + /// Marks the start of a fixed size array of fields. /// @see addArray StartArrayFieldType = 0xFFFFFFFB, - + /// Marks the end of a fixed size array of fields. /// @see endArray EndArrayFieldType = 0xFFFFFFFC, - + /// Marks the beginning of a group of fields. /// @see addGroup StartGroupFieldType = 0xFFFFFFFD, - + /// Marks the beginning of a group of fields. /// @see endGroup EndGroupFieldType = 0xFFFFFFFE, - - /// Marks a field that is depreciated and no + + /// Marks a field that is depreciated and no /// longer stores a value. /// @see addDeprecatedField DeprecatedFieldType = 0xFFFFFFFF }; - + enum FieldFlags { FIELD_HideInInspectors = BIT( 0 ), ///< Do not show the field in inspectors. }; - struct Field + struct Field { Field() : pFieldname( NULL ), @@ -525,10 +521,10 @@ public: /// @name Console Type Interface /// @{ - + virtual void* getNativeVariable() { return new ( AbstractClassRep* ); } // Any pointer-sized allocation will do. virtual void deleteNativeVariable( void* var ) { delete reinterpret_cast< AbstractClassRep** >( var ); } - + /// @} /// @name Abstract Class Database @@ -574,10 +570,10 @@ template< class T > class ConcreteClassRep : public AbstractClassRep { public: - + static EnginePropertyTable _smPropertyTable; static EnginePropertyTable& smPropertyTable; - + ConcreteClassRep( const char* name, const char* conTypeName, S32* conTypeIdPtr, @@ -591,10 +587,10 @@ class ConcreteClassRep : public AbstractClassRep mClassName = StringTable->insert( name ); mCategory = T::__category(); mTypeInfo = _MAPTYPE< T >(); - + if( mTypeInfo ) const_cast< EngineTypeInfo* >( mTypeInfo )->mPropertyTable = &smPropertyTable; - + if( &T::__description != parentDesc ) mDescription = T::__description(); @@ -642,7 +638,7 @@ class ConcreteClassRep : public AbstractClassRep // Get handle to our parent class, if any, and ourselves (we are our parent's child). AbstractClassRep *parent = T::getParentStaticClassRep(); AbstractClassRep *child = T::getStaticClassRep(); - + // If we got reps, then link those namespaces! (To get proper inheritance.) if(parent && child) Con::classLinkNamespaces(parent->getNameSpace(), child->getNameSpace()); @@ -657,7 +653,7 @@ class ConcreteClassRep : public AbstractClassRep /// Wrap constructor. ConsoleObject* create() const { return new T; } - + /// @name Console Type Interface /// @{ @@ -671,16 +667,16 @@ class ConcreteClassRep : public AbstractClassRep else Con::errorf( "Cannot set multiple args to a single ConsoleObject*."); } - + virtual const char* getData( void* dptr, const EnumTable* tbl, BitSet32 flag ) { T** obj = ( T** ) dptr; return Con::getReturnBuffer( T::__getObjectId( *obj ) ); } - + virtual const char* getTypeClassName() { return mClassName; } virtual const bool isDatablock() { return T::__smIsDatablock; }; - + /// @} }; @@ -751,7 +747,7 @@ bool defaultProtectedWriteFn(void* obj, StringTableEntry pFieldName); class ConsoleObject : public EngineObject { DECLARE_ABSTRACT_CLASS( ConsoleObject, EngineObject ); - + protected: /// @deprecated This is disallowed. @@ -760,7 +756,7 @@ protected: public: ConsoleObject() {} - + /// Get a reference to a field by name. const AbstractClassRep::Field *findField(StringTableEntry fieldName) const; @@ -769,7 +765,7 @@ public: /// Set the value of a field. bool setField(const char *fieldName, const char *value); - + public: /// @name Object Creation @@ -799,11 +795,11 @@ public: static void endGroup(const char* in_pGroupname); /// Marks the start of a fixed size array of fields. - /// @see console_autodoc + /// @see console_autodoc static void addArray( const char *arrayName, S32 count ); /// Marks the end of an array of fields. - /// @see console_autodoc + /// @see console_autodoc static void endArray( const char *arrayName ); /// Register a complex field. @@ -928,16 +924,16 @@ public: static bool removeField(const char* in_pFieldname); /// @} - + /// @name Logging /// @{ - + /// Overload this in subclasses to change the message formatting. /// @param fmt A printf style format string. /// @param args A va_list containing the args passed ot a log function. /// @note It is suggested that you use String::VToString. virtual String _getLogMessage(const char* fmt, va_list args) const; - + /// @} public: @@ -946,16 +942,16 @@ public: /// These functions will try to print out a message along the lines /// of "ObjectClass - ObjectName(ObjectId) - formatted message" /// @{ - + /// Logs with Con::printf. void logMessage(const char* fmt, ...) const; - + /// Logs with Con::warnf. void logWarning(const char* fmt, ...) const; - + /// Logs with Con::errorf. void logError(const char* fmt, ...) const; - + /// @} /// Register dynamic fields in a subclass of ConsoleObject. @@ -1016,16 +1012,16 @@ public: static const char* __category() { return ""; } static const char* __description() { return ""; } - + /// Subclasses of ConsoleObjects that are datablocks should redefine this static member variable /// and set it to true. static const bool __smIsDatablock = false; - + /// @name Object IDs and lookup. /// For a subclass hierarchy based on ConsoleObject to become functional for use as a console object type, /// the hierarchy must implement a naming scheme and indexing function for looking up objects by name. /// @{ - + static ConsoleObject* __findObject( const char* ) { return NULL; } static const char* __getObjectId( ConsoleObject* ) { return ""; } }; @@ -1120,11 +1116,11 @@ inline bool& ConsoleObject::getDynamicGroupExpand() static SimObjectRefConsoleBaseType< className > ptrRefType; \ static AbstractClassRep::WriteCustomTamlSchema getStaticWriteCustomTamlSchema(); \ static AbstractClassRep* getContainerChildStaticClassRep(); \ - virtual AbstractClassRep* getClassRep() const - + virtual AbstractClassRep* getClassRep() const + #define DECLARE_CATEGORY( string ) \ static const char* __category() { return string; } - + #define DECLARE_DESCRIPTION( string ) \ static const char* __description() { return string; } @@ -1199,7 +1195,7 @@ inline bool& ConsoleObject::getDynamicGroupExpand() AbstractClassRep* className::getContainerChildStaticClassRep() { return NULL; } \ AbstractClassRep::WriteCustomTamlSchema className::getStaticWriteCustomTamlSchema() { return NULL; } \ ConcreteClassRep className::dynClassRep(#className, "Type" #className, &_smTypeId, NetClassGroupGameMask, NetClassTypeDataBlock, 0, className::getParentStaticClassRep(), &Parent::__description ) - + // Support for adding properties to classes CONOBJECT style. #define PROPERTY_TABLE( className ) \ namespace { namespace _ ## className { \ @@ -1209,13 +1205,13 @@ inline bool& ConsoleObject::getDynamicGroupExpand() ConcreteClassRep< className >::smPropertyTable = _ ## className::_propTable; \ namespace { namespace _ ## className { \ EnginePropertyTable::Property _props[] = { - + #define END_PROPERTY_TABLE \ { NULL } \ }; \ EnginePropertyTable _propTable( sizeof( _props ) / sizeof( _props[ 0 ] ) - 1, _props ); \ } } - + /// Add an auto-doc for a class. #define ConsoleDocClass( className, docString ) \ CLASSDOC( className, docString ) @@ -1225,7 +1221,7 @@ inline bool& ConsoleObject::getDynamicGroupExpand() //------------------------------------------------------------------------------ // Protected field default get/set functions // -// The reason for these functions is that it will save one branch per console +// The reason for these functions is that it will save one branch per console // data request and script functions will still execute at the same speed as // before the modifications to allow protected static fields. These will just // inline and the code should be roughly the same size, and just as fast as From b0b39b5f83cb55f79da537bcd854f4a44da64631 Mon Sep 17 00:00:00 2001 From: Azaezel Date: Fri, 27 Nov 2015 16:17:30 -0600 Subject: [PATCH 20/47] mDirtyTiles changed from std::queue to a vector allows us to leverage .push_back_unique(&foo); and .clear(); --- Engine/source/navigation/navMesh.cpp | 16 ++++++++-------- Engine/source/navigation/navMesh.h | 2 +- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/Engine/source/navigation/navMesh.cpp b/Engine/source/navigation/navMesh.cpp index 7df05ee2e..02de1b071 100644 --- a/Engine/source/navigation/navMesh.cpp +++ b/Engine/source/navigation/navMesh.cpp @@ -637,7 +637,7 @@ DefineEngineMethod(NavMesh, build, bool, (bool background, bool save), (true, fa void NavMesh::cancelBuild() { - while(!mDirtyTiles.empty()) mDirtyTiles.pop(); + mDirtyTiles.clear(); ctx->stopTimer(RC_TIMER_TOTAL); mBuilding = false; } @@ -707,7 +707,7 @@ void NavMesh::updateTiles(bool dirty) mTiles.clear(); mTileData.clear(); - while(!mDirtyTiles.empty()) mDirtyTiles.pop(); + mDirtyTiles.clear(); const Box3F &box = DTStoRC(getWorldBox()); if(box.isEmpty()) @@ -741,7 +741,7 @@ void NavMesh::updateTiles(bool dirty) tileBmin, tileBmax)); if(dirty) - mDirtyTiles.push(mTiles.size() - 1); + mDirtyTiles.push_back_unique(mTiles.size() - 1); if(mSaveIntermediates) mTileData.increment(); @@ -760,7 +760,7 @@ void NavMesh::buildNextTile() { // Pop a single dirty tile and process it. U32 i = mDirtyTiles.front(); - mDirtyTiles.pop(); + mDirtyTiles.pop_front(); const Tile &tile = mTiles[i]; // Intermediate data for tile build. TileData tempdata; @@ -844,7 +844,7 @@ unsigned char *NavMesh::buildTileData(const Tile &tile, TileData &data, U32 &dat // Check for no geometry. if(!data.geom.getVertCount()) - return false; + return NULL; // Figure out voxel dimensions of this tile. U32 width = 0, height = 0; @@ -1066,7 +1066,7 @@ void NavMesh::buildTiles(const Box3F &box) if(!tile.box.isOverlapped(box)) continue; // Mark as dirty. - mDirtyTiles.push(i); + mDirtyTiles.push_back_unique(i); } if(mDirtyTiles.size()) ctx->startTimer(RC_TIMER_TOTAL); @@ -1082,7 +1082,7 @@ void NavMesh::buildTile(const U32 &tile) { if(tile < mTiles.size()) { - mDirtyTiles.push(tile); + mDirtyTiles.push_back_unique(tile); ctx->startTimer(RC_TIMER_TOTAL); } } @@ -1104,7 +1104,7 @@ void NavMesh::buildLinks() mLinksUnsynced[j]) { // Mark tile for build. - mDirtyTiles.push(i); + mDirtyTiles.push_back_unique(i); // Delete link if necessary if(mDeleteLinks[j]) { diff --git a/Engine/source/navigation/navMesh.h b/Engine/source/navigation/navMesh.h index 1d9eba1b1..ff279c3be 100644 --- a/Engine/source/navigation/navMesh.h +++ b/Engine/source/navigation/navMesh.h @@ -325,7 +325,7 @@ private: Vector mTileData; /// List of indices to the tile array which are dirty. - std::queue mDirtyTiles; + Vector mDirtyTiles; /// Update tile dimensions. void updateTiles(bool dirty = false); From a90eb9762b4bff4e3fb90576d1b653ce78d0e0b4 Mon Sep 17 00:00:00 2001 From: Areloch Date: Tue, 1 Dec 2015 00:10:13 -0600 Subject: [PATCH 21/47] Re-submission of the Volumetric Fog PR, with cleanup. --- Engine/source/gui/core/guiCanvas.cpp | 3 + Engine/source/gui/core/guiCanvas.h | 10 + .../renderInstance/renderPassManager.cpp | 1 + .../source/renderInstance/renderPassManager.h | 1 + .../renderInstance/renderTranslucentMgr.cpp | 10 + .../source/windowManager/platformWindow.cpp | 7 +- Engine/source/windowManager/platformWindow.h | 11 +- .../windowManager/win32/win32Window.cpp | 2 + .../game/art/environment/FogMod_heavy.dds | Bin 0 -> 131200 bytes .../game/art/environment/FogMod_light.dds | Bin 0 -> 131200 bytes .../Empty/game/art/environment/FogMod_med.dds | Bin 0 -> 131200 bytes .../Empty/game/art/environment/Fog_Cube.DAE | 177 ++++++++ .../Empty/game/art/environment/Fog_Cube.cs | 8 + .../game/core/scripts/client/postFx/glow.cs | 76 ++++ .../postFx/postFxManager.gui.settings.cs | 1 + .../game/core/scripts/client/renderManager.cs | 2 + .../game/scripts/server/VolumetricFog.cs | 106 +++++ .../Empty/game/scripts/server/scriptExec.cs | 1 + .../shaders/common/VolumetricFog/VFogP.hlsl | 87 ++++ .../common/VolumetricFog/VFogPreP.hlsl | 39 ++ .../common/VolumetricFog/VFogPreV.hlsl | 46 ++ .../common/VolumetricFog/VFogRefl.hlsl | 36 ++ .../shaders/common/VolumetricFog/VFogV.hlsl | 45 ++ .../common/VolumetricFog/gl/VFogP.glsl | 87 ++++ .../common/VolumetricFog/gl/VFogPreP.glsl | 37 ++ .../common/VolumetricFog/gl/VFogPreV.glsl | 42 ++ .../common/VolumetricFog/gl/VFogRefl.glsl | 33 ++ .../common/VolumetricFog/gl/VFogV.glsl | 38 ++ .../shaders/common/postFx/VolFogGlowP.hlsl | 74 +++ .../shaders/common/postFx/gl/VolFogGlowP.glsl | 67 +++ .../game/tools/classIcons/VolumetricFog.png | Bin 0 -> 3642 bytes .../worldEditor/gui/objectBuilderGui.ed.gui | 14 +- .../worldEditor/scripts/editors/creator.ed.cs | 1 + .../game/art/environment/FogMod_heavy.dds | Bin 0 -> 131200 bytes .../game/art/environment/FogMod_light.dds | Bin 0 -> 131200 bytes .../Full/game/art/environment/FogMod_med.dds | Bin 0 -> 131200 bytes .../Full/game/art/environment/Fog_Cube.DAE | 177 ++++++++ .../Full/game/art/environment/Fog_Cube.cs | 8 + .../art/environment/LightVolume_Sphere.DAE | 423 ++++++++++++++++++ .../art/environment/LightVolume_Sphere.cs | 8 + .../art/environment/LightVolume_Sphere.dts | Bin 0 -> 12883 bytes .../game/core/scripts/client/postFx/glow.cs | 76 ++++ .../postFx/postFxManager.gui.settings.cs | 1 + .../game/core/scripts/client/renderManager.cs | 2 + .../Full/game/core/scripts/client/shaders.cs | 36 ++ .../Full/game/scripts/server/VolumetricFog.cs | 106 +++++ .../Full/game/scripts/server/scriptExec.cs | 1 + .../shaders/common/VolumetricFog/VFogP.hlsl | 87 ++++ .../common/VolumetricFog/VFogPreP.hlsl | 39 ++ .../common/VolumetricFog/VFogPreV.hlsl | 46 ++ .../common/VolumetricFog/VFogRefl.hlsl | 37 ++ .../shaders/common/VolumetricFog/VFogV.hlsl | 45 ++ .../common/VolumetricFog/gl/VFogP.glsl | 87 ++++ .../common/VolumetricFog/gl/VFogPreP.glsl | 37 ++ .../common/VolumetricFog/gl/VFogPreV.glsl | 42 ++ .../common/VolumetricFog/gl/VFogRefl.glsl | 33 ++ .../common/VolumetricFog/gl/VFogV.glsl | 38 ++ .../shaders/common/postFx/VolFogGlowP.hlsl | 74 +++ .../shaders/common/postFx/gl/VolFogGlowP.glsl | 67 +++ .../game/tools/classIcons/VolumetricFog.png | Bin 0 -> 3642 bytes .../worldEditor/gui/objectBuilderGui.ed.gui | 14 +- .../worldEditor/scripts/editors/creator.ed.cs | 1 + 62 files changed, 2541 insertions(+), 6 deletions(-) create mode 100644 Templates/Empty/game/art/environment/FogMod_heavy.dds create mode 100644 Templates/Empty/game/art/environment/FogMod_light.dds create mode 100644 Templates/Empty/game/art/environment/FogMod_med.dds create mode 100644 Templates/Empty/game/art/environment/Fog_Cube.DAE create mode 100644 Templates/Empty/game/art/environment/Fog_Cube.cs create mode 100644 Templates/Empty/game/scripts/server/VolumetricFog.cs create mode 100644 Templates/Empty/game/shaders/common/VolumetricFog/VFogP.hlsl create mode 100644 Templates/Empty/game/shaders/common/VolumetricFog/VFogPreP.hlsl create mode 100644 Templates/Empty/game/shaders/common/VolumetricFog/VFogPreV.hlsl create mode 100644 Templates/Empty/game/shaders/common/VolumetricFog/VFogRefl.hlsl create mode 100644 Templates/Empty/game/shaders/common/VolumetricFog/VFogV.hlsl create mode 100644 Templates/Empty/game/shaders/common/VolumetricFog/gl/VFogP.glsl create mode 100644 Templates/Empty/game/shaders/common/VolumetricFog/gl/VFogPreP.glsl create mode 100644 Templates/Empty/game/shaders/common/VolumetricFog/gl/VFogPreV.glsl create mode 100644 Templates/Empty/game/shaders/common/VolumetricFog/gl/VFogRefl.glsl create mode 100644 Templates/Empty/game/shaders/common/VolumetricFog/gl/VFogV.glsl create mode 100644 Templates/Empty/game/shaders/common/postFx/VolFogGlowP.hlsl create mode 100644 Templates/Empty/game/shaders/common/postFx/gl/VolFogGlowP.glsl create mode 100644 Templates/Empty/game/tools/classIcons/VolumetricFog.png create mode 100644 Templates/Full/game/art/environment/FogMod_heavy.dds create mode 100644 Templates/Full/game/art/environment/FogMod_light.dds create mode 100644 Templates/Full/game/art/environment/FogMod_med.dds create mode 100644 Templates/Full/game/art/environment/Fog_Cube.DAE create mode 100644 Templates/Full/game/art/environment/Fog_Cube.cs create mode 100644 Templates/Full/game/art/environment/LightVolume_Sphere.DAE create mode 100644 Templates/Full/game/art/environment/LightVolume_Sphere.cs create mode 100644 Templates/Full/game/art/environment/LightVolume_Sphere.dts create mode 100644 Templates/Full/game/scripts/server/VolumetricFog.cs create mode 100644 Templates/Full/game/shaders/common/VolumetricFog/VFogP.hlsl create mode 100644 Templates/Full/game/shaders/common/VolumetricFog/VFogPreP.hlsl create mode 100644 Templates/Full/game/shaders/common/VolumetricFog/VFogPreV.hlsl create mode 100644 Templates/Full/game/shaders/common/VolumetricFog/VFogRefl.hlsl create mode 100644 Templates/Full/game/shaders/common/VolumetricFog/VFogV.hlsl create mode 100644 Templates/Full/game/shaders/common/VolumetricFog/gl/VFogP.glsl create mode 100644 Templates/Full/game/shaders/common/VolumetricFog/gl/VFogPreP.glsl create mode 100644 Templates/Full/game/shaders/common/VolumetricFog/gl/VFogPreV.glsl create mode 100644 Templates/Full/game/shaders/common/VolumetricFog/gl/VFogRefl.glsl create mode 100644 Templates/Full/game/shaders/common/VolumetricFog/gl/VFogV.glsl create mode 100644 Templates/Full/game/shaders/common/postFx/VolFogGlowP.hlsl create mode 100644 Templates/Full/game/shaders/common/postFx/gl/VolFogGlowP.glsl create mode 100644 Templates/Full/game/tools/classIcons/VolumetricFog.png diff --git a/Engine/source/gui/core/guiCanvas.cpp b/Engine/source/gui/core/guiCanvas.cpp index 84fe6e0c2..a3f2344f2 100644 --- a/Engine/source/gui/core/guiCanvas.cpp +++ b/Engine/source/gui/core/guiCanvas.cpp @@ -321,8 +321,11 @@ void GuiCanvas::setWindowTitle(const char *newTitle) mPlatformWindow->setCaption(newTitle); } +CanvasSizeChangeSignal GuiCanvas::smCanvasSizeChangeSignal; + void GuiCanvas::handleResize( WindowId did, S32 width, S32 height ) { + getCanvasSizeChangeSignal().trigger(this); if (Journal::IsPlaying() && mPlatformWindow) { mPlatformWindow->lockSize(false); diff --git a/Engine/source/gui/core/guiCanvas.h b/Engine/source/gui/core/guiCanvas.h index b1444ce32..0a2e44fa5 100644 --- a/Engine/source/gui/core/guiCanvas.h +++ b/Engine/source/gui/core/guiCanvas.h @@ -33,6 +33,10 @@ #include "platform/platformInput.h" #endif +#ifndef _SIGNAL_H_ +#include "core/util/tSignal.h" +#endif + #include "component/interfaces/IProcessInput.h" #include "windowManager/platformWindowMgr.h" #include "gfx/gfxFence.h" @@ -74,6 +78,8 @@ /// screen will be painted normally. If you are making an animated GuiControl /// you need to add your control to the dirty areas of the canvas. /// +class guiCanvas; +typedef Signal CanvasSizeChangeSignal; class GuiCanvas : public GuiControl, public IProcessInput { @@ -183,6 +189,8 @@ protected: virtual void setupFences(); void checkLockMouseMove( const GuiEvent& event ); + //Signal used to let others know this canvas has changed size. + static CanvasSizeChangeSignal smCanvasSizeChangeSignal; GuiControl *mMenuBarCtrl; @@ -200,6 +208,8 @@ public: static void initPersistFields(); + static CanvasSizeChangeSignal& getCanvasSizeChangeSignal() { return smCanvasSizeChangeSignal; } + /// @name Rendering methods /// /// @{ diff --git a/Engine/source/renderInstance/renderPassManager.cpp b/Engine/source/renderInstance/renderPassManager.cpp index 236cccd9b..68daed77e 100644 --- a/Engine/source/renderInstance/renderPassManager.cpp +++ b/Engine/source/renderInstance/renderPassManager.cpp @@ -53,6 +53,7 @@ const RenderInstType RenderPassManager::RIT_ObjectTranslucent("ObjectTranslucent const RenderInstType RenderPassManager::RIT_Decal("Decal"); const RenderInstType RenderPassManager::RIT_Water("Water"); const RenderInstType RenderPassManager::RIT_Foliage("Foliage"); +const RenderInstType RenderPassManager::RIT_VolumetricFog("ObjectVolumetricFog"); const RenderInstType RenderPassManager::RIT_Translucent("Translucent"); const RenderInstType RenderPassManager::RIT_Begin("Begin"); const RenderInstType RenderPassManager::RIT_Custom("Custom"); diff --git a/Engine/source/renderInstance/renderPassManager.h b/Engine/source/renderInstance/renderPassManager.h index b7f72b06c..b192fdb0e 100644 --- a/Engine/source/renderInstance/renderPassManager.h +++ b/Engine/source/renderInstance/renderPassManager.h @@ -110,6 +110,7 @@ public: static const RenderInstType RIT_Decal; static const RenderInstType RIT_Water; static const RenderInstType RIT_Foliage; + static const RenderInstType RIT_VolumetricFog; static const RenderInstType RIT_Translucent; static const RenderInstType RIT_Begin; static const RenderInstType RIT_Custom; diff --git a/Engine/source/renderInstance/renderTranslucentMgr.cpp b/Engine/source/renderInstance/renderTranslucentMgr.cpp index b755e12c9..7ad324a26 100644 --- a/Engine/source/renderInstance/renderTranslucentMgr.cpp +++ b/Engine/source/renderInstance/renderTranslucentMgr.cpp @@ -51,6 +51,7 @@ RenderTranslucentMgr::RenderTranslucentMgr() { notifyType( RenderPassManager::RIT_ObjectTranslucent ); notifyType( RenderPassManager::RIT_Particle ); + notifyType( RenderPassManager::RIT_VolumetricFog); } RenderTranslucentMgr::~RenderTranslucentMgr() @@ -187,6 +188,15 @@ void RenderTranslucentMgr::render( SceneRenderState *state ) j++; continue; } + else if (baseRI->type == RenderPassManager::RIT_VolumetricFog) + { + ObjectRenderInst* objRI = static_cast(baseRI); + objRI->renderDelegate(objRI, state, NULL); + lastVB = NULL; + lastPB = NULL; + j++; + continue; + } else if ( baseRI->type == RenderPassManager::RIT_Particle ) { ParticleRenderInst *ri = static_cast(baseRI); diff --git a/Engine/source/windowManager/platformWindow.cpp b/Engine/source/windowManager/platformWindow.cpp index 8a7ad65fb..b11ac0bb7 100644 --- a/Engine/source/windowManager/platformWindow.cpp +++ b/Engine/source/windowManager/platformWindow.cpp @@ -22,7 +22,7 @@ #include "windowManager/platformWindow.h" - +ScreenResChangeSignal PlatformWindow::smScreenResChangeSignal; //----------------------------------------------------------------------------- void PlatformWindow::setFullscreen( const bool fullscreen ) @@ -48,3 +48,8 @@ bool PlatformWindow::shouldNotTranslate( U32 modifiers, U32 keyCode ) const else return false; } +void PlatformWindow::setVideoMode(const GFXVideoMode &mode) +{ + _setVideoMode(mode); + getScreenResChangeSignal().trigger(this, true); +} \ No newline at end of file diff --git a/Engine/source/windowManager/platformWindow.h b/Engine/source/windowManager/platformWindow.h index 6db7ce423..df1b51595 100644 --- a/Engine/source/windowManager/platformWindow.h +++ b/Engine/source/windowManager/platformWindow.h @@ -28,6 +28,9 @@ #include "core/util/safeDelete.h" #include "windowManager/platformCursorController.h" #include "windowManager/windowInputGenerator.h" +#ifndef _SIGNAL_H_ //Volumetric Fog +#include "core/util/tSignal.h" +#endif //forward decl's class PlatformWindowManager; @@ -35,7 +38,7 @@ class GFXDevice; struct GFXVideoMode; class GFXWindowTarget; class IProcessInput; - +typedef Signal ScreenResChangeSignal; /// Abstract representation of a native OS window. /// /// Every windowing system has its own representations and conventions as @@ -110,7 +113,7 @@ protected: // This controller maps window input (Mouse/Keyboard) to a generic input consumer mWindowInputGenerator = new WindowInputGenerator( this ); } - + static ScreenResChangeSignal smScreenResChangeSignal; public: /// To get rid of a window, just delete it. Make sure the GFXDevice is @@ -158,7 +161,7 @@ public: virtual GFXWindowTarget *getGFXTarget()=0; /// Set the video mode for this window. - virtual void setVideoMode(const GFXVideoMode &mode)=0; + virtual void setVideoMode(const GFXVideoMode &mode); /// Get our current video mode - if the window has been resized, it will /// reflect this. @@ -497,6 +500,7 @@ public: IdleEvent idleEvent; /// @} + static ScreenResChangeSignal& getScreenResChangeSignal() { return smScreenResChangeSignal; } /// Get the platform specific object needed to create or attach an accelerated /// graohics drawing context on or to the window @@ -507,6 +511,7 @@ public: virtual void* getPlatformDrawable() const = 0; protected: virtual void _setFullscreen(const bool fullScreen) {}; + virtual void _setVideoMode(const GFXVideoMode &mode) {}; }; #endif diff --git a/Engine/source/windowManager/win32/win32Window.cpp b/Engine/source/windowManager/win32/win32Window.cpp index 88be80cf1..5c9b8ed11 100644 --- a/Engine/source/windowManager/win32/win32Window.cpp +++ b/Engine/source/windowManager/win32/win32Window.cpp @@ -287,6 +287,8 @@ void Win32Window::setVideoMode( const GFXVideoMode &mode ) mOwningManager->raiseCurtain(); SetForegroundWindow(getHWND()); + + getScreenResChangeSignal().trigger(this, true); } bool Win32Window::clearFullscreen() diff --git a/Templates/Empty/game/art/environment/FogMod_heavy.dds b/Templates/Empty/game/art/environment/FogMod_heavy.dds new file mode 100644 index 0000000000000000000000000000000000000000..197dd43327352716bc08bd069209499bf6b5a8f1 GIT binary patch literal 131200 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 n;hV-7aDAP}zDS literal 0 HcmV?d00001 diff --git a/Templates/Empty/game/art/environment/FogMod_light.dds b/Templates/Empty/game/art/environment/FogMod_light.dds new file mode 100644 index 0000000000000000000000000000000000000000..d726795fa1de24d57dc54259c7c57f984e3d6704 GIT binary patch literal 131200 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%0DDkgQ;%|w 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൏u$o87pO_E*IzlWcQhKlOkZMNW<&fqwN}9Y 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 bRO-0LHU0XoSI+pJx4tj`BkL3><($#K7P0$f literal 0 HcmV?d00001 diff --git a/Templates/Empty/game/art/environment/Fog_Cube.DAE b/Templates/Empty/game/art/environment/Fog_Cube.DAE new file mode 100644 index 000000000..34cad9f48 --- /dev/null +++ b/Templates/Empty/game/art/environment/Fog_Cube.DAE @@ -0,0 +1,177 @@ + + + + + Richard + OpenCOLLADA for 3ds Max; Version: 1.4.1; Revision: exported; Platform: x64; Configuration: Release_Max2011_static + file:///G:/Documents%20and%20Settings/Richard/Mijn%20documenten/3dsmax/scenes/FogVolumes.max + + 2014-08-16T10:10:23 + 2014-08-16T10:10:23 + + Z_UP + + + + + + + + 0 0 0 1 + + + 0.588 0.588 0.588 1 + + + 0.588 0.588 0.588 1 + + + 0.9 0.9 0.9 1 + + + 0 + + + 0 0 0 1 + + + 1 1 1 1 + + + 1 + + + + + + + + 0 + 0 + 0 + 1.5 + 0 + 3 + 1 + 0 + + + 1 + 1 + 0 + 0.1 + 0 + + + + + + + + + + + + + + + -0.85 -1 -0.85 0.85 -0.85 -1 -1 0.85 -0.85 0.85 0.85 -1 -0.85 -1 0.85 1 -0.85 0.85 -1 0.85 0.85 0.85 1 0.85 -1 -0.85 -0.85 -0.85 -0.85 -1 1 -0.85 -0.85 0.85 -1 -0.85 -0.85 1 -0.85 -0.85 0.85 -1 0.85 1 -0.85 1 0.85 -0.85 -0.85 -0.85 1 -1 -0.85 0.85 0.85 -0.85 1 0.85 -1 0.85 -0.85 0.85 1 -0.85 1 0.85 0.85 0.85 1 1 0.85 0.85 + + + + + + + + + + -0.341586 -0.341586 -0.8755786 -0.341586 0.341586 -0.8755788 0.341586 0.341586 -0.8755788 0.341586 -0.341586 -0.8755788 -0.341586 -0.341586 0.8755786 0.341586 -0.341586 0.8755788 0.341586 0.341586 0.8755788 -0.341586 0.341586 0.8755788 -0.341586 -0.8755786 -0.341586 0.341586 -0.8755788 -0.341586 0.341586 -0.8755786 0.341586 -0.341586 -0.8755788 0.341586 0.8755786 -0.341586 -0.341586 0.8755788 0.341586 -0.341586 0.8755786 0.341586 0.341586 0.8755788 -0.341586 0.341586 0.341586 0.8755786 -0.341586 -0.341586 0.8755788 -0.341586 -0.341586 0.8755786 0.341586 0.341586 0.8755788 0.341586 -0.8755786 0.341586 -0.341586 -0.8755788 -0.341586 -0.341586 -0.8755786 -0.341586 0.341586 -0.8755788 0.341586 0.341586 + + + + + + + + + + 0 0 0 1 0 0 0 1 0 1 1 0 0 0 0 1 0 0 0 1 0 1 1 0 0 0 0 1 0 0 0 1 0 1 1 0 0.07542458 0.07542461 4.99755e-4 0.07542479 0.07542461 4.99547e-4 0.07542455 0.07542461 4.99755e-4 0.07542461 0.9245752 4.99547e-4 0.07542458 0.9245754 4.99755e-4 0.07542458 0.9245754 0.9995003 0.07542455 0.9245754 4.99755e-4 0.07542455 0.9245754 0.9995003 0.9245752 0.07542461 4.99576e-4 0.9245754 0.07542479 4.99547e-4 0.07542458 0.07542461 0.9995003 0.9245752 0.07542461 4.99576e-4 0.9245752 0.07542461 0.9995004 0.9245752 0.9245754 4.99547e-4 0.07542455 0.07542461 0.9995003 0.9245752 0.07542461 0.9995004 0.07542461 0.07542479 0.9995005 0.9245752 0.9245754 4.99576e-4 0.9245752 0.07542461 0.9995005 0.9245752 0.9245754 4.99576e-4 0.07542479 0.9245754 0.9995005 0.9245752 0.9245754 0.9995004 0.9245754 0.9245752 0.9995005 0.9245752 0.9245754 0.9995004 0.9995003 0.07542461 0.07542458 0.9245752 4.99547e-4 0.07542461 0.9245752 4.99547e-4 0.07542461 0.9995003 0.07542461 0.07542458 0.9995003 0.07542461 0.9245754 0.9245752 4.99547e-4 0.9245754 0.9245752 4.99547e-4 0.9245754 0.9995003 0.07542461 0.9245754 0.9995003 0.9245754 0.07542458 0.9245752 0.9995005 0.07542461 0.9995003 0.9245754 0.07542458 0.9245752 0.9995005 0.07542461 0.9995003 0.9245754 0.9245754 0.9245752 0.9995005 0.9245754 0.9995003 0.9245754 0.9245754 0.9245752 0.9995005 0.9245754 0.9995004 0.07542482 0.07542461 0.9995003 0.9245754 0.07542461 0.9245752 0.9995004 0.07542461 0.07542455 0.9995003 0.07542461 4.99606e-4 0.9245752 0.07542461 4.99725e-4 0.07542458 0.07542461 0.07542479 4.99576e-4 0.07542461 0.9245754 4.99755e-4 0.07542461 0.07542458 4.99755e-4 0.9245754 0.9245752 4.99576e-4 0.9245754 0.9995003 0.07542458 0.9245754 0.9995004 0.9245752 0.9245754 0.9245754 0.9995003 0.9245754 0.07542482 0.9995004 0.9245754 4.99755e-4 0.9245754 0.9245754 4.99576e-4 0.07542482 0.9245754 0.9995003 0.07542461 0.07542458 0.9995003 0.9245754 0.07542458 0.9995003 0.9245754 0.07542458 0.9995003 0.07542461 0.07542458 0.9995003 0.07542461 0.9245754 0.9995003 0.9245754 0.9245754 0.9995003 0.07542461 0.9245754 0.9995003 0.9245754 0.9245754 + + + + + + + + + + -0.8644259 0.01841655 0.3300502 -0.8715108 -0.05526615 0.3184382 -0.8644259 0.01841664 -0.3300501 -0.8715108 -0.05526611 -0.3184382 0.8738725 -0.06754867 0.3145678 0.8597026 -0.006149054 -0.3377912 0.8738725 -0.06754874 -0.3145678 0.8597026 -0.006148929 0.3377911 0.883319 -0.2990854 -0.116681 0.8478944 0.3571441 -0.06756432 0.8597026 0.3377913 0.00614921 0.883319 -0.2990854 0.116681 0.2990854 0.883319 -0.116681 -0.3571441 0.8478944 -0.06756432 -0.3377913 0.8597026 0.00614921 0.2990854 0.883319 0.116681 -0.883319 0.2990854 -0.116681 -0.8478944 -0.3571441 -0.06756432 -0.8597026 -0.3377913 0.00614921 -0.883319 0.2990854 0.116681 -0.2990854 -0.883319 -0.116681 0.3571441 -0.8478944 -0.06756432 0.3377913 -0.8597026 0.00614921 -0.2990854 -0.883319 0.116681 0.8360862 -0.3764972 0.1289794 0.7071068 -0.7071068 0 0.7071068 0.7071068 0 0.3764972 0.8360862 0.1289794 -0.3764972 -0.8360862 0.1289794 -0.7071068 -0.7071068 0 -0.7071068 0.7071068 0 -0.8360862 0.3764972 0.1289794 0.8360862 -0.3764971 -0.1289794 0.7071068 -0.7071068 0 0.3764971 0.8360862 -0.1289794 0.7071068 0.7071068 0 -0.3764971 -0.8360862 -0.1289794 -0.7071068 -0.7071068 0 -0.8360862 0.3764971 -0.1289794 -0.7071068 0.7071068 0 -0.376497 0.1289792 0.8360862 -0.3764973 -0.1289798 0.8360861 -0.8833191 -0.2990855 0.1166808 -0.883319 0.2990853 -0.1166812 -0.3764971 0.1289794 -0.8360862 -0.3764972 -0.1289795 -0.8360862 -0.8833191 -0.2990855 -0.1166807 -0.883319 0.2990853 0.1166812 0.883319 -0.2990853 0.1166812 0.8833191 0.2990855 -0.1166807 0.3764971 0.1289797 -0.8360862 0.3764971 -0.1289793 -0.8360862 0.883319 -0.2990853 -0.1166811 0.8833191 0.2990855 0.1166808 0.3764972 0.1289799 0.8360861 0.3764971 -0.128979 0.8360862 0.3764972 0.8360862 0.1289794 0.3764971 0.8360862 -0.1289794 0.8360862 -0.3764971 -0.1289794 0.8360862 -0.3764972 0.1289794 -0.8360862 0.3764972 0.1289794 -0.8360862 0.3764971 -0.1289794 -0.3764972 -0.8360862 0.1289794 -0.3764971 -0.8360862 -0.1289794 + + + + + + + + + + 0.1043954 -0.9396398 0.3258505 -0.06496345 -0.9379679 -0.3405817 0.1043953 -0.9396398 -0.3258505 -0.06496349 -0.937968 0.3405817 0.05187585 -0.9370471 -0.3453283 -0.1307439 -0.939827 -0.3156443 0.05187577 -0.9370471 0.3453283 -0.1307438 -0.939827 0.3156443 0 0.3634471 -0.9316148 -0.196368 0.2889368 -0.9369926 0.1307441 -0.3156442 -0.939827 0 -0.3634471 -0.9316148 -0.3634471 0 -0.9316148 -0.2889368 -0.196368 -0.9369926 0.3156442 0.1307441 -0.939827 0.3634471 0 -0.9316148 0 -0.3634471 -0.9316148 0.196368 -0.2889368 -0.9369926 -0.1307441 0.3156442 -0.939827 0 0.3634471 -0.9316148 0.3634471 0 -0.9316148 0.2889368 0.196368 -0.9369926 -0.3156442 -0.1307441 -0.939827 -0.3634471 0 -0.9316148 0.2608475 0.2608475 -0.9294714 0.6191276 0.6191276 -0.4830755 -0.6191276 0.6191276 -0.4830755 -0.2608475 0.2608475 -0.9294714 0.2608475 -0.2608475 -0.9294714 0.6191276 -0.6191276 -0.4830755 -0.6191276 -0.6191276 -0.4830755 -0.2608475 -0.2608475 -0.9294714 -0.2608475 -0.2608475 -0.9294714 -0.6191276 -0.6191276 -0.4830755 0.2608475 -0.2608475 -0.9294714 0.6191276 -0.6191276 -0.4830755 -0.2608475 0.2608475 -0.9294714 -0.6191276 0.6191276 -0.4830755 0.2608475 0.2608475 -0.9294714 0.6191276 0.6191276 -0.4830755 0.2608476 -0.9294715 0.2608473 -0.2608474 -0.9294714 -0.2608479 1.81809e-7 -0.363447 -0.9316149 2.27262e-7 -0.3634472 -0.9316148 0.2608475 -0.9294714 -0.2608475 -0.2608475 -0.9294714 0.2608477 2.72714e-7 -0.363447 0.9316149 2.72714e-7 -0.3634472 0.9316148 2.72714e-7 -0.3634472 -0.9316148 2.72714e-7 -0.363447 -0.9316149 -0.2608474 -0.9294714 -0.2608478 0.2608476 -0.9294714 0.2608474 1.81809e-7 -0.3634472 0.9316148 2.27262e-7 -0.3634471 0.9316149 -0.2608473 -0.9294714 0.260848 0.2608477 -0.9294715 -0.2608472 -0.2608475 0.2608475 -0.9294714 0.2608475 -0.2608475 -0.9294714 -0.2608475 -0.2608475 -0.9294714 0.2608475 0.2608475 -0.9294714 -0.2608475 -0.2608475 -0.9294714 0.2608475 0.2608475 -0.9294714 0.2608475 -0.2608475 -0.9294714 -0.2608475 0.2608475 -0.9294714 + + + + + + + + + + + + + + + + + +

9 0 21 0 13 1 25 1 3 2 15 2 3 2 15 2 1 3 13 3 9 0 21 0 16 4 28 4 18 5 30 5 22 6 34 6 22 6 34 6 20 7 32 7 16 4 28 4 0 8 12 8 11 9 23 9 19 10 31 10 19 10 31 10 4 11 16 11 0 8 12 8 10 12 22 12 15 13 27 13 23 14 35 14 23 14 35 14 5 15 17 15 10 12 22 12 14 16 26 16 12 17 24 17 21 18 33 18 21 18 33 18 7 19 19 19 14 16 26 16 2 20 14 20 8 21 20 21 17 22 29 22 17 22 29 22 6 23 18 23 2 20 14 20 0 8 36 24 8 21 20 21 9 0 37 25 1 3 38 26 10 12 39 27 11 9 23 9 2 20 40 28 12 17 24 17 13 1 41 29 3 2 42 30 14 16 43 31 15 13 27 13 4 11 44 32 16 4 45 33 17 22 29 22 5 15 46 34 18 5 47 35 19 10 31 10 6 23 48 36 20 7 49 37 21 18 33 18 7 19 50 38 22 6 51 39 23 14 35 14 9 0 21 0 8 21 52 40 2 20 53 41 2 20 53 41 13 1 25 1 9 0 21 0 13 1 25 1 12 17 54 42 14 16 55 43 14 16 55 43 3 2 15 2 13 1 25 1 3 2 15 2 15 13 56 44 10 12 57 45 10 12 57 45 1 3 13 3 3 2 15 2 1 3 13 3 11 9 58 46 0 8 59 47 0 8 59 47 9 0 21 0 1 3 13 3 16 4 28 4 4 11 60 48 19 10 61 49 19 10 61 49 18 5 30 5 16 4 28 4 18 5 30 5 5 15 62 50 23 14 63 51 23 14 63 51 22 6 34 6 18 5 30 5 22 6 34 6 7 19 64 52 21 18 65 53 21 18 65 53 20 7 32 7 22 6 34 6 20 7 32 7 6 23 66 54 17 22 67 55 17 22 67 55 16 4 28 4 20 7 32 7 11 9 23 9 10 12 68 56 5 15 69 57 5 15 69 57 19 10 31 10 11 9 23 9 4 11 70 58 17 22 29 22 8 21 20 21 8 21 20 21 0 8 71 59 4 11 70 58 15 13 27 13 14 16 72 60 7 19 73 61 7 19 73 61 23 14 35 14 15 13 27 13 12 17 24 17 2 20 74 62 6 23 75 63 6 23 75 63 21 18 33 18 12 17 24 17

+
+
+
+
+ + + + + 0 0 0 + + + + + + + + + + + + + + + + + + + + 1 + 1 + 1 + 1 + + + + + + + + +
\ No newline at end of file diff --git a/Templates/Empty/game/art/environment/Fog_Cube.cs b/Templates/Empty/game/art/environment/Fog_Cube.cs new file mode 100644 index 000000000..3c686032c --- /dev/null +++ b/Templates/Empty/game/art/environment/Fog_Cube.cs @@ -0,0 +1,8 @@ + +singleton TSShapeConstructor(Fog_CubeDAE) +{ + baseShape = "./Fog_Cube.DAE"; + lodType = "TrailingNumber"; + neverImport = "env*"; + loadLights = "0"; +}; diff --git a/Templates/Empty/game/core/scripts/client/postFx/glow.cs b/Templates/Empty/game/core/scripts/client/postFx/glow.cs index 3cc946b04..78c46e56d 100644 --- a/Templates/Empty/game/core/scripts/client/postFx/glow.cs +++ b/Templates/Empty/game/core/scripts/client/postFx/glow.cs @@ -106,3 +106,79 @@ singleton PostEffect( GlowPostFx ) target = "$backBuffer"; }; }; + +singleton ShaderData( PFX_VolFogGlowBlurVertShader ) +{ + DXVertexShaderFile = "shaders/common/postFx/glowBlurV.hlsl"; + DXPixelShaderFile = "shaders/common/postFx/VolFogGlowP.hlsl"; + + OGLVertexShaderFile = "shaders/common/postFx/gl/glowBlurV.glsl"; + OGLPixelShaderFile = "shaders/common/postFx/gl/VolFogGlowP.glsl"; + + defines = "BLUR_DIR=float2(0.0,1.0)"; + samplerNames[0] = "$diffuseMap"; + pixVersion = 2.0; +}; +singleton ShaderData( PFX_VolFogGlowBlurHorzShader : PFX_VolFogGlowBlurVertShader ) +{ + DXVertexShaderFile = "shaders/common/postFx/glowBlurV.hlsl"; + DXPixelShaderFile = "shaders/common/postFx/VolFogGlowP.hlsl"; + + OGLVertexShaderFile = "shaders/common/postFx/gl/glowBlurV.glsl"; + OGLPixelShaderFile = "shaders/common/postFx/gl/VolFogGlowP.glsl"; + + defines = "BLUR_DIR=float2(1.0,0.0)"; +}; + +$VolFogGlowPostFx::glowStrength = 0.3; + +singleton PostEffect( VolFogGlowPostFx ) +{ + // Do not allow the glow effect to work in reflection + // passes by default so we don't do the extra drawing. + allowReflectPass = false; + renderTime = "PFXAfterBin"; + renderBin = "FogBin"; + renderPriority = 1; + // First we down sample the glow buffer. + shader = PFX_PassthruShader; + stateBlock = PFX_DefaultStateBlock; + texture[0] = "$backbuffer"; + target = "$outTex"; + targetScale = "0.5 0.5"; + isEnabled = true; + // Blur vertically + new PostEffect() + { + shader = PFX_VolFogGlowBlurVertShader; + stateBlock = PFX_DefaultStateBlock; + internalName = "vert"; + texture[0] = "$inTex"; + target = "$outTex"; + }; + // Blur horizontally + new PostEffect() + { + shader = PFX_VolFogGlowBlurHorzShader; + stateBlock = PFX_DefaultStateBlock; + internalName = "hor"; + texture[0] = "$inTex"; + target = "$outTex"; + }; + // Upsample and combine with the back buffer. + new PostEffect() + { + shader = PFX_PassthruShader; + stateBlock = PFX_GlowCombineStateBlock; + texture[0] = "$inTex"; + target = "$backBuffer"; + }; +}; + +function VolFogGlowPostFx::setShaderConsts( %this ) +{ + %vp=%this-->vert; + %vp.setShaderConst( "$strength", $VolFogGlowPostFx::glowStrength ); + %vp=%this-->hor; + %vp.setShaderConst( "$strength", $VolFogGlowPostFx::glowStrength ); +} \ No newline at end of file diff --git a/Templates/Empty/game/core/scripts/client/postFx/postFxManager.gui.settings.cs b/Templates/Empty/game/core/scripts/client/postFx/postFxManager.gui.settings.cs index d30d2314b..77d664f41 100644 --- a/Templates/Empty/game/core/scripts/client/postFx/postFxManager.gui.settings.cs +++ b/Templates/Empty/game/core/scripts/client/postFx/postFxManager.gui.settings.cs @@ -70,6 +70,7 @@ function PostFXManager::settingsSetEnabled(%this, %bEnablePostFX) postVerbose("% - PostFX Manager - PostFX disabled"); } + VolFogGlowPostFx.disable(); } function PostFXManager::settingsEffectSetEnabled(%this, %sName, %bEnable) diff --git a/Templates/Empty/game/core/scripts/client/renderManager.cs b/Templates/Empty/game/core/scripts/client/renderManager.cs index dcd1628fe..5734bbce6 100644 --- a/Templates/Empty/game/core/scripts/client/renderManager.cs +++ b/Templates/Empty/game/core/scripts/client/renderManager.cs @@ -75,6 +75,8 @@ function initRenderManager() DiffuseRenderPassManager.addManager( new RenderParticleMgr() { renderOrder = 1.35; processAddOrder = 1.35; } ); DiffuseRenderPassManager.addManager( new RenderTranslucentMgr() { renderOrder = 1.4; processAddOrder = 1.4; } ); + DiffuseRenderPassManager.addManager(new RenderObjectMgr(FogBin){ bintype = "ObjectVolumetricFog"; renderOrder = 1.45; processAddOrder = 1.45; } ); + // Note that the GlowPostFx is triggered after this bin. DiffuseRenderPassManager.addManager( new RenderGlowMgr(GlowBin) { renderOrder = 1.5; processAddOrder = 1.5; } ); diff --git a/Templates/Empty/game/scripts/server/VolumetricFog.cs b/Templates/Empty/game/scripts/server/VolumetricFog.cs new file mode 100644 index 000000000..53e03adf3 --- /dev/null +++ b/Templates/Empty/game/scripts/server/VolumetricFog.cs @@ -0,0 +1,106 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2012 GarageGames, LLC +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- + +function VolumetricFog::onEnterFog(%this,%obj) +{ + // This method is called whenever the control object (Camera or Player) + // %obj enters the fog area. + + // echo("Control Object " @ %obj @ " enters fog " @ %this); +} + +function VolumetricFog::onLeaveFog(%this,%obj) +{ + // This method is called whenever the control object (Camera or Player) + // %obj leaves the fog area. + + // echo("Control Object " @ %obj @ " left fog " @ %this); +} + +function VolumetricFog::Dissolve(%this,%speed,%delete) +{ + // This method dissolves the fog at speed milliseconds + %this.isBuilding = true; + if (%this.FogDensity > 0) + { + %this.setFogDensity(%this.FogDensity - 0.005); + %this.schedule(%speed,Dissolve,%speed,%delete); + } + else + { + %this.isBuilding = false; + %this.SetFogDensity(0.0); + if (%delete !$= "" && %delete !$="0" && %delete !$="false") + %this.schedule(250,delete); + } +} + +function VolumetricFog::Thicken(%this,%speed, %end_density) +{ + // This method thickens the fog at speed milliseconds to a density of %end_density + + %this.isBuilding = true; + if (%this.FogDensity + 0.005 < %end_density) + { + %this.setFogDensity(%this.FogDensity + 0.005); + %this.schedule(%speed,Thicken,%speed, %end_density); + } + else + { + %this.setFogDensity(%end_density); + %this.isBuilding = false; + } +} + +function GenerateFog(%pos,%scale,%color,%density) +{ + // This function can be used to generate some fog caused by massive gunfire etc. + // Change shape and modulation data to your likings. + + %fog=new VolumetricFog() { + shapeName = "art/environment/Fog_Sphere.dts"; + fogColor = %color; + fogDensity = "0.0"; + ignoreWater = "0"; + MinSize = "250"; + FadeSize = "750"; + texture = "art/environment/FogMod_heavy.dds"; + tiles = "1"; + modStrength = "0.2"; + PrimSpeed = "-0.01 0.04"; + SecSpeed = "0.02 0.02"; + position = %pos; + rotation = "0 0 1 20.354"; + scale = %scale; + canSave = "1"; + canSaveDynamicFields = "1"; + }; + + if (isObject(%fog)) + { + MissionCleanup.add(%fog); + + %fog.Thicken(500,%density); + } + + return %fog; +} \ No newline at end of file diff --git a/Templates/Empty/game/scripts/server/scriptExec.cs b/Templates/Empty/game/scripts/server/scriptExec.cs index f2f2d1f58..77a5d8d27 100644 --- a/Templates/Empty/game/scripts/server/scriptExec.cs +++ b/Templates/Empty/game/scripts/server/scriptExec.cs @@ -22,3 +22,4 @@ // Load up all scripts. This function is called when // a server is constructed. +exec("./VolumetricFog.cs"); \ No newline at end of file diff --git a/Templates/Empty/game/shaders/common/VolumetricFog/VFogP.hlsl b/Templates/Empty/game/shaders/common/VolumetricFog/VFogP.hlsl new file mode 100644 index 000000000..aaadbf479 --- /dev/null +++ b/Templates/Empty/game/shaders/common/VolumetricFog/VFogP.hlsl @@ -0,0 +1,87 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2012 GarageGames, LLC +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- + +// Volumetric Fog final pixel shader V2.00 + +#include "shadergen:/autogenConditioners.h" +#include "../torque.hlsl" + +uniform sampler2D prepassTex : register(S0); +uniform sampler2D depthBuffer : register(S1); +uniform sampler2D frontBuffer : register(S2); +uniform sampler2D density : register(S3); + +uniform float accumTime; +uniform float4 fogColor; +uniform float fogDensity; +uniform float preBias; +uniform float textured; +uniform float modstrength; +uniform float4 modspeed;//xy speed layer 1, zw speed layer 2 +uniform float2 viewpoint; +uniform float2 texscale; +uniform float3 ambientColor; +uniform float numtiles; +uniform float fadesize; +uniform float2 PixelSize; + +struct ConnectData +{ + float4 hpos : POSITION; + float4 htpos : TEXCOORD0; + float2 uv0 : TEXCOORD1; +}; + +float4 main( ConnectData IN ) : COLOR0 +{ + float2 uvscreen=((IN.htpos.xy/IN.htpos.w) + 1.0 ) / 2.0; + uvscreen.y = 1.0 - uvscreen.y; + + float obj_test = prepassUncondition( prepassTex, uvscreen).w * preBias; + float depth = tex2D(depthBuffer,uvscreen).r; + float front = tex2D(frontBuffer,uvscreen).r; + + if (depth <= front) + return float4(0,0,0,0); + else if ( obj_test < depth ) + depth = obj_test; + if ( front >= 0.0) + depth -= front; + + float diff = 1.0; + float3 col = fogColor.rgb; + if (textured != 0.0) + { + float2 offset = viewpoint + ((-0.5 + (texscale * uvscreen)) * numtiles); + + float2 mod1 = tex2D(density,(offset + (modspeed.xy*accumTime))).rg; + float2 mod2= tex2D(density,(offset + (modspeed.zw*accumTime))).rg; + diff = (mod2.r + mod1.r) * modstrength; + col *= (2.0 - ((mod1.g + mod2.g) * fadesize))/2.0; + } + + col *= ambientColor; + + float4 resultColor = float4(col, 1.0 - saturate(exp(-fogDensity * depth * diff * fadesize))); + + return hdrEncode(resultColor); +} diff --git a/Templates/Empty/game/shaders/common/VolumetricFog/VFogPreP.hlsl b/Templates/Empty/game/shaders/common/VolumetricFog/VFogPreP.hlsl new file mode 100644 index 000000000..bb06f5f7c --- /dev/null +++ b/Templates/Empty/game/shaders/common/VolumetricFog/VFogPreP.hlsl @@ -0,0 +1,39 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2012 GarageGames, LLC +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- + +// Volumetric Fog prepass pixel shader V1.00 + +struct ConnectData +{ + float4 hpos : POSITION; + float4 pos : TEXCOORD0; +}; + +float4 main( ConnectData IN ) : COLOR0 +{ + float OUT; + + clip( IN.pos.w ); + OUT = IN.pos.w; + + return float4(OUT,0,0,1); +} diff --git a/Templates/Empty/game/shaders/common/VolumetricFog/VFogPreV.hlsl b/Templates/Empty/game/shaders/common/VolumetricFog/VFogPreV.hlsl new file mode 100644 index 000000000..2d13cdf01 --- /dev/null +++ b/Templates/Empty/game/shaders/common/VolumetricFog/VFogPreV.hlsl @@ -0,0 +1,46 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2012 GarageGames, LLC +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- + +// Volumetric Fog prepass vertex shader V1.00 + +#include "shaders/common/hlslstructs.h" + +struct ConnectData +{ + float4 hpos : POSITION; + float4 pos : TEXCOORD0; +}; + +uniform float4x4 modelView; + +ConnectData main( VertexIn_P IN) +{ + ConnectData OUT; + + float4 inPos = IN.pos; + inPos.w = 1.0; + + OUT.hpos = mul( modelView, inPos ); + OUT.pos = OUT.hpos; + + return OUT; +} diff --git a/Templates/Empty/game/shaders/common/VolumetricFog/VFogRefl.hlsl b/Templates/Empty/game/shaders/common/VolumetricFog/VFogRefl.hlsl new file mode 100644 index 000000000..87226a1ac --- /dev/null +++ b/Templates/Empty/game/shaders/common/VolumetricFog/VFogRefl.hlsl @@ -0,0 +1,36 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2012 GarageGames, LLC +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- + +uniform float4 fogColor; +uniform float fogDensity; +uniform float reflStrength; + +struct ConnectData +{ + float4 hpos : POSITION; + float4 pos : TEXCOORD0; +}; + +float4 main( ConnectData IN ) : COLOR0 +{ + return float4(fogColor.rgb,saturate(fogDensity*reflStrength)); +} diff --git a/Templates/Empty/game/shaders/common/VolumetricFog/VFogV.hlsl b/Templates/Empty/game/shaders/common/VolumetricFog/VFogV.hlsl new file mode 100644 index 000000000..7f86802b5 --- /dev/null +++ b/Templates/Empty/game/shaders/common/VolumetricFog/VFogV.hlsl @@ -0,0 +1,45 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2012 GarageGames, LLC +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- + +// Volumetric Fog final vertex shader V1.00 + +#include "shaders/common/hlslstructs.h" + +struct ConnectData +{ + float4 hpos : POSITION; + float4 htpos : TEXCOORD0; + float2 uv0 : TEXCOORD1; +}; + +uniform float4x4 modelView; + +ConnectData main( VertexIn_PNT IN) +{ + ConnectData OUT; + + OUT.hpos = mul(modelView, IN.pos); + OUT.htpos = OUT.hpos; + OUT.uv0 = IN.uv0; + + return OUT; +} diff --git a/Templates/Empty/game/shaders/common/VolumetricFog/gl/VFogP.glsl b/Templates/Empty/game/shaders/common/VolumetricFog/gl/VFogP.glsl new file mode 100644 index 000000000..7895d9e2d --- /dev/null +++ b/Templates/Empty/game/shaders/common/VolumetricFog/gl/VFogP.glsl @@ -0,0 +1,87 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2012 GarageGames, LLC +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- + +#include "../../gl/hlslCompat.glsl" +#include "shadergen:/autogenConditioners.h" +#include "../../gl/torque.glsl" + +uniform sampler2D prepassTex; +uniform sampler2D depthBuffer; +uniform sampler2D frontBuffer; +uniform sampler2D density; + +uniform float accumTime; +uniform vec4 fogColor; +uniform float fogDensity; +uniform float preBias; +uniform float textured; +uniform float modstrength; +uniform vec4 modspeed;//xy speed layer 1, zw speed layer 2 +uniform vec2 viewpoint; +uniform vec2 texscale; +uniform vec3 ambientColor; +uniform float numtiles; +uniform float fadesize; +uniform vec2 PixelSize; + +in vec4 _hpos; +#define IN_hpos _hpos +out vec4 OUT_col; + +void main() +{ + vec2 uvscreen=((IN_hpos.xy/IN_hpos.w) + 1.0 ) / 2.0; + uvscreen.y = 1.0 - uvscreen.y; + + float obj_test = prepassUncondition( prepassTex, uvscreen).w * preBias; + float depth = tex2D(depthBuffer,uvscreen).r; + float front = tex2D(frontBuffer,uvscreen).r; + + if (depth <= front) + { + OUT_col = vec4(0,0,0,0); + return; + } + + else if ( obj_test < depth ) + depth = obj_test; + if ( front >= 0.0) + depth -= front; + + float diff = 1.0; + vec3 col = fogColor.rgb; + if (textured != 0.0) + { + vec2 offset = viewpoint + ((-0.5 + (texscale * uvscreen)) * numtiles); + + vec2 mod1 = tex2D(density,(offset + (modspeed.xy*accumTime))).rg; + vec2 mod2= tex2D(density,(offset + (modspeed.zw*accumTime))).rg; + diff = (mod2.r + mod1.r) * modstrength; + col *= (2.0 - ((mod1.g + mod2.g) * fadesize))/2.0; + } + + col *= ambientColor; + + vec4 returnColor = vec4(col, 1.0 - saturate(exp(-fogDensity * depth * diff * fadesize))); + + OUT_col = hdrEncode(returnColor); +} diff --git a/Templates/Empty/game/shaders/common/VolumetricFog/gl/VFogPreP.glsl b/Templates/Empty/game/shaders/common/VolumetricFog/gl/VFogPreP.glsl new file mode 100644 index 000000000..017ea6ef8 --- /dev/null +++ b/Templates/Empty/game/shaders/common/VolumetricFog/gl/VFogPreP.glsl @@ -0,0 +1,37 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2012 GarageGames, LLC +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- + +#include "../../gl/hlslCompat.glsl" + +in vec4 _hpos; +#define IN_hpos _hpos + +out vec4 OUT_col; + +void main() +{ + float OUT; + clip( IN_hpos.w ); + OUT = IN_hpos.w; + + OUT_col = vec4(OUT,0,0,1); +} diff --git a/Templates/Empty/game/shaders/common/VolumetricFog/gl/VFogPreV.glsl b/Templates/Empty/game/shaders/common/VolumetricFog/gl/VFogPreV.glsl new file mode 100644 index 000000000..2f2a1318a --- /dev/null +++ b/Templates/Empty/game/shaders/common/VolumetricFog/gl/VFogPreV.glsl @@ -0,0 +1,42 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2012 GarageGames, LLC +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- + +#include "../../gl/hlslCompat.glsl" + +in vec4 vPosition; +#define IN_position vPosition + +out vec4 _hpos; +#define OUT_hpos _hpos + +uniform mat4 modelView; + +void main() +{ + vec4 inPos = IN_position; + inPos.w = 1.0; + + OUT_hpos = tMul( modelView, inPos ); + + gl_Position = OUT_hpos; + correctSSP(gl_Position); +} diff --git a/Templates/Empty/game/shaders/common/VolumetricFog/gl/VFogRefl.glsl b/Templates/Empty/game/shaders/common/VolumetricFog/gl/VFogRefl.glsl new file mode 100644 index 000000000..78e149fbf --- /dev/null +++ b/Templates/Empty/game/shaders/common/VolumetricFog/gl/VFogRefl.glsl @@ -0,0 +1,33 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2012 GarageGames, LLC +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- + +#include "../../gl/hlslCompat.glsl" + +uniform vec4 fogColor; +uniform float fogDensity; +uniform float reflStrength; +out vec4 OUT_col; + +void main() +{ + OUT_col = vec4(fogColor.rgb,saturate(fogDensity*reflStrength)); +} diff --git a/Templates/Empty/game/shaders/common/VolumetricFog/gl/VFogV.glsl b/Templates/Empty/game/shaders/common/VolumetricFog/gl/VFogV.glsl new file mode 100644 index 000000000..57b3ba87e --- /dev/null +++ b/Templates/Empty/game/shaders/common/VolumetricFog/gl/VFogV.glsl @@ -0,0 +1,38 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2012 GarageGames, LLC +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- + +#include "../../gl/hlslCompat.glsl" + +in vec4 vPosition; +#define IN_position vPosition + +out vec4 _hpos; +#define OUT_hpos _hpos + +uniform mat4 modelView; + +void main() +{ + OUT_hpos = tMul(modelView, IN_position); + gl_Position = OUT_hpos; + correctSSP(gl_Position); +} diff --git a/Templates/Empty/game/shaders/common/postFx/VolFogGlowP.hlsl b/Templates/Empty/game/shaders/common/postFx/VolFogGlowP.hlsl new file mode 100644 index 000000000..8a61b5928 --- /dev/null +++ b/Templates/Empty/game/shaders/common/postFx/VolFogGlowP.hlsl @@ -0,0 +1,74 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2014 R.G.S. - Richards Game Studio, the Netherlands +// http://www.richardsgamestudio.com/ +// +// If you find this code useful or you are feeling particularly generous I +// would ask that you please go to http://www.richardsgamestudio.com/ then +// choose Donations from the menu on the left side and make a donation to +// Richards Game Studio. It will be highly appreciated. +// +// The MIT License: +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- + +// Volumetric Fog Glow postFx pixel shader V1.00 + +#include "./postFx.hlsl" + +uniform sampler2D diffuseMap : register(S0); +uniform float strength; + +struct VertToPix +{ + float4 hpos : POSITION; + + float2 uv0 : TEXCOORD0; + float2 uv1 : TEXCOORD1; + float2 uv2 : TEXCOORD2; + float2 uv3 : TEXCOORD3; + + float2 uv4 : TEXCOORD4; + float2 uv5 : TEXCOORD5; + float2 uv6 : TEXCOORD6; + float2 uv7 : TEXCOORD7; +}; + +float4 main( VertToPix IN ) : COLOR +{ + float4 kernel = float4( 0.175, 0.275, 0.375, 0.475 ) * strength; + + float4 OUT = 0; + OUT += tex2D( diffuseMap, IN.uv0 ) * kernel.x; + OUT += tex2D( diffuseMap, IN.uv1 ) * kernel.y; + OUT += tex2D( diffuseMap, IN.uv2 ) * kernel.z; + OUT += tex2D( diffuseMap, IN.uv3 ) * kernel.w; + + OUT += tex2D( diffuseMap, IN.uv4 ) * kernel.x; + OUT += tex2D( diffuseMap, IN.uv5 ) * kernel.y; + OUT += tex2D( diffuseMap, IN.uv6 ) * kernel.z; + OUT += tex2D( diffuseMap, IN.uv7 ) * kernel.w; + + // Calculate a lumenance value in the alpha so we + // can use alpha test to save fillrate. + float3 rgb2lum = float3( 0.30, 0.59, 0.11 ); + OUT.a = dot( OUT.rgb, rgb2lum ); + + return OUT; +} diff --git a/Templates/Empty/game/shaders/common/postFx/gl/VolFogGlowP.glsl b/Templates/Empty/game/shaders/common/postFx/gl/VolFogGlowP.glsl new file mode 100644 index 000000000..01b072dd9 --- /dev/null +++ b/Templates/Empty/game/shaders/common/postFx/gl/VolFogGlowP.glsl @@ -0,0 +1,67 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2014 R.G.S. - Richards Game Studio, the Netherlands +// http://www.richardsgamestudio.com/ +// +// If you find this code useful or you are feeling particularly generous I +// would ask that you please go to http://www.richardsgamestudio.com/ then +// choose Donations from the menu on the left side and make a donation to +// Richards Game Studio. It will be highly appreciated. +// +// The MIT License: +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- + +// Volumetric Fog Glow postFx pixel shader V1.00 + +uniform sampler2D diffuseMap; +uniform float strength; + +out vec4 OUT_col; + +in vec2 uv0; +in vec2 uv1; +in vec2 uv2; +in vec2 uv3; + +in vec2 uv4; +in vec2 uv5; +in vec2 uv6; +in vec2 uv7; + +void main() +{ + vec4 kernel = vec4( 0.175, 0.275, 0.375, 0.475 ) * strength; + + OUT_col = vec4(0); + OUT_col += texture( diffuseMap, uv0 ) * kernel.x; + OUT_col += texture( diffuseMap, uv1 ) * kernel.y; + OUT_col += texture( diffuseMap, uv2 ) * kernel.z; + OUT_col += texture( diffuseMap, uv3 ) * kernel.w; + + OUT_col += texture( diffuseMap, uv4 ) * kernel.x; + OUT_col += texture( diffuseMap, uv5 ) * kernel.y; + OUT_col += texture( diffuseMap, uv6 ) * kernel.z; + OUT_col += texture( diffuseMap, uv7 ) * kernel.w; + + // Calculate a lumenance value in the alpha so we + // can use alpha test to save fillrate. + vec3 rgb2lum = vec3( 0.30, 0.59, 0.11 ); + OUT_col.a = dot( OUT_col.rgb, rgb2lum ); +} diff --git a/Templates/Empty/game/tools/classIcons/VolumetricFog.png b/Templates/Empty/game/tools/classIcons/VolumetricFog.png new file mode 100644 index 0000000000000000000000000000000000000000..5dc516cb53d99e0ae0d125507d6d95c9a2942107 GIT binary patch literal 3642 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 n;hV-7aDAP}zDS literal 0 HcmV?d00001 diff --git a/Templates/Full/game/art/environment/FogMod_light.dds b/Templates/Full/game/art/environment/FogMod_light.dds new file mode 100644 index 0000000000000000000000000000000000000000..d726795fa1de24d57dc54259c7c57f984e3d6704 GIT binary patch literal 131200 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%0DDkgQ;%|w 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൏u$o87pO_E*IzlWcQhKlOkZMNW<&fqwN}9Y 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 bRO-0LHU0XoSI+pJx4tj`BkL3><($#K7P0$f literal 0 HcmV?d00001 diff --git a/Templates/Full/game/art/environment/Fog_Cube.DAE b/Templates/Full/game/art/environment/Fog_Cube.DAE new file mode 100644 index 000000000..34cad9f48 --- /dev/null +++ b/Templates/Full/game/art/environment/Fog_Cube.DAE @@ -0,0 +1,177 @@ + + + + + Richard + OpenCOLLADA for 3ds Max; Version: 1.4.1; Revision: exported; Platform: x64; Configuration: Release_Max2011_static + file:///G:/Documents%20and%20Settings/Richard/Mijn%20documenten/3dsmax/scenes/FogVolumes.max + + 2014-08-16T10:10:23 + 2014-08-16T10:10:23 + + Z_UP + + + + + + + + 0 0 0 1 + + + 0.588 0.588 0.588 1 + + + 0.588 0.588 0.588 1 + + + 0.9 0.9 0.9 1 + + + 0 + + + 0 0 0 1 + + + 1 1 1 1 + + + 1 + + + + + + + + 0 + 0 + 0 + 1.5 + 0 + 3 + 1 + 0 + + + 1 + 1 + 0 + 0.1 + 0 + + + + + + + + + + + + + + + -0.85 -1 -0.85 0.85 -0.85 -1 -1 0.85 -0.85 0.85 0.85 -1 -0.85 -1 0.85 1 -0.85 0.85 -1 0.85 0.85 0.85 1 0.85 -1 -0.85 -0.85 -0.85 -0.85 -1 1 -0.85 -0.85 0.85 -1 -0.85 -0.85 1 -0.85 -0.85 0.85 -1 0.85 1 -0.85 1 0.85 -0.85 -0.85 -0.85 1 -1 -0.85 0.85 0.85 -0.85 1 0.85 -1 0.85 -0.85 0.85 1 -0.85 1 0.85 0.85 0.85 1 1 0.85 0.85 + + + + + + + + + + -0.341586 -0.341586 -0.8755786 -0.341586 0.341586 -0.8755788 0.341586 0.341586 -0.8755788 0.341586 -0.341586 -0.8755788 -0.341586 -0.341586 0.8755786 0.341586 -0.341586 0.8755788 0.341586 0.341586 0.8755788 -0.341586 0.341586 0.8755788 -0.341586 -0.8755786 -0.341586 0.341586 -0.8755788 -0.341586 0.341586 -0.8755786 0.341586 -0.341586 -0.8755788 0.341586 0.8755786 -0.341586 -0.341586 0.8755788 0.341586 -0.341586 0.8755786 0.341586 0.341586 0.8755788 -0.341586 0.341586 0.341586 0.8755786 -0.341586 -0.341586 0.8755788 -0.341586 -0.341586 0.8755786 0.341586 0.341586 0.8755788 0.341586 -0.8755786 0.341586 -0.341586 -0.8755788 -0.341586 -0.341586 -0.8755786 -0.341586 0.341586 -0.8755788 0.341586 0.341586 + + + + + + + + + + 0 0 0 1 0 0 0 1 0 1 1 0 0 0 0 1 0 0 0 1 0 1 1 0 0 0 0 1 0 0 0 1 0 1 1 0 0.07542458 0.07542461 4.99755e-4 0.07542479 0.07542461 4.99547e-4 0.07542455 0.07542461 4.99755e-4 0.07542461 0.9245752 4.99547e-4 0.07542458 0.9245754 4.99755e-4 0.07542458 0.9245754 0.9995003 0.07542455 0.9245754 4.99755e-4 0.07542455 0.9245754 0.9995003 0.9245752 0.07542461 4.99576e-4 0.9245754 0.07542479 4.99547e-4 0.07542458 0.07542461 0.9995003 0.9245752 0.07542461 4.99576e-4 0.9245752 0.07542461 0.9995004 0.9245752 0.9245754 4.99547e-4 0.07542455 0.07542461 0.9995003 0.9245752 0.07542461 0.9995004 0.07542461 0.07542479 0.9995005 0.9245752 0.9245754 4.99576e-4 0.9245752 0.07542461 0.9995005 0.9245752 0.9245754 4.99576e-4 0.07542479 0.9245754 0.9995005 0.9245752 0.9245754 0.9995004 0.9245754 0.9245752 0.9995005 0.9245752 0.9245754 0.9995004 0.9995003 0.07542461 0.07542458 0.9245752 4.99547e-4 0.07542461 0.9245752 4.99547e-4 0.07542461 0.9995003 0.07542461 0.07542458 0.9995003 0.07542461 0.9245754 0.9245752 4.99547e-4 0.9245754 0.9245752 4.99547e-4 0.9245754 0.9995003 0.07542461 0.9245754 0.9995003 0.9245754 0.07542458 0.9245752 0.9995005 0.07542461 0.9995003 0.9245754 0.07542458 0.9245752 0.9995005 0.07542461 0.9995003 0.9245754 0.9245754 0.9245752 0.9995005 0.9245754 0.9995003 0.9245754 0.9245754 0.9245752 0.9995005 0.9245754 0.9995004 0.07542482 0.07542461 0.9995003 0.9245754 0.07542461 0.9245752 0.9995004 0.07542461 0.07542455 0.9995003 0.07542461 4.99606e-4 0.9245752 0.07542461 4.99725e-4 0.07542458 0.07542461 0.07542479 4.99576e-4 0.07542461 0.9245754 4.99755e-4 0.07542461 0.07542458 4.99755e-4 0.9245754 0.9245752 4.99576e-4 0.9245754 0.9995003 0.07542458 0.9245754 0.9995004 0.9245752 0.9245754 0.9245754 0.9995003 0.9245754 0.07542482 0.9995004 0.9245754 4.99755e-4 0.9245754 0.9245754 4.99576e-4 0.07542482 0.9245754 0.9995003 0.07542461 0.07542458 0.9995003 0.9245754 0.07542458 0.9995003 0.9245754 0.07542458 0.9995003 0.07542461 0.07542458 0.9995003 0.07542461 0.9245754 0.9995003 0.9245754 0.9245754 0.9995003 0.07542461 0.9245754 0.9995003 0.9245754 0.9245754 + + + + + + + + + + -0.8644259 0.01841655 0.3300502 -0.8715108 -0.05526615 0.3184382 -0.8644259 0.01841664 -0.3300501 -0.8715108 -0.05526611 -0.3184382 0.8738725 -0.06754867 0.3145678 0.8597026 -0.006149054 -0.3377912 0.8738725 -0.06754874 -0.3145678 0.8597026 -0.006148929 0.3377911 0.883319 -0.2990854 -0.116681 0.8478944 0.3571441 -0.06756432 0.8597026 0.3377913 0.00614921 0.883319 -0.2990854 0.116681 0.2990854 0.883319 -0.116681 -0.3571441 0.8478944 -0.06756432 -0.3377913 0.8597026 0.00614921 0.2990854 0.883319 0.116681 -0.883319 0.2990854 -0.116681 -0.8478944 -0.3571441 -0.06756432 -0.8597026 -0.3377913 0.00614921 -0.883319 0.2990854 0.116681 -0.2990854 -0.883319 -0.116681 0.3571441 -0.8478944 -0.06756432 0.3377913 -0.8597026 0.00614921 -0.2990854 -0.883319 0.116681 0.8360862 -0.3764972 0.1289794 0.7071068 -0.7071068 0 0.7071068 0.7071068 0 0.3764972 0.8360862 0.1289794 -0.3764972 -0.8360862 0.1289794 -0.7071068 -0.7071068 0 -0.7071068 0.7071068 0 -0.8360862 0.3764972 0.1289794 0.8360862 -0.3764971 -0.1289794 0.7071068 -0.7071068 0 0.3764971 0.8360862 -0.1289794 0.7071068 0.7071068 0 -0.3764971 -0.8360862 -0.1289794 -0.7071068 -0.7071068 0 -0.8360862 0.3764971 -0.1289794 -0.7071068 0.7071068 0 -0.376497 0.1289792 0.8360862 -0.3764973 -0.1289798 0.8360861 -0.8833191 -0.2990855 0.1166808 -0.883319 0.2990853 -0.1166812 -0.3764971 0.1289794 -0.8360862 -0.3764972 -0.1289795 -0.8360862 -0.8833191 -0.2990855 -0.1166807 -0.883319 0.2990853 0.1166812 0.883319 -0.2990853 0.1166812 0.8833191 0.2990855 -0.1166807 0.3764971 0.1289797 -0.8360862 0.3764971 -0.1289793 -0.8360862 0.883319 -0.2990853 -0.1166811 0.8833191 0.2990855 0.1166808 0.3764972 0.1289799 0.8360861 0.3764971 -0.128979 0.8360862 0.3764972 0.8360862 0.1289794 0.3764971 0.8360862 -0.1289794 0.8360862 -0.3764971 -0.1289794 0.8360862 -0.3764972 0.1289794 -0.8360862 0.3764972 0.1289794 -0.8360862 0.3764971 -0.1289794 -0.3764972 -0.8360862 0.1289794 -0.3764971 -0.8360862 -0.1289794 + + + + + + + + + + 0.1043954 -0.9396398 0.3258505 -0.06496345 -0.9379679 -0.3405817 0.1043953 -0.9396398 -0.3258505 -0.06496349 -0.937968 0.3405817 0.05187585 -0.9370471 -0.3453283 -0.1307439 -0.939827 -0.3156443 0.05187577 -0.9370471 0.3453283 -0.1307438 -0.939827 0.3156443 0 0.3634471 -0.9316148 -0.196368 0.2889368 -0.9369926 0.1307441 -0.3156442 -0.939827 0 -0.3634471 -0.9316148 -0.3634471 0 -0.9316148 -0.2889368 -0.196368 -0.9369926 0.3156442 0.1307441 -0.939827 0.3634471 0 -0.9316148 0 -0.3634471 -0.9316148 0.196368 -0.2889368 -0.9369926 -0.1307441 0.3156442 -0.939827 0 0.3634471 -0.9316148 0.3634471 0 -0.9316148 0.2889368 0.196368 -0.9369926 -0.3156442 -0.1307441 -0.939827 -0.3634471 0 -0.9316148 0.2608475 0.2608475 -0.9294714 0.6191276 0.6191276 -0.4830755 -0.6191276 0.6191276 -0.4830755 -0.2608475 0.2608475 -0.9294714 0.2608475 -0.2608475 -0.9294714 0.6191276 -0.6191276 -0.4830755 -0.6191276 -0.6191276 -0.4830755 -0.2608475 -0.2608475 -0.9294714 -0.2608475 -0.2608475 -0.9294714 -0.6191276 -0.6191276 -0.4830755 0.2608475 -0.2608475 -0.9294714 0.6191276 -0.6191276 -0.4830755 -0.2608475 0.2608475 -0.9294714 -0.6191276 0.6191276 -0.4830755 0.2608475 0.2608475 -0.9294714 0.6191276 0.6191276 -0.4830755 0.2608476 -0.9294715 0.2608473 -0.2608474 -0.9294714 -0.2608479 1.81809e-7 -0.363447 -0.9316149 2.27262e-7 -0.3634472 -0.9316148 0.2608475 -0.9294714 -0.2608475 -0.2608475 -0.9294714 0.2608477 2.72714e-7 -0.363447 0.9316149 2.72714e-7 -0.3634472 0.9316148 2.72714e-7 -0.3634472 -0.9316148 2.72714e-7 -0.363447 -0.9316149 -0.2608474 -0.9294714 -0.2608478 0.2608476 -0.9294714 0.2608474 1.81809e-7 -0.3634472 0.9316148 2.27262e-7 -0.3634471 0.9316149 -0.2608473 -0.9294714 0.260848 0.2608477 -0.9294715 -0.2608472 -0.2608475 0.2608475 -0.9294714 0.2608475 -0.2608475 -0.9294714 -0.2608475 -0.2608475 -0.9294714 0.2608475 0.2608475 -0.9294714 -0.2608475 -0.2608475 -0.9294714 0.2608475 0.2608475 -0.9294714 0.2608475 -0.2608475 -0.9294714 -0.2608475 0.2608475 -0.9294714 + + + + + + + + + + + + + + + + + +

9 0 21 0 13 1 25 1 3 2 15 2 3 2 15 2 1 3 13 3 9 0 21 0 16 4 28 4 18 5 30 5 22 6 34 6 22 6 34 6 20 7 32 7 16 4 28 4 0 8 12 8 11 9 23 9 19 10 31 10 19 10 31 10 4 11 16 11 0 8 12 8 10 12 22 12 15 13 27 13 23 14 35 14 23 14 35 14 5 15 17 15 10 12 22 12 14 16 26 16 12 17 24 17 21 18 33 18 21 18 33 18 7 19 19 19 14 16 26 16 2 20 14 20 8 21 20 21 17 22 29 22 17 22 29 22 6 23 18 23 2 20 14 20 0 8 36 24 8 21 20 21 9 0 37 25 1 3 38 26 10 12 39 27 11 9 23 9 2 20 40 28 12 17 24 17 13 1 41 29 3 2 42 30 14 16 43 31 15 13 27 13 4 11 44 32 16 4 45 33 17 22 29 22 5 15 46 34 18 5 47 35 19 10 31 10 6 23 48 36 20 7 49 37 21 18 33 18 7 19 50 38 22 6 51 39 23 14 35 14 9 0 21 0 8 21 52 40 2 20 53 41 2 20 53 41 13 1 25 1 9 0 21 0 13 1 25 1 12 17 54 42 14 16 55 43 14 16 55 43 3 2 15 2 13 1 25 1 3 2 15 2 15 13 56 44 10 12 57 45 10 12 57 45 1 3 13 3 3 2 15 2 1 3 13 3 11 9 58 46 0 8 59 47 0 8 59 47 9 0 21 0 1 3 13 3 16 4 28 4 4 11 60 48 19 10 61 49 19 10 61 49 18 5 30 5 16 4 28 4 18 5 30 5 5 15 62 50 23 14 63 51 23 14 63 51 22 6 34 6 18 5 30 5 22 6 34 6 7 19 64 52 21 18 65 53 21 18 65 53 20 7 32 7 22 6 34 6 20 7 32 7 6 23 66 54 17 22 67 55 17 22 67 55 16 4 28 4 20 7 32 7 11 9 23 9 10 12 68 56 5 15 69 57 5 15 69 57 19 10 31 10 11 9 23 9 4 11 70 58 17 22 29 22 8 21 20 21 8 21 20 21 0 8 71 59 4 11 70 58 15 13 27 13 14 16 72 60 7 19 73 61 7 19 73 61 23 14 35 14 15 13 27 13 12 17 24 17 2 20 74 62 6 23 75 63 6 23 75 63 21 18 33 18 12 17 24 17

+
+
+
+
+ + + + + 0 0 0 + + + + + + + + + + + + + + + + + + + + 1 + 1 + 1 + 1 + + + + + + + + +
\ No newline at end of file diff --git a/Templates/Full/game/art/environment/Fog_Cube.cs b/Templates/Full/game/art/environment/Fog_Cube.cs new file mode 100644 index 000000000..3c686032c --- /dev/null +++ b/Templates/Full/game/art/environment/Fog_Cube.cs @@ -0,0 +1,8 @@ + +singleton TSShapeConstructor(Fog_CubeDAE) +{ + baseShape = "./Fog_Cube.DAE"; + lodType = "TrailingNumber"; + neverImport = "env*"; + loadLights = "0"; +}; diff --git a/Templates/Full/game/art/environment/LightVolume_Sphere.DAE b/Templates/Full/game/art/environment/LightVolume_Sphere.DAE new file mode 100644 index 000000000..81c93d8e0 --- /dev/null +++ b/Templates/Full/game/art/environment/LightVolume_Sphere.DAE @@ -0,0 +1,423 @@ + + + + + Richard + OpenCOLLADA for 3ds Max; Version: 1.4.1; Revision: exported; Platform: x64; Configuration: Release_Max2011_static + file:///G:/Documents%20and%20Settings/Richard/Mijn%20documenten/3dsmax/scenes/lightfog.max + + 2014-08-22T22:51:35 + 2014-08-22T22:51:35 + + Z_UP + + + + + + + + 0 0 0 1 + + + 0.588 0.588 0.588 1 + + + 0.588 0.588 0.588 1 + + + 0.9 0.9 0.9 1 + + + 0 + + + 0 0 0 1 + + + 1 1 1 1 + + + 1 + + + + + + + + 0 + 0 + 0 + 1.5 + 0 + 3 + 1 + 0 + + + 1 + 1 + 0 + 0.1 + 0 + + + + + + + + + + + + + + + 0 0 5 -9.48283e-8 2.169419 4.504844 -0.9412758 1.954579 4.504844 -1.69612 1.35261 4.504844 -2.115027 0.4827411 4.504844 -2.115027 -0.482741 4.504844 -1.69612 -1.35261 4.504844 -0.9412759 -1.954579 4.504844 2.58701e-8 -2.169419 4.504844 0.9412759 -1.954579 4.504844 1.696121 -1.35261 4.504844 2.115027 -0.4827399 4.504844 2.115026 0.4827427 4.504844 1.696119 1.352612 4.504844 0.9412734 1.95458 4.504844 -1.70875e-7 3.909158 3.117449 -1.69612 3.522029 3.117449 -3.056303 2.43732 3.117449 -3.811147 0.8698694 3.117449 -3.811147 -0.8698691 3.117449 -3.056303 -2.43732 3.117449 -1.696121 -3.522029 3.117449 4.66162e-8 -3.909158 3.117449 1.696121 -3.522029 3.117449 3.056304 -2.437319 3.117449 3.811147 -0.8698672 3.117449 3.811146 0.8698722 3.117449 3.0563 2.437323 3.117449 1.696116 3.522031 3.117449 -2.13077e-7 4.87464 1.112604 -2.115027 4.391898 1.112604 -3.811147 3.039288 1.112604 -4.752422 1.084709 1.112604 -4.752422 -1.084709 1.112604 -3.811147 -3.039288 1.112604 -2.115028 -4.391898 1.112604 5.81295e-8 -4.87464 1.112604 2.115028 -4.391898 1.112604 3.811148 -3.039287 1.112604 4.752423 -1.084707 1.112604 4.752421 1.084713 1.112604 3.811144 3.039291 1.112604 2.115022 4.391901 1.112604 -2.13077e-7 4.87464 -1.112605 -2.115027 4.391898 -1.112605 -3.811147 3.039288 -1.112605 -4.752422 1.084709 -1.112605 -4.752422 -1.084709 -1.112605 -3.811147 -3.039288 -1.112605 -2.115028 -4.391898 -1.112605 5.81295e-8 -4.87464 -1.112605 2.115028 -4.391898 -1.112605 3.811148 -3.039287 -1.112605 4.752423 -1.084707 -1.112605 4.752421 1.084713 -1.112605 3.811144 3.039291 -1.112605 2.115022 4.391901 -1.112605 -1.70875e-7 3.909157 -3.11745 -1.69612 3.522028 -3.11745 -3.056302 2.437319 -3.11745 -3.811146 0.8698692 -3.11745 -3.811146 -0.869869 -3.11745 -3.056302 -2.437319 -3.11745 -1.69612 -3.522028 -3.11745 4.66162e-8 -3.909157 -3.11745 1.69612 -3.522028 -3.11745 3.056303 -2.437318 -3.11745 3.811146 -0.8698671 -3.11745 3.811145 0.8698721 -3.11745 3.0563 2.437322 -3.11745 1.696116 3.52203 -3.11745 -9.48283e-8 2.169418 -4.504845 -0.9412755 1.954578 -4.504845 -1.696119 1.35261 -4.504845 -2.115026 0.4827409 -4.504845 -2.115026 -0.4827408 -4.504845 -1.69612 -1.35261 -4.504845 -0.9412756 -1.954578 -4.504845 2.58701e-8 -2.169418 -4.504845 0.9412756 -1.954578 -4.504845 1.69612 -1.352609 -4.504845 2.115026 -0.4827397 -4.504845 2.115026 0.4827425 -4.504845 1.696118 1.352612 -4.504845 0.9412731 1.954579 -4.504845 0 0 -5 + + + + + + + + + + 3.34297e-8 3.12427e-8 1 -1.46401e-7 0.4589442 0.8884651 -0.1991285 0.4134944 0.888465 -0.358817 0.286147 0.8884651 -0.4474375 0.1021247 0.888465 -0.4474375 -0.1021246 0.8884651 -0.358817 -0.286147 0.888465 -0.1991284 -0.4134944 0.8884651 -4.96273e-9 -0.4589442 0.888465 0.1991285 -0.4134944 0.888465 0.3588171 -0.2861469 0.888465 0.4474375 -0.1021244 0.8884651 0.4474374 0.102125 0.888465 0.3588168 0.2861473 0.8884651 0.1991281 0.4134945 0.8884651 -2.38195e-7 0.7935484 0.6085071 -0.3443078 0.7149624 0.6085071 -0.6204212 0.4947692 0.6085072 -0.7736526 0.1765811 0.6085071 -0.7736526 -0.176581 0.608507 -0.6204212 -0.4947692 0.6085072 -0.3443078 -0.7149624 0.6085071 -1.26699e-8 -0.7935485 0.6085071 0.3443078 -0.7149624 0.6085072 0.6204213 -0.4947691 0.6085071 0.7736526 -0.1765807 0.6085072 0.7736524 0.1765818 0.6085072 0.6204207 0.4947699 0.608507 0.3443072 0.7149627 0.6085071 -2.56849e-7 0.9764001 0.2159697 -0.4236442 0.879706 0.2159697 -0.7633804 0.6087754 0.2159697 -0.9519197 0.2172694 0.2159697 -0.9519197 -0.2172693 0.2159698 -0.7633804 -0.6087753 0.2159698 -0.4236441 -0.8797061 0.2159698 2.56849e-9 -0.9764001 0.2159697 0.4236443 -0.879706 0.2159698 0.7633805 -0.6087751 0.2159698 0.9519198 -0.2172689 0.2159698 0.9519196 0.2172702 0.2159698 0.7633796 0.6087762 0.2159697 0.4236434 0.8797064 0.2159697 -2.56849e-7 0.9764 -0.2159699 -0.4236442 0.8797059 -0.2159699 -0.7633803 0.6087754 -0.2159699 -0.9519196 0.2172694 -0.2159698 -0.9519197 -0.2172693 -0.2159699 -0.7633804 -0.6087753 -0.2159699 -0.4236442 -0.879706 -0.2159699 2.31164e-8 -0.9764 -0.2159699 0.4236442 -0.8797059 -0.2159699 0.7633805 -0.6087751 -0.2159699 0.9519197 -0.2172689 -0.2159699 0.9519195 0.2172701 -0.2159699 0.7633796 0.6087762 -0.2159699 0.4236434 0.8797063 -0.2159699 -1.95117e-7 0.7935483 -0.6085073 -0.3443078 0.7149623 -0.6085073 -0.6204211 0.4947692 -0.6085073 -0.7736524 0.1765811 -0.6085073 -0.7736524 -0.1765811 -0.6085073 -0.6204211 -0.4947692 -0.6085073 -0.3443078 -0.7149622 -0.6085073 1.77379e-8 -0.7935483 -0.6085073 0.3443078 -0.7149622 -0.6085073 0.6204212 -0.494769 -0.6085073 0.7736525 -0.1765806 -0.6085073 0.7736523 0.1765817 -0.6085073 0.6204206 0.4947698 -0.6085073 0.3443071 0.7149625 -0.6085073 -1.16624e-7 0.4589441 -0.8884652 -0.1991284 0.4134943 -0.8884652 -0.358817 0.2861468 -0.8884652 -0.4474374 0.1021247 -0.8884652 -0.4474373 -0.1021246 -0.8884652 -0.3588169 -0.2861468 -0.8884652 -0.1991284 -0.4134943 -0.8884652 -9.92546e-9 -0.4589441 -0.8884651 0.1991285 -0.4134943 -0.8884651 0.358817 -0.2861468 -0.8884652 0.4474374 -0.1021244 -0.8884651 0.4474373 0.102125 -0.8884652 0.3588167 0.2861473 -0.8884651 0.1991281 0.4134944 -0.8884652 2.59315e-8 -2.62439e-8 -1 + + + + + + + + + + -0.03571416 1 0.999001 3.79455e-8 0.8571429 0.999001 0.0714286 0.8571428 0.9990011 0.1428572 0.8571428 0.9990011 0.2142857 0.8571428 0.9990011 0.2857142 0.8571428 0.9990011 0.3571428 0.8571428 0.9990011 0.4285714 0.8571428 0.9990011 0.4999999 0.8571429 0.999001 0.5714285 0.8571429 0.999001 0.6428571 0.8571429 0.999001 0.7142857 0.8571429 0.999001 0.7857143 0.8571429 0.999001 0.857143 0.8571429 0.999001 0.9285716 0.8571429 0.999001 1 0.7142857 0.9990011 0.0714286 0.7142857 0.9990011 0.1428572 0.7142857 0.9990011 0.2142857 0.7142857 0.9990011 0.2857142 0.7142857 0.9990011 0.3571428 0.7142857 0.9990011 0.4285714 0.7142857 0.9990011 0.5 0.7142857 0.9990011 0.5714285 0.7142857 0.999001 0.6428571 0.7142857 0.999001 0.7142857 0.7142857 0.9990009 0.7857143 0.7142857 0.999001 0.857143 0.7142857 0.999001 0.9285716 0.7142857 0.999001 0.9999999 0.5714285 0.999001 0.0714286 0.5714285 0.999001 0.1428572 0.5714285 0.9990011 0.2142857 0.5714285 0.9990011 0.2857142 0.5714285 0.9990011 0.3571428 0.5714285 0.9990011 0.4285714 0.5714285 0.9990011 0.5 0.5714285 0.999001 0.5714285 0.5714285 0.999001 0.6428571 0.5714285 0.999001 0.7142857 0.5714285 0.9990009 0.7857143 0.5714285 0.9990009 0.8571429 0.5714285 0.999001 0.9285716 0.5714285 0.999001 0.9999999 0.4285714 0.999001 0.0714286 0.4285714 0.999001 0.1428572 0.4285714 0.9990011 0.2142857 0.4285714 0.9990011 0.2857142 0.4285714 0.9990011 0.3571428 0.4285714 0.9990011 0.4285714 0.4285714 0.9990011 0.5 0.4285714 0.999001 0.5714285 0.4285714 0.999001 0.6428571 0.4285714 0.999001 0.7142857 0.4285714 0.999001 0.7857143 0.4285714 0.999001 0.8571429 0.4285714 0.999001 0.9285716 0.4285714 0.999001 1 0.2857142 0.999001 0.0714286 0.2857142 0.9990011 0.1428572 0.2857142 0.9990011 0.2142857 0.2857142 0.9990011 0.2857142 0.2857143 0.9990011 0.3571428 0.2857143 0.9990011 0.4285714 0.2857142 0.9990011 0.5 0.2857142 0.999001 0.5714285 0.2857142 0.999001 0.6428571 0.2857142 0.999001 0.7142857 0.2857142 0.999001 0.7857143 0.2857142 0.999001 0.857143 0.2857142 0.999001 0.9285716 0.2857142 0.999001 3.79455e-8 0.1428571 0.999001 0.0714286 0.1428572 0.9990011 0.1428572 0.1428571 0.999001 0.2142857 0.1428572 0.9990011 0.2857142 0.1428572 0.9990011 0.3571428 0.1428572 0.9990011 0.4285714 0.1428572 0.9990011 0.4999999 0.1428571 0.999001 0.5714285 0.1428571 0.999001 0.6428571 0.1428571 0.999001 0.7142857 0.1428571 0.999001 0.7857143 0.1428571 0.999001 0.857143 0.1428571 0.999001 0.9285716 0.1428571 0.999001 -0.03571416 0 0.999001 0.03571432 1 0.999001 0.1071429 1 0.999001 0.1785714 1 0.999001 0.25 1 0.999001 0.3214285 1 0.999001 0.3928571 1 0.999001 0.4642856 1 0.999001 0.5357142 1 0.999001 0.6071428 1 0.999001 0.6785715 1 0.999001 0.75 1 0.999001 0.8214287 1 0.999001 0.8928573 1 0.999001 -0.07142836 0.8571429 0.999001 0 0.7142857 0.9990011 -0.07142836 0.8571429 0.999001 0 0.7142857 0.9990011 0 0.7142857 0.9990011 -5.96046e-8 0.5714285 0.999001 0 0.7142857 0.9990011 -5.96046e-8 0.5714285 0.999001 -5.96046e-8 0.4285714 0.999001 -5.96046e-8 0.5714285 0.999001 -5.96046e-8 0.4285714 0.999001 0 0.2857142 0.999001 -5.96046e-8 0.4285714 0.999001 0 0.2857142 0.999001 0 0.2857142 0.999001 -0.07142836 0.2857142 0.999001 -0.07142836 0.1428571 0.999001 -0.07142836 0.2857142 0.999001 0 0.2857142 0.999001 0.03571432 0 0.999001 0.1071429 0 0.999001 0.1785714 0 0.999001 0.25 0 0.999001 0.3214285 0 0.999001 0.3928571 0 0.999001 0.4642856 0 0.999001 0.5357142 0 0.999001 0.6071428 0 0.999001 0.6785715 0 0.999001 0.75 0 0.999001 0.8214287 0 0.999001 0.8928573 0 0.999001 -0.07142836 0.1428571 0.999001 + + + + + + + + + + -0.9749277 -0.2225218 3.95437e-8 -0.9749279 -0.03513084 0.01814697 -0.8631371 -0.4546571 0.01814702 -0.7818314 -0.6234899 4.56159e-8 -0.5803916 -0.7841328 0.01814686 -0.4338837 -0.9009689 4.26533e-8 -0.1826924 -0.9583017 0.01814685 1.04443e-15 -1 3.12427e-8 0.2511913 -0.9426673 0.01814685 0.4338836 -0.900969 1.36441e-8 0.6353235 -0.740326 0.01814683 0.7818314 -0.6234899 -6.65688e-9 0.8936221 -0.3913545 0.01814665 0.9749277 -0.2225219 -2.56394e-8 0.9749278 0.03512998 0.01814669 0.9749279 0.222521 -3.95437e-8 0.8631371 0.4546568 0.01814684 0.7818313 0.62349 -4.56159e-8 0.5803913 0.7841329 0.01814687 0.4338832 0.9009691 -4.26533e-8 0.1826917 0.9583018 0.01814686 -7.40827e-7 1 -3.12427e-8 -0.2511921 0.942667 0.01814683 -0.4338844 0.9009686 -1.36441e-8 -0.6353242 0.7403254 0.01814688 -0.7818321 0.623489 6.65693e-9 -0.852976 0.4757568 -0.03024468 -0.974928 0.2225204 2.56394e-8 -0.9545922 0.2647484 0.09073415 -0.974928 -0.08239544 0.1074507 -0.8783796 -0.4230055 1.2098e-7 -0.6078575 -0.7622294 -2.40103e-8 -0.2169419 -0.9504844 3.08126e-9 0.2169418 -0.9504845 1.00124e-8 0.6078575 -0.7622294 -1.22219e-8 0.8783796 -0.4230055 2.27489e-8 0.9749279 -1.0315e-7 -1.14217e-7 0.8783796 0.4230055 2.7348e-8 0.6078573 0.7622295 2.9091e-8 0.2169413 0.9504846 1.53869e-8 -0.2169426 0.9504843 -1.74207e-8 -0.6078583 0.7622288 -1.32728e-8 -0.8783801 0.4230047 1.08194e-8 -0.974928 0.08239487 -0.1074508 -0.9545922 0.2647484 0.09073415 -0.974928 0.08239487 -0.1074508 -0.9749279 -0.08239547 0.1074508 -0.9749279 -0.01037927 0.04692359 -0.8783797 -0.4230054 1.38382e-9 -0.974928 -0.08239544 0.1074507 -0.6078575 -0.7622294 -2.5756e-9 -0.2169418 -0.9504845 -4.34778e-9 0.2169417 -0.9504845 7.21083e-10 0.6078575 -0.7622294 2.68537e-9 0.8783797 -0.4230054 -1.49521e-8 0.9749279 9.89275e-9 3.31305e-8 0.8783796 0.4230055 6.33846e-10 0.6078573 0.7622295 2.8277e-9 0.2169413 0.9504845 1.9462e-9 -0.2169426 0.9504842 3.51617e-9 -0.6078584 0.7622287 -1.28249e-8 -0.8783801 0.4230047 -3.55722e-8 -0.974928 0.01037875 -0.04692358 -0.9749279 -0.01037927 0.04692359 -0.9749279 -0.01037929 -0.04692363 -0.8783796 -0.4230055 7.11577e-9 -0.9749279 -0.01037927 0.04692359 -0.6078576 -0.7622294 -5.38627e-9 -0.2169418 -0.9504845 -4.0761e-8 0.2169417 -0.9504845 -6.37691e-9 0.6078574 -0.7622295 4.32713e-8 0.8783797 -0.4230054 4.91462e-8 0.9749279 7.86884e-9 6.87766e-8 0.8783796 0.4230055 7.54338e-8 0.6078573 0.7622295 -3.74104e-9 0.2169413 0.9504845 -6.87179e-10 -0.2169426 0.9504843 -5.06594e-9 -0.6078584 0.7622287 1.11192e-8 -0.8783801 0.4230047 -7.55682e-8 -0.974928 0.01037875 0.04692348 -0.9749279 -0.01037935 -0.04692387 -0.9749279 -0.08239562 -0.107451 -0.8783797 -0.4230055 5.99473e-9 -0.9749279 -0.01037929 -0.04692363 -0.6078575 -0.7622295 -5.14789e-8 -0.2169418 -0.9504844 -6.99784e-8 0.2169419 -0.9504845 -6.77193e-8 0.6078575 -0.7622295 8.75301e-8 0.8783796 -0.4230056 2.38485e-7 0.9749279 -3.58523e-8 7.51737e-8 0.8783796 0.4230055 1.39721e-9 0.6078573 0.7622295 6.92574e-8 0.2169412 0.9504845 -5.31509e-8 -0.2169425 0.9504843 -5.50918e-9 -0.6078583 0.7622288 -2.65355e-8 -0.8605051 0.4601225 0.05372539 -0.974928 0.08239491 0.1074507 -0.9749278 -0.08239586 -0.1074513 -0.9749279 0.03512977 0.0181467 -0.8936222 -0.3913543 0.01814683 -0.9749279 -0.08239562 -0.107451 -0.6353234 -0.740326 0.01814686 -0.2511912 -0.9426673 0.01814672 0.1826924 -0.9583017 0.01814681 0.5803915 -0.7841328 0.01814685 0.8631371 -0.454657 0.01814701 0.9749278 -0.03513059 0.01814698 0.8936221 0.3913542 0.01814686 0.6353234 0.7403261 0.01814691 0.2511908 0.9426673 0.01814683 -0.1826932 0.9583015 0.01814677 -0.5803923 0.7841322 0.01814686 -0.802168 0.5812611 0.09073409 -0.91413 0.3487692 -0.1074508 -0.9545922 0.2647484 -0.09073412 -0.91413 0.3487692 -0.1074508 -0.974928 0.08239496 0.1074508 -0.9749278 -0.2225216 -1.94415e-8 -0.7818317 -0.6234895 -3.91125e-9 -0.4338831 -0.9009692 1.23937e-8 -6.80542e-16 -1 2.62439e-8 0.4338836 -0.9009689 3.48962e-8 0.7818314 -0.6234899 3.66368e-8 0.9749278 -0.2225216 3.11211e-8 0.9749279 0.222521 1.94415e-8 0.7818313 0.6234901 3.91122e-9 0.4338837 0.9009689 -1.23937e-8 -1.19783e-6 1 -2.62439e-8 -0.4338844 0.9009685 -3.48962e-8 -0.7818321 0.623489 -3.66368e-8 -0.974928 0.2225205 -3.11211e-8 -0.9545922 0.2647484 -0.09073412 + + + + + + + + + + -0.2225218 0.9749277 -2.30205e-8 -0.04052453 0.8877353 -0.4585672 -0.4216851 0.7822389 -0.4585672 -0.6234899 0.7818314 -3.58345e-9 -0.7193257 0.5218109 -0.4585672 -0.9009689 0.4338837 1.65634e-8 -0.8744953 0.1580317 -0.4585672 -1 0 3.34297e-8 -0.8564605 -0.2370475 -0.4585672 -0.900969 -0.4338836 4.36748e-8 -0.6687932 -0.5851767 -0.4585672 -0.6234899 -0.7818314 4.52696e-8 -0.3486635 -0.8174044 -0.4585672 -0.2225219 -0.9749277 3.78982e-8 0.04052361 -0.8877353 -0.4585672 0.222521 -0.9749279 2.30206e-8 0.4216849 -0.7822391 -0.4585672 0.62349 -0.7818313 3.58345e-9 0.7193259 -0.5218107 -0.4585672 0.9009691 -0.4338832 -1.65634e-8 0.8744955 -0.1580312 -0.4585672 1 7.40827e-7 -3.34297e-8 0.8564603 0.2370483 -0.4585672 0.9009686 0.4338844 -4.36748e-8 0.6687926 0.5851774 -0.4585672 0.623489 0.7818321 -4.52696e-8 0.445375 0.7693955 -0.4578992 0.2225204 0.974928 -3.78982e-8 0.1987407 0.8707421 -0.4497891 -0.1375673 0.6027217 -0.7860037 -0.2640215 0.5482458 -0.7935484 -0.4757501 0.3793979 -0.7935484 -0.5932505 0.1354056 -0.7935484 -0.5932505 -0.1354055 -0.7935485 -0.4757501 -0.3793979 -0.7935484 -0.2640214 -0.5482459 -0.7935484 -1.5735e-7 -0.6085071 -0.7935484 0.2640215 -0.5482459 -0.7935484 0.4757502 -0.3793978 -0.7935484 0.5932507 -0.1354052 -0.7935484 0.5932505 0.135406 -0.7935484 0.4757496 0.3793984 -0.7935485 0.2640209 0.5482461 -0.7935484 0.1375669 0.6027217 -0.7860037 0.1987407 0.8707421 -0.4497891 0.137567 0.6027217 -0.7860037 -0.1375673 0.6027217 -0.7860037 -0.04923392 0.2157078 -0.975216 -0.09370578 0.194582 -0.9764001 -0.1375673 0.6027217 -0.7860037 -0.168852 0.1346549 -0.9764001 -0.2105549 0.04805777 -0.9764001 -0.2105549 -0.04805776 -0.9764001 -0.168852 -0.1346549 -0.9764001 -0.09370578 -0.194582 -0.9764001 3.5372e-8 -0.2159697 -0.9764001 0.09370579 -0.194582 -0.9764001 0.168852 -0.1346549 -0.9764 0.210555 -0.04805767 -0.9764 0.2105549 0.04805796 -0.9764 0.1688518 0.1346551 -0.9764001 0.09370564 0.1945821 -0.9764001 0.04923379 0.2157078 -0.975216 -0.04923392 0.2157078 -0.975216 0.04923396 -0.215708 -0.9752159 0.09370587 -0.1945822 -0.9764 -0.04923392 0.2157078 -0.975216 0.1688521 -0.134655 -0.9764 0.2105551 -0.04805776 -0.9764 0.210555 0.04805779 -0.9764 0.1688521 0.134655 -0.9764 0.0937059 0.1945822 -0.9764 6.71373e-8 0.2159699 -0.9764 -0.09370582 0.1945822 -0.9764 -0.1688522 0.134655 -0.9764 -0.2105552 0.04805771 -0.9764 -0.210555 -0.04805798 -0.9764 -0.1688519 -0.1346552 -0.9764 -0.09370562 -0.1945823 -0.9764 -0.0492337 -0.215708 -0.9752159 0.04923421 -0.215708 -0.9752159 0.1375676 -0.6027218 -0.7860035 0.2640215 -0.5482461 -0.7935483 0.04923396 -0.215708 -0.9752159 0.4757503 -0.379398 -0.7935483 0.5932507 -0.1354055 -0.7935483 0.5932507 0.1354057 -0.7935483 0.4757503 0.379398 -0.7935482 0.2640218 0.548246 -0.7935483 8.35655e-8 0.6085073 -0.7935483 -0.2640215 0.5482461 -0.7935483 -0.4757503 0.379398 -0.7935483 -0.5932509 0.1354052 -0.7935483 -0.5932507 -0.135406 -0.7935483 -0.4757498 -0.3793985 -0.7935483 -0.3258031 -0.5168711 -0.7916417 -0.1375669 -0.6027219 -0.7860036 0.137568 -0.6027218 -0.7860035 -0.04052343 -0.8877354 -0.458567 0.3486632 -0.8174045 -0.4585671 0.1375676 -0.6027218 -0.7860035 0.6687933 -0.5851768 -0.458567 0.8564606 -0.2370474 -0.4585671 0.8744955 0.1580318 -0.458567 0.7193258 0.5218109 -0.458567 0.4216851 0.782239 -0.458567 0.04052431 0.8877353 -0.4585671 -0.3486632 0.8174045 -0.4585671 -0.6687933 0.5851767 -0.458567 -0.8564607 0.2370471 -0.4585671 -0.8744953 -0.1580326 -0.458567 -0.7193253 -0.5218116 -0.4585671 -0.5568597 -0.6982815 -0.449789 -0.137567 -0.6027219 -0.7860035 -0.1987408 -0.8707422 -0.449789 -0.137567 -0.6027219 -0.7860035 -0.137567 -0.6027219 -0.7860036 0.2225216 -0.9749278 3.13562e-8 0.6234895 -0.7818317 3.66863e-8 0.9009692 -0.4338831 3.47502e-8 1 0 2.59315e-8 0.9009689 0.4338836 1.19766e-8 0.6234899 0.7818314 -4.35029e-9 0.2225216 0.9749278 -1.98156e-8 -0.222521 0.9749279 -3.13562e-8 -0.6234901 0.7818313 -3.66863e-8 -0.9009689 0.4338837 -3.47502e-8 -1 -1.19783e-6 -2.59314e-8 -0.9009685 -0.4338844 -1.19766e-8 -0.623489 -0.7818321 4.35033e-9 -0.2225205 -0.974928 1.98156e-8 -0.1987408 -0.8707422 -0.449789 + + + + + + + + + + + + + + + + + +

0 0 86 0 1 1 1 1 2 2 2 2 0 0 87 3 2 2 2 2 3 3 3 4 0 0 88 5 3 3 3 4 4 4 4 6 0 0 89 7 4 4 4 6 5 5 5 8 0 0 90 9 5 5 5 8 6 6 6 10 0 0 91 11 6 6 6 10 7 7 7 12 0 0 92 13 7 7 7 12 8 8 8 14 0 0 93 15 8 8 8 14 9 9 9 16 0 0 94 17 9 9 9 16 10 10 10 18 0 0 95 19 10 10 10 18 11 11 11 20 0 0 96 21 11 11 11 20 12 12 12 22 0 0 97 23 12 12 12 22 13 13 13 24 0 0 98 25 13 13 13 24 14 14 14 26 0 0 0 27 14 14 99 28 1 1 1 1 1 1 1 1 15 15 100 29 16 16 16 30 1 1 1 1 16 16 16 30 2 2 2 2 2 2 2 2 16 16 16 30 17 17 17 31 2 2 2 2 17 17 17 31 3 3 3 4 3 3 3 4 17 17 17 31 18 18 18 32 3 3 3 4 18 18 18 32 4 4 4 6 4 4 4 6 18 18 18 32 19 19 19 33 4 4 4 6 19 19 19 33 5 5 5 8 5 5 5 8 19 19 19 33 20 20 20 34 5 5 5 8 20 20 20 34 6 6 6 10 6 6 6 10 20 20 20 34 21 21 21 35 6 6 6 10 21 21 21 35 7 7 7 12 7 7 7 12 21 21 21 35 22 22 22 36 7 7 7 12 22 22 22 36 8 8 8 14 8 8 8 14 22 22 22 36 23 23 23 37 8 8 8 14 23 23 23 37 9 9 9 16 9 9 9 16 23 23 23 37 24 24 24 38 9 9 9 16 24 24 24 38 10 10 10 18 10 10 10 18 24 24 24 38 25 25 25 39 10 10 10 18 25 25 25 39 11 11 11 20 11 11 11 20 25 25 25 39 26 26 26 40 11 11 11 20 26 26 26 40 12 12 12 22 12 12 12 22 26 26 26 40 27 27 27 41 12 12 12 22 27 27 27 41 13 13 13 24 13 13 13 24 27 27 27 41 28 28 28 42 13 13 13 24 28 28 28 42 14 14 14 26 14 14 14 26 28 28 28 42 15 15 15 43 14 14 101 44 15 15 102 45 1 1 1 1 15 15 103 46 29 29 104 47 30 30 30 48 15 15 105 49 30 30 30 48 16 16 16 30 16 16 16 30 30 30 30 48 31 31 31 50 16 16 16 30 31 31 31 50 17 17 17 31 17 17 17 31 31 31 31 50 32 32 32 51 17 17 17 31 32 32 32 51 18 18 18 32 18 18 18 32 32 32 32 51 33 33 33 52 18 18 18 32 33 33 33 52 19 19 19 33 19 19 19 33 33 33 33 52 34 34 34 53 19 19 19 33 34 34 34 53 20 20 20 34 20 20 20 34 34 34 34 53 35 35 35 54 20 20 20 34 35 35 35 54 21 21 21 35 21 21 21 35 35 35 35 54 36 36 36 55 21 21 21 35 36 36 36 55 22 22 22 36 22 22 22 36 36 36 36 55 37 37 37 56 22 22 22 36 37 37 37 56 23 23 23 37 23 23 23 37 37 37 37 56 38 38 38 57 23 23 23 37 38 38 38 57 24 24 24 38 24 24 24 38 38 38 38 57 39 39 39 58 24 24 24 38 39 39 39 58 25 25 25 39 25 25 25 39 39 39 39 58 40 40 40 59 25 25 25 39 40 40 40 59 26 26 26 40 26 26 26 40 40 40 40 59 41 41 41 60 26 26 26 40 41 41 41 60 27 27 27 41 27 27 27 41 41 41 41 60 42 42 42 61 27 27 27 41 42 42 42 61 28 28 28 42 28 28 28 42 42 42 42 61 29 29 29 62 28 28 28 42 29 29 29 62 15 15 15 43 29 29 106 63 43 43 107 64 44 44 44 65 29 29 108 66 44 44 44 65 30 30 30 48 30 30 30 48 44 44 44 65 45 45 45 67 30 30 30 48 45 45 45 67 31 31 31 50 31 31 31 50 45 45 45 67 46 46 46 68 31 31 31 50 46 46 46 68 32 32 32 51 32 32 32 51 46 46 46 68 47 47 47 69 32 32 32 51 47 47 47 69 33 33 33 52 33 33 33 52 47 47 47 69 48 48 48 70 33 33 33 52 48 48 48 70 34 34 34 53 34 34 34 53 48 48 48 70 49 49 49 71 34 34 34 53 49 49 49 71 35 35 35 54 35 35 35 54 49 49 49 71 50 50 50 72 35 35 35 54 50 50 50 72 36 36 36 55 36 36 36 55 50 50 50 72 51 51 51 73 36 36 36 55 51 51 51 73 37 37 37 56 37 37 37 56 51 51 51 73 52 52 52 74 37 37 37 56 52 52 52 74 38 38 38 57 38 38 38 57 52 52 52 74 53 53 53 75 38 38 38 57 53 53 53 75 39 39 39 58 39 39 39 58 53 53 53 75 54 54 54 76 39 39 39 58 54 54 54 76 40 40 40 59 40 40 40 59 54 54 54 76 55 55 55 77 40 40 40 59 55 55 55 77 41 41 41 60 41 41 41 60 55 55 55 77 56 56 56 78 41 41 41 60 56 56 56 78 42 42 42 61 42 42 42 61 56 56 56 78 43 43 43 79 42 42 42 61 43 43 43 79 29 29 29 62 43 43 109 80 57 57 110 81 58 58 58 82 43 43 111 83 58 58 58 82 44 44 44 65 44 44 44 65 58 58 58 82 59 59 59 84 44 44 44 65 59 59 59 84 45 45 45 67 45 45 45 67 59 59 59 84 60 60 60 85 45 45 45 67 60 60 60 85 46 46 46 68 46 46 46 68 60 60 60 85 61 61 61 86 46 46 46 68 61 61 61 86 47 47 47 69 47 47 47 69 61 61 61 86 62 62 62 87 47 47 47 69 62 62 62 87 48 48 48 70 48 48 48 70 62 62 62 87 63 63 63 88 48 48 48 70 63 63 63 88 49 49 49 71 49 49 49 71 63 63 63 88 64 64 64 89 49 49 49 71 64 64 64 89 50 50 50 72 50 50 50 72 64 64 64 89 65 65 65 90 50 50 50 72 65 65 65 90 51 51 51 73 51 51 51 73 65 65 65 90 66 66 66 91 51 51 51 73 66 66 66 91 52 52 52 74 52 52 52 74 66 66 66 91 67 67 67 92 52 52 52 74 67 67 67 92 53 53 53 75 53 53 53 75 67 67 67 92 68 68 68 93 53 53 53 75 68 68 68 93 54 54 54 76 54 54 54 76 68 68 68 93 69 69 69 94 54 54 54 76 69 69 69 94 55 55 55 77 55 55 55 77 69 69 69 94 70 70 70 95 55 55 55 77 70 70 70 95 56 56 56 78 56 56 56 78 70 70 70 95 57 57 57 96 56 56 56 78 57 57 57 96 43 43 43 79 57 57 112 97 71 71 71 98 72 72 72 99 57 57 113 100 72 72 72 99 58 58 58 82 58 58 58 82 72 72 72 99 73 73 73 101 58 58 58 82 73 73 73 101 59 59 59 84 59 59 59 84 73 73 73 101 74 74 74 102 59 59 59 84 74 74 74 102 60 60 60 85 60 60 60 85 74 74 74 102 75 75 75 103 60 60 60 85 75 75 75 103 61 61 61 86 61 61 61 86 75 75 75 103 76 76 76 104 61 61 61 86 76 76 76 104 62 62 62 87 62 62 62 87 76 76 76 104 77 77 77 105 62 62 62 87 77 77 77 105 63 63 63 88 63 63 63 88 77 77 77 105 78 78 78 106 63 63 63 88 78 78 78 106 64 64 64 89 64 64 64 89 78 78 78 106 79 79 79 107 64 64 64 89 79 79 79 107 65 65 65 90 65 65 65 90 79 79 79 107 80 80 80 108 65 65 65 90 80 80 80 108 66 66 66 91 66 66 66 91 80 80 80 108 81 81 81 109 66 66 66 91 81 81 81 109 67 67 67 92 67 67 67 92 81 81 81 109 82 82 82 110 67 67 67 92 82 82 82 110 68 68 68 93 68 68 68 93 82 82 82 110 83 83 83 111 68 68 68 93 83 83 83 111 69 69 69 94 69 69 69 94 83 83 83 111 84 84 84 112 69 69 69 94 84 84 84 112 70 70 70 95 70 70 114 113 84 84 115 114 71 71 71 98 70 70 116 115 71 71 71 98 57 57 117 116 85 85 118 117 72 72 72 99 71 71 71 98 85 85 119 118 73 73 73 101 72 72 72 99 85 85 120 119 74 74 74 102 73 73 73 101 85 85 121 120 75 75 75 103 74 74 74 102 85 85 122 121 76 76 76 104 75 75 75 103 85 85 123 122 77 77 77 105 76 76 76 104 85 85 124 123 78 78 78 106 77 77 77 105 85 85 125 124 79 79 79 107 78 78 78 106 85 85 126 125 80 80 80 108 79 79 79 107 85 85 127 126 81 81 81 109 80 80 80 108 85 85 128 127 82 82 82 110 81 81 81 109 85 85 129 128 83 83 83 111 82 82 82 110 85 85 130 129 84 84 84 112 83 83 83 111 85 85 85 130 71 71 71 98 84 84 131 131

+
+
+
+ + + + 0 0 5 -1.28465e-7 2.938926 4.045085 -1.727457 2.377641 4.045085 -2.795085 0.9081783 4.045085 -2.795085 -0.9081781 4.045085 -1.727458 -2.377641 4.045085 3.50463e-8 -2.938926 4.045085 1.727458 -2.377641 4.045085 2.795085 -0.9081767 4.045085 2.795084 0.9081804 4.045085 1.727455 2.377643 4.045085 -2.0786e-7 4.755283 1.545085 -2.795085 3.847105 1.545085 -4.522542 1.469463 1.545085 -4.522543 -1.469463 1.545085 -2.795086 -3.847104 1.545085 5.67062e-8 -4.755283 1.545085 2.795086 -3.847104 1.545085 4.522543 -1.469461 1.545085 4.522542 1.469467 1.545085 2.795081 3.847108 1.545085 -2.0786e-7 4.755282 -1.545085 -2.795084 3.847104 -1.545085 -4.522542 1.469463 -1.545085 -4.522542 -1.469463 -1.545085 -2.795086 -3.847103 -1.545085 5.67062e-8 -4.755282 -1.545085 2.795086 -3.847103 -1.545085 4.522543 -1.469461 -1.545085 4.522542 1.469467 -1.545085 2.795081 3.847107 -1.545085 -1.28465e-7 2.938926 -4.045085 -1.727457 2.377641 -4.045085 -2.795085 0.9081782 -4.045085 -2.795085 -0.908178 -4.045085 -1.727458 -2.37764 -4.045085 3.50463e-8 -2.938926 -4.045085 1.727458 -2.37764 -4.045085 2.795085 -0.9081766 -4.045085 2.795084 0.9081803 -4.045085 1.727455 2.377643 -4.045085 0 0 -5 + + + + + + + + + + 0 -2.11156e-8 1 -2.11354e-7 0.6252257 0.780444 -0.3674984 0.5058182 0.780444 -0.5946249 0.1932054 0.780444 -0.594625 -0.1932053 0.780444 -0.3674985 -0.5058182 0.780444 1.05677e-8 -0.6252257 0.780444 0.3674986 -0.5058181 0.780444 0.5946251 -0.1932051 0.780444 0.5946248 0.1932058 0.780444 0.3674981 0.5058185 0.780444 -2.70626e-7 0.9562714 0.2924812 -0.5620822 0.7736397 0.2924811 -0.909468 0.2955042 0.2924811 -0.9094681 -0.295504 0.2924812 -0.5620822 -0.7736397 0.2924811 5.52297e-9 -0.9562714 0.2924811 0.5620824 -0.7736396 0.2924811 0.9094682 -0.2955036 0.2924811 0.9094678 0.2955048 0.2924812 0.5620816 0.7736402 0.2924811 -2.70626e-7 0.9562712 -0.2924812 -0.5620822 0.7736397 -0.2924812 -0.909468 0.2955042 -0.2924812 -0.9094681 -0.295504 -0.2924812 -0.5620822 -0.7736396 -0.2924812 2.76149e-9 -0.9562712 -0.2924812 0.5620824 -0.7736395 -0.2924812 0.9094682 -0.2955037 -0.2924812 0.9094678 0.2955048 -0.2924812 0.5620815 0.7736402 -0.2924812 -1.638e-7 0.6252257 -0.780444 -0.3674985 0.5058182 -0.780444 -0.594625 0.1932054 -0.780444 -0.594625 -0.1932053 -0.780444 -0.3674985 -0.5058182 -0.780444 -3.17032e-8 -0.6252257 -0.780444 0.3674986 -0.5058181 -0.780444 0.5946251 -0.1932051 -0.780444 0.5946248 0.1932058 -0.780444 0.3674981 0.5058185 -0.780444 1.51768e-8 -4.22312e-8 -1 + + + + + + + + + + 0.95 1 0.999001 0.9999999 0.8 0.9990011 0.09999996 0.8 0.999001 0.2 0.8 0.999001 0.3 0.8 0.999001 0.3999999 0.8 0.999001 0.5 0.8 0.9990011 0.6 0.8 0.9990011 0.7 0.8 0.9990011 0.8000001 0.8 0.9990011 0.9000001 0.8 0.9990011 0.9999999 0.6 0.9990011 0.09999996 0.6 0.999001 0.2 0.6 0.999001 0.3 0.6 0.9990011 0.3999999 0.6 0.999001 0.5 0.6 0.9990011 0.6 0.6 0.9990011 0.7 0.6 0.9990011 0.8000001 0.6 0.9990011 0.9000001 0.6 0.9990011 0.9999999 0.4 0.9990011 0.09999996 0.4 0.999001 0.2 0.4 0.9990009 0.3 0.4 0.999001 0.3999999 0.4 0.999001 0.5 0.4 0.9990011 0.6 0.4 0.999001 0.7 0.4 0.9990011 0.8000001 0.4 0.9990011 0.9000001 0.4 0.999001 0.9999999 0.2 0.9990011 0.09999996 0.2 0.999001 0.2 0.2 0.999001 0.3 0.2 0.999001 0.3999999 0.2 0.999001 0.5 0.2 0.9990011 0.6 0.2 0.9990011 0.7 0.2 0.9990011 0.8000001 0.2 0.9990011 0.9000001 0.2 0.9990011 0.95 0 0.999001 0.04999995 1 0.999001 -5.96046e-8 0.8 0.9990011 0.15 1 0.999001 0.25 1 0.999001 0.35 1 0.999001 0.45 1 0.999001 0.55 1 0.999001 0.65 1 0.999001 0.7500001 1 0.999001 0.8500001 1 0.999001 -5.96046e-8 0.8 0.9990011 -5.96046e-8 0.6 0.9990011 -5.96046e-8 0.8 0.9990011 -5.96046e-8 0.6 0.9990011 -5.96046e-8 0.4 0.9990011 -5.96046e-8 0.6 0.9990011 -5.96046e-8 0.4 0.9990011 -5.96046e-8 0.2 0.9990011 -5.96046e-8 0.4 0.9990011 0.04999995 0 0.999001 -5.96046e-8 0.2 0.9990011 0.15 0 0.999001 0.25 0 0.999001 0.35 0 0.999001 0.45 0 0.999001 0.55 0 0.999001 0.65 0 0.999001 0.7500001 0 0.999001 0.8500001 0 0.999001 + + + + + + + + + + -0.9510565 -0.3090171 -6.52508e-9 -0.9510565 -0.1882202 0.1507859 -0.7472943 -0.5894716 0.03015721 -0.5877853 -0.809017 -1.70829e-8 -0.2580911 -0.9161411 0.03015718 -1.31262e-7 -1 -2.11156e-8 0.3296941 -0.8928759 0.0301572 0.5877852 -0.809017 -1.70829e-8 0.7915474 -0.5285625 0.03015717 0.9510565 -0.3090172 -6.52508e-9 0.9510565 0.03764403 0.0301572 0.9510565 0.3090172 6.52508e-9 0.7472941 0.5894718 0.03015722 0.587785 0.8090172 1.70829e-8 0.2580906 0.9161412 0.03015722 -6.5631e-7 1 2.11156e-8 -0.3296949 0.8928756 0.0301572 -0.587786 0.8090165 1.70829e-8 -0.7915479 0.5285618 0.03015718 -0.9510567 0.3090165 6.52507e-9 -0.9510567 0.1882196 -0.1507859 -0.9510565 -0.1882202 0.1507858 -0.9510566 -0.02643514 0.08642931 -0.7694209 -0.559017 7.9155e-10 -0.9510565 -0.1882202 0.1507859 -0.2938927 -0.9045085 -4.0073e-9 0.2938925 -0.9045085 -7.41231e-10 0.7694209 -0.5590171 -6.34775e-9 0.9510565 4.77085e-9 -2.3606e-9 0.7694207 0.5590172 -6.72929e-9 0.2938922 0.9045086 -2.86915e-9 -0.2938933 0.9045082 -2.409e-9 -0.7694214 0.5590164 -1.96186e-8 -0.9510566 0.0264346 -0.0864293 -0.9510566 -0.02643514 0.08642932 -0.9510566 -0.02643521 -0.08642933 -0.7694209 -0.559017 1.17386e-8 -0.9510566 -0.02643514 0.08642931 -0.2938927 -0.9045085 -3.27196e-9 0.2938926 -0.9045085 1.16709e-8 0.7694209 -0.5590171 -4.67655e-8 0.9510565 2.37408e-9 1.21738e-9 0.7694207 0.5590172 1.66922e-8 0.2938922 0.9045086 -7.07564e-9 -0.2938933 0.9045082 1.75192e-8 -0.7694214 0.5590164 1.41495e-8 -0.9510566 0.02643467 0.08642932 -0.9510567 -0.0264351 -0.08642897 -0.9510566 -0.1882199 -0.1507856 -0.7915475 -0.5285623 0.03015731 -0.9510566 -0.02643521 -0.08642933 -0.3296942 -0.8928758 0.03015721 0.258091 -0.9161412 0.03015719 0.7472943 -0.5894716 0.03015712 0.9510565 -0.03764394 0.03015711 0.7915473 0.5285625 0.03015719 0.3296938 0.892876 0.03015719 -0.2580917 0.9161409 0.03015721 -0.7472948 0.5894711 0.03015717 -0.9510567 0.1882196 0.1507858 -0.9510566 -0.3090166 -1.38389e-9 -0.9510567 -0.1882199 -0.1507856 -0.5877853 -0.8090169 2.5245e-8 -6.40936e-16 -1 4.22312e-8 0.5877852 -0.809017 4.30865e-8 0.9510566 -0.3090169 2.74842e-8 0.9510565 0.3090172 1.38386e-9 0.587785 0.8090172 -2.5245e-8 -6.5631e-7 1 -4.22312e-8 -0.587786 0.8090165 -4.30865e-8 -0.9510567 0.3090165 -2.74842e-8 + + + + + + + + + + -0.3090171 0.9510565 2.00821e-8 -0.2458018 0.7565 -0.6060439 -0.4991224 0.60081 -0.6244231 -0.809017 0.5877853 1.24114e-8 -0.7569457 0.1926888 -0.6244232 -1 1.31262e-7 2.77168e-15 -0.7256415 -0.289033 -0.6244231 -0.809017 -0.5877852 -1.24114e-8 -0.417167 -0.660354 -0.6244232 -0.3090172 -0.9510565 -2.00821e-8 0.05065125 -0.7794422 -0.6244232 0.3090172 -0.9510565 -2.00821e-8 0.4991225 -0.6008098 -0.6244231 0.8090172 -0.587785 -1.24114e-8 0.7569458 -0.1926883 -0.6244232 1 6.5631e-7 1.38584e-14 0.7256413 0.2890337 -0.6244231 0.8090165 0.587786 1.24115e-8 0.4171665 0.6603543 -0.6244232 0.3090165 0.9510567 2.00821e-8 0.2458013 0.7565002 -0.6060439 -0.2458018 0.7565 -0.6060439 -0.09460663 0.2911693 -0.9519822 -0.1719161 0.2366222 -0.9562713 -0.2458018 0.7565 -0.6060439 -0.2781661 0.09038166 -0.9562713 -0.2781661 -0.09038162 -0.9562713 -0.1719161 -0.2366222 -0.9562713 -9.06353e-10 -0.2924811 -0.9562713 0.1719161 -0.2366221 -0.9562713 0.2781661 -0.09038149 -0.9562713 0.2781661 0.09038187 -0.9562713 0.1719159 0.2366223 -0.9562713 0.09460646 0.2911693 -0.9519822 -0.09460664 0.2911693 -0.9519822 0.09460667 -0.2911693 -0.9519821 0.1719161 -0.2366223 -0.9562713 -0.09460663 0.2911693 -0.9519822 0.2781661 -0.09038168 -0.9562713 0.2781662 0.09038165 -0.9562713 0.1719161 0.2366223 -0.9562713 4.93948e-10 0.2924813 -0.9562713 -0.1719162 0.2366222 -0.9562713 -0.2781662 0.09038154 -0.9562713 -0.2781661 -0.09038187 -0.9562713 -0.171916 -0.2366224 -0.9562713 -0.09460649 -0.2911694 -0.9519821 0.09460628 -0.2911694 -0.9519822 0.2458014 -0.7565001 -0.6060439 0.4171668 -0.6603542 -0.6244231 0.09460667 -0.2911693 -0.9519821 0.7256415 -0.2890331 -0.6244232 0.7569457 0.1926887 -0.6244231 0.4991223 0.60081 -0.6244231 0.05065112 0.7794422 -0.6244232 -0.4171671 0.6603539 -0.6244232 -0.7256416 0.2890327 -0.6244232 -0.7569456 -0.1926893 -0.6244231 -0.4991219 -0.6008104 -0.6244231 -0.2458013 -0.7565002 -0.6060439 0.3090166 -0.9510566 4.48541e-8 0.2458014 -0.7565001 -0.6060439 0.8090169 -0.5877853 3.71012e-8 1 0 1.51768e-8 0.809017 0.5877852 -1.25446e-8 0.3090169 0.9510566 -3.54744e-8 -0.3090172 0.9510565 -4.48541e-8 -0.8090172 0.587785 -3.71012e-8 -1 -6.5631e-7 -1.51768e-8 -0.8090165 -0.587786 1.25446e-8 -0.3090165 -0.9510567 3.54744e-8 + + + + + + + + + + + + + + + + + +

0 0 42 0 1 1 43 1 2 2 2 2 0 0 44 3 2 2 2 2 3 3 3 4 0 0 45 5 3 3 3 4 4 4 4 6 0 0 46 7 4 4 4 6 5 5 5 8 0 0 47 9 5 5 5 8 6 6 6 10 0 0 48 11 6 6 6 10 7 7 7 12 0 0 49 13 7 7 7 12 8 8 8 14 0 0 50 15 8 8 8 14 9 9 9 16 0 0 51 17 9 9 9 16 10 10 10 18 0 0 0 19 10 10 10 18 1 1 1 20 1 1 52 21 11 11 53 22 12 12 12 23 1 1 54 24 12 12 12 23 2 2 2 2 2 2 2 2 12 12 12 23 13 13 13 25 2 2 2 2 13 13 13 25 3 3 3 4 3 3 3 4 13 13 13 25 14 14 14 26 3 3 3 4 14 14 14 26 4 4 4 6 4 4 4 6 14 14 14 26 15 15 15 27 4 4 4 6 15 15 15 27 5 5 5 8 5 5 5 8 15 15 15 27 16 16 16 28 5 5 5 8 16 16 16 28 6 6 6 10 6 6 6 10 16 16 16 28 17 17 17 29 6 6 6 10 17 17 17 29 7 7 7 12 7 7 7 12 17 17 17 29 18 18 18 30 7 7 7 12 18 18 18 30 8 8 8 14 8 8 8 14 18 18 18 30 19 19 19 31 8 8 8 14 19 19 19 31 9 9 9 16 9 9 9 16 19 19 19 31 20 20 20 32 9 9 9 16 20 20 20 32 10 10 10 18 10 10 10 18 20 20 20 32 11 11 11 33 10 10 10 18 11 11 11 33 1 1 1 20 11 11 55 34 21 21 56 35 22 22 22 36 11 11 57 37 22 22 22 36 12 12 12 23 12 12 12 23 22 22 22 36 23 23 23 38 12 12 12 23 23 23 23 38 13 13 13 25 13 13 13 25 23 23 23 38 24 24 24 39 13 13 13 25 24 24 24 39 14 14 14 26 14 14 14 26 24 24 24 39 25 25 25 40 14 14 14 26 25 25 25 40 15 15 15 27 15 15 15 27 25 25 25 40 26 26 26 41 15 15 15 27 26 26 26 41 16 16 16 28 16 16 16 28 26 26 26 41 27 27 27 42 16 16 16 28 27 27 27 42 17 17 17 29 17 17 17 29 27 27 27 42 28 28 28 43 17 17 17 29 28 28 28 43 18 18 18 30 18 18 18 30 28 28 28 43 29 29 29 44 18 18 18 30 29 29 29 44 19 19 19 31 19 19 19 31 29 29 29 44 30 30 30 45 19 19 19 31 30 30 30 45 20 20 20 32 20 20 20 32 30 30 30 45 21 21 21 46 20 20 20 32 21 21 21 46 11 11 11 33 21 21 58 47 31 31 59 48 32 32 32 49 21 21 60 50 32 32 32 49 22 22 22 36 22 22 22 36 32 32 32 49 33 33 33 51 22 22 22 36 33 33 33 51 23 23 23 38 23 23 23 38 33 33 33 51 34 34 34 52 23 23 23 38 34 34 34 52 24 24 24 39 24 24 24 39 34 34 34 52 35 35 35 53 24 24 24 39 35 35 35 53 25 25 25 40 25 25 25 40 35 35 35 53 36 36 36 54 25 25 25 40 36 36 36 54 26 26 26 41 26 26 26 41 36 36 36 54 37 37 37 55 26 26 26 41 37 37 37 55 27 27 27 42 27 27 27 42 37 37 37 55 38 38 38 56 27 27 27 42 38 38 38 56 28 28 28 43 28 28 28 43 38 38 38 56 39 39 39 57 28 28 28 43 39 39 39 57 29 29 29 44 29 29 29 44 39 39 39 57 40 40 40 58 29 29 29 44 40 40 40 58 30 30 30 45 30 30 30 45 40 40 40 58 31 31 31 59 30 30 30 45 31 31 31 59 21 21 21 46 41 41 61 60 32 32 32 49 31 31 62 61 41 41 63 62 33 33 33 51 32 32 32 49 41 41 64 63 34 34 34 52 33 33 33 51 41 41 65 64 35 35 35 53 34 34 34 52 41 41 66 65 36 36 36 54 35 35 35 53 41 41 67 66 37 37 37 55 36 36 36 54 41 41 68 67 38 38 38 56 37 37 37 55 41 41 69 68 39 39 39 57 38 38 38 56 41 41 70 69 40 40 40 58 39 39 39 57 41 41 41 70 31 31 31 59 40 40 40 58

+
+
+
+ + + + 0 0 5 -1.54543e-7 3.535534 3.535534 -2.5 2.5 3.535534 -3.535534 -3.09086e-7 3.535534 -2.5 -2.5 3.535534 4.21608e-8 -3.535534 3.535534 2.5 -2.5 3.535534 3.535534 -1.0677e-6 3.535534 2.500001 2.499999 3.535534 -2.18557e-7 5 -2.18557e-7 -3.535534 3.535534 -2.18557e-7 -5 -4.37114e-7 -2.18557e-7 -3.535533 -3.535534 -2.18557e-7 5.96244e-8 -5 -2.18557e-7 3.535533 -3.535534 -2.18557e-7 5 -1.50996e-6 -2.18557e-7 3.535536 3.535532 -2.18557e-7 -1.54543e-7 3.535534 -3.535534 -2.5 2.5 -3.535534 -3.535534 -3.09086e-7 -3.535534 -2.5 -2.5 -3.535534 4.21608e-8 -3.535534 -3.535534 2.5 -2.5 -3.535534 3.535534 -1.0677e-6 -3.535534 2.500001 2.499999 -3.535534 0 0 -5 + + + + + + + + + + 9.88537e-9 3.95415e-8 1 6.9026e-8 0.7486158 0.6630041 -0.5293514 0.5293513 0.6630041 -0.7486159 -8.05304e-8 0.6630041 -0.5293513 -0.5293514 0.663004 1.15043e-8 -0.7486158 0.6630041 0.5293513 -0.5293514 0.6630041 0.7486158 -2.01326e-7 0.6630041 0.5293515 0.5293512 0.6630041 7.27742e-8 1 -1.2129e-8 -0.7071067 0.7071068 -3.63871e-8 -1 -9.70323e-8 -1.81936e-8 -0.7071068 -0.7071068 -1.2129e-8 0 -1 3.03226e-8 0.7071066 -0.7071069 0 1 -3.21419e-7 -4.24516e-8 0.7071069 0.7071065 -1.2129e-8 6.32739e-8 0.7486157 -0.6630041 -0.5293513 0.5293513 -0.6630042 -0.7486158 -6.9026e-8 -0.6630042 -0.5293512 -0.5293514 -0.663004 2.30087e-8 -0.7486158 -0.6630041 0.5293512 -0.5293514 -0.6630041 0.7486158 -1.86945e-7 -0.6630042 0.5293514 0.5293511 -0.6630041 9.88537e-9 2.82439e-8 -1 + + + + + + + + + + 0.5 0.5 5.5 0.5000007 4.035534 4.035534 -2 3 4.035534 -3.035534 0.5000005 4.035534 -2 -2 4.035534 0.4999992 -3.035534 4.035534 2.999999 -2.000001 4.035534 4.035534 0.4999981 4.035534 3.000002 2.999998 4.035534 0.500001 5.5 0.4999998 -3.035533 4.035535 0.4999998 -4.5 0.5000008 0.4999998 -3.035534 -3.035533 0.4999998 0.4999989 -4.5 0.4999998 4.035532 -3.035535 0.4999998 5.5 0.4999973 0.4999998 4.035537 4.035532 0.4999998 0.5000007 4.035534 -3.035534 -2 3 -3.035534 -3.035534 0.5000005 -3.035534 -2 -2 -3.035534 0.4999992 -3.035534 -3.035534 2.999999 -2.000001 -3.035534 4.035534 0.4999981 -3.035534 3.000002 2.999998 -3.035534 0.5 0.5 -4.5 + + + + + + + + + + 0.954739 2.15833e-7 -9.43795e-9 0.8185035 -0.07019225 0.07925587 0.7049205 -0.02852993 0.5855967 0.6144843 1.61232e-7 0.6938309 0.7364077 -0.004867014 0.5840719 0.8185036 -0.07019225 -0.07925597 0.7049205 -0.02852995 -0.5855966 0.6144844 1.36677e-7 -0.6938309 0.7364076 -0.004866982 -0.584072 0.7071067 -5.4318e-8 -0.2357023 0.2724478 0.2724477 -0.03612882 -1.08617e-14 7.48297e-8 -5.34923e-9 0.2724474 -0.2724474 0.03612879 0.7071068 7.1471e-9 0.2357022 0.2724478 0.2724477 0.03612882 3.23075e-14 2.23624e-7 1.56345e-8 0.2724472 -0.2724473 -0.03612873 0.8185034 0.07019258 0.07925641 0.7364079 0.004867376 -0.5840717 0.6144844 1.60997e-7 -0.6938308 0.7049204 0.02853028 -0.5855968 0.8185035 0.07019259 -0.07925631 0.736408 0.004867405 0.5840716 0.6144844 1.54593e-7 0.6938308 0.7049204 0.02853028 0.5855969 0.954739 2.15833e-7 9.43795e-9 + + + + + + + + + + 2.26065e-7 -1 3.95415e-8 -0.1282771 -0.6575266 0.742431 -0.3587224 -0.8478319 0.3905115 1.75624e-7 -1 7.68394e-8 0.3255071 -0.8483869 -0.4174744 -0.1282772 -0.6575266 -0.742431 -0.3587225 -0.8478319 -0.3905116 -5.29431e-8 -1 -2.43878e-7 0.325507 -0.848387 0.4174741 0.3162278 -1.15066e-8 0.9486833 0.06601453 0.06601457 0.9956325 -2.5066e-8 0.07130344 0.9974547 0.06601458 -0.06601456 -0.9956325 0.3162277 -2.87665e-8 -0.9486833 0.06601455 0.06601453 -0.9956325 -1.99311e-8 0.06974413 -0.9975649 0.06601449 -0.06601451 0.9956325 -0.1282779 0.6575266 0.7424309 0.3255066 0.848387 0.4174746 -1.66844e-7 1 8.42766e-8 -0.3587228 0.8478319 -0.3905113 -0.1282778 0.6575265 -0.7424309 0.3255067 0.8483869 -0.4174747 2.93614e-8 1 -2.48815e-7 -0.3587227 0.847832 0.3905111 -2.26065e-7 1 2.82439e-8 + + + + + + + + + + + + + + + + + +

0 0 0 0 1 1 1 1 2 2 2 2 0 0 0 0 2 2 2 2 3 3 3 3 0 0 0 0 3 3 3 3 4 4 4 4 0 0 0 0 4 4 4 4 5 5 5 5 0 0 0 0 5 5 5 5 6 6 6 6 0 0 0 0 6 6 6 6 7 7 7 7 0 0 0 0 7 7 7 7 8 8 8 8 0 0 0 0 8 8 8 8 1 1 1 1 1 1 1 1 9 9 9 9 10 10 10 10 1 1 1 1 10 10 10 10 2 2 2 2 2 2 2 2 10 10 10 10 11 11 11 11 2 2 2 2 11 11 11 11 3 3 3 3 3 3 3 3 11 11 11 11 12 12 12 12 3 3 3 3 12 12 12 12 4 4 4 4 4 4 4 4 12 12 12 12 13 13 13 13 4 4 4 4 13 13 13 13 5 5 5 5 5 5 5 5 13 13 13 13 14 14 14 14 5 5 5 5 14 14 14 14 6 6 6 6 6 6 6 6 14 14 14 14 15 15 15 15 6 6 6 6 15 15 15 15 7 7 7 7 7 7 7 7 15 15 15 15 16 16 16 16 7 7 7 7 16 16 16 16 8 8 8 8 8 8 8 8 16 16 16 16 9 9 9 9 8 8 8 8 9 9 9 9 1 1 1 1 9 9 9 9 17 17 17 17 18 18 18 18 9 9 9 9 18 18 18 18 10 10 10 10 10 10 10 10 18 18 18 18 19 19 19 19 10 10 10 10 19 19 19 19 11 11 11 11 11 11 11 11 19 19 19 19 20 20 20 20 11 11 11 11 20 20 20 20 12 12 12 12 12 12 12 12 20 20 20 20 21 21 21 21 12 12 12 12 21 21 21 21 13 13 13 13 13 13 13 13 21 21 21 21 22 22 22 22 13 13 13 13 22 22 22 22 14 14 14 14 14 14 14 14 22 22 22 22 23 23 23 23 14 14 14 14 23 23 23 23 15 15 15 15 15 15 15 15 23 23 23 23 24 24 24 24 15 15 15 15 24 24 24 24 16 16 16 16 16 16 16 16 24 24 24 24 17 17 17 17 16 16 16 16 17 17 17 17 9 9 9 9 25 25 25 25 18 18 18 18 17 17 17 17 25 25 25 25 19 19 19 19 18 18 18 18 25 25 25 25 20 20 20 20 19 19 19 19 25 25 25 25 21 21 21 21 20 20 20 20 25 25 25 25 22 22 22 22 21 21 21 21 25 25 25 25 23 23 23 23 22 22 22 22 25 25 25 25 24 24 24 24 23 23 23 23 25 25 25 25 17 17 17 17 24 24 24 24

+
+
+
+ + + + 0 0 5 -1.89276e-7 4.330127 2.5 -3.75 2.165064 2.5 -3.75 -2.165064 2.5 5.16362e-8 -4.330127 2.5 3.75 -2.165064 2.5 3.750001 2.165062 2.5 -1.89276e-7 4.330127 -2.5 -3.75 2.165064 -2.5 -3.75 -2.165063 -2.5 5.16362e-8 -4.330127 -2.5 3.75 -2.165064 -2.5 3.750001 2.165062 -2.5 0 0 -5 + + + + + + + + + + -1.99952e-8 1.33301e-8 1 7.03834e-8 0.8973439 0.441332 -0.7771226 0.448672 0.441332 -0.7771226 -0.448672 0.441332 -3.51917e-8 -0.8973439 0.441332 0.7771224 -0.4486721 0.441332 0.7771227 0.4486718 0.441332 8.44601e-8 0.8973438 -0.4413321 -0.7771226 0.4486719 -0.4413322 -0.7771226 -0.4486719 -0.4413321 -4.92684e-8 -0.8973439 -0.4413321 0.7771225 -0.4486721 -0.4413321 0.7771227 0.4486717 -0.4413321 -6.66506e-9 1.33301e-8 -1 + + + + + + + + + + 0.9166666 1 0.999001 0.9999999 0.6666667 0.9990011 0.1666667 0.6666666 0.9990012 0.3333333 0.6666667 0.9990011 0.5 0.6666667 0.9990011 0.6666666 0.6666667 0.999001 0.8333333 0.6666667 0.999001 0.9999999 0.3333333 0.999001 0.1666666 0.3333333 0.9990011 0.3333333 0.3333333 0.9990011 0.5 0.3333333 0.999001 0.6666666 0.3333333 0.999001 0.8333332 0.3333333 0.9990009 0.9166666 0 0.999001 0.08333331 1 0.999001 -5.96046e-8 0.6666667 0.9990011 0.25 1 0.999001 0.4166666 1 0.999001 0.5833333 1 0.999001 0.7499999 1 0.999001 -5.96046e-8 0.6666667 0.9990011 -5.96046e-8 0.3333333 0.999001 -5.96046e-8 0.6666667 0.9990011 0.08333328 0 0.999001 -5.96046e-8 0.3333333 0.999001 0.25 0 0.999001 0.4166666 0 0.999001 0.5833333 0 0.999001 0.7499999 0 0.999001 + + + + + + + + + + -0.8660253 -0.5000002 -1.06513e-8 -0.8660252 -0.09738706 0.1980136 -0.4161448 -0.7597387 0.03960266 -3.09715e-7 -1 1.33301e-8 0.4498806 -0.7402613 0.03960252 0.8660254 -0.5 2.39814e-8 0.8660254 0.01947738 0.03960269 0.8660254 0.4999999 1.06513e-8 0.416145 0.7597387 0.03960266 3.30363e-7 1 -1.33301e-8 -0.4498804 0.7402614 0.03960264 -0.8660253 0.5000001 -2.39814e-8 -0.8660254 0.09738707 -0.1980133 -0.8660254 -0.09738693 0.1980133 -0.8660254 -0.09738697 -0.1980133 -0.4498806 -0.7402613 0.03960274 -0.8660254 -0.09738709 0.1980137 0.4161448 -0.7597387 0.03960259 0.8660254 -0.01947747 0.03960272 0.4498808 0.7402612 0.03960273 -0.4161446 0.7597387 0.0396026 -0.8660254 0.09738708 0.1980132 -0.8660254 -0.5 -8.92948e-10 -0.8660254 -0.09738697 -0.1980133 0 -1 -1.33301e-8 0.8660254 -0.5 -1.24372e-8 0.8660255 0.4999998 8.92944e-10 2.75302e-7 1 1.33301e-8 -0.8660254 0.5 1.24372e-8 + + + + + + + + + + -0.5000002 0.8660253 -2.15418e-8 -0.2469142 0.4276673 -0.8695597 -0.4071567 0.176304 -0.896181 -1 3.09715e-7 -1.99952e-8 -0.3562622 -0.2644559 -0.896181 -0.5 -0.8660254 1.54663e-9 0.05089461 -0.4407601 -0.896181 0.4999999 -0.8660254 2.15418e-8 0.4071567 -0.1763041 -0.8961809 1 -3.30363e-7 1.99952e-8 0.3562622 0.2644559 -0.896181 0.5000001 0.8660253 -1.54663e-9 0.2469139 0.4276673 -0.8695598 -0.2469138 0.4276673 -0.8695598 0.2469139 -0.4276674 -0.8695598 0.3562622 -0.2644562 -0.8961809 -0.2469142 0.4276672 -0.8695597 0.4071568 0.1763041 -0.8961809 0.05089469 0.4407602 -0.8961809 -0.3562621 0.2644562 -0.8961809 -0.4071568 -0.176304 -0.8961809 -0.2469138 -0.4276673 -0.8695598 0.5 -0.8660254 -1.48767e-8 0.2469139 -0.4276674 -0.8695598 1 0 -6.66506e-9 0.5 0.8660254 8.21169e-9 -0.4999998 0.8660255 1.48767e-8 -1 2.75302e-7 6.66506e-9 -0.5 -0.8660254 -8.21169e-9 + + + + + + + + + + + + + + + + + +

0 0 14 0 1 1 15 1 2 2 2 2 0 0 16 3 2 2 2 2 3 3 3 4 0 0 17 5 3 3 3 4 4 4 4 6 0 0 18 7 4 4 4 6 5 5 5 8 0 0 19 9 5 5 5 8 6 6 6 10 0 0 0 11 6 6 6 10 1 1 1 12 1 1 20 13 7 7 21 14 8 8 8 15 1 1 22 16 8 8 8 15 2 2 2 2 2 2 2 2 8 8 8 15 9 9 9 17 2 2 2 2 9 9 9 17 3 3 3 4 3 3 3 4 9 9 9 17 10 10 10 18 3 3 3 4 10 10 10 18 4 4 4 6 4 4 4 6 10 10 10 18 11 11 11 19 4 4 4 6 11 11 11 19 5 5 5 8 5 5 5 8 11 11 11 19 12 12 12 20 5 5 5 8 12 12 12 20 6 6 6 10 6 6 6 10 12 12 12 20 7 7 7 21 6 6 6 10 7 7 7 21 1 1 1 12 13 13 23 22 8 8 8 15 7 7 24 23 13 13 25 24 9 9 9 17 8 8 8 15 13 13 26 25 10 10 10 18 9 9 9 17 13 13 27 26 11 11 11 19 10 10 10 18 13 13 28 27 12 12 12 20 11 11 11 19 13 13 13 28 7 7 7 21 12 12 12 20

+
+
+
+
+ + + + + 0 0 0 + + + + + + + + + + + + + + + + + + + + 1 + 1 + 1 + 1 + + + + + + + + + + + + + + 1 + 1 + 1 + 1 + + + + + + + + + + + + + + 1 + 1 + 1 + 1 + + + + + + + + + + + + + + 1 + 1 + 1 + 1 + + + + + + + + +
\ No newline at end of file diff --git a/Templates/Full/game/art/environment/LightVolume_Sphere.cs b/Templates/Full/game/art/environment/LightVolume_Sphere.cs new file mode 100644 index 000000000..475da3bee --- /dev/null +++ b/Templates/Full/game/art/environment/LightVolume_Sphere.cs @@ -0,0 +1,8 @@ + +singleton TSShapeConstructor(LightVolume_SphereDAE) +{ + baseShape = "./LightVolume_Sphere.DAE"; + lodType = "TrailingNumber"; + neverImport = "env*"; + loadLights = "0"; +}; diff --git a/Templates/Full/game/art/environment/LightVolume_Sphere.dts b/Templates/Full/game/art/environment/LightVolume_Sphere.dts new file mode 100644 index 0000000000000000000000000000000000000000..223993dd637b8baf3e81194b0aa8598c58df0429 GIT binary patch literal 12883 zcmd6ud309gwZ=c@K?oS80HTpOfDrOAIPsmMNFWld3Mir=C?MbmB9k+I6ujQz0HU`l zdTq4Qr4dDvK-I!`PK$~|v_+-B!lAeX(c9~dR%>gE+~@b6_a(<9f84veR#%T}v!CbL z``vq==}mIF+AVQw;?6dSL^s(GS<^%!(MZPOe8lSi8;`RNYbBc{Ya-*gW?k!Zu!y;T z%fdwBxcS1yT)ksD$i#D?N2vDS#tmrntj&lJd2TjAa}YVNppi#Dv1XBc{NLtQck{G3 z9{In6mP+MXv^GmJo?Cf>fG%^Qt?Y+=Z$2-P$OPC^F1Z2EY#h;SLyoVxFp?Ym*Uith zNF-hx?fMipm>r4C&k^0n*Uoio@*=sxe{-zbPM-PPecRjNp|I`IM?&uT{tgfM!hUqm z6T_8e4z9%w7DukkpZDaOl{@#g_BZ!i=P&toQLu5ycOJMlt;}EEZGSMa=d<1_wppMQbs%xd6#$A7!Xd$xh=6W4d%G_q>rkemII)nmxyfLea=jFHa?)A8L3)kFjFtb&xI@e&HuVC*Qj~t5wu+0gf8wHIel*Lny8NOA8h^Cm6Nr7@6bJ3YUhd1>G0lp_Xcie zu$vj|W{%+?mJ@>A%wRXO)y>RcH?zTZX7C<6GuX`xb~A(Hb8^ie*RwHU_1KVi;fU@9 zc&VNZ-A99U@4`U$4jsH*_cWFh#?~6lv!R+!_f*qhJxhKwJsY-;|ER6=mac7$tl%=v^D_q zUaMwkbx$>ou6%F2-d}Xy&8KV~aC5z<=(Fv+2`<+A$bJQm&mY%g`&js|jM*t2yJxkUbK6d?+hNll~GyJ~Z zuiN|shVR?<--aJOb}U7o`+B!BKRbJs5td-G5$}-Zm)c40oP#tsL1E0@btyg7f;_vKVUq4;q=AR z7f)Y2eeo}-FP^^m?~mPXJbn9UEqx=Oo5Ir#nTthb;i>d&vnN0{4x`L)k{9t zTpRkr>5Hc?p1ydVN7m67PhUKJ@$|*h7yqI9;#=yuqAwmEy+;`@dT%o7!~4SThrA~l zFM2;RUi4mMyy$&^^B!b056^$bi=KPd@w{ie=sC}L(es`0nwaOBcyvs8pj~p?kmgBp zuPN$Lwf(!#Q%e?K?Ol3ge0I&&cT?93$8$c|_RH-1E7zNxxPE8nL)l;V-94&qK6+K( z-8-lm&$o55b@MNZ`ey6qKe4)ei)O2ruQ^kiv!4EkZNE(IU%9@Xu6a@qH!#m?>7O+) z|L;}ja0BN%N`3Fq^{G2&T)*o#w^tqQGu}I8S9h;R$@AG=Ek+vr$9GQ-uDQw1n zbBcp!cMnUE1OCPCVc8zSHYZDtT^o?|+w#jQj`bODu=JE_2IPG4?#bSai;re)9dEtr zpm)kC_TE>0@F&W-MSZE?N^7g_Jn=c(9r{Vt<=@=o74(~yI`rwj?EGOf4L+P69aQb> zZgAr*OM;JXnVupCyziFj*+OA*D))5{zz4PV+F>&dzIogMXc36Q2`2RWpz5H!aJ|bCm=B#Lf&>O*6A< zX5Gx_Zf3WZ*}$3mUM*5hgH$x$6MGx*r^OS~M-40bbvnfW?9Pkhd)D=(`0 zo1TrHySfM5-&b@m!2e~R4Y2N=c{XA=8_O}6wLA3;pyy0~s7N&p=Gkz%o+WRZo(*!k z=y|wH&jz@o@E$!I;E$Daqn-_LGp&8i&J&;W#l_!MzNr0S+2X4M-qU~6^AF}--lKN} ztoO+51K^B(_rd$4oGjR`HTa3u11eOL_dVcUR!xIdGo_j)hj-Jyv(z;2DRthheK!N% zJN7H|`22DGufc~!UoAXXp}j8nSH}E(%<-29nxV?-# zzN7S!5rd<{!NX+a6GMZ8b7kb6DC;XD21kd3`RGDEF*G>1ql~-`vVJmRaCA6$gp7P* zXmD_68F`&#{bj`9=y32z8TrJ};9$Nfk=I35AR`7xhl5X-kxvW_4(=u+udBraEXR{a zY@iHIF8EB#(aw;OhX!^U^_^Z~WB73vlM5yfeTwDyOD!foRz?mO-ElnUgLaA4!E<7~ zSeP7g$#EP%LPqXv88JM3ndOt^$#XHs$4Fx>F*L{V!)4T&B_oE1FSUG(b9}Tk))GT=9G{d?=PDU7Jbba`7t539Vve6HjkUzk z9LE>Qs54VW3=hBF@{8ojb1}!yk;YnLXpZBD%BV9#Mhp*MB!gclBhSSg_ocCx7@9AG z;|paoWLL_F;b+LMlfi!^^DQRkxF^h7-)fHIhsemCZew`(Ld!3ZCy!dh98U?emKd7j z_`#O*vjNPyX)^Ng@CBAnkY|mHIgV%j6*AVOt%noCN@e7L(H+P0^9Rq*9x(CCWoQ_f z7@pX*7EhH&#}k_$Kxjn(JMgYo1omvP(>IkOi7Pn0#X#{V|4>4kOS z*ntm)d@mRFg?; zoUvlAM^0V+iWPH%y84u;PFPp}-5s5i>QzryzNfzRboKSeG*JI3>8l!;$5WjP8kj$R zj;9n}S;e)P^2#e7=k=En%MC8q^_$jZyJz$W2jJ(G^Yw`3Avph@B}uNa)qSUPy-T}n zH~FgL-)`$XqB)z6jOxexg2zNN1UeV$GeZ!Y!C`6!%uo}}5HN$*G6TBr^waq5!GdE=>zr!JnlcZ+Ehi>EH0x_Ij1sT=90x2X%KE}pu0>f)pOm7#~um2Xthx3B1a zWW4A;WR%PGhjZOCUUa=PUUZ!^>cjP|{l=v^5*0JIR-oNob5+%wIr-k;H^+Km|Lxfc zw>2_2o^#0=dBM;3j!BUd*QZE-bnlpKU43U%C#b8Reb4YB^{S`u>c2fzdRwD<`qVS> zytNI~pDaDwz&zVj=i&zDkDuec=igT~?Cqsq*YH15kA2cE@Y@!9orDj)GdGx2`d|wD zsqlo-2eYx90DbMtJBDhl!B2eB&hy$98+_!Qxt^zday}NGt2(TGKshD0e!MTZFq$Fj zW>9|C%>a(gU~=e%zVYQzL$%gmW*B94W*8mKoQ=(pz2DBj+IZi@!6ELx2ljq(-vjQc zz1IfY`|EPJM?tFrEi3JP3}W{#h~2Lsc8`MCeF@@ydrkjwQN_&Rm3j_?eNcba%CMXKE-nU$uZ2|J&v~*=64d-p}~n4SPtg*eaCwUlS3|=<2l0ZWW>5(BRbMcYN~j@Ra5Kb{n#l+Td`?=6|>+KGwZAtuGsW>6?jmji_fomzja2hQ<=fisbMfR_B{Q@ zR&vge-d_fe&Cl#^e)_oioo=+){3e$*ZZ1227@J=??kEfGwPUODv>$kd#pi~?#=tfD z-v=Y^`-g<{dacxT@N_+VADpi>ErpdAoM^VZb>Seb8)oXP3lD1zbvi5efT{Jo-%+@m zERlHL*R$uHEZko?|7d^BY0g9592dP;P;}{g1-kYbZ}C|VBuh4W-p^ku@a|vLBDil= z3xmgR^n#q4O_k`<0%DH~FMe`Nk@5qpn>Ao+(cS#ydu@L;u8Mq}t9NfSf55f+ z{?V_rEoTDWL5_8i%f~mCv7Zyev%iDUT|OS2eHo1B;AahM$YtNdbAXA#$z@OHK)A$OSu1&!N$YfmuVGJob7tIJlz>-SvdK9QJM2;#q^PXVk1AAB^Wb zSjV174jxXNJswXE7|+pGMjkP+%SB`Fr4AlWyqS#k9AGqfbIaw-HG*^G$lN+KIP37# zCB`*vCnJt02IidM#NGMB`8mT{@*D?qeTbnE2QxpO7?{KD(_9-4&W+~;i}w3P;hc4A zLhXxT)5IcQ*cX4V4Ck$DEf01FHH;qC)i=C4EgAK! zm+z}iy?o}H(Lnw93^AL^+k8R%z4}T;ScL1>`|tCcl`e`*Y2tEa(=Zl z-xbQs%Tv#m4@hm2PuTAWXxPNbd)WIqJox0vo!DO!<>dnm|NfX~_~glx4KFXBZ#aJs zlh5DT&nWj7s*gv*Q!nBJjGw6WaMt0UH1pN|{T$7a@uL12<^1B$F3;^fomvAQZ#u5uey&(Ybm*IDQ4CsIf4j-7QC@)93r6O9@- zY1*uLiBsfonf!O@vOYhXwz$#LJD$Dj zoT-(UE-l-1>c@BH&$+eqv5$WLlch)6SMRL%oiSxclWbFa7=fySkt7 zx6@xdJYx0gFV4T@^PAf|c+U;Dyz|ZBZwCJ0Xn$gQ`>b^D^q%zA^abh8>HX>F(vp^z zo%-=@;g|pO(UzropX}U~TQK{zCmzUaw(o8H{UrE~I{Tv<@@YF@OqbC>1UrI#(3 zJ+!c}FcHC#$I-CkNMRdI%$mJ)=Df7Yk0ALGBL8?;*O&iqg6vert; + %vp.setShaderConst( "$strength", $VolFogGlowPostFx::glowStrength ); + %vp=%this-->hor; + %vp.setShaderConst( "$strength", $VolFogGlowPostFx::glowStrength ); +} \ No newline at end of file diff --git a/Templates/Full/game/core/scripts/client/postFx/postFxManager.gui.settings.cs b/Templates/Full/game/core/scripts/client/postFx/postFxManager.gui.settings.cs index d30d2314b..77d664f41 100644 --- a/Templates/Full/game/core/scripts/client/postFx/postFxManager.gui.settings.cs +++ b/Templates/Full/game/core/scripts/client/postFx/postFxManager.gui.settings.cs @@ -70,6 +70,7 @@ function PostFXManager::settingsSetEnabled(%this, %bEnablePostFX) postVerbose("% - PostFX Manager - PostFX disabled"); } + VolFogGlowPostFx.disable(); } function PostFXManager::settingsEffectSetEnabled(%this, %sName, %bEnable) diff --git a/Templates/Full/game/core/scripts/client/renderManager.cs b/Templates/Full/game/core/scripts/client/renderManager.cs index dcd1628fe..5734bbce6 100644 --- a/Templates/Full/game/core/scripts/client/renderManager.cs +++ b/Templates/Full/game/core/scripts/client/renderManager.cs @@ -75,6 +75,8 @@ function initRenderManager() DiffuseRenderPassManager.addManager( new RenderParticleMgr() { renderOrder = 1.35; processAddOrder = 1.35; } ); DiffuseRenderPassManager.addManager( new RenderTranslucentMgr() { renderOrder = 1.4; processAddOrder = 1.4; } ); + DiffuseRenderPassManager.addManager(new RenderObjectMgr(FogBin){ bintype = "ObjectVolumetricFog"; renderOrder = 1.45; processAddOrder = 1.45; } ); + // Note that the GlowPostFx is triggered after this bin. DiffuseRenderPassManager.addManager( new RenderGlowMgr(GlowBin) { renderOrder = 1.5; processAddOrder = 1.5; } ); diff --git a/Templates/Full/game/core/scripts/client/shaders.cs b/Templates/Full/game/core/scripts/client/shaders.cs index 98d0529eb..002053a1a 100644 --- a/Templates/Full/game/core/scripts/client/shaders.cs +++ b/Templates/Full/game/core/scripts/client/shaders.cs @@ -101,4 +101,40 @@ new ShaderData( fxFoliageReplicatorShader ) samplerNames[1] = "$alphaMap"; pixVersion = 1.4; +}; + +singleton ShaderData( VolumetricFogPrePassShader ) +{ + DXVertexShaderFile = "shaders/common/VolumetricFog/VFogPreV.hlsl"; + DXPixelShaderFile = "shaders/common/VolumetricFog/VFogPreP.hlsl"; + + OGLVertexShaderFile = "shaders/common/VolumetricFog/gl/VFogPreV.glsl"; + OGLPixelShaderFile = "shaders/common/VolumetricFog/gl/VFogPreP.glsl"; + + pixVersion = 3.0; +}; +singleton ShaderData( VolumetricFogShader ) +{ + DXVertexShaderFile = "shaders/common/VolumetricFog/VFogV.hlsl"; + DXPixelShaderFile = "shaders/common/VolumetricFog/VFogP.hlsl"; + + OGLVertexShaderFile = "shaders/common/VolumetricFog/gl/VFogV.glsl"; + OGLPixelShaderFile = "shaders/common/VolumetricFog/gl/VFogP.glsl"; + + samplerNames[0] = "$prepassTex"; + samplerNames[1] = "$depthBuffer"; + samplerNames[2] = "$frontBuffer"; + samplerNames[3] = "$density"; + + pixVersion = 3.0; +}; +singleton ShaderData( VolumetricFogReflectionShader ) +{ + DXVertexShaderFile = "shaders/common/VolumetricFog/VFogPreV.hlsl"; + DXPixelShaderFile = "shaders/common/VolumetricFog/VFogRefl.hlsl"; + + OGLVertexShaderFile = "shaders/common/VolumetricFog/gl/VFogPreV.glsl"; + OGLPixelShaderFile = "shaders/common/VolumetricFog/gl/VFogRefl.glsl"; + + pixVersion = 3.0; }; \ No newline at end of file diff --git a/Templates/Full/game/scripts/server/VolumetricFog.cs b/Templates/Full/game/scripts/server/VolumetricFog.cs new file mode 100644 index 000000000..53e03adf3 --- /dev/null +++ b/Templates/Full/game/scripts/server/VolumetricFog.cs @@ -0,0 +1,106 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2012 GarageGames, LLC +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- + +function VolumetricFog::onEnterFog(%this,%obj) +{ + // This method is called whenever the control object (Camera or Player) + // %obj enters the fog area. + + // echo("Control Object " @ %obj @ " enters fog " @ %this); +} + +function VolumetricFog::onLeaveFog(%this,%obj) +{ + // This method is called whenever the control object (Camera or Player) + // %obj leaves the fog area. + + // echo("Control Object " @ %obj @ " left fog " @ %this); +} + +function VolumetricFog::Dissolve(%this,%speed,%delete) +{ + // This method dissolves the fog at speed milliseconds + %this.isBuilding = true; + if (%this.FogDensity > 0) + { + %this.setFogDensity(%this.FogDensity - 0.005); + %this.schedule(%speed,Dissolve,%speed,%delete); + } + else + { + %this.isBuilding = false; + %this.SetFogDensity(0.0); + if (%delete !$= "" && %delete !$="0" && %delete !$="false") + %this.schedule(250,delete); + } +} + +function VolumetricFog::Thicken(%this,%speed, %end_density) +{ + // This method thickens the fog at speed milliseconds to a density of %end_density + + %this.isBuilding = true; + if (%this.FogDensity + 0.005 < %end_density) + { + %this.setFogDensity(%this.FogDensity + 0.005); + %this.schedule(%speed,Thicken,%speed, %end_density); + } + else + { + %this.setFogDensity(%end_density); + %this.isBuilding = false; + } +} + +function GenerateFog(%pos,%scale,%color,%density) +{ + // This function can be used to generate some fog caused by massive gunfire etc. + // Change shape and modulation data to your likings. + + %fog=new VolumetricFog() { + shapeName = "art/environment/Fog_Sphere.dts"; + fogColor = %color; + fogDensity = "0.0"; + ignoreWater = "0"; + MinSize = "250"; + FadeSize = "750"; + texture = "art/environment/FogMod_heavy.dds"; + tiles = "1"; + modStrength = "0.2"; + PrimSpeed = "-0.01 0.04"; + SecSpeed = "0.02 0.02"; + position = %pos; + rotation = "0 0 1 20.354"; + scale = %scale; + canSave = "1"; + canSaveDynamicFields = "1"; + }; + + if (isObject(%fog)) + { + MissionCleanup.add(%fog); + + %fog.Thicken(500,%density); + } + + return %fog; +} \ No newline at end of file diff --git a/Templates/Full/game/scripts/server/scriptExec.cs b/Templates/Full/game/scripts/server/scriptExec.cs index 64d4adc06..26f4f8280 100644 --- a/Templates/Full/game/scripts/server/scriptExec.cs +++ b/Templates/Full/game/scripts/server/scriptExec.cs @@ -24,6 +24,7 @@ // a server is constructed. exec("./camera.cs"); exec("./triggers.cs"); +exec("./VolumetricFog.cs"); exec("./inventory.cs"); exec("./shapeBase.cs"); exec("./item.cs"); diff --git a/Templates/Full/game/shaders/common/VolumetricFog/VFogP.hlsl b/Templates/Full/game/shaders/common/VolumetricFog/VFogP.hlsl new file mode 100644 index 000000000..aaadbf479 --- /dev/null +++ b/Templates/Full/game/shaders/common/VolumetricFog/VFogP.hlsl @@ -0,0 +1,87 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2012 GarageGames, LLC +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- + +// Volumetric Fog final pixel shader V2.00 + +#include "shadergen:/autogenConditioners.h" +#include "../torque.hlsl" + +uniform sampler2D prepassTex : register(S0); +uniform sampler2D depthBuffer : register(S1); +uniform sampler2D frontBuffer : register(S2); +uniform sampler2D density : register(S3); + +uniform float accumTime; +uniform float4 fogColor; +uniform float fogDensity; +uniform float preBias; +uniform float textured; +uniform float modstrength; +uniform float4 modspeed;//xy speed layer 1, zw speed layer 2 +uniform float2 viewpoint; +uniform float2 texscale; +uniform float3 ambientColor; +uniform float numtiles; +uniform float fadesize; +uniform float2 PixelSize; + +struct ConnectData +{ + float4 hpos : POSITION; + float4 htpos : TEXCOORD0; + float2 uv0 : TEXCOORD1; +}; + +float4 main( ConnectData IN ) : COLOR0 +{ + float2 uvscreen=((IN.htpos.xy/IN.htpos.w) + 1.0 ) / 2.0; + uvscreen.y = 1.0 - uvscreen.y; + + float obj_test = prepassUncondition( prepassTex, uvscreen).w * preBias; + float depth = tex2D(depthBuffer,uvscreen).r; + float front = tex2D(frontBuffer,uvscreen).r; + + if (depth <= front) + return float4(0,0,0,0); + else if ( obj_test < depth ) + depth = obj_test; + if ( front >= 0.0) + depth -= front; + + float diff = 1.0; + float3 col = fogColor.rgb; + if (textured != 0.0) + { + float2 offset = viewpoint + ((-0.5 + (texscale * uvscreen)) * numtiles); + + float2 mod1 = tex2D(density,(offset + (modspeed.xy*accumTime))).rg; + float2 mod2= tex2D(density,(offset + (modspeed.zw*accumTime))).rg; + diff = (mod2.r + mod1.r) * modstrength; + col *= (2.0 - ((mod1.g + mod2.g) * fadesize))/2.0; + } + + col *= ambientColor; + + float4 resultColor = float4(col, 1.0 - saturate(exp(-fogDensity * depth * diff * fadesize))); + + return hdrEncode(resultColor); +} diff --git a/Templates/Full/game/shaders/common/VolumetricFog/VFogPreP.hlsl b/Templates/Full/game/shaders/common/VolumetricFog/VFogPreP.hlsl new file mode 100644 index 000000000..bb06f5f7c --- /dev/null +++ b/Templates/Full/game/shaders/common/VolumetricFog/VFogPreP.hlsl @@ -0,0 +1,39 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2012 GarageGames, LLC +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- + +// Volumetric Fog prepass pixel shader V1.00 + +struct ConnectData +{ + float4 hpos : POSITION; + float4 pos : TEXCOORD0; +}; + +float4 main( ConnectData IN ) : COLOR0 +{ + float OUT; + + clip( IN.pos.w ); + OUT = IN.pos.w; + + return float4(OUT,0,0,1); +} diff --git a/Templates/Full/game/shaders/common/VolumetricFog/VFogPreV.hlsl b/Templates/Full/game/shaders/common/VolumetricFog/VFogPreV.hlsl new file mode 100644 index 000000000..2d13cdf01 --- /dev/null +++ b/Templates/Full/game/shaders/common/VolumetricFog/VFogPreV.hlsl @@ -0,0 +1,46 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2012 GarageGames, LLC +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- + +// Volumetric Fog prepass vertex shader V1.00 + +#include "shaders/common/hlslstructs.h" + +struct ConnectData +{ + float4 hpos : POSITION; + float4 pos : TEXCOORD0; +}; + +uniform float4x4 modelView; + +ConnectData main( VertexIn_P IN) +{ + ConnectData OUT; + + float4 inPos = IN.pos; + inPos.w = 1.0; + + OUT.hpos = mul( modelView, inPos ); + OUT.pos = OUT.hpos; + + return OUT; +} diff --git a/Templates/Full/game/shaders/common/VolumetricFog/VFogRefl.hlsl b/Templates/Full/game/shaders/common/VolumetricFog/VFogRefl.hlsl new file mode 100644 index 000000000..bd9866cf8 --- /dev/null +++ b/Templates/Full/game/shaders/common/VolumetricFog/VFogRefl.hlsl @@ -0,0 +1,37 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2012 GarageGames, LLC +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- + +// Volumetric Fog Reflection pixel shader V1.00 +uniform float4 fogColor; +uniform float fogDensity; +uniform float reflStrength; + +struct ConnectData +{ + float4 hpos : POSITION; + float4 pos : TEXCOORD0; +}; + +float4 main( ConnectData IN ) : COLOR0 +{ + return float4(fogColor.rgb,saturate(fogDensity*reflStrength)); +} diff --git a/Templates/Full/game/shaders/common/VolumetricFog/VFogV.hlsl b/Templates/Full/game/shaders/common/VolumetricFog/VFogV.hlsl new file mode 100644 index 000000000..7f86802b5 --- /dev/null +++ b/Templates/Full/game/shaders/common/VolumetricFog/VFogV.hlsl @@ -0,0 +1,45 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2012 GarageGames, LLC +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- + +// Volumetric Fog final vertex shader V1.00 + +#include "shaders/common/hlslstructs.h" + +struct ConnectData +{ + float4 hpos : POSITION; + float4 htpos : TEXCOORD0; + float2 uv0 : TEXCOORD1; +}; + +uniform float4x4 modelView; + +ConnectData main( VertexIn_PNT IN) +{ + ConnectData OUT; + + OUT.hpos = mul(modelView, IN.pos); + OUT.htpos = OUT.hpos; + OUT.uv0 = IN.uv0; + + return OUT; +} diff --git a/Templates/Full/game/shaders/common/VolumetricFog/gl/VFogP.glsl b/Templates/Full/game/shaders/common/VolumetricFog/gl/VFogP.glsl new file mode 100644 index 000000000..7895d9e2d --- /dev/null +++ b/Templates/Full/game/shaders/common/VolumetricFog/gl/VFogP.glsl @@ -0,0 +1,87 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2012 GarageGames, LLC +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- + +#include "../../gl/hlslCompat.glsl" +#include "shadergen:/autogenConditioners.h" +#include "../../gl/torque.glsl" + +uniform sampler2D prepassTex; +uniform sampler2D depthBuffer; +uniform sampler2D frontBuffer; +uniform sampler2D density; + +uniform float accumTime; +uniform vec4 fogColor; +uniform float fogDensity; +uniform float preBias; +uniform float textured; +uniform float modstrength; +uniform vec4 modspeed;//xy speed layer 1, zw speed layer 2 +uniform vec2 viewpoint; +uniform vec2 texscale; +uniform vec3 ambientColor; +uniform float numtiles; +uniform float fadesize; +uniform vec2 PixelSize; + +in vec4 _hpos; +#define IN_hpos _hpos +out vec4 OUT_col; + +void main() +{ + vec2 uvscreen=((IN_hpos.xy/IN_hpos.w) + 1.0 ) / 2.0; + uvscreen.y = 1.0 - uvscreen.y; + + float obj_test = prepassUncondition( prepassTex, uvscreen).w * preBias; + float depth = tex2D(depthBuffer,uvscreen).r; + float front = tex2D(frontBuffer,uvscreen).r; + + if (depth <= front) + { + OUT_col = vec4(0,0,0,0); + return; + } + + else if ( obj_test < depth ) + depth = obj_test; + if ( front >= 0.0) + depth -= front; + + float diff = 1.0; + vec3 col = fogColor.rgb; + if (textured != 0.0) + { + vec2 offset = viewpoint + ((-0.5 + (texscale * uvscreen)) * numtiles); + + vec2 mod1 = tex2D(density,(offset + (modspeed.xy*accumTime))).rg; + vec2 mod2= tex2D(density,(offset + (modspeed.zw*accumTime))).rg; + diff = (mod2.r + mod1.r) * modstrength; + col *= (2.0 - ((mod1.g + mod2.g) * fadesize))/2.0; + } + + col *= ambientColor; + + vec4 returnColor = vec4(col, 1.0 - saturate(exp(-fogDensity * depth * diff * fadesize))); + + OUT_col = hdrEncode(returnColor); +} diff --git a/Templates/Full/game/shaders/common/VolumetricFog/gl/VFogPreP.glsl b/Templates/Full/game/shaders/common/VolumetricFog/gl/VFogPreP.glsl new file mode 100644 index 000000000..017ea6ef8 --- /dev/null +++ b/Templates/Full/game/shaders/common/VolumetricFog/gl/VFogPreP.glsl @@ -0,0 +1,37 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2012 GarageGames, LLC +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- + +#include "../../gl/hlslCompat.glsl" + +in vec4 _hpos; +#define IN_hpos _hpos + +out vec4 OUT_col; + +void main() +{ + float OUT; + clip( IN_hpos.w ); + OUT = IN_hpos.w; + + OUT_col = vec4(OUT,0,0,1); +} diff --git a/Templates/Full/game/shaders/common/VolumetricFog/gl/VFogPreV.glsl b/Templates/Full/game/shaders/common/VolumetricFog/gl/VFogPreV.glsl new file mode 100644 index 000000000..2f2a1318a --- /dev/null +++ b/Templates/Full/game/shaders/common/VolumetricFog/gl/VFogPreV.glsl @@ -0,0 +1,42 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2012 GarageGames, LLC +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- + +#include "../../gl/hlslCompat.glsl" + +in vec4 vPosition; +#define IN_position vPosition + +out vec4 _hpos; +#define OUT_hpos _hpos + +uniform mat4 modelView; + +void main() +{ + vec4 inPos = IN_position; + inPos.w = 1.0; + + OUT_hpos = tMul( modelView, inPos ); + + gl_Position = OUT_hpos; + correctSSP(gl_Position); +} diff --git a/Templates/Full/game/shaders/common/VolumetricFog/gl/VFogRefl.glsl b/Templates/Full/game/shaders/common/VolumetricFog/gl/VFogRefl.glsl new file mode 100644 index 000000000..78e149fbf --- /dev/null +++ b/Templates/Full/game/shaders/common/VolumetricFog/gl/VFogRefl.glsl @@ -0,0 +1,33 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2012 GarageGames, LLC +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- + +#include "../../gl/hlslCompat.glsl" + +uniform vec4 fogColor; +uniform float fogDensity; +uniform float reflStrength; +out vec4 OUT_col; + +void main() +{ + OUT_col = vec4(fogColor.rgb,saturate(fogDensity*reflStrength)); +} diff --git a/Templates/Full/game/shaders/common/VolumetricFog/gl/VFogV.glsl b/Templates/Full/game/shaders/common/VolumetricFog/gl/VFogV.glsl new file mode 100644 index 000000000..57b3ba87e --- /dev/null +++ b/Templates/Full/game/shaders/common/VolumetricFog/gl/VFogV.glsl @@ -0,0 +1,38 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2012 GarageGames, LLC +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- + +#include "../../gl/hlslCompat.glsl" + +in vec4 vPosition; +#define IN_position vPosition + +out vec4 _hpos; +#define OUT_hpos _hpos + +uniform mat4 modelView; + +void main() +{ + OUT_hpos = tMul(modelView, IN_position); + gl_Position = OUT_hpos; + correctSSP(gl_Position); +} diff --git a/Templates/Full/game/shaders/common/postFx/VolFogGlowP.hlsl b/Templates/Full/game/shaders/common/postFx/VolFogGlowP.hlsl new file mode 100644 index 000000000..8a61b5928 --- /dev/null +++ b/Templates/Full/game/shaders/common/postFx/VolFogGlowP.hlsl @@ -0,0 +1,74 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2014 R.G.S. - Richards Game Studio, the Netherlands +// http://www.richardsgamestudio.com/ +// +// If you find this code useful or you are feeling particularly generous I +// would ask that you please go to http://www.richardsgamestudio.com/ then +// choose Donations from the menu on the left side and make a donation to +// Richards Game Studio. It will be highly appreciated. +// +// The MIT License: +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- + +// Volumetric Fog Glow postFx pixel shader V1.00 + +#include "./postFx.hlsl" + +uniform sampler2D diffuseMap : register(S0); +uniform float strength; + +struct VertToPix +{ + float4 hpos : POSITION; + + float2 uv0 : TEXCOORD0; + float2 uv1 : TEXCOORD1; + float2 uv2 : TEXCOORD2; + float2 uv3 : TEXCOORD3; + + float2 uv4 : TEXCOORD4; + float2 uv5 : TEXCOORD5; + float2 uv6 : TEXCOORD6; + float2 uv7 : TEXCOORD7; +}; + +float4 main( VertToPix IN ) : COLOR +{ + float4 kernel = float4( 0.175, 0.275, 0.375, 0.475 ) * strength; + + float4 OUT = 0; + OUT += tex2D( diffuseMap, IN.uv0 ) * kernel.x; + OUT += tex2D( diffuseMap, IN.uv1 ) * kernel.y; + OUT += tex2D( diffuseMap, IN.uv2 ) * kernel.z; + OUT += tex2D( diffuseMap, IN.uv3 ) * kernel.w; + + OUT += tex2D( diffuseMap, IN.uv4 ) * kernel.x; + OUT += tex2D( diffuseMap, IN.uv5 ) * kernel.y; + OUT += tex2D( diffuseMap, IN.uv6 ) * kernel.z; + OUT += tex2D( diffuseMap, IN.uv7 ) * kernel.w; + + // Calculate a lumenance value in the alpha so we + // can use alpha test to save fillrate. + float3 rgb2lum = float3( 0.30, 0.59, 0.11 ); + OUT.a = dot( OUT.rgb, rgb2lum ); + + return OUT; +} diff --git a/Templates/Full/game/shaders/common/postFx/gl/VolFogGlowP.glsl b/Templates/Full/game/shaders/common/postFx/gl/VolFogGlowP.glsl new file mode 100644 index 000000000..01b072dd9 --- /dev/null +++ b/Templates/Full/game/shaders/common/postFx/gl/VolFogGlowP.glsl @@ -0,0 +1,67 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2014 R.G.S. - Richards Game Studio, the Netherlands +// http://www.richardsgamestudio.com/ +// +// If you find this code useful or you are feeling particularly generous I +// would ask that you please go to http://www.richardsgamestudio.com/ then +// choose Donations from the menu on the left side and make a donation to +// Richards Game Studio. It will be highly appreciated. +// +// The MIT License: +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- + +// Volumetric Fog Glow postFx pixel shader V1.00 + +uniform sampler2D diffuseMap; +uniform float strength; + +out vec4 OUT_col; + +in vec2 uv0; +in vec2 uv1; +in vec2 uv2; +in vec2 uv3; + +in vec2 uv4; +in vec2 uv5; +in vec2 uv6; +in vec2 uv7; + +void main() +{ + vec4 kernel = vec4( 0.175, 0.275, 0.375, 0.475 ) * strength; + + OUT_col = vec4(0); + OUT_col += texture( diffuseMap, uv0 ) * kernel.x; + OUT_col += texture( diffuseMap, uv1 ) * kernel.y; + OUT_col += texture( diffuseMap, uv2 ) * kernel.z; + OUT_col += texture( diffuseMap, uv3 ) * kernel.w; + + OUT_col += texture( diffuseMap, uv4 ) * kernel.x; + OUT_col += texture( diffuseMap, uv5 ) * kernel.y; + OUT_col += texture( diffuseMap, uv6 ) * kernel.z; + OUT_col += texture( diffuseMap, uv7 ) * kernel.w; + + // Calculate a lumenance value in the alpha so we + // can use alpha test to save fillrate. + vec3 rgb2lum = vec3( 0.30, 0.59, 0.11 ); + OUT_col.a = dot( OUT_col.rgb, rgb2lum ); +} diff --git a/Templates/Full/game/tools/classIcons/VolumetricFog.png b/Templates/Full/game/tools/classIcons/VolumetricFog.png new file mode 100644 index 0000000000000000000000000000000000000000..5dc516cb53d99e0ae0d125507d6d95c9a2942107 GIT binary patch literal 3642 zcmV-A4#n|_P)KLZ*U+IBfRsybQWXdwQbLP>6pAqfylh#{fb6;Z(vMMVS~$e@S=j*ftg6;Uhf59&ghTmgWD0l;*T zI709Y^p6lP1rIRMx#05C~cW=H_Aw*bJ-5DT&Z2n+x)QHX^p z00esgV8|mQcmRZ%02D^@S3L16t`O%c004NIvOKvYIYoh62rY33S640`D9%Y2D-rV&neh&#Q1i z007~1e$oCcFS8neI|hJl{-P!B1ZZ9hpmq0)X0i`JwE&>$+E?>%_LC6RbVIkUx0b+_+BaR3cnT7Zv!AJxW zizFb)h!jyGOOZ85F;a?DAXP{m@;!0_IfqH8(HlgRxt7s3}k3K`kFu>>-2Q$QMFfPW!La{h336o>X zu_CMttHv6zR;&ZNiS=X8v3CR#fknUxHUxJ0uoBa_M6WNWeqIg~6QE69c9o#eyhGvpiOA@W-aonk<7r1(?fC{oI5N*U!4 zfg=2N-7=cNnjjOr{yriy6mMFgG#l znCF=fnQv8CDz++o6_Lscl}eQ+l^ZHARH>?_s@|##Rr6KLRFA1%Q+=*RRWnoLsR`7U zt5vFIcfW3@?wFpwUVxrVZ>QdQz32KIeJ}k~{cZZE^+ya? z2D1z#2HOnI7(B%_ac?{wFUQ;QQA1tBKtrWrm0_3Rgps+?Jfqb{jYbcQX~taRB;#$y zZN{S}1|}gUOHJxc?wV3fxuz+mJ4`!F$IZ;mqRrNsHJd##*D~ju=bP7?-?v~|cv>vB zsJ6IeNwVZxrdjT`yl#bBIa#GxRa#xMMy;K#CDyyGyQdMSxlWT#tDe?p!?5wT$+oGt z8L;Kp2HUQ-ZMJ=3XJQv;x5ci*?vuTfeY$;({XGW_huIFR9a(?@3)XSs8O^N5RyOM=TTmp(3=8^+zpz2r)C z^>JO{deZfso3oq3?Wo(Y?l$ge?uXo;%ru`Vo>?<<(8I_>;8Eq#KMS9gFl*neeosSB zfoHYnBQIkwkyowPu(zdms`p{<7e4kra-ZWq<2*OsGTvEV%s0Td$hXT+!*8Bnh2KMe zBmZRodjHV?r+_5^X9J0WL4jKW`}lf%A-|44I@@LTvf1rHjG(ze6+w@Jt%Bvjts!X0 z?2xS?_ve_-kiKB_KiJlZ$9G`c^=E@oNG)mWWaNo-3TIW8)$Hg0Ub-~8?KhvJ>$ z3*&nim@mj(aCxE5!t{lw7O5^0EIO7zOo&c6l<+|iDySBWCGrz@C5{St!X3hAA}`T4 z(TLbXTq+(;@<=L8dXnssyft|w#WSTW<++3>sgS%(4NTpeI-VAqb|7ssJvzNHgOZVu zaYCvgO_R1~>SyL=cFU|~g|hy|Zi}}s9+d~lYqOB71z9Z$wnC=pR9Yz4DhIM>Wmjgu z&56o6maCpC&F##y%G;1PobR9i?GnNg;gYtchD%p19a!eQtZF&3JaKv33gZ<8D~47E ztUS1iwkmDaPpj=$m#%)jCVEY4fnLGNg2A-`YwHVD3gv};>)hAvT~AmqS>Lr``i7kw zJ{5_It`yrBmlc25DBO7E8;5VoznR>Ww5hAaxn$2~(q`%A-YuS64wkBy=9dm`4cXeX z4c}I@?e+FW+b@^RDBHV(wnMq2zdX3SWv9u`%{xC-q*U}&`cyXV(%rRT*Z6MH?i+i& z_B8C(+grT%{XWUQ+f@NoP1R=AW&26{v-dx)iK^-Nmiuj8txj!m?Z*Ss1N{dh4z}01 z)YTo*JycSU)+_5r4#yw9{+;i4Ee$peRgIj+;v;ZGdF1K$3E%e~4LaI(jC-u%2h$&R z9cLXcYC@Xwnns&bn)_Q~Te?roKGD|d-g^8;+aC{{G(1^(O7m37Y1-+6)01cN&y1aw zoqc{T`P^XJqPBbIW6s}d4{z_f5Om?vMgNQEJG?v2T=KYd^0M3I6IZxbny)%vZR&LD zJpPl@Psh8QyPB@KTx+@RdcC!KX7}kEo;S|j^u2lU7XQ}Oo;f|;z4Ll+_r>@1-xl3| zawq-H%e&ckC+@AhPrP6BKT#_XdT7&;F71j}Joy zkC~6lh7E@6o;W@^IpRNZ{ptLtL(gQ-CY~4mqW;US7Zxvm_|@yz&e53Bp_lTPlfP|z zrTyx_>lv@x#=^!PzR7qqF<$gm`|ZJZ+;<)Cqu&ot2z=0000WV@Og>004R=004l4008;_004mL004C`008P>0026e000+nl3&F} z000AJNkl9kNXb9;;<2!NH znsiy4Zgt--Ts3J^cd%(1u`#6(l!CQskx~@vbJU9r;0%Z}-nldP{@pZ<@$A0jJIfD{)_^I^O+{5a?kaZ= zQ1QH@C8J3IT;+bCP#^WI>8aTM(st)^=CTvfBP(4kU3SNw4!Nyzn?IM%#jJvrP^d~n z8c!8!MN3ALDAYkAMDNkfM;q6lY+U7`^zna2<4gX>yRzZ=&WF{h&WojAWU=Mh`F9iV z`2tq?ru+7NO%vKR9oT1kcJGl5M_!re_^skh-z9&e(M)ZqhVX_UuWxB1U2k!F;;;5Q z*&FRw(qnwM>)}wEx)g{gkUH*6b2f?j+0kWfF;(soz|O zUC1#zcb9>)gNGV|tzXaQ7MrE5=Xcs|Pq*F4P5bRa9@Fq)2K>}E*I?&u(oUM9Tfiw6 z@H~&2wT(2z>oCLe@UkznOLt_UX5G4a>e~+DxHbxf^h?SUA&S!_@@^hy!68r^!ZS-~ z(x7+mex{eNM#cxnj_Lw|%0Wo{amOFSH~`19T*Rq+Tp*WvBm zZxL&0LJW%*T_|zu?)Zb|ja!-sR#$NEl11rant`dG$mMM8l;T3wFlJQZ-7L_ws)_7K zmboYQ(S?rI5qcvQEk!F;QB<0bd|bcqH$UGRLOwHiGulaKcRMW)Hsa5g^Z3ydrmY#S zTi2MJnZZ{K%;vUaZPkO;@su>V4IintAQpulf#4zl^$1-NnpE=Iq3Y zi9P4$&t*KkD?aHv#cRIuZDMoua?!9 Date: Tue, 1 Dec 2015 00:49:37 -0600 Subject: [PATCH 22/47] Missed a few files. --- Engine/source/environment/VolumetricFog.cpp | 1319 +++++++++++++++++ Engine/source/environment/VolumetricFog.h | 243 +++ .../environment/VolumetricFogRTManager.cpp | 299 ++++ .../environment/VolumetricFogRTManager.h | 92 ++ 4 files changed, 1953 insertions(+) create mode 100644 Engine/source/environment/VolumetricFog.cpp create mode 100644 Engine/source/environment/VolumetricFog.h create mode 100644 Engine/source/environment/VolumetricFogRTManager.cpp create mode 100644 Engine/source/environment/VolumetricFogRTManager.h diff --git a/Engine/source/environment/VolumetricFog.cpp b/Engine/source/environment/VolumetricFog.cpp new file mode 100644 index 000000000..e6be112dc --- /dev/null +++ b/Engine/source/environment/VolumetricFog.cpp @@ -0,0 +1,1319 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2012 GarageGames, LLC +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- + +#include "environment/VolumetricFog.h" +#include "windowManager/platformWindowMgr.h" +#include "gfx/gfxTransformSaver.h" +#include "renderInstance/renderPassManager.h" +#include "math/mathIO.h" +#include "materials/shaderData.h" +#include "math/util/matrixSet.h" +#include "core/resourceManager.h" +#include "core/stream/bitStream.h" +#include "T3D/gameBase/gameConnection.h" +#include "T3D/shapeBase.h" +#include "ts/tsShapeInstance.h" +#include "console/engineAPI.h" +#include "gui/core/guiCanvas.h" +#include "VolumetricFogRTManager.h" +#include "lighting/lightInfo.h" +#include "lighting/lightManager.h" + +#define COLBOX_SCALE Point3F(1.02f, 1.02f, 1.02f) + +IMPLEMENT_CO_NETOBJECT_V1(VolumetricFog); + +ConsoleDocClass(VolumetricFog, +"@brief Volumetric Fog Object class. Main class defining the Volumetric\n" +"Fog objects in the scene. Used in conjunction with the VolumetricFogRTManager\n" +"class which is responsible for the required rendertargets.\n\n" +"Methods (exposed to script):\n" +" setFogColorF(color) Changes the overall fog color (color.rgba range 0.0 - 1.0).\n;" +" setFogColor(color) Changes the overall fog color color.rgba range 0 - 255).\n;" +" setFogDensity(density) Changes the overall fog density.\n" +" setFogModulation(strength, speed1, speed2) changes the strength\n" +" and the speeds of the 2 animation layers.\n\n" +"Callbacks:\n" +"onEnterFog triggered whenever the controlobject (Player or Camera) enters the Fog.\n" +" (current Fog object and the controlobject are exposed to script.\n" +"onLeaveFog triggered whenever the controlobject (Player or Camera) left the Fog.\n" +" (current Fog object and the controlobject are exposed to script.\n\n" +"@tsexample\n" +" new VolumetricFog()\n" +" {\n" +" shapeName = \"art/environment/FogRCube.dts\";\n" +" fogColor = \"200 200 200 128\";\n" +" fogDensity = \"0.2\";\n" +" ignoreWater = \"0\";\n" +" MinSize = \"250\";\n" +" FadeSize = \"750\";\n" +" texture = \"art/environment/FogMod_heavy.dds\";\n" +" tiles = \"1.5\";\n" +" modStrength = \"0.2\";\n" +" PrimSpeed = \"-0.01 0.04\";\n" +" SecSpeed = \"0.02 -0.02\";\n" +" position = \"748.644 656.371 65.3506\"; \n" +" rotation = \"0 0 1 20.354\";\n" +" scale = \"40 30 6\";\n" +" };\n" +"@endtsexample\n" +); + +IMPLEMENT_CALLBACK(VolumetricFog, onEnterFog, void, (SimObjectId obj), (obj), +"@brief Called when an object enters the volume of the Fog instance.\n\n" + +"@param obj the controlobject entering the fog."); + +IMPLEMENT_CALLBACK(VolumetricFog, onLeaveFog, void, (SimObjectId obj), (obj), +"@brief Called when an object left the volume of the Fog instance.\n\n" + +"@param obj the controlobject leaving the fog."); + + +VolumetricFog::VolumetricFog() +{ + AssertFatal(VFRTM != NULL, "VolumetricFog Fatal Error: No Manager found"); + + if (!VFRTM->IsInitialized()) + VFRTM->Init(); + + mNetFlags.set(Ghostable | ScopeAlways); + + mTypeMask |= EnvironmentObjectType | StaticObjectType; + + mPrepassTarget = NULL; + mDepthBufferTarget = NULL; + mFrontBufferTarget = NULL; + + z_buf = NULL; + mTexture = NULL; + + mIsVBDirty = false; + mIsPBDirty = false; + + mFogColor.set(200, 200, 200, 255); + mFogDensity = 0.3f; + mIgnoreWater = false; + mReflect = false; + mCamInFog = false; + mResizing = false; + mFogReflStrength = 20.0; + mUseGlow = false; + mGlowStrength = 0.3f; + mGlowing = 0; + mModifLightRays = false; + mLightRayMod = 1.0f; + mOldLightRayStrength = 0.1f; + + mShapeName = ""; + mShapeLoaded = false; + mMinDisplaySize = 10.0f; + mFadeSize = 0.0f; + mCurDetailLevel = 0; + mNumDetailLevels = 0; + det_size.clear(); + + mTextureName = ""; + mIsTextured = false; + mStrength = 0.5f; + mTexTiles = 1.0f; + mSpeed1.set(0.5f, 0.0f); + mSpeed2.set(0.1f, 0.1f); +} + +VolumetricFog::~VolumetricFog() +{ + if (isClientObject()) + return; + + for (S32 i = 0; i < det_size.size(); i++) + { + if (det_size[i].indices != NULL) + delete(det_size[i].indices); + if (det_size[i].piArray != NULL) + delete(det_size[i].piArray); + if (det_size[i].verts != NULL) + delete(det_size[i].verts); + } + det_size.clear(); + + if (z_buf.isValid()) + SAFE_DELETE(z_buf); + + if (!mTexture.isNull()) + mTexture.free(); +} + +void VolumetricFog::initPersistFields() +{ + addGroup("VolumetricFogData"); + addField("shapeName", TypeShapeFilename, Offset(mShapeName, VolumetricFog), + "Path and filename of the model file (.DTS, .DAE) to use for this Volume."); + addField("FogColor", TypeColorI, Offset(mFogColor, VolumetricFog), + "Fog color RGBA (Alpha is ignored)"); + addField("FogDensity", TypeF32, Offset(mFogDensity, VolumetricFog), + "Overal fog density value (0 disables the fog)."); + addField("IgnoreWater", TypeBool, Offset(mIgnoreWater, VolumetricFog), + "Set to true if volumetric fog should continue while submerged."); + addField("MinSize", TypeF32, Offset(mMinDisplaySize, VolumetricFog), + "Min size (in pixels) for fog to be rendered."); + addField("FadeSize", TypeF32, Offset(mFadeSize, VolumetricFog), + "Object size in pixels at which the FX-fading kicks in (0 disables fading)."); + endGroup("VolumetricFogData"); + + addGroup("VolumetricFogModulation"); + addField("texture", TypeImageFilename, Offset(mTextureName, VolumetricFog), + "A texture which contains Fogdensity modulator in the red channel and color with 1-green channel. No texture disables modulation."); + addField("tiles", TypeF32, Offset(mTexTiles, VolumetricFog), + "How many times the texture is mapped to the object."); + addField("modStrength", TypeF32, Offset(mStrength, VolumetricFog), + "Overall strength of the density modulation (0 disables modulation)."); + addField("PrimSpeed", TypePoint2F, Offset(mSpeed1, VolumetricFog), + "Overall primary speed of the density modulation (x-speed(u) y-speed(v))"); + addField("SecSpeed", TypePoint2F, Offset(mSpeed2, VolumetricFog), + "Overall secundary speed of the density modulation (x-speed(u) y-speed(v))"); + endGroup("VolumetricFogModulation"); + + addGroup("Reflections"); + addField("Reflectable", TypeBool, Offset(mReflect, VolumetricFog), + "Set to true if volumetric fog should be reflected."); + addField("ReflectStrength", TypeF32, Offset(mFogReflStrength, VolumetricFog), + "Strength of the reflections (0 disables the fog)."); + endGroup("Reflections"); + + addGroup("PostFX"); + addField("useGlow", TypeBool, Offset(mUseGlow, VolumetricFog), + "Set to true if volumetric fog should use glow PostFX."); + addField("glowStrength", TypeF32, Offset(mGlowStrength, VolumetricFog), + "Overall strength of the glow PostFX."); + addField("modLightRay", TypeBool, Offset(mModifLightRays, VolumetricFog), + "Set to true if volumetric fog should modify the brightness of the Lightrays."); + addField("lightRayMod", TypeF32, Offset(mLightRayMod, VolumetricFog), + "Modifier for LightRay PostFX when inside Fog."); + endGroup("PostFX"); + Parent::initPersistFields(); +} + +void VolumetricFog::inspectPostApply() +{ + Parent::inspectPostApply(); + mSpeed.set(mSpeed1.x, mSpeed1.y, mSpeed2.x, mSpeed2.y); + setMaskBits(VolumetricFogMask | FogColorMask | FogDensityMask | FogModulationMask | FogPostFXMask | FogShapeMask); +} + +bool VolumetricFog::onAdd() +{ + if (!Parent::onAdd()) + return false; + + if (!VFRTM->IsInitialized()) + { + Con::errorf("No VolumetricFogRTManager present!!"); + return false; + } + + resetWorldBox(); + + mShapeLoaded = LoadShape(); + + setRenderTransform(mObjToWorld); + + addToScene(); + ColBox.set(getTransform(), (mObjBox.getExtents() * getScale() * COLBOX_SCALE)); + mObjSize = mWorldBox.getGreatestDiagonalLength(); + mObjScale = getScale(); + mTexTiles = mAbs(mTexTiles); + mSpeed.set(mSpeed1.x, mSpeed1.y, mSpeed2.x, mSpeed2.y); + mInvScale = (1.0f / getMax(getMax(mObjScale.x, mObjScale.y), mObjScale.z)); + + if (isClientObject()) + { + conn = GameConnection::getConnectionToServer(); + if (!conn) + { + Con::errorf("VolumetricFog::onAdd - No Serverconnection"); + return false; + } + + glowFX = static_cast(Sim::findObject("VolFogGlowPostFx")); + + mOldLightRayStrength = Con::getFloatVariable("$LightRayPostFX::brightScalar",1.0f); + + GuiCanvas* cv = dynamic_cast(Sim::findObject("Canvas")); + if (cv == NULL) + { + Con::errorf("VolumetricFog::onAdd - Canvas not found!!"); + return false; + } + mPlatformWindow = cv->getPlatformWindow(); + VolumetricFogRTManager::getVolumetricFogRTMResizeSignal().notify(this, &VolumetricFog::handleResize); + GuiCanvas::getCanvasSizeChangeSignal().notify(this, &VolumetricFog::handleCanvasResize); + + InitTexture(); + return setupRenderer(); + } + + VFRTM->IncFogObjects(); + + return true; +} + +void VolumetricFog::onRemove() +{ + if (isClientObject()) + { + if (isTicking()) + { + setProcessTick(false); + if (mGlowing != 0) + { + mGlowing = 0; + glowFX->disable(); + } + _leaveFog(static_cast(conn->getControlObject())); + } + VolumetricFogRTManager::getVolumetricFogRTMResizeSignal().remove(this, &VolumetricFog::handleResize); + GuiCanvas::getCanvasSizeChangeSignal().remove(this, &VolumetricFog::handleCanvasResize); + } + removeFromScene(); + VFRTM->DecFogObjects(); + Parent::onRemove(); +} +void VolumetricFog::handleCanvasResize(GuiCanvas* canvas) +{ + UpdateBuffers(0,true); +} + +void VolumetricFog::handleResize(VolumetricFogRTManager *RTM, bool resize) +{ + if (resize) + { + mResizing = true; + RTM->FogAnswered(); + } + else + mResizing = false; + + if (mIsTextured) + { + F32 width = (F32)mPlatformWindow->getClientExtent().x; + F32 height = (F32)mPlatformWindow->getClientExtent().y; + if (!mPlatformWindow->isFullscreen()) + height -= 20;//subtract caption bar from rendertarget size. + mTexScale.x = 2.0f - ((F32)mTexture.getWidth() / width); + mTexScale.y = 2.0f - ((F32)mTexture.getHeight() / height); + } + + UpdateBuffers(0,true); +} + +//----------------------------------------------------------------------------- +// Loadshape extracted from TSMesh and TSShapeInstance +//----------------------------------------------------------------------------- + +bool VolumetricFog::LoadShape() +{ + GFXPrimitiveType GFXdrawTypes[] = { GFXTriangleList, GFXTriangleStrip }; + if (!mShapeName || mShapeName[0] == '\0') + { + Con::errorf("VolumetricFog::LoadShape() - No shape name! Volumetric Fog will not be rendered!"); + return false; + } + + // Load shape, server side only reads bounds and radius + + Resource mShape; + mShape = ResourceManager::get().load(mShapeName); + if (bool(mShape) == false) + { + Con::errorf("VolumetricFog::LoadShape() - Unable to load shape: %s", mShapeName); + return false; + } + + mObjBox = mShape->bounds; + mRadius = mShape->radius; + resetWorldBox(); + + if (!isClientObject()) + return false; + + TSShapeInstance *mShapeInstance = new TSShapeInstance(mShape, false); + meshes mesh_detail; + + for (S32 i = 0; i < det_size.size(); i++) + { + if (det_size[i].indices != NULL) + delete(det_size[i].indices); + if (det_size[i].piArray != NULL) + delete(det_size[i].piArray); + if (det_size[i].verts != NULL) + delete(det_size[i].verts); + } + det_size.clear(); + + // browsing model for detail levels + + for (U32 i = 0; i < mShape->details.size(); i++) + { + const TSDetail *detail = &mShape->details[i]; + mesh_detail.det_size = detail->size; + mesh_detail.sub_shape = detail->subShapeNum; + mesh_detail.obj_det = detail->objectDetailNum; + mesh_detail.verts = NULL; + mesh_detail.piArray = NULL; + mesh_detail.indices = NULL; + if (detail->size >= 0.0f && detail->subShapeNum >= 0) + det_size.push_back(mesh_detail); + } + + for (U32 i = 0; i < det_size.size(); i++) + { + const S32 ss = det_size[i].sub_shape; + if (ss >= 0) + { + const S32 start = mShape->subShapeFirstObject[ss]; + const S32 end = start + mShape->subShapeNumObjects[ss]; + for (S32 j = start; j < end; j++) + { + // Loading shape, only the first mesh for each detail will be used! + TSShapeInstance::MeshObjectInstance *meshObj = &mShapeInstance->mMeshObjects[j]; + if (!meshObj) + continue; + TSMesh *mesh = meshObj->getMesh(det_size[i].obj_det); + if (mesh != NULL) + { + const U32 numNrms = mesh->mNumVerts; + GFXVertexPNTT *tmpVerts = NULL; + tmpVerts = new GFXVertexPNTT[numNrms]; + mIsVBDirty = true; + for (U32 k = 0; k < numNrms; k++) + { + Point3F norm = mesh->mVertexData[k].normal(); + Point3F vert = mesh->mVertexData[k].vert(); + Point2F uv = mesh->mVertexData[k].tvert(); + tmpVerts[k].point = vert; + tmpVerts[k].texCoord = uv; + tmpVerts[k].normal = norm; + } + det_size[i].verts = tmpVerts; + det_size[i].num_verts = numNrms; + + det_size[i].piArray = new Vector(); + GFXPrimitive pInfo; + + det_size[i].indices = new Vector(); + + for (U32 k = 0; k < mesh->indices.size(); k++) + det_size[i].indices->push_back(mesh->indices[k]); + + U32 primitivesSize = mesh->primitives.size(); + for (U32 k = 0; k < primitivesSize; k++) + { + const TSDrawPrimitive & draw = mesh->primitives[k]; + GFXPrimitiveType drawType = GFXdrawTypes[draw.matIndex >> 30]; + switch (drawType) + { + case GFXTriangleList: + pInfo.type = drawType; + pInfo.numPrimitives = draw.numElements / 3; + pInfo.startIndex = draw.start; + // Use the first index to determine which 16-bit address space we are operating in + pInfo.startVertex = mesh->indices[draw.start] & 0xFFFF0000; + pInfo.minIndex = pInfo.startVertex; + pInfo.numVertices = getMin((U32)0x10000, mesh->mNumVerts - pInfo.startVertex); + break; + case GFXTriangleStrip: + pInfo.type = drawType; + pInfo.numPrimitives = draw.numElements - 2; + pInfo.startIndex = draw.start; + // Use the first index to determine which 16-bit address space we are operating in + pInfo.startVertex = mesh->indices[draw.start] & 0xFFFF0000; + pInfo.minIndex = pInfo.startVertex; + pInfo.numVertices = getMin((U32)0x10000, mesh->mNumVerts - pInfo.startVertex); + break; + default: + Con::errorf("VolumetricFog::LoadShape Unknown drawtype!?!"); + return false; + break; + } + det_size[i].piArray->push_back(pInfo); + j = end; + } + } + else + { + Con::errorf("VolumetricFog::LoadShape Error loading mesh from shape!"); + delete mShapeInstance; + return false; + } + mIsVBDirty = true; + mIsPBDirty = true; + } + } + } + + mNumDetailLevels = det_size.size(); + mCurDetailLevel = 0; + UpdateBuffers(mCurDetailLevel); + delete mShapeInstance; + + return true; +} + +//----------------------------------------------------------------------------- +// UpdateBuffers called whenever detaillevel changes (LOD) +//----------------------------------------------------------------------------- + + +bool VolumetricFog::UpdateBuffers(U32 dl, bool force) +{ + if (mVB.isNull() || mIsVBDirty || dl != mCurDetailLevel || force) + { + mVB.set(GFX, det_size[dl].num_verts, GFXBufferTypeDynamic); + mIsVBDirty = false; + } + GFXVertexPNTT *vertPtr = mVB.lock(); + if (!vertPtr) + { + mVB.unlock(); + return false; + } + dMemcpy(vertPtr, det_size[dl].verts, sizeof (GFXVertexPNTT)* det_size[dl].num_verts); + mVB.unlock(); + + if (mIsPBDirty || mPB.isNull() || dl != mCurDetailLevel || force) + { + #ifdef TORQUE_DEBUG + mPB.set(GFX, det_size[dl].indices->size(), det_size[dl].piArray->size(), GFXBufferTypeDynamic, avar("%s() - VolFogPrimBuffer (line %d)", __FUNCTION__, __LINE__)); + #else + mPB.set(GFX, det_size[dl].indices->size(), det_size[dl].piArray->size(), GFXBufferTypeDynamic); + #endif + U16 *ibIndices = NULL; + GFXPrimitive *piInput = NULL; + mPB.lock(&ibIndices, &piInput); + dCopyArray(ibIndices, det_size[dl].indices->address(), det_size[dl].indices->size()); + dMemcpy(piInput, det_size[dl].piArray->address(), det_size[dl].piArray->size() * sizeof(GFXPrimitive)); + mPB.unlock(); + mIsPBDirty = false; + } + mCurDetailLevel = dl; + return true; +} + +U32 VolumetricFog::packUpdate(NetConnection *con, U32 mask, BitStream *stream) +{ + U32 retMask = Parent::packUpdate(con, mask, stream); + if (stream->writeFlag(mask & FogColorMask)) + stream->write(mFogColor); + if (stream->writeFlag(mask & FogDensityMask)) + stream->write(mFogDensity); + if (stream->writeFlag(mask & FogModulationMask)) + { + stream->write(mTextureName); + mTexTiles = mFabs(mTexTiles); + stream->write(mTexTiles); + stream->write(mStrength); + mathWrite(*stream, mSpeed); + } + if (stream->writeFlag(mask & FogPostFXMask)) + { + stream->writeFlag(mUseGlow); + stream->write(mGlowStrength); + stream->writeFlag(mModifLightRays); + stream->write(mLightRayMod); + } + if (stream->writeFlag(mask & VolumetricFogMask)) + { + stream->writeFlag(mIgnoreWater); + stream->writeFlag(mReflect); + stream->write(mFogReflStrength); + stream->writeFlag(mResizing); + stream->write(mMinDisplaySize); + stream->write(mFadeSize); + } + if (stream->writeFlag(mask & FogShapeMask)) + { + stream->writeString(mShapeName); + mathWrite(*stream, getTransform()); + mathWrite(*stream, getScale()); + if (!mShapeName || mShapeName[0] == '\0') + return retMask; + Resource mShape; + mShape = ResourceManager::get().load(mShapeName); + if (bool(mShape) == false) + return retMask; + mObjBox = mShape->bounds; + mRadius = mShape->radius; + resetWorldBox(); + mObjSize = mWorldBox.getGreatestDiagonalLength(); + mObjScale = getScale(); + mInvScale = (1.0f / getMax(getMax(mObjScale.x, mObjScale.y), mObjScale.z)); + } + return retMask; +} + +void VolumetricFog::unpackUpdate(NetConnection *con, BitStream *stream) +{ + Parent::unpackUpdate(con, stream); + MatrixF mat; + VectorF scale; + VectorF mOldScale = getScale(); + String oldTextureName = mTextureName; + StringTableEntry oldShape = mShapeName; + + if (stream->readFlag())// Fog color + stream->read(&mFogColor); + if (stream->readFlag())// Fog Density + { + stream->read(&mFogDensity); + if (isTicking()) + { + char buf[20]; + dSprintf(buf, sizeof(buf), "%3.7f", mFogDensity); + Con::setVariable("$VolumetricFog::density", buf); + } + } + if (stream->readFlag())// Fog Modulation + { + stream->read(&mTextureName); + stream->read(&mTexTiles); + mTexTiles = mFabs(mTexTiles); + stream->read(&mStrength); + mathRead(*stream, &mSpeed); + mSpeed1.set(mSpeed.x, mSpeed.y); + mSpeed2.set(mSpeed.z, mSpeed.w); + + if (isProperlyAdded()) + { + if (oldTextureName != mTextureName) + InitTexture(); + if (oldTextureName.isNotEmpty() && mTextureName.isEmpty()) + { + mIsTextured = false; + mTexture.free(); + } + } + } + if (stream->readFlag())//Fog PostFX + { + mUseGlow = stream->readFlag(); + stream->read(&mGlowStrength); + mModifLightRays = stream->readFlag(); + stream->read(&mLightRayMod); + if (isTicking()) + { + char buf[20]; + dSprintf(buf, sizeof(buf), "%3.7f", mGlowStrength); + Con::setVariable("$VolFogGlowPostFx::glowStrength", buf); + if (mUseGlow && !glowFX->isEnabled()) + glowFX->enable(); + if (!mUseGlow && glowFX->isEnabled()) + glowFX->disable(); + if (mModifLightRays) + { + char buf[20]; + dSprintf(buf, sizeof(buf), "%3.7f", mOldLightRayStrength * mLightRayMod); + Con::setVariable("$LightRayPostFX::brightScalar", buf); + } + if (!mModifLightRays) + { + char buf[20]; + dSprintf(buf, sizeof(buf), "%3.7f", mOldLightRayStrength); + Con::setVariable("$LightRayPostFX::brightScalar", buf); + } + } + } + if (stream->readFlag())//Volumetric Fog + { + mIgnoreWater = stream->readFlag(); + mReflect = stream->readFlag(); + stream->read(&mFogReflStrength); + mResizing = stream->readFlag(); + stream->read(&mMinDisplaySize); + stream->read(&mFadeSize); + } + if (stream->readFlag())//Fog shape + { + mShapeName = stream->readSTString(); + mathRead(*stream, &mat); + mathRead(*stream, &scale); + if (strcmp(oldShape, mShapeName) != 0) + { + mIsVBDirty = true; + mShapeLoaded = LoadShape(); + } + setScale(scale); + setTransform(mat); + ColBox.set(getTransform(), (mObjBox.getExtents() * getScale() * COLBOX_SCALE)); + mObjSize = mWorldBox.getGreatestDiagonalLength(); + mObjScale = getScale(); + mInvScale = (1.0f / getMax(getMax(mObjScale.x, mObjScale.y), mObjScale.z)); + } +} + +void VolumetricFog::processTick(const Move* move) +{ + Parent::processTick(move); + mCounter++; + if ( mGlowing==1 && mCurGlow < mGlowStrength ) + { + mCurGlow += (mGlowStrength / 10.0); + char buf[20]; + dSprintf(buf, sizeof(buf), "%3.7f", mCurGlow); + Con::setVariable("$VolFogGlowPostFx::glowStrength", buf); + } + else if ( mGlowing == 2 && mCurGlow > 0.0f ) + { + mCurGlow -= (mGlowStrength / 5.0f); + if (mCurGlow <= 0.0f) + { + glowFX->disable(); + mGlowing = 0; + setProcessTick(false); + return; + } + else + { + char buf[20]; + dSprintf(buf, sizeof(buf), "%3.7f", mCurGlow); + Con::setVariable("$VolFogGlowPostFx::glowStrength", buf); + } + } + if (mCounter == 3) + { + ShapeBase* control = static_cast(conn->getControlObject()); + MatrixF xfm; + control->getRenderEyeTransform(&xfm); + Point3F pos = xfm.getPosition(); + if (!ColBox.isContained(pos)) + _leaveFog(control); + mCounter = 0; + } +} + +void VolumetricFog::_enterFog(ShapeBase *control) +{ + if (mUseGlow) + { + if (glowFX) + { + mCurGlow = 0.0f; + Con::setVariable("$VolFogGlowPostFx::glowStrength", "0.0"); + glowFX->enable(); + mGlowing = 1; + } + } + if (mModifLightRays) + { + char buf[20]; + dSprintf(buf, sizeof(buf), "%3.7f", mOldLightRayStrength * mLightRayMod); + Con::setVariable("$LightRayPostFX::brightScalar", buf); + } + mCounter = 0; + char buf[20]; + dSprintf(buf, sizeof(buf), "%3.7f", mFogDensity); + Con::setVariable("$VolumetricFog::density", buf); + setProcessTick(true); + if (control) + onEnterFog_callback(control->getId()); +} + +void VolumetricFog::_leaveFog(ShapeBase *control) +{ + mCamInFog = false; + Con::setVariable("$VolumetricFog::density", "0.0"); + if (mModifLightRays) + { + char buf[20]; + dSprintf(buf, sizeof(buf), "%3.7f", mOldLightRayStrength); + Con::setVariable("$LightRayPostFX::brightScalar", buf); + } + if (mUseGlow) + { + if (glowFX && mGlowing != 2) + { + mCurGlow = mGlowStrength; + mGlowing = 2; + if (control) + onLeaveFog_callback(control->getId()); + } + } + else + { + setProcessTick(false); + if (control) + onLeaveFog_callback(control->getId()); + } +} + +//----------------------------------------------------------------------------- +// Setting up the renderers +//----------------------------------------------------------------------------- + +bool VolumetricFog::setupRenderer() +{ + // Search for the prepass rendertarget and shadermacros. + mPrepassTarget = NamedTexTarget::find("prepass"); + if (!mPrepassTarget.isValid()) + { + Con::errorf("VolumetricFog::setupRenderer - could not find PrepassTarget"); + return false; + } + + Vector macros; + if (mPrepassTarget) + mPrepassTarget->getShaderMacros(¯os); + + // Search the depth and frontbuffers which are created by the VolumetricFogRTManager + + mDepthBufferTarget = NamedTexTarget::find("volfogdepth"); + if (!mDepthBufferTarget.isValid()) + { + Con::errorf("VolumetricFog::setupRenderer - could not find depthbuffer"); + return false; + } + + mFrontBufferTarget = NamedTexTarget::find("volfogfront"); + if (!mFrontBufferTarget.isValid()) + { + Con::errorf("VolumetricFog::setupRenderer - could not find frontbuffer"); + return false; + } + + // Find and setup the prepass Shader + + ShaderData *shaderData; + mPrePassShader = Sim::findObject("VolumetricFogPrePassShader", shaderData) ? + shaderData->getShader() : NULL; + if (!mPrePassShader) + { + Con::errorf("VolumetricFog::setupRenderer - could not find VolumetricFogPrePassShader"); + return false; + } + + // Create ShaderConstBuffer and Handles + + mPPShaderConsts = mPrePassShader->allocConstBuffer(); + if (mPPShaderConsts.isNull()) + { + Con::errorf("VolumetricFog::setupRenderer - could not allocate ShaderConstants 1."); + return false; + } + + mPPModelViewProjSC = mPrePassShader->getShaderConstHandle("$modelView"); + + // Find and setup the VolumetricFog Shader + + shaderData = NULL; + mShader = Sim::findObject("VolumetricFogShader", shaderData) ? + shaderData->getShader(macros) : NULL; + if (!mShader) + { + Con::errorf("VolumetricFog::setupRenderer - could not find VolumetricFogShader"); + return false; + } + + // Create ShaderConstBuffer and Handles + + mShaderConsts = mShader->allocConstBuffer(); + if (mShaderConsts.isNull()) + { + Con::errorf("VolumetricFog::setupRenderer - could not allocate ShaderConstants 2."); + return false; + } + + mModelViewProjSC = mShader->getShaderConstHandle("$modelView"); + mFadeSizeSC = mShader->getShaderConstHandle("$fadesize"); + mFogColorSC = mShader->getShaderConstHandle("$fogColor"); + mFogDensitySC = mShader->getShaderConstHandle("$fogDensity"); + mPreBias = mShader->getShaderConstHandle("$preBias"); + mAccumTime = mShader->getShaderConstHandle("$accumTime"); + mIsTexturedSC = mShader->getShaderConstHandle("$textured"); + mTexTilesSC = mShader->getShaderConstHandle("$numtiles"); + mModStrengthSC = mShader->getShaderConstHandle("$modstrength"); + mModSpeedSC = mShader->getShaderConstHandle("$modspeed"); + mViewPointSC = mShader->getShaderConstHandle("$viewpoint"); + mTexScaleSC = mShader->getShaderConstHandle("$texscale"); + mAmbientColorSC = mShader->getShaderConstHandle("$ambientColor"); + + // Find and setup the reflection Shader + + shaderData = NULL; + mReflectionShader = Sim::findObject("VolumetricFogReflectionShader", shaderData) ? + shaderData->getShader() : NULL; + if (!mReflectionShader) + { + Con::errorf("VolumetricFog::setupRenderer - could not find VolumetricFogReflectionShader"); + return false; + } + + mReflShaderConsts = mReflectionShader->allocConstBuffer(); + if (mReflShaderConsts.isNull()) + { + Con::errorf("VolumetricFog::setupRenderer - could not allocate ShaderConstants for VolumetricFogReflectionShader."); + return false; + } + + mReflModelViewProjSC = mReflectionShader->getShaderConstHandle("$modelView"); + mReflFogColorSC = mReflectionShader->getShaderConstHandle("$fogColor"); + mReflFogDensitySC = mReflectionShader->getShaderConstHandle("$fogDensity"); + mReflFogStrengthSC = mReflectionShader->getShaderConstHandle("$reflStrength"); + + // Create the prepass StateBlock + + desc_preD.setCullMode(GFXCullCW); + desc_preD.setBlend(true); + desc_preD.setZReadWrite(false, false); + desc_preD.stencilEnable = false; + desc_preF.setCullMode(GFXCullCCW); + desc_preF.setBlend(true); + desc_preF.setZReadWrite(true, false); + desc_preF.stencilEnable = false; + + // Create the VolumetricFog StateBlock + + descD.setCullMode(GFXCullCW); + descD.setBlend(true); + descD.setZReadWrite(false, false);// desc.setZReadWrite(true, false); + + // prepassBuffer sampler + descD.samplersDefined = true; + descD.samplers[0].addressModeU = GFXAddressClamp; + descD.samplers[0].addressModeV = GFXAddressClamp; + descD.samplers[0].addressModeW = GFXAddressClamp; + descD.samplers[0].magFilter = GFXTextureFilterLinear; + descD.samplers[0].minFilter = GFXTextureFilterLinear; + descD.samplers[0].mipFilter = GFXTextureFilterLinear; + descD.samplers[0].textureColorOp = GFXTOPDisable; + + // DepthBuffer sampler + descD.samplers[1].addressModeU = GFXAddressClamp; + descD.samplers[1].addressModeV = GFXAddressClamp; + descD.samplers[1].addressModeW = GFXAddressClamp; + descD.samplers[1].magFilter = GFXTextureFilterLinear; + descD.samplers[1].minFilter = GFXTextureFilterLinear; + descD.samplers[1].mipFilter = GFXTextureFilterLinear; + descD.samplers[1].textureColorOp = GFXTOPModulate; + + // FrontBuffer sampler + descD.samplers[2].addressModeU = GFXAddressClamp; + descD.samplers[2].addressModeV = GFXAddressClamp; + descD.samplers[2].addressModeW = GFXAddressClamp; + descD.samplers[2].magFilter = GFXTextureFilterLinear; + descD.samplers[2].minFilter = GFXTextureFilterLinear; + descD.samplers[2].mipFilter = GFXTextureFilterLinear; + descD.samplers[2].textureColorOp = GFXTOPModulate; + + // animated density modifier map sampler + descD.samplers[3].addressModeU = GFXAddressWrap; + descD.samplers[3].addressModeV = GFXAddressWrap; + descD.samplers[3].addressModeW = GFXAddressWrap; + descD.samplers[3].magFilter = GFXTextureFilterLinear; + descD.samplers[3].minFilter = GFXTextureFilterLinear; + descD.samplers[3].mipFilter = GFXTextureFilterLinear; + descD.samplers[3].textureColorOp = GFXTOPModulate; + + dMemcpy(&descF, &descD, sizeof(GFXStateBlockDesc)); + descF.setCullMode(GFXCullCCW); + descF.setBlend(true); + descF.setZReadWrite(true, false); + + desc_refl.setCullMode(GFXCullCCW); + desc_refl.setBlend(true); + desc_refl.setZReadWrite(true, false); + + mStateblock_preD = GFX->createStateBlock(desc_preD); + mStateblock_preF = GFX->createStateBlock(desc_preF); + mStateblockD = GFX->createStateBlock(descD); + mStateblockF = GFX->createStateBlock(descF); + mStateblock_refl = GFX->createStateBlock(desc_refl); + + // Create Rendertarget + + z_buf = GFX->allocRenderToTextureTarget(); + if (z_buf == NULL) + { + Con::errorf("VolumetricFog::setupRenderer - Could not create Render Target"); + return false; + } + + return true; +} + +void VolumetricFog::prepRenderImage(SceneRenderState *state) +{ + if (!mShapeLoaded || mFogDensity <= 0.0f || mResizing) + return; + + if (!state->isDiffusePass()) + { + if (!state->isReflectPass()) + return; + } + + PROFILE_SCOPE(VolumetricFog_prepRenderImage); + + // Time critical therefore static_cast + ShapeBase* control = static_cast(conn->getControlObject()); + if (control->getWaterCoverage() >= 0.9f && !mIgnoreWater) + return; + + camPos = state->getCameraPosition(); + F32 dist = (camPos - getBoxCenter()).len(); + F32 scaleFactor = dist * mInvScale; + if (scaleFactor <= 0.0f) + { + if (mCurDetailLevel != 0) + UpdateBuffers(0); + } + const F32 pixelScale = state->getViewport().extent.y / 300.0f; + + mPixelSize = (mRadius / scaleFactor) * state->getWorldToScreenScale().y * pixelScale; + if (mPixelSize < mMinDisplaySize) + return; + if (mNumDetailLevels > 1) + { + if ((det_size[mCurDetailLevel].det_size > mPixelSize) && (mCurDetailLevel < mNumDetailLevels - 1)) + UpdateBuffers(mCurDetailLevel + 1); + else if (mCurDetailLevel > 0) + { + if (mPixelSize >= det_size[mCurDetailLevel - 1].det_size) + UpdateBuffers(mCurDetailLevel - 1); + } + } + + if (state->isReflectPass() && mReflect) + { + ObjectRenderInst *ri = state->getRenderPass()->allocInst(); + ri->renderDelegate.bind(this, &VolumetricFog::reflect_render); + ri->type = RenderPassManager::RIT_VolumetricFog; + ri->translucentSort = true; + ri->sortDistSq = getRenderWorldBox().getSqDistanceToPoint(camPos); + if (dist < 1.0f) + ri->defaultKey = 1; + else + ri->defaultKey = U32(dist); + state->getRenderPass()->addInst(ri); + return; + } + else if (state->isDiffusePass()) + { + viewDist = state->getFarPlane(); + mFOV = state->getCameraFrustum().getFov() / M_PI_F; + Point3F mEyeVec = state->getVectorEye() * viewDist; + + mViewPoint.x = ((mAtan2(mEyeVec.x, mEyeVec.y) / M_PI_F) + 1.0f) * mTexTiles; + mViewPoint.y = (0.5f - (mAsin(mEyeVec.z) / M_PI_F)) * mTexTiles; + + bool isInside = ColBox.isContained(camPos); + if (isInside && !mCamInFog) + { + mCamInFog = true; + _enterFog(control); + } + else if (!isInside && mCamInFog) + mCamInFog = false; + + ObjectRenderInst *ri = state->getRenderPass()->allocInst(); + ri->renderDelegate.bind(this, &VolumetricFog::render); + ri->type = RenderPassManager::RIT_VolumetricFog; + ri->translucentSort = true; + ri->sortDistSq = getRenderWorldBox().getSqDistanceToPoint(camPos); + if (dist < 1.0f) + ri->defaultKey = 1; + else + ri->defaultKey = U32(dist); + state->getRenderPass()->addInst(ri); + return; + } + return; +} + +void VolumetricFog::render(ObjectRenderInst *ri, SceneRenderState *state, BaseMatInstance *overrideMat) +{ + if (overrideMat || !mShapeLoaded || !isClientObject() || mResizing) + return; + + PROFILE_SCOPE(VolumetricFog_Render); + + GFXTransformSaver saver; + GFX->setVertexBuffer(mVB); + GFX->setPrimitiveBuffer(mPB); + + MatrixF mat = getRenderTransform(); + mat.scale(mObjScale); + GFX->multWorld(mat); + + GFX->setShader(mPrePassShader); + GFX->setShaderConstBuffer(mPPShaderConsts); + GFX->setStateBlock(mStateblock_preD); + + // Set all the shader consts... + + MatrixF xform(GFX->getProjectionMatrix()); + xform *= GFX->getViewMatrix(); + xform *= GFX->getWorldMatrix(); + + mPPShaderConsts->setSafe(mPPModelViewProjSC, xform); + + LightInfo *lightinfo = LIGHTMGR->getSpecialLight(LightManager::slSunLightType); + const ColorF &sunlight = state->getAmbientLightColor(); + + Point3F ambientColor(sunlight.red, sunlight.green, sunlight.blue); + mShaderConsts->setSafe(mAmbientColorSC, ambientColor); + + GFXTextureObject *mDepthBuffer = mDepthBufferTarget ? mDepthBufferTarget->getTexture(0) : NULL; + GFXTextureObject *mFrontBuffer = mFrontBufferTarget ? mFrontBufferTarget->getTexture(0) : NULL; + + GFX->pushActiveRenderTarget(); + + //render backside to target mDepthBuffer + z_buf->attachTexture(GFXTextureTarget::DepthStencil, GFXTextureTarget::sDefaultDepthStencil); + z_buf->attachTexture(GFXTextureTarget::Color0, mDepthBuffer); + + GFX->setActiveRenderTarget(z_buf); + GFX->clear(GFXClearStencil | GFXClearTarget , ColorI(0,0,0,0), 1.0f, 0); + + GFX->drawPrimitive(0); + z_buf->resolve(); + + //render frontside to target mFrontBuffer + z_buf->attachTexture(GFXTextureTarget::DepthStencil, GFXTextureTarget::sDefaultDepthStencil); + z_buf->attachTexture(GFXTextureTarget::Color0, mFrontBuffer); + GFX->clear(GFXClearStencil | GFXClearTarget, ColorI(0, 0, 0, 0), 1.0f, 0); + + GFX->setStateBlock(mStateblock_preF); + + GFX->drawPrimitive(0); + z_buf->resolve(); + + GFX->popActiveRenderTarget(); + z_buf->attachTexture(GFXTextureTarget::Color0, NULL); + + //render Volumetric Fog + GFX->setShader(mShader); + GFX->setShaderConstBuffer(mShaderConsts); + + mShaderConsts->setSafe(mModelViewProjSC, xform); + if (mFadeSize > 0.0f) + mShaderConsts->setSafe(mFadeSizeSC, mClampF(mPixelSize / mFadeSize, 0.0f, 1.0f)); + else + mShaderConsts->setSafe(mFadeSizeSC, 1.0f); + mShaderConsts->setSafe(mFogColorSC, mFogColor); + mShaderConsts->setSafe(mFogDensitySC, mFogDensity); + mShaderConsts->setSafe(mPreBias, viewDist); + mShaderConsts->setSafe(mAccumTime, (F32)Sim::getCurrentTime() / 1000.0f); + mShaderConsts->setSafe(mModStrengthSC, mStrength); + mShaderConsts->setSafe(mModSpeedSC, mSpeed); + mShaderConsts->setSafe(mViewPointSC, mViewPoint); + mShaderConsts->setSafe(mTexScaleSC, mTexScale * mFOV); + mShaderConsts->setSafe(mTexTilesSC, mTexTiles); + + GFXTextureObject *prepasstex = mPrepassTarget ? mPrepassTarget->getTexture(0) : NULL; + + GFX->setTexture(0, prepasstex); + GFX->setTexture(1, mDepthBuffer); + GFX->setTexture(2, mFrontBuffer); + + if (mIsTextured && mStrength > 0.0f) + { + GFX->setTexture(3, mTexture); + mShaderConsts->setSafe(mIsTexturedSC, 1.0f); + } + else + mShaderConsts->setSafe(mIsTexturedSC, 0.0f); + + if (mCamInFog) + { + /*GFXLockedRect *rect=mDepthBuffer->lock(); + U32 pixoffset = 0;// 1572864 + (512 * 4); + U8 red = rect->bits[pixoffset]; + U8 green = rect->bits[pixoffset+1]; + U8 blue = rect->bits[pixoffset+2]; + U8 alpha = rect->bits[pixoffset+3]; + mDepthBuffer->unlock(); + S32 lval = ((alpha << 24) + (blue << 16) + (green << 8) + (red)); + F32 fval = ((F32)lval / S32_MAX); + Con::printf("Color %d %d %d %d %d %f", red, green, blue, alpha, lval, fval);*/ + GFX->setStateBlock(mStateblockD); + } + else + GFX->setStateBlock(mStateblockF); + + GFX->drawPrimitive(0); +} + +void VolumetricFog::reflect_render(ObjectRenderInst *ri, SceneRenderState *state, BaseMatInstance *overrideMat) +{ + if (overrideMat || !mShapeLoaded || !isClientObject() || mResizing || (mFogReflStrength==0.0f)) + return; + + GFXTransformSaver saver; + GFX->setVertexBuffer(mVB); + GFX->setPrimitiveBuffer(mPB); + + MatrixF mat = getRenderTransform(); + mat.scale(mObjScale); + GFX->multWorld(mat); + + GFX->setShader(mReflectionShader); + GFX->setShaderConstBuffer(mReflShaderConsts); + GFX->setStateBlock(mStateblock_refl); + + // Set all the shader consts... + MatrixF xform(GFX->getProjectionMatrix()); + xform *= GFX->getViewMatrix(); + xform *= GFX->getWorldMatrix(); + + mReflShaderConsts->setSafe(mReflModelViewProjSC, xform); + mReflShaderConsts->setSafe(mReflFogColorSC, mFogColor); + mReflShaderConsts->setSafe(mReflFogDensitySC, mFogDensity); + mReflShaderConsts->setSafe(mReflFogStrengthSC, mFogReflStrength); + + GFX->drawPrimitive(0); +} + +//----------------------------------------------------------------------------- +// InitTexture is called whenever a modulation texture is added to the object +//----------------------------------------------------------------------------- + +void VolumetricFog::InitTexture() +{ + mIsTextured = false; + + if (mTextureName.isNotEmpty()) + mTexture.set(mTextureName, &GFXDefaultStaticDiffuseProfile, "VolumetricFogMod"); + + if (!mTexture.isNull()) + { + mIsTextured = true; + + F32 width = (F32)mPlatformWindow->getClientExtent().x; + F32 height = (F32)mPlatformWindow->getClientExtent().y; + + if (!mPlatformWindow->isFullscreen()) + height -= 20;//subtract caption bar from rendertarget size. + + mTexScale.x = 2.0f - ((F32)mTexture.getWidth() / width); + mTexScale.y = 2.0f - ((F32)mTexture.getHeight() / height); + } +} + +void VolumetricFog::setFogColor(ColorF color) +{ + mFogColor.set(255 * color.red,255 * color.green,255 * color.blue); + setMaskBits(FogColorMask); +} + +void VolumetricFog::setFogColor(ColorI color) +{ + mFogColor = color; + setMaskBits(FogColorMask); +} + +void VolumetricFog::setFogDensity(F32 density) +{ + if (density < 0.0f) + density = 0.0f; + mFogDensity = density; + setMaskBits(FogDensityMask); +} + +void VolumetricFog::setFogModulation(F32 strength,Point2F speed1,Point2F speed2) +{ + mStrength = strength; + mSpeed1 = speed1; + mSpeed2 = speed2; + mSpeed.set(speed1.x, speed1.y, speed2.x, speed2.y); + setMaskBits(FogModulationMask); +} + +void VolumetricFog::setFogGlow(bool on_off, F32 strength) +{ + mUseGlow = on_off; + mGlowStrength = strength; + setMaskBits(FogPostFXMask); +} + +void VolumetricFog::setFogLightray(bool on_off, F32 strength) +{ + mModifLightRays = on_off; + mLightRayMod = strength; + setMaskBits(FogPostFXMask); +} + +bool VolumetricFog::isInsideFog() +{ + return mCamInFog; +} + +DefineEngineMethod(VolumetricFog, SetFogColorF, void, (ColorF new_color), , +"@brief Changes the color of the fog\n\n." +"@params new_color the new fog color (rgb 0.0 - 1.0, a is ignored.") +{ + object->setFogColor(new_color); +} + +DefineEngineMethod(VolumetricFog, SetFogColor, void, (ColorI new_color), , +"@brief Changes the color of the fog\n\n." +"@params new_color the new fog color (rgb 0-255, a is ignored.") +{ + object->setFogColor(new_color); +} + +DefineEngineMethod(VolumetricFog, SetFogDensity, void, (F32 new_density), , +"@brief Changes the density of the fog\n\n." +"@params new_density the new fog density.") +{ + object->setFogDensity(new_density); +} + +DefineEngineMethod(VolumetricFog, SetFogModulation, void, (F32 new_strenght, Point2F new_speed1, Point2F new_speed2), , +"@brief Changes the modulation of the fog\n\n." +"@params new_strenght the new strength of the modulation.\n" +"@params new_speed1 the new speed (x y) of the modulation layer 1.\n" +"@params new_speed2 the new speed (x y) of the modulation layer 2.\n") +{ + object->setFogModulation(new_strenght, new_speed1, new_speed2); +} + +DefineEngineMethod(VolumetricFog, SetFogGlow, void, (bool on_off,F32 strength), , +"@brief Changes the glow postfx when inside the fog\n\n." +"@params on_off set to true to enable glow.\n" +"@params strength glow strength.\n") +{ + object->setFogGlow(on_off, strength); +} + +DefineEngineMethod(VolumetricFog, SetFogLightray, void, (bool on_off, F32 strength), , +"@brief Changes the lightrays postfx when inside the fog\n\n." +"@params on_off set to true to modification of the lightray postfx.\n" +"@params strength lightray strength.\n") +{ + object->setFogLightray(on_off, strength); +} + +DefineEngineMethod(VolumetricFog, isInsideFog, bool, (), , +"@brief returns true if control object is inside the fog\n\n.") +{ + return object->isInsideFog(); +} \ No newline at end of file diff --git a/Engine/source/environment/VolumetricFog.h b/Engine/source/environment/VolumetricFog.h new file mode 100644 index 000000000..ef2f39929 --- /dev/null +++ b/Engine/source/environment/VolumetricFog.h @@ -0,0 +1,243 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2012 GarageGames, LLC +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- + +#ifndef _VolumetricFog_H_ +#define _VolumetricFog_H_ + +#ifndef _SCENEOBJECT_H_ +#include "scene/sceneObject.h" +#endif +#ifndef _MATTEXTURETARGET_H_ +#include "materials/matTextureTarget.h" +#endif +#ifndef _GFXSHADER_H_ +#include "gfx/gfxShader.h" +#endif +#ifndef _GFXTARGET_H_ +#include "gfx/gfxTarget.h" +#endif +#ifndef _GFXVERTEXBUFFER_H_ +#include "gfx/gfxVertexBuffer.h" +#endif +#ifndef _TSSHAPE_H_ +#include "ts/tsShape.h" +#endif +#ifndef _POST_EFFECT_H_ +#include "postFx/postEffect.h" +#endif + +#include "gui/core/guiCanvas.h" + +class VolumetricFogRTManager; + +class VolumetricFog : public SceneObject +{ + typedef SceneObject Parent; + + // Maskbits for updating + enum + { + VolumetricFogMask = Parent::NextFreeMask, + FogColorMask = Parent::NextFreeMask << 1, + FogDensityMask = Parent::NextFreeMask << 2, + FogModulationMask = Parent::NextFreeMask << 3, + FogPostFXMask = Parent::NextFreeMask << 4, + FogShapeMask = Parent::NextFreeMask << 5, + NextFreeMask = Parent::NextFreeMask << 6 + }; + +// Struct which holds the shape details + struct meshes + { + F32 det_size; + S32 sub_shape; + S32 obj_det; + U32 num_verts; + GFXVertexPNTT *verts; + Vector *piArray; + Vector *indices; + }; + + protected: + // Rendertargets; + GFXTextureTargetRef z_buf; + NamedTexTargetRef mPrepassTarget; + NamedTexTargetRef mDepthBufferTarget; + NamedTexTargetRef mFrontBufferTarget; + + // Fog Modulation texture + GFXTexHandle mTexture; + + // Shaders + GFXShaderRef mShader; + GFXShaderRef mPrePassShader; + GFXShaderRef mReflectionShader; + + // Stateblocks + GFXStateBlockDesc descD; + GFXStateBlockDesc descF; + GFXStateBlockDesc desc_preD; + GFXStateBlockDesc desc_preF; + GFXStateBlockDesc desc_refl; + + GFXStateBlockRef mStateblockD; + GFXStateBlockRef mStateblockF; + GFXStateBlockRef mStateblock_preD; + GFXStateBlockRef mStateblock_preF; + GFXStateBlockRef mStateblock_refl; + + // Shaderconstants + GFXShaderConstBufferRef mShaderConsts; + GFXShaderConstHandle *mModelViewProjSC; + GFXShaderConstHandle *mFadeSizeSC; + GFXShaderConstHandle *mFogColorSC; + GFXShaderConstHandle *mFogDensitySC; + GFXShaderConstHandle *mPreBias; + GFXShaderConstHandle *mAccumTime; + GFXShaderConstHandle *mIsTexturedSC; + GFXShaderConstHandle *mModSpeedSC; + GFXShaderConstHandle *mModStrengthSC; + GFXShaderConstHandle *mViewPointSC; + GFXShaderConstHandle *mTexScaleSC; + GFXShaderConstHandle *mTexTilesSC; + + GFXShaderConstBufferRef mPPShaderConsts; + GFXShaderConstHandle *mPPModelViewProjSC; + + GFXShaderConstHandle *mAmbientColorSC; + + GFXShaderConstBufferRef mReflShaderConsts; + GFXShaderConstHandle *mReflModelViewProjSC; + GFXShaderConstHandle *mReflFogColorSC; + GFXShaderConstHandle *mReflFogDensitySC; + GFXShaderConstHandle *mReflFogStrengthSC; + + // Vertex and Prim. Buffer + GFXVertexBufferHandle mVB; + GFXPrimitiveBufferHandle mPB; + + // Fog volume data; + StringTableEntry mShapeName; + ColorI mFogColor; + F32 mFogDensity; + bool mIgnoreWater; + bool mReflect; + Vector det_size; + bool mShapeLoaded; + F32 mPixelSize; + F32 mFadeSize; + U32 mCurDetailLevel; + U32 mNumDetailLevels; + F32 mObjSize; + F32 mRadius; + OrientedBox3F ColBox; + VectorF mObjScale; + F32 mMinDisplaySize; + F32 mInvScale; + + // Fog Modulation data + String mTextureName; + bool mIsTextured; + F32 mTexTiles; + F32 mStrength; + Point2F mSpeed1; + Point2F mSpeed2; + Point4F mSpeed; + Point2F mTexScale; + + // Fog Rendering data + Point3F camPos; + Point2F mViewPoint; + F32 mFOV; + F32 viewDist; + bool mIsVBDirty; + bool mIsPBDirty; + bool mCamInFog; + bool mResizing; + PlatformWindow *mPlatformWindow; + + // Reflections + F32 mFogReflStrength; + + // PostFX + PostEffect *glowFX; + bool mUseGlow; + F32 mGlowStrength; + U8 mGlowing; + F32 mCurGlow; + + bool mModifLightRays; + F32 mLightRayMod; + F32 mOldLightRayStrength; + + GameConnection* conn; + U32 mCounter; + + void ResizeRT(PlatformWindow *win, bool resize); + + protected: + // Protected methods + bool onAdd(); + void onRemove(); + void handleResize(VolumetricFogRTManager *RTM, bool resize); + void handleCanvasResize(GuiCanvas* canvas); + + bool LoadShape(); + bool setupRenderer(); + void InitTexture(); + bool UpdateBuffers(U32 dl,bool force=true); + + void processTick(const Move *move); + void _enterFog(ShapeBase *control); + void _leaveFog(ShapeBase *control); + + public: + // Public methods + VolumetricFog(); + ~VolumetricFog(); + + static void initPersistFields(); + virtual void inspectPostApply(); + + U32 packUpdate(NetConnection *conn, U32 mask, BitStream *stream); + void unpackUpdate(NetConnection *conn, BitStream *stream); + + void prepRenderImage(SceneRenderState* state); + void render(ObjectRenderInst *ri, SceneRenderState *state, BaseMatInstance *overrideMat); + void reflect_render(ObjectRenderInst *ri, SceneRenderState *state, BaseMatInstance *overrideMat); + + // Methods for modifying & networking various fog elements + // Used in script + void setFogColor(ColorF color); + void setFogColor(ColorI color); + void setFogDensity(F32 density); + void setFogModulation(F32 strength, Point2F speed1, Point2F speed2); + void setFogGlow(bool on_off, F32 strength); + void setFogLightray(bool on_off, F32 strength); + bool isInsideFog(); + + DECLARE_CONOBJECT(VolumetricFog); + + DECLARE_CALLBACK(void, onEnterFog, (SimObjectId obj)); + DECLARE_CALLBACK(void, onLeaveFog, (SimObjectId obj)); +}; +#endif \ No newline at end of file diff --git a/Engine/source/environment/VolumetricFogRTManager.cpp b/Engine/source/environment/VolumetricFogRTManager.cpp new file mode 100644 index 000000000..2a927cc09 --- /dev/null +++ b/Engine/source/environment/VolumetricFogRTManager.cpp @@ -0,0 +1,299 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2012 GarageGames, LLC +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// Volumetric Fog Rendertarget Manager +// +// Creates and maintains one set of rendertargets to be used by every +// VolumetricFog object in the scene. +// +// Will be loaded at startup end removed when ending game. +// +//----------------------------------------------------------------------------- + +#include "VolumetricFogRTManager.h" +#include "core/module.h" +#include "scene/sceneManager.h" +#include "windowManager/platformWindowMgr.h" +#include "console/engineAPI.h" +#include "gui/core/guiCanvas.h" + +MODULE_BEGIN(VolumetricFogRTManager) + +MODULE_INIT_AFTER(Scene) +MODULE_SHUTDOWN_BEFORE(Scene) + +MODULE_INIT +{ + gVolumetricFogRTManager = new VolumetricFogRTManager; + gClientSceneGraph->addObjectToScene(gVolumetricFogRTManager); +} + +MODULE_SHUTDOWN +{ + gClientSceneGraph->removeObjectFromScene(gVolumetricFogRTManager); + SAFE_DELETE(gVolumetricFogRTManager); +} + +MODULE_END; + +ConsoleDocClass( VolumetricFogRTManager, +"@brief Creates and maintains one set of rendertargets to be used by every\n" +"VolumetricFog object in the scene.\n\n" +"Will be loaded at startup end removed when ending game.\n\n" +"Methods:\n" +" get() returns the currently loaded VolumetricFogRTManager, also accessible\n" +" through VFRTM define.\n" +" Init() Initializes the rendertargets, called when a VolumetricFog object is\n" +" added to the scene.\n" +" isInitialed() returns true if Rendertargets are present, false if not, then\n" +" Init() should be called to create the rendertargets.\n" +" setQuality(U32 Quality) Normally a rendertarget has the same size as the view,\n" +" with this method you can scale down the size of it.\n" +" Be aware that scaling down will introduce renderartefacts.\n" +"@ingroup Atmosphere" +); + +VolumetricFogRTMResizeSignal VolumetricFogRTManager::smVolumetricFogRTMResizeSignal; + +VolumetricFogRTManager *gVolumetricFogRTManager = NULL; + +S32 VolumetricFogRTManager::mTargetScale = 1; + +IMPLEMENT_CONOBJECT(VolumetricFogRTManager); + +VolumetricFogRTManager::VolumetricFogRTManager() +{ + setGlobalBounds(); + mTypeMask |= EnvironmentObjectType; + mNetFlags.set(IsGhost); + mIsInitialized = false; + mNumFogObjects = 0; +} + +VolumetricFogRTManager::~VolumetricFogRTManager() +{ + if (mFrontTarget.isRegistered()) + mFrontTarget.unregister(); + + if (mDepthTarget.isRegistered()) + mDepthTarget.unregister(); + + if (mDepthBuffer.isValid()) + mDepthBuffer->kill(); + + if (mFrontBuffer.isValid()) + mFrontBuffer->kill(); +} + +void VolumetricFogRTManager::onSceneRemove() +{ + if (mIsInitialized) + mPlatformWindow->getScreenResChangeSignal().remove(this, &VolumetricFogRTManager::ResizeRT); +} + +void VolumetricFogRTManager::onRemove() +{ + removeFromScene(); + Parent::onRemove(); +} + +void VolumetricFogRTManager::consoleInit() +{ + Con::addVariable("$pref::VolumetricFog::Quality", TypeS32, &mTargetScale, + "The scale of the rendertargets.\n" + "@ingroup Rendering\n"); +} + +bool VolumetricFogRTManager::Init() +{ + if (mIsInitialized) + { + Con::errorf("VolumetricFogRTManager allready initialized!!"); + return true; + } + + GuiCanvas* cv = dynamic_cast(Sim::findObject("Canvas")); + if (cv == NULL) + { + Con::errorf("VolumetricFogRTManager::Init() - Canvas not found!!"); + return false; + } + + mPlatformWindow = cv->getPlatformWindow(); + mPlatformWindow->getScreenResChangeSignal().notify(this,&VolumetricFogRTManager::ResizeRT); + + if (mTargetScale < 1) + mTargetScale = 1; + + mWidth = mFloor(mPlatformWindow->getClientExtent().x / mTargetScale); + mHeight = mPlatformWindow->getClientExtent().y; + mFullScreen = mPlatformWindow->isFullscreen(); + if (!mFullScreen) + mHeight -= 20;//subtract caption bar from rendertarget size. + mHeight = mFloor(mHeight / mTargetScale); + + mDepthBuffer = GFXTexHandle(mWidth, mHeight, GFXFormatR32F, + &GFXDefaultRenderTargetProfile, avar("%s() - mDepthBuffer (line %d)", __FUNCTION__, __LINE__)); + if (!mDepthBuffer.isValid()) + { + Con::errorf("VolumetricFogRTManager Fatal Error: Unable to create Depthbuffer"); + return false; + } + if (!mDepthTarget.registerWithName("volfogdepth")) + { + Con::errorf("VolumetricFogRTManager Fatal Error : Unable to register Depthbuffer"); + return false; + } + mDepthTarget.setTexture(mDepthBuffer); + + mFrontBuffer = GFXTexHandle(mWidth, mHeight, GFXFormatR32F, + &GFXDefaultRenderTargetProfile, avar("%s() - mFrontBuffer (line %d)", __FUNCTION__, __LINE__)); + if (!mFrontBuffer.isValid()) + { + Con::errorf("VolumetricFogRTManager Fatal Error: Unable to create front buffer"); + return false; + } + if (!mFrontTarget.registerWithName("volfogfront")) + { + Con::errorf("VolumetricFogRTManager Fatal Error : Unable to register Frontbuffer"); + return false; + } + + mFrontTarget.setTexture(mFrontBuffer); + + Con::setVariable("$VolumetricFog::density", "0.0"); + + mIsInitialized = true; + + return true; +} + +U32 VolumetricFogRTManager::IncFogObjects() +{ + mNumFogObjects++; + return mNumFogObjects; +} + +U32 VolumetricFogRTManager::DecFogObjects() +{ + if (mNumFogObjects > 0) + mNumFogObjects--; + return mNumFogObjects; +} + +void VolumetricFogRTManager::ResizeRT(PlatformWindow* win,bool resize) +{ + mFogHasAnswered = 0; + smVolumetricFogRTMResizeSignal.trigger(this, true); +} + +void VolumetricFogRTManager::FogAnswered() +{ + mFogHasAnswered++; + if (mFogHasAnswered == mNumFogObjects) + { + if (Resize()) + smVolumetricFogRTMResizeSignal.trigger(this, false); + else + Con::errorf("VolumetricFogRTManager::FogAnswered - Error resizing rendertargets!"); + } +} + +bool VolumetricFogRTManager::Resize() +{ + if (mTargetScale < 1) + mTargetScale = 1; + mWidth = mFloor(mPlatformWindow->getClientExtent().x / mTargetScale); + mHeight = mPlatformWindow->getClientExtent().y; + + if (!mPlatformWindow->isFullscreen()) + mHeight -= 20;//subtract caption bar from rendertarget size. + mHeight = mFloor(mHeight / mTargetScale); + + if (mWidth < 16 || mHeight < 16) + return false; + + if (mFrontTarget.isRegistered()) + mFrontTarget.setTexture(NULL); + + if (mDepthTarget.isRegistered()) + mDepthTarget.setTexture(NULL); + + if (mDepthBuffer.isValid()) + mDepthBuffer->kill(); + + if (mFrontBuffer.isValid()) + mFrontBuffer->kill(); + + mFrontBuffer = GFXTexHandle(mWidth, mHeight, GFXFormatR32F, + &GFXDefaultRenderTargetProfile, avar("%s() - mFrontBuffer (line %d)", __FUNCTION__, __LINE__)); + if (!mFrontBuffer.isValid()) + { + Con::errorf("VolumetricFogRTManager::Resize() Fatal Error: Unable to create front buffer"); + return false; + } + mFrontTarget.setTexture(mFrontBuffer); + + mDepthBuffer = GFXTexHandle(mWidth, mHeight, GFXFormatR32F, + &GFXDefaultRenderTargetProfile, avar("%s() - mDepthBuffer (line %d)", __FUNCTION__, __LINE__)); + if (!mDepthBuffer.isValid()) + { + Con::errorf("VolumetricFogRTManager::Resize() Fatal Error: Unable to create Depthbuffer"); + return false; + } + mDepthTarget.setTexture(mDepthBuffer); + return true; +} + +S32 VolumetricFogRTManager::setQuality(U32 Quality) +{ + if (!mIsInitialized) + return (mTargetScale = Quality); + + if (Quality < 1) + Quality = 1; + + if (Quality == mTargetScale) + return mTargetScale; + + mTargetScale = Quality; + + mFogHasAnswered = 0; + smVolumetricFogRTMResizeSignal.trigger(this, true); + + return mTargetScale; +} + +VolumetricFogRTManager* VolumetricFogRTManager::get() +{ + return gVolumetricFogRTManager; +} + +DefineConsoleFunction(SetFogVolumeQuality, S32, (U32 new_quality), , +"@brief Resizes the rendertargets of the Volumetric Fog object.\n" +"@params new_quality new quality for the rendertargets 1 = full size, 2 = halfsize, 3 = 1/3, 4 = 1/4 ...") +{ + if (VFRTM == NULL) + return -1; + return VFRTM->setQuality(new_quality); +} \ No newline at end of file diff --git a/Engine/source/environment/VolumetricFogRTManager.h b/Engine/source/environment/VolumetricFogRTManager.h new file mode 100644 index 000000000..d69bed6bd --- /dev/null +++ b/Engine/source/environment/VolumetricFogRTManager.h @@ -0,0 +1,92 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2012 GarageGames, LLC +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- + +#ifndef _VolumetricFogRTManager_H_ +#define _VolumetricFogRTManager_H_ + +#ifndef _SCENEOBJECT_H_ +#include "scene/sceneObject.h" +#endif +#ifndef _MATTEXTURETARGET_H_ +#include "materials/matTextureTarget.h" +#endif +#ifndef _GFXTARGET_H_ +#include "gfx/gfxTarget.h" +#endif +#ifndef _SIGNAL_H_ +#include "core/util/tSignal.h" +#endif + +class VolumetricFogRTManager; + +typedef Signal VolumetricFogRTMResizeSignal; + +#define VFRTM VolumetricFogRTManager::get() + +class VolumetricFogRTManager : public SceneObject +{ + public: + typedef SceneObject Parent; + + protected: + GFXTexHandle mDepthBuffer; + GFXTexHandle mFrontBuffer; + + NamedTexTarget mDepthTarget; + NamedTexTarget mFrontTarget; + + PlatformWindow* mPlatformWindow; + + static S32 mTargetScale; + bool mIsInitialized; + U32 mNumFogObjects; + U32 mFogHasAnswered; + U32 mWidth; + U32 mHeight; + bool mFullScreen; + + void onRemove(); + void onSceneRemove(); + void ResizeRT(PlatformWindow *win, bool resize); + + static VolumetricFogRTMResizeSignal smVolumetricFogRTMResizeSignal; + + public: + VolumetricFogRTManager(); + ~VolumetricFogRTManager(); + static VolumetricFogRTManager *get(); + bool Init(); + bool IsInitialized() { return mIsInitialized; } + static void consoleInit(); + static VolumetricFogRTMResizeSignal& getVolumetricFogRTMResizeSignal() { return smVolumetricFogRTMResizeSignal; } + void FogAnswered(); + S32 setQuality(U32 Quality); + bool Resize(); + U32 IncFogObjects(); + U32 DecFogObjects(); + + DECLARE_CONOBJECT(VolumetricFogRTManager); +}; + +extern VolumetricFogRTManager* gVolumetricFogRTManager; + +#endif \ No newline at end of file From d6226a71caab12be53a0854d8816b0742d243c4d Mon Sep 17 00:00:00 2001 From: Robert MacGregor Date: Wed, 2 Dec 2015 01:47:29 -0500 Subject: [PATCH 23/47] Fix NULL pointer deref crashes in WorldEditor::selectObject & WorldEditor::unSelectObject --- Engine/source/gui/worldEditor/worldEditor.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Engine/source/gui/worldEditor/worldEditor.cpp b/Engine/source/gui/worldEditor/worldEditor.cpp index 0273ffeb4..6065b233e 100644 --- a/Engine/source/gui/worldEditor/worldEditor.cpp +++ b/Engine/source/gui/worldEditor/worldEditor.cpp @@ -2810,7 +2810,7 @@ void WorldEditor::clearSelection() void WorldEditor::selectObject( SimObject *obj ) { - if ( mSelectionLocked || !mSelected ) + if ( mSelectionLocked || !mSelected || !obj ) return; // Don't check isSelectionEnabled of SceneObjects here as we @@ -2833,7 +2833,7 @@ void WorldEditor::selectObject( const char* obj ) void WorldEditor::unselectObject( SimObject *obj ) { - if ( mSelectionLocked || !mSelected ) + if ( mSelectionLocked || !mSelected || !obj ) return; if ( !objClassIgnored( obj ) && mSelected->objInSet( obj ) ) From ac7d6e66912425b259685aad7584110e4aaea516 Mon Sep 17 00:00:00 2001 From: Marc Chapman Date: Sun, 13 Dec 2015 03:33:39 +0000 Subject: [PATCH 24/47] Updated paths for collada tdictionary.h --- Engine/source/ts/collada/colladaAppMesh.h | 2 +- Engine/source/ts/collada/colladaAppNode.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Engine/source/ts/collada/colladaAppMesh.h b/Engine/source/ts/collada/colladaAppMesh.h index 17ac1cad1..72c16e56d 100644 --- a/Engine/source/ts/collada/colladaAppMesh.h +++ b/Engine/source/ts/collada/colladaAppMesh.h @@ -24,7 +24,7 @@ #define _COLLADA_APPMESH_H_ #ifndef _TDICTIONARY_H_ -#include "core/tDictionary.h" +#include "core/util/tDictionary.h" #endif #ifndef _APPMESH_H_ #include "ts/loader/appMesh.h" diff --git a/Engine/source/ts/collada/colladaAppNode.h b/Engine/source/ts/collada/colladaAppNode.h index 472ec505c..f633e7be6 100644 --- a/Engine/source/ts/collada/colladaAppNode.h +++ b/Engine/source/ts/collada/colladaAppNode.h @@ -24,7 +24,7 @@ #define _COLLADA_APPNODE_H_ #ifndef _TDICTIONARY_H_ -#include "core/tDictionary.h" +#include "core/util/tDictionary.h" #endif #ifndef _APPNODE_H_ #include "ts/loader/appNode.h" From e3b228db8bf7c34f205724a55505f9294b2c41bf Mon Sep 17 00:00:00 2001 From: rextimmy Date: Mon, 28 Dec 2015 09:17:14 +1000 Subject: [PATCH 25/47] Fix for OpenGL/D3D11 bottom border offset --- Engine/source/gfx/gfxDrawUtil.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Engine/source/gfx/gfxDrawUtil.cpp b/Engine/source/gfx/gfxDrawUtil.cpp index 1e677685e..34b1c8872 100644 --- a/Engine/source/gfx/gfxDrawUtil.cpp +++ b/Engine/source/gfx/gfxDrawUtil.cpp @@ -526,10 +526,10 @@ void GFXDrawUtil::drawRectFill( const Point2F &upperLeft, const Point2F &lowerRi F32 ulOffset = 0.5f - mDevice->getFillConventionOffset(); - verts[0].point.set( upperLeft.x+nw.x+ulOffset, upperLeft.y+nw.y+ulOffset, 0.0f ); - verts[1].point.set( lowerRight.x+ne.x, upperLeft.y+ne.y+ulOffset, 0.0f ); - verts[2].point.set( upperLeft.x-ne.x+ulOffset, lowerRight.y-ne.y, 0.0f ); - verts[3].point.set( lowerRight.x-nw.x, lowerRight.y-nw.y, 0.0f ); + verts[0].point.set( upperLeft.x + nw.x + ulOffset, upperLeft.y + nw.y + ulOffset, 0.0f); + verts[1].point.set( lowerRight.x + ne.x + ulOffset, upperLeft.y + ne.y + ulOffset, 0.0f); + verts[2].point.set( upperLeft.x - ne.x + ulOffset, lowerRight.y - ne.y + ulOffset, 0.0f); + verts[3].point.set( lowerRight.x - nw.x + ulOffset, lowerRight.y - nw.y + ulOffset, 0.0f); for (S32 i=0; i<4; i++) verts[i].color = color; From c2da755dc26b5d4e904785cdb72d9f4ca7a05c98 Mon Sep 17 00:00:00 2001 From: Areloch Date: Fri, 8 Jan 2016 00:19:11 -0600 Subject: [PATCH 26/47] Fix for the directory scan for modules so it doesn't trim off characters in the path. Resubmitted to clear the excess history entries. --- Engine/source/platformWin32/winFileio.cpp | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/Engine/source/platformWin32/winFileio.cpp b/Engine/source/platformWin32/winFileio.cpp index d5fdde104..85f8676a3 100644 --- a/Engine/source/platformWin32/winFileio.cpp +++ b/Engine/source/platformWin32/winFileio.cpp @@ -1321,6 +1321,7 @@ static bool recurseDumpDirectories(const char *basePath, const char *subPath, Ve dsize_t subtrLen = subPath ? dStrlen(subPath) : 0; char trail = trLen > 0 ? basePath[ trLen - 1 ] : '\0'; char subTrail = subtrLen > 0 ? subPath[ subtrLen - 1 ] : '\0'; + char subLead = subtrLen > 0 ? subPath[0] : '\0'; if( trail == '/' ) { @@ -1380,13 +1381,23 @@ static bool recurseDumpDirectories(const char *basePath, const char *subPath, Ve { if( ( subPath && ( dStrncmp( subPath, "", 1 ) != 0 ) ) ) { - char szPath [ 1024 ]; - dMemset( szPath, 0, 1024 ); - if( trail != '/' ) - dSprintf( szPath, 1024, "%s%s", basePath, subPath ); + char szPath[1024]; + dMemset(szPath, 0, 1024); + if (trail == '/') + { + if (subLead == '/') + dSprintf(szPath, 1024, "%s%s", basePath, &subPath[1]); + else + dSprintf(szPath, 1024, "%s%s", basePath, subPath); + } else - dSprintf( szPath, 1024, "%s%s", basePath, &subPath[1] ); - directoryVector.push_back( StringTable->insert( szPath ) ); + { + if (subLead == '/') + dSprintf(szPath, 1024, "%s%s", basePath, subPath); + else + dSprintf(szPath, 1024, "%s/%s", basePath, subPath); + } + directoryVector.push_back(StringTable->insert(szPath)); } else directoryVector.push_back( StringTable->insert( basePath ) ); From 4c17d4bb499ad78de05c49d0c609669e21a193de Mon Sep 17 00:00:00 2001 From: Cameron Porter Date: Sat, 9 Jan 2016 00:37:41 -0600 Subject: [PATCH 27/47] Fix case sensitivity and Platform::fileDelete for linux and OSX. Correct a couple of warnings and errors preventing builds on linux. --- Engine/source/T3D/assets/ShapeAsset.h | 2 +- Engine/source/core/stream/stream.cpp | 2 +- Engine/source/gfx/gfxDevice.cpp | 2 +- Engine/source/math/mathUtils.cpp | 2 +- Engine/source/persistence/taml/fsTinyXml.cpp | 6 +++--- Engine/source/persistence/taml/fsTinyXml.h | 4 ++-- Engine/source/persistence/taml/xml/tamlXmlParser.h | 4 ++-- Engine/source/persistence/taml/xml/tamlXmlReader.cpp | 2 +- Engine/source/persistence/taml/xml/tamlXmlWriter.cpp | 2 +- Engine/source/platformMac/macCarbFileio.mm | 5 +++++ Engine/source/platformX86UNIX/x86UNIXFileio.cpp | 7 ++++++- 11 files changed, 24 insertions(+), 14 deletions(-) diff --git a/Engine/source/T3D/assets/ShapeAsset.h b/Engine/source/T3D/assets/ShapeAsset.h index 81b716d08..7c87cf8de 100644 --- a/Engine/source/T3D/assets/ShapeAsset.h +++ b/Engine/source/T3D/assets/ShapeAsset.h @@ -39,7 +39,7 @@ #endif #ifndef _TSSHAPE_H_ -#include "ts/TSShape.h" +#include "ts/tsShape.h" #endif #ifndef __RESOURCE_H__ #include "core/resource.h" diff --git a/Engine/source/core/stream/stream.cpp b/Engine/source/core/stream/stream.cpp index da1b1dc82..8a7fb2b40 100644 --- a/Engine/source/core/stream/stream.cpp +++ b/Engine/source/core/stream/stream.cpp @@ -128,7 +128,7 @@ bool Stream::writeFormattedBuffer(const char *format, ...) char buffer[4096]; va_list args; va_start(args, format); - const S32 length = vsprintf(buffer, format, args); + const S32 length = dVsprintf(buffer, sizeof(buffer), format, args); // Sanity! AssertFatal(length <= sizeof(buffer), "writeFormattedBuffer - String format exceeded buffer size. This will cause corruption."); diff --git a/Engine/source/gfx/gfxDevice.cpp b/Engine/source/gfx/gfxDevice.cpp index c72c109d0..3f63fb884 100644 --- a/Engine/source/gfx/gfxDevice.cpp +++ b/Engine/source/gfx/gfxDevice.cpp @@ -148,7 +148,7 @@ GFXDevice::GFXDevice() mGlobalAmbientColor = ColorF(0.0f, 0.0f, 0.0f, 1.0f); mLightMaterialDirty = false; - dMemset(&mCurrentLightMaterial, NULL, sizeof(GFXLightMaterial)); + dMemset(&mCurrentLightMaterial, 0, sizeof(GFXLightMaterial)); // State block mStateBlockDirty = false; diff --git a/Engine/source/math/mathUtils.cpp b/Engine/source/math/mathUtils.cpp index f6086c5e4..5ffd9a870 100644 --- a/Engine/source/math/mathUtils.cpp +++ b/Engine/source/math/mathUtils.cpp @@ -1847,7 +1847,7 @@ U32 extrudePolygonEdgesFromPoint( const Point3F* vertices, U32 numVertices, cons //----------------------------------------------------------------------------- -void MathUtils::mBuildHull2D(const Vector _inPoints, Vector &hullPoints) +void mBuildHull2D(const Vector _inPoints, Vector &hullPoints) { /// Andrew's monotone chain convex hull algorithm implementation diff --git a/Engine/source/persistence/taml/fsTinyXml.cpp b/Engine/source/persistence/taml/fsTinyXml.cpp index 1fb97398b..441169742 100644 --- a/Engine/source/persistence/taml/fsTinyXml.cpp +++ b/Engine/source/persistence/taml/fsTinyXml.cpp @@ -38,7 +38,7 @@ bool fsTiXmlDocument::LoadFile( const char * pFilename, TiXmlEncoding encoding ) #endif // File open for read? - if ( !stream.open( filenameBuffer, Torque::FS::File::AccessMode::Read ) ) + if ( !stream.open( filenameBuffer, Torque::FS::File::Read ) ) { // No, so warn. Con::warnf("TamlXmlParser::parse() - Could not open filename '%s' for parse.", filenameBuffer ); @@ -67,7 +67,7 @@ bool fsTiXmlDocument::SaveFile( const char * pFilename ) const FileStream stream; // File opened? - if ( !stream.open( filenameBuffer, Torque::FS::File::AccessMode::Write ) ) + if ( !stream.open( filenameBuffer, Torque::FS::File::Write ) ) { // No, so warn. Con::warnf("Taml::writeFile() - Could not open filename '%s' for write.", filenameBuffer ); @@ -744,4 +744,4 @@ return 0; // All is well. return p; } -*/ \ No newline at end of file +*/ diff --git a/Engine/source/persistence/taml/fsTinyXml.h b/Engine/source/persistence/taml/fsTinyXml.h index f2fb14129..864abec09 100644 --- a/Engine/source/persistence/taml/fsTinyXml.h +++ b/Engine/source/persistence/taml/fsTinyXml.h @@ -25,7 +25,7 @@ #ifndef TINYXML_INCLUDED -#include "tinyXML/tinyxml.h" +#include "tinyxml/tinyxml.h" #endif #include "platform/platform.h" @@ -245,4 +245,4 @@ static bool AttemptPrintTiNode(class fsTiXmlDocument* node, FileStream& stream, } return false; } -#endif //_FSTINYXML_H_ \ No newline at end of file +#endif //_FSTINYXML_H_ diff --git a/Engine/source/persistence/taml/xml/tamlXmlParser.h b/Engine/source/persistence/taml/xml/tamlXmlParser.h index 85b34079d..28b51a472 100644 --- a/Engine/source/persistence/taml/xml/tamlXmlParser.h +++ b/Engine/source/persistence/taml/xml/tamlXmlParser.h @@ -28,7 +28,7 @@ #endif #ifndef TINYXML_INCLUDED -#include "tinyXML/tinyxml.h" +#include "tinyxml/tinyxml.h" #endif //----------------------------------------------------------------------------- @@ -54,4 +54,4 @@ private: bool mDocumentDirty; }; -#endif // _TAML_XMLPARSER_H_ \ No newline at end of file +#endif // _TAML_XMLPARSER_H_ diff --git a/Engine/source/persistence/taml/xml/tamlXmlReader.cpp b/Engine/source/persistence/taml/xml/tamlXmlReader.cpp index 04b43a5d2..aa8be618f 100644 --- a/Engine/source/persistence/taml/xml/tamlXmlReader.cpp +++ b/Engine/source/persistence/taml/xml/tamlXmlReader.cpp @@ -24,7 +24,7 @@ // Debug Profiling. #include "platform/profiler.h" -#include "persistence/taml/fsTinyxml.h" +#include "persistence/taml/fsTinyXml.h" //----------------------------------------------------------------------------- diff --git a/Engine/source/persistence/taml/xml/tamlXmlWriter.cpp b/Engine/source/persistence/taml/xml/tamlXmlWriter.cpp index 4ffad7223..e8481cb87 100644 --- a/Engine/source/persistence/taml/xml/tamlXmlWriter.cpp +++ b/Engine/source/persistence/taml/xml/tamlXmlWriter.cpp @@ -24,7 +24,7 @@ // Debug Profiling. #include "platform/profiler.h" -#include "persistence/taml/fsTinyxml.h" +#include "persistence/taml/fsTinyXml.h" //----------------------------------------------------------------------------- diff --git a/Engine/source/platformMac/macCarbFileio.mm b/Engine/source/platformMac/macCarbFileio.mm index 7a913986e..a1961d710 100644 --- a/Engine/source/platformMac/macCarbFileio.mm +++ b/Engine/source/platformMac/macCarbFileio.mm @@ -724,6 +724,11 @@ bool Platform::hasSubDirectory(const char *path) return false; // either this dir had no subdirectories, or they were all on the exclude list. } + bool Platform::fileDelete(const char * name) + { + return dFileDelete(name); + } + //----------------------------------------------------------------------------- bool recurseDumpDirectories(const char *basePath, const char *path, Vector &directoryVector, S32 depth, bool noBasePath) { diff --git a/Engine/source/platformX86UNIX/x86UNIXFileio.cpp b/Engine/source/platformX86UNIX/x86UNIXFileio.cpp index 22c40a187..6c2dd6955 100644 --- a/Engine/source/platformX86UNIX/x86UNIXFileio.cpp +++ b/Engine/source/platformX86UNIX/x86UNIXFileio.cpp @@ -325,7 +325,7 @@ bool dPathCopy(const char *fromName, const char *toName, bool nooverwrite) if (modType == TOUCH) return(utime(prefPathName, 0) != -1); else if (modType == DELETE) - return (remove(prefPathName) != -1); + return (remove(prefPathName) == 0); else AssertFatal(false, "Unknown File Mod type"); return false; @@ -1140,6 +1140,11 @@ bool dPathCopy(const char *fromName, const char *toName, bool nooverwrite) return false; } + bool Platform::fileDelete(const char * name) + { + return ModifyFile(name, DELETE); + } + static bool recurseDumpDirectories(const char *basePath, const char *subPath, Vector &directoryVector, S32 currentDepth, S32 recurseDepth, bool noBasePath) { char Path[1024]; From cae97cac37a1aed5849d27eb7a3b48b35000740a Mon Sep 17 00:00:00 2001 From: Anis Date: Thu, 14 Jan 2016 23:51:35 +0100 Subject: [PATCH 28/47] Glow buffer graphic corruption fix on OpenGL. Caused by a wrong target size. (probably it was ok on the very old OpenGL 1.5 version) Before fix, wrong behaviour: http://goo.gl/dik7Ia After fix, all right: http://goo.gl/IsrckM --- Engine/source/renderInstance/renderTexTargetBinManager.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Engine/source/renderInstance/renderTexTargetBinManager.cpp b/Engine/source/renderInstance/renderTexTargetBinManager.cpp index c26231152..5353f4566 100644 --- a/Engine/source/renderInstance/renderTexTargetBinManager.cpp +++ b/Engine/source/renderInstance/renderTexTargetBinManager.cpp @@ -107,8 +107,7 @@ void RenderTexTargetBinManager::initPersistFields() bool RenderTexTargetBinManager::setTargetSize(const Point2I &newTargetSize) { - if( GFX->getAdapterType() != OpenGL && // Targets need to match up exactly in size on OpenGL. - mTargetSize.x >= newTargetSize.x && + if( mTargetSize.x >= newTargetSize.x && mTargetSize.y >= newTargetSize.y ) return true; From 58a604d363cac4cabf9148d402e3a17c44e28008 Mon Sep 17 00:00:00 2001 From: Anis Date: Mon, 18 Jan 2016 05:49:05 +0100 Subject: [PATCH 29/47] Update gfxGLCircularVolatileBuffer.h --- Engine/source/gfx/gl/gfxGLCircularVolatileBuffer.h | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Engine/source/gfx/gl/gfxGLCircularVolatileBuffer.h b/Engine/source/gfx/gl/gfxGLCircularVolatileBuffer.h index c291cb229..6d7d0e4b1 100644 --- a/Engine/source/gfx/gl/gfxGLCircularVolatileBuffer.h +++ b/Engine/source/gfx/gl/gfxGLCircularVolatileBuffer.h @@ -143,6 +143,11 @@ public: init(); } + ~GLCircularVolatileBuffer() + { + glDeleteBuffers(1, &mBufferName); + } + void init() { glGenBuffers(1, &mBufferName); @@ -290,4 +295,4 @@ protected: }; -#endif \ No newline at end of file +#endif From 07282822870c6a86de7da7f42a1de4e85c15c402 Mon Sep 17 00:00:00 2001 From: Anis Date: Mon, 18 Jan 2016 05:55:36 +0100 Subject: [PATCH 30/47] Update gfxGLTextureTarget.cpp --- Engine/source/gfx/gl/gfxGLTextureTarget.cpp | 23 ++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/Engine/source/gfx/gl/gfxGLTextureTarget.cpp b/Engine/source/gfx/gl/gfxGLTextureTarget.cpp index 1569b9a85..202265107 100644 --- a/Engine/source/gfx/gl/gfxGLTextureTarget.cpp +++ b/Engine/source/gfx/gl/gfxGLTextureTarget.cpp @@ -163,6 +163,10 @@ void _GFXGLTextureTargetFBOImpl::applyState() PRESERVE_FRAMEBUFFER(); glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer); + bool drawbufs[16]; + int bufsize = 0; + for (int i = 0; i < 16; i++) + drawbufs[i] = false; bool hasColor = false; for(int i = 0; i < GFXGL->getNumRenderTargets(); ++i) { @@ -200,6 +204,20 @@ void _GFXGLTextureTargetFBOImpl::applyState() glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, 0, 0); } + GLenum *buf = new GLenum[bufsize]; + int count = 0; + for (int i = 0; i < bufsize; i++) + { + if (drawbufs[i]) + { + buf[count] = GL_COLOR_ATTACHMENT0 + i; + count++; + } + } + + glDrawBuffers(bufsize, buf); + + delete[] buf; CHECK_FRAMEBUFFER_STATUS(); } @@ -260,7 +278,10 @@ GFXGLTextureTarget::GFXGLTextureTarget() : mCopyFboSrc(0), mCopyFboDst(0) GFXGLTextureTarget::~GFXGLTextureTarget() { - GFXTextureManager::removeEventDelegate( this, &GFXGLTextureTarget::_onTextureEvent ); + GFXTextureManager::removeEventDelegate(this, &GFXGLTextureTarget::_onTextureEvent); + + glDeleteFramebuffers(1, &mCopyFboSrc); + glDeleteFramebuffers(1, &mCopyFboDst); } const Point2I GFXGLTextureTarget::getSize() From c3ef59e39c9784812810d7c24c17b775a91f0e48 Mon Sep 17 00:00:00 2001 From: Anis Date: Mon, 18 Jan 2016 05:55:48 +0100 Subject: [PATCH 31/47] Update gfxGLWindowTarget.cpp --- Engine/source/gfx/gl/gfxGLWindowTarget.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/Engine/source/gfx/gl/gfxGLWindowTarget.cpp b/Engine/source/gfx/gl/gfxGLWindowTarget.cpp index c02ff1bc3..5f8808cae 100644 --- a/Engine/source/gfx/gl/gfxGLWindowTarget.cpp +++ b/Engine/source/gfx/gl/gfxGLWindowTarget.cpp @@ -42,6 +42,14 @@ GFXGLWindowTarget::GFXGLWindowTarget(PlatformWindow *win, GFXDevice *d) win->appEvent.notify(this, &GFXGLWindowTarget::_onAppSignal); } +GFXGLWindowTarget::~GFXGLWindowTarget() +{ + if(glIsFramebuffer(mCopyFBO)) + { + glDeleteFramebuffers(1, &mCopyFBO); + } +} + void GFXGLWindowTarget::resetMode() { if(mWindow->getVideoMode().fullScreen != mWindow->isFullscreen()) @@ -49,6 +57,7 @@ void GFXGLWindowTarget::resetMode() _teardownCurrentMode(); _setupNewMode(); } + GFX->beginReset(); } void GFXGLWindowTarget::_onAppSignal(WindowId wnd, S32 event) From 500a237892db6fa6a445aa646815f20cec7ccbfa Mon Sep 17 00:00:00 2001 From: Anis Date: Mon, 18 Jan 2016 05:56:00 +0100 Subject: [PATCH 32/47] Update gfxGLWindowTarget.h --- Engine/source/gfx/gl/gfxGLWindowTarget.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Engine/source/gfx/gl/gfxGLWindowTarget.h b/Engine/source/gfx/gl/gfxGLWindowTarget.h index 4baa6a53f..af368e192 100644 --- a/Engine/source/gfx/gl/gfxGLWindowTarget.h +++ b/Engine/source/gfx/gl/gfxGLWindowTarget.h @@ -30,6 +30,8 @@ class GFXGLWindowTarget : public GFXWindowTarget public: GFXGLWindowTarget(PlatformWindow *win, GFXDevice *d); + ~GFXGLWindowTarget(); + const Point2I getSize() { return mWindow->getClientExtent(); @@ -64,4 +66,4 @@ private: void _WindowPresent(); }; -#endif \ No newline at end of file +#endif From ca31ef3f1aef7c3f0643246c788beeb980474b43 Mon Sep 17 00:00:00 2001 From: Anis Date: Mon, 18 Jan 2016 06:15:07 +0100 Subject: [PATCH 33/47] Update gfxGLWindowTarget.cpp --- Engine/source/gfx/gl/gfxGLWindowTarget.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/Engine/source/gfx/gl/gfxGLWindowTarget.cpp b/Engine/source/gfx/gl/gfxGLWindowTarget.cpp index 5f8808cae..c00506835 100644 --- a/Engine/source/gfx/gl/gfxGLWindowTarget.cpp +++ b/Engine/source/gfx/gl/gfxGLWindowTarget.cpp @@ -57,7 +57,6 @@ void GFXGLWindowTarget::resetMode() _teardownCurrentMode(); _setupNewMode(); } - GFX->beginReset(); } void GFXGLWindowTarget::_onAppSignal(WindowId wnd, S32 event) From e2d789e87de69d1b525763ca99aa5daef15b8e74 Mon Sep 17 00:00:00 2001 From: Anis Date: Mon, 18 Jan 2016 06:17:20 +0100 Subject: [PATCH 34/47] Update gfxGLTextureTarget.cpp --- Engine/source/gfx/gl/gfxGLTextureTarget.cpp | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/Engine/source/gfx/gl/gfxGLTextureTarget.cpp b/Engine/source/gfx/gl/gfxGLTextureTarget.cpp index 202265107..ddb308adc 100644 --- a/Engine/source/gfx/gl/gfxGLTextureTarget.cpp +++ b/Engine/source/gfx/gl/gfxGLTextureTarget.cpp @@ -163,10 +163,6 @@ void _GFXGLTextureTargetFBOImpl::applyState() PRESERVE_FRAMEBUFFER(); glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer); - bool drawbufs[16]; - int bufsize = 0; - for (int i = 0; i < 16; i++) - drawbufs[i] = false; bool hasColor = false; for(int i = 0; i < GFXGL->getNumRenderTargets(); ++i) { @@ -204,20 +200,6 @@ void _GFXGLTextureTargetFBOImpl::applyState() glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, 0, 0); } - GLenum *buf = new GLenum[bufsize]; - int count = 0; - for (int i = 0; i < bufsize; i++) - { - if (drawbufs[i]) - { - buf[count] = GL_COLOR_ATTACHMENT0 + i; - count++; - } - } - - glDrawBuffers(bufsize, buf); - - delete[] buf; CHECK_FRAMEBUFFER_STATUS(); } From 23c4b52e1f69fbec2594ffde6bd2952e55bb2e3b Mon Sep 17 00:00:00 2001 From: Azaezel Date: Mon, 18 Jan 2016 00:28:09 -0600 Subject: [PATCH 35/47] courtessy @Lopuska: opengl occlusion query fix --- .../advanced/advancedLightBinManager.cpp | 14 +++------ .../lighting/shadowMap/lightShadowMap.cpp | 31 +++++-------------- .../lighting/shadowMap/lightShadowMap.h | 22 ++++--------- .../lighting/shadowMap/shadowMapPass.cpp | 14 ++++----- 4 files changed, 25 insertions(+), 56 deletions(-) diff --git a/Engine/source/lighting/advanced/advancedLightBinManager.cpp b/Engine/source/lighting/advanced/advancedLightBinManager.cpp index dd71afeb0..98330a5de 100644 --- a/Engine/source/lighting/advanced/advancedLightBinManager.cpp +++ b/Engine/source/lighting/advanced/advancedLightBinManager.cpp @@ -318,6 +318,8 @@ void AdvancedLightBinManager::render( SceneRenderState *state ) const U32 numPrims = curEntry.numPrims; const U32 numVerts = curEntry.vertBuffer->mNumVerts; + ShadowMapParams *lsp = curLightInfo->getExtended(); + // Skip lights which won't affect the scene. if ( !curLightMat || curLightInfo->getBrightness() <= 0.001f ) continue; @@ -329,15 +331,12 @@ void AdvancedLightBinManager::render( SceneRenderState *state ) mShadowManager->setLightShadowMap( curEntry.shadowMap ); mShadowManager->setLightDynamicShadowMap( curEntry.dynamicShadowMap ); - // Let the shadow know we're about to render from it. - if ( curEntry.shadowMap ) - curEntry.shadowMap->preLightRender(); - if ( curEntry.dynamicShadowMap ) curEntry.dynamicShadowMap->preLightRender(); - // Set geometry GFX->setVertexBuffer( curEntry.vertBuffer ); GFX->setPrimitiveBuffer( curEntry.primBuffer ); + lsp->getOcclusionQuery()->begin(); + // Render the material passes while( curLightMat->matInstance->setupPass( state, sgData ) ) { @@ -352,10 +351,7 @@ void AdvancedLightBinManager::render( SceneRenderState *state ) GFX->drawPrimitive(GFXTriangleList, 0, numPrims); } - // Tell it we're done rendering. - if ( curEntry.shadowMap ) - curEntry.shadowMap->postLightRender(); - if ( curEntry.dynamicShadowMap ) curEntry.dynamicShadowMap->postLightRender(); + lsp->getOcclusionQuery()->end(); } // Set NULL for active shadow map (so nothing gets confused) diff --git a/Engine/source/lighting/shadowMap/lightShadowMap.cpp b/Engine/source/lighting/shadowMap/lightShadowMap.cpp index 53a6f4e8d..984f6cbc6 100644 --- a/Engine/source/lighting/shadowMap/lightShadowMap.cpp +++ b/Engine/source/lighting/shadowMap/lightShadowMap.cpp @@ -89,8 +89,6 @@ LightShadowMap::LightShadowMap( LightInfo *light ) mLastUpdate( 0 ), mLastCull( 0 ), mIsViewDependent( false ), - mVizQuery( NULL ), - mWasOccluded( false ), mLastScreenSize( 0.0f ), mLastPriority( 0.0f ), mIsDynamic( false ) @@ -98,9 +96,7 @@ LightShadowMap::LightShadowMap( LightInfo *light ) GFXTextureManager::addEventDelegate( this, &LightShadowMap::_onTextureEvent ); mTarget = GFX->allocRenderToTextureTarget(); - mVizQuery = GFX->createOcclusionQuery(); - - smShadowMaps.push_back(this); + smShadowMaps.push_back( this ); mStaticRefreshTimer = PlatformTimer::create(); mDynamicRefreshTimer = PlatformTimer::create(); } @@ -108,8 +104,9 @@ LightShadowMap::LightShadowMap( LightInfo *light ) LightShadowMap::~LightShadowMap() { mTarget = NULL; - SAFE_DELETE( mVizQuery ); - + SAFE_DELETE(mStaticRefreshTimer); + SAFE_DELETE(mDynamicRefreshTimer); + releaseTextures(); smShadowMaps.remove( this ); @@ -334,23 +331,6 @@ void LightShadowMap::render( RenderPassManager* renderPass, mLastUpdate = Sim::getCurrentTime(); } -void LightShadowMap::preLightRender() -{ - PROFILE_SCOPE( LightShadowMap_prepLightRender ); - - if ( mVizQuery ) - { - mWasOccluded = mVizQuery->getStatus( true ) == GFXOcclusionQuery::Occluded; - mVizQuery->begin(); - } -} - -void LightShadowMap::postLightRender() -{ - if ( mVizQuery ) - mVizQuery->end(); -} - BaseMatInstance* LightShadowMap::getShadowMaterial( BaseMatInstance *inMat ) const { // See if we have an existing material hook. @@ -610,11 +590,14 @@ ShadowMapParams::ShadowMapParams( LightInfo *light ) shadowSoftness = 0.15f; fadeStartDist = 0.0f; lastSplitTerrainOnly = false; + mQuery = GFX->createOcclusionQuery(); + _validate(); } ShadowMapParams::~ShadowMapParams() { + SAFE_DELETE( mQuery ); SAFE_DELETE( mShadowMap ); SAFE_DELETE( mDynamicShadowMap ); } diff --git a/Engine/source/lighting/shadowMap/lightShadowMap.h b/Engine/source/lighting/shadowMap/lightShadowMap.h index 2cbb2ca5e..d96481192 100644 --- a/Engine/source/lighting/shadowMap/lightShadowMap.h +++ b/Engine/source/lighting/shadowMap/lightShadowMap.h @@ -47,6 +47,9 @@ #ifndef _GFXSHADER_H_ #include "gfx/gfxShader.h" #endif +#ifndef _GFXOCCLUSIONQUERY_H_ +#include "gfx/gfxOcclusionQuery.h" +#endif #ifndef _PLATFORM_PLATFORMTIMER_H_ #include "platform/platformTimer.h" #endif @@ -61,7 +64,6 @@ struct SceneData; class GFXShaderConstBuffer; class GFXShaderConstHandle; class GFXShader; -class GFXOcclusionQuery; class LightManager; class RenderPassManager; @@ -169,12 +171,6 @@ public: bool isViewDependent() const { return mIsViewDependent; } - bool wasOccluded() const { return mWasOccluded; } - - void preLightRender(); - - void postLightRender(); - void updatePriority( const SceneRenderState *state, U32 currTimeMs ); F32 getLastScreenSize() const { return mLastScreenSize; } @@ -257,15 +253,6 @@ protected: /// The time this shadow was last culled and prioritized. U32 mLastCull; - /// The shadow occlusion query used when the light is - /// rendered to determine if any pixel of it is visible. - GFXOcclusionQuery *mVizQuery; - - /// If true the light was occluded by geometry the - /// last frame it was updated. - //the last frame. - bool mWasOccluded; - F32 mLastScreenSize; F32 mLastPriority; @@ -325,6 +312,8 @@ public: bool hasCookieTex() const { return cookie.isNotEmpty(); } + GFXOcclusionQuery* getOcclusionQuery() const { return mQuery; } + GFXTextureObject* getCookieTex(); GFXCubemap* getCookieCubeTex(); @@ -339,6 +328,7 @@ protected: /// LightShadowMap *mShadowMap; LightShadowMap *mDynamicShadowMap; + GFXOcclusionQuery* mQuery; LightInfo *mLight; diff --git a/Engine/source/lighting/shadowMap/shadowMapPass.cpp b/Engine/source/lighting/shadowMap/shadowMapPass.cpp index 7c17046e1..dea7305b5 100644 --- a/Engine/source/lighting/shadowMap/shadowMapPass.cpp +++ b/Engine/source/lighting/shadowMap/shadowMapPass.cpp @@ -174,12 +174,12 @@ void ShadowMapPass::render( SceneManager *sceneManager, continue; // --- Static Shadow Map --- - LightShadowMap *lsm = params->getOrCreateShadowMap(); - LightShadowMap *dlsm = params->getOrCreateShadowMap(true); + LightShadowMap *lsm = params->getOrCreateShadowMap(); + LightShadowMap *dlsm = params->getOrCreateShadowMap(true); // First check the visiblity query... if it wasn't // visible skip it. - if (lsm->wasOccluded() || dlsm->wasOccluded()) + if(params->getOcclusionQuery()->getStatus(true) == GFXOcclusionQuery::Occluded) continue; // Any shadow that is visible is counted as being @@ -187,9 +187,9 @@ void ShadowMapPass::render( SceneManager *sceneManager, ++smActiveShadowMaps; // Do a priority update for this shadow. - lsm->updatePriority(diffuseState, currTime); + lsm->updatePriority(diffuseState, currTime); - shadowMaps.push_back(lsm); + shadowMaps.push_back(lsm); // --- Dynamic Shadow Map --- @@ -198,7 +198,7 @@ void ShadowMapPass::render( SceneManager *sceneManager, ++smActiveShadowMaps; // Do a priority update for this shadow. - dlsm->updatePriority(diffuseState, currTime); + dlsm->updatePriority(diffuseState, currTime); shadowMaps.push_back( dlsm ); } @@ -306,4 +306,4 @@ void DynamicShadowRenderPassManager::addInst( RenderInst *inst ) } Parent::addInst(inst); -} \ No newline at end of file +} From 0f173df0d4c81f0e9a66b5724c918b082161b4ed Mon Sep 17 00:00:00 2001 From: Azaezel Date: Thu, 28 Jan 2016 00:42:08 -0600 Subject: [PATCH 36/47] setDetailFromDistance aspect ratio friendly adjustment --- Engine/source/ts/tsShapeInstance.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Engine/source/ts/tsShapeInstance.cpp b/Engine/source/ts/tsShapeInstance.cpp index 821e02dba..03b8c79c3 100644 --- a/Engine/source/ts/tsShapeInstance.cpp +++ b/Engine/source/ts/tsShapeInstance.cpp @@ -593,7 +593,7 @@ S32 TSShapeInstance::setDetailFromDistance( const SceneRenderState *state, F32 s // 4:3 aspect ratio, we've changed the reference value // to 300 to be more compatible with legacy shapes. // - const F32 pixelScale = state->getViewport().extent.y / 300.0f; + const F32 pixelScale = (state->getViewport().extent.x / state->getViewport().extent.y); // This is legacy DTS support for older "multires" based // meshes. The original crossbow weapon uses this. From 7924f056bdfcabb4152c2b55c79695dac8534e27 Mon Sep 17 00:00:00 2001 From: RoundedIcon Date: Mon, 1 Feb 2016 16:58:39 -0700 Subject: [PATCH 37/47] Fix for collision issues with scaled players Players scaled after their creation have collision issues with terrain. Changing this bit of code fixes those issues for downsized players, even when shrunk to 10% of their original size. --- Engine/source/T3D/player.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Engine/source/T3D/player.cpp b/Engine/source/T3D/player.cpp index 3c258c374..6e33284a6 100644 --- a/Engine/source/T3D/player.cpp +++ b/Engine/source/T3D/player.cpp @@ -4659,9 +4659,9 @@ Point3F Player::_move( const F32 travelTime, Collision *outCol ) } Point3F distance = end - start; - if (mFabs(distance.x) < mObjBox.len_x() && - mFabs(distance.y) < mObjBox.len_y() && - mFabs(distance.z) < mObjBox.len_z()) + if (mFabs(distance.x) < mScaledBox.len_x() && + mFabs(distance.y) < mScaledBox.len_y() && + mFabs(distance.z) < mScaledBox.len_z()) { // We can potentially early out of this. If there are no polys in the clipped polylist at our // end position, then we can bail, and just set start = end; From 7aeec65a3ba207ff97922bea3b92b75d69e27859 Mon Sep 17 00:00:00 2001 From: Anis Date: Sat, 13 Feb 2016 20:27:30 +0100 Subject: [PATCH 38/47] Update win32Window.cpp --- .../windowManager/win32/win32Window.cpp | 173 ++++++++---------- 1 file changed, 81 insertions(+), 92 deletions(-) diff --git a/Engine/source/windowManager/win32/win32Window.cpp b/Engine/source/windowManager/win32/win32Window.cpp index 5c9b8ed11..c714586b9 100644 --- a/Engine/source/windowManager/win32/win32Window.cpp +++ b/Engine/source/windowManager/win32/win32Window.cpp @@ -26,8 +26,10 @@ #include #include #include "math/mMath.h" +#include "gfx/gfxDevice.h" #include "gfx/gfxStructs.h" +#include "windowManager/platformWindowMgr.h" #include "windowManager/win32/win32Window.h" #include "windowManager/win32/win32WindowMgr.h" #include "windowManager/win32/win32CursorController.h" @@ -39,11 +41,6 @@ // for winState structure #include "platformWin32/platformWin32.h" -#include -#include "gfx/gfxDevice.h" - -#include - const UTF16* _MainWindowClassName = L"TorqueJuggernaughtWindow"; const UTF16* _CurtainWindowClassName = L"TorqueJuggernaughtCurtainWindow"; @@ -148,96 +145,93 @@ const GFXVideoMode & Win32Window::getVideoMode() void Win32Window::setVideoMode( const GFXVideoMode &mode ) { - bool needCurtain = (mVideoMode.fullScreen != mode.fullScreen); + bool needCurtain = ( mVideoMode.fullScreen != mode.fullScreen ); - if(needCurtain) + if( needCurtain ) { - Con::errorf("Win32Window::setVideoMode - invoking curtain"); + Con::printf( "Win32Window::setVideoMode - invoking curtain" ); mOwningManager->lowerCurtain(); } - mVideoMode = mode; - mSuppressReset = true; + mVideoMode = mode; + mSuppressReset = true; // Can't switch to fullscreen while a child of another window - if(mode.fullScreen && !Platform::getWebDeployment() && mOwningManager->getParentWindow()) + if( mode.fullScreen && !Platform::getWebDeployment() && mOwningManager->getParentWindow() ) { - mOldParent = (HWND)mOwningManager->getParentWindow(); - mOwningManager->setParentWindow(NULL); + mOldParent = reinterpret_cast( mOwningManager->getParentWindow() ); + mOwningManager->setParentWindow( NULL ); } - else if(!mode.fullScreen && mOldParent) + else if( !mode.fullScreen && mOldParent ) { - mOwningManager->setParentWindow(mOldParent); + mOwningManager->setParentWindow( mOldParent ); mOldParent = NULL; } - // Set our window to have the right style based on the mode - if(mode.fullScreen && !Platform::getWebDeployment() && !mOffscreenRender) + // Set our window to have the right style based on the mode + if( mode.fullScreen && !Platform::getWebDeployment() && !mOffscreenRender ) { - WINDOWPLACEMENT wplacement = { sizeof(wplacement) }; - DWORD dwStyle = GetWindowLong(getHWND(), GWL_STYLE); - MONITORINFO mi = { sizeof(mi) }; + WINDOWPLACEMENT wplacement = { sizeof( wplacement ) }; + DWORD dwStyle = GetWindowLong( getHWND(), GWL_STYLE ); + MONITORINFO mi = { sizeof(mi) }; - if (GetWindowPlacement(getHWND(), &wplacement) && GetMonitorInfo(MonitorFromWindow(getHWND(), MONITOR_DEFAULTTOPRIMARY), &mi)) - { - DISPLAY_DEVICE dd = GetPrimaryDevice(); - DEVMODE dv; - ZeroMemory(&dv, sizeof(dv)); - dv.dmSize = sizeof(DEVMODE); - EnumDisplaySettings(dd.DeviceName, ENUM_CURRENT_SETTINGS, &dv); - dv.dmPelsWidth = mode.resolution.x; - dv.dmPelsHeight = mode.resolution.y; - dv.dmBitsPerPel = mode.bitDepth; - dv.dmDisplayFrequency = mode.refreshRate; - dv.dmFields = (DM_PELSWIDTH | DM_PELSHEIGHT); - ChangeDisplaySettings(&dv, CDS_FULLSCREEN); - SetWindowLong(getHWND(), GWL_STYLE, dwStyle & ~WS_OVERLAPPEDWINDOW); - SetWindowPos(getHWND(), HWND_TOP, - mi.rcMonitor.left, - mi.rcMonitor.top, - mi.rcMonitor.right - mi.rcMonitor.left, - mi.rcMonitor.bottom - mi.rcMonitor.top, - SWP_NOOWNERZORDER | SWP_FRAMECHANGED); - } - - if(mDisplayWindow) - ShowWindow(getHWND(), SW_SHOWNORMAL); - - // Clear the menu bar from the window for full screen - HMENU menu = GetMenu(getHWND()); - if(menu) + if ( GetWindowPlacement( getHWND(), &wplacement ) && GetMonitorInfo( MonitorFromWindow( getHWND(), MONITOR_DEFAULTTOPRIMARY ), &mi ) ) { - SetMenu(getHWND(), NULL); + DISPLAY_DEVICE dd = GetPrimaryDevice(); + DEVMODE dv; + ZeroMemory( &dv, sizeof( dv ) ); + dv.dmSize = sizeof( DEVMODE ); + EnumDisplaySettings( dd.DeviceName, ENUM_CURRENT_SETTINGS, &dv ); + dv.dmPelsWidth = mode.resolution.x; + dv.dmPelsHeight = mode.resolution.y; + dv.dmBitsPerPel = mode.bitDepth; + dv.dmDisplayFrequency = mode.refreshRate; + dv.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT; + ChangeDisplaySettings( &dv, CDS_FULLSCREEN ); + SetWindowLong( getHWND(), GWL_STYLE, dwStyle & ~WS_OVERLAPPEDWINDOW ); + SetWindowPos( getHWND(), HWND_TOP, mi.rcMonitor.left, + mi.rcMonitor.top, + mi.rcMonitor.right - mi.rcMonitor.left, + mi.rcMonitor.bottom - mi.rcMonitor.top, + SWP_NOOWNERZORDER | SWP_FRAMECHANGED ); } + if( mDisplayWindow ) + ShowWindow( getHWND(), SW_SHOWNORMAL ); + + // Clear the menu bar from the window for full screen + if( GetMenu( getHWND() ) ) + SetMenu( getHWND(), NULL ); + // When switching to Fullscreen, reset device after setting style - if(mTarget.isValid()) - mTarget->resetMode(); + if( mTarget.isValid() ) + mTarget->resetMode(); mFullscreen = true; - } - else - { - DISPLAY_DEVICE dd = GetPrimaryDevice(); - DEVMODE dv; - ZeroMemory(&dv, sizeof(dv)); - dv.dmSize = sizeof(DEVMODE); - EnumDisplaySettings(dd.DeviceName, ENUM_CURRENT_SETTINGS, &dv); + } + else + { + DISPLAY_DEVICE dd = GetPrimaryDevice(); + DEVMODE dv; + ZeroMemory( &dv, sizeof( dv ) ); + dv.dmSize = sizeof( DEVMODE ); + EnumDisplaySettings( dd.DeviceName, ENUM_CURRENT_SETTINGS, &dv ); - if ((mode.resolution.x != dv.dmPelsWidth) || (mode.resolution.y != dv.dmPelsHeight)) - ChangeDisplaySettings(NULL, 0); + if ( ( WindowManager->getDesktopResolution() != mode.resolution || + ( mode.resolution.x != dv.dmPelsWidth ) || ( mode.resolution.y != dv.dmPelsHeight ) ) ) + ChangeDisplaySettings( NULL, 0 ); - // Reset device *first*, so that when we call setSize() and let it - // access the monitor settings, it won't end up with our fullscreen - // geometry that is just about to change. + // Reset device *first*, so that when we call setSize() and let it + // access the monitor settings, it won't end up with our fullscreen + // geometry that is just about to change. - if(mTarget.isValid()) - mTarget->resetMode(); + if( mTarget.isValid() ) + mTarget->resetMode(); - if (!mOffscreenRender) + if ( !mOffscreenRender ) { - SetWindowLong( getHWND(), GWL_STYLE, mWindowedWindowStyle); - SetWindowPos( getHWND(), HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_FRAMECHANGED); + SetWindowLong( getHWND(), GWL_STYLE, mWindowedWindowStyle); + SetWindowPos( getHWND(), HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_FRAMECHANGED); // Put back the menu bar, if any if(mMenuHandle) @@ -253,42 +247,37 @@ void Win32Window::setVideoMode( const GFXVideoMode &mode ) } else { - HWND parentWin = (HWND)mOwningManager->getParentWindow(); + HWND parentWin = reinterpret_cast( mOwningManager->getParentWindow() ); RECT windowRect; - GetClientRect(parentWin, &windowRect); - Point2I res(windowRect.right-windowRect.left, windowRect.bottom-windowRect.top); - if (res.x == 0 || res.y == 0) - { - // Must be too early in the window set up to obtain the parent's size. - setSize(mode.resolution); - } + GetClientRect( parentWin, &windowRect ); + Point2I res( windowRect.right - windowRect.left, windowRect.bottom - windowRect.top ); + + if ( res.x == 0 || res.y == 0 ) + setSize( mode.resolution ); // Must be too early in the window set up to obtain the parent's size. else - { - setSize(res); - } + setSize( res ); } - if (!mOffscreenRender) + if ( !mOffscreenRender ) { - // We have to force Win32 to update the window frame and make the window - // visible and no longer topmost - this code might be possible to simplify. - SetWindowPos( getHWND(), HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_FRAMECHANGED); + // We have to force Win32 to update the window frame and make the window + // visible and no longer topmost - this code might be possible to simplify. + SetWindowPos( getHWND(), HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_FRAMECHANGED ); if(mDisplayWindow) - ShowWindow( getHWND(), SW_SHOWNORMAL); + ShowWindow( getHWND(), SW_SHOWNORMAL ); } mFullscreen = false; - } + } - mSuppressReset = false; + mSuppressReset = false; - if(needCurtain) - mOwningManager->raiseCurtain(); + if( needCurtain ) + mOwningManager->raiseCurtain(); - SetForegroundWindow(getHWND()); - - getScreenResChangeSignal().trigger(this, true); + SetForegroundWindow( getHWND() ); + getScreenResChangeSignal().trigger( this, true ); } bool Win32Window::clearFullscreen() From 39613c0d87ace06e9648b3fb0d886f3c7758475c Mon Sep 17 00:00:00 2001 From: irei1as Date: Mon, 15 Feb 2016 18:43:56 +0100 Subject: [PATCH 39/47] Optimized You're right. If the normalized quaternions are in a variable or something for normal uses it's just a waste to force the change hidden inside again. --- Engine/source/math/mQuat.h | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/Engine/source/math/mQuat.h b/Engine/source/math/mQuat.h index 628e298ba..10efb0619 100644 --- a/Engine/source/math/mQuat.h +++ b/Engine/source/math/mQuat.h @@ -227,12 +227,8 @@ inline F32 QuatF::dot( const QuatF &q ) const inline F32 QuatF::angleBetween( const QuatF & q ) { - // angle between two quaternions - QuatF base(x,y,z,w); - base.normalize(); - QuatF q_norm=q; - q_norm.normalize(); - return 2.0f*mAcos(base.dot(q_norm)); + // angle between two quaternions. + return mAcos(q.dot(*this)) * 2.0f; } #endif // _MQUAT_H_ From 6891d348af015f5695d568aac6976c77b0890212 Mon Sep 17 00:00:00 2001 From: irei1as Date: Mon, 15 Feb 2016 18:50:18 +0100 Subject: [PATCH 40/47] Update mQuat.h --- Engine/source/math/mQuat.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Engine/source/math/mQuat.h b/Engine/source/math/mQuat.h index 10efb0619..ca6ed5d82 100644 --- a/Engine/source/math/mQuat.h +++ b/Engine/source/math/mQuat.h @@ -227,7 +227,7 @@ inline F32 QuatF::dot( const QuatF &q ) const inline F32 QuatF::angleBetween( const QuatF & q ) { - // angle between two quaternions. + // angle between two normalized quaternions. return mAcos(q.dot(*this)) * 2.0f; } From d25b03cd5278d75c04a204d05d55dcc81d5a7942 Mon Sep 17 00:00:00 2001 From: Azaezel Date: Mon, 15 Feb 2016 18:12:56 -0600 Subject: [PATCH 41/47] vsprintf replacement with engine vairant resolves first issue in https://github.com/GarageGames/Torque3D/issues/1515#issuecomment-184446719 --- Engine/source/core/stream/stream.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Engine/source/core/stream/stream.cpp b/Engine/source/core/stream/stream.cpp index da1b1dc82..8a7fb2b40 100644 --- a/Engine/source/core/stream/stream.cpp +++ b/Engine/source/core/stream/stream.cpp @@ -128,7 +128,7 @@ bool Stream::writeFormattedBuffer(const char *format, ...) char buffer[4096]; va_list args; va_start(args, format); - const S32 length = vsprintf(buffer, format, args); + const S32 length = dVsprintf(buffer, sizeof(buffer), format, args); // Sanity! AssertFatal(length <= sizeof(buffer), "writeFormattedBuffer - String format exceeded buffer size. This will cause corruption."); From db4755a00f75e1627552b9a0e2530a1dc7ecebbb Mon Sep 17 00:00:00 2001 From: Azaezel Date: Mon, 15 Feb 2016 19:05:09 -0600 Subject: [PATCH 42/47] namespace conflict resolution --- Engine/source/persistence/taml/fsTinyXml.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Engine/source/persistence/taml/fsTinyXml.cpp b/Engine/source/persistence/taml/fsTinyXml.cpp index 1fb97398b..a4fdafb57 100644 --- a/Engine/source/persistence/taml/fsTinyXml.cpp +++ b/Engine/source/persistence/taml/fsTinyXml.cpp @@ -38,7 +38,7 @@ bool fsTiXmlDocument::LoadFile( const char * pFilename, TiXmlEncoding encoding ) #endif // File open for read? - if ( !stream.open( filenameBuffer, Torque::FS::File::AccessMode::Read ) ) + if ( !stream.open( filenameBuffer, Torque::FS::File::Read ) ) { // No, so warn. Con::warnf("TamlXmlParser::parse() - Could not open filename '%s' for parse.", filenameBuffer ); @@ -67,7 +67,7 @@ bool fsTiXmlDocument::SaveFile( const char * pFilename ) const FileStream stream; // File opened? - if ( !stream.open( filenameBuffer, Torque::FS::File::AccessMode::Write ) ) + if ( !stream.open( filenameBuffer, Torque::FS::File::Write ) ) { // No, so warn. Con::warnf("Taml::writeFile() - Could not open filename '%s' for write.", filenameBuffer ); From f8c4dd9d1d4cf8c72eaa77e3875ee1a1073a7da3 Mon Sep 17 00:00:00 2001 From: Azaezel Date: Mon, 15 Feb 2016 19:08:03 -0600 Subject: [PATCH 43/47] http://stackoverflow.com/questions/8461832/explicit-qualification-in-declaration --- Engine/source/math/mathUtils.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Engine/source/math/mathUtils.cpp b/Engine/source/math/mathUtils.cpp index f6086c5e4..5ffd9a870 100644 --- a/Engine/source/math/mathUtils.cpp +++ b/Engine/source/math/mathUtils.cpp @@ -1847,7 +1847,7 @@ U32 extrudePolygonEdgesFromPoint( const Point3F* vertices, U32 numVertices, cons //----------------------------------------------------------------------------- -void MathUtils::mBuildHull2D(const Vector _inPoints, Vector &hullPoints) +void mBuildHull2D(const Vector _inPoints, Vector &hullPoints) { /// Andrew's monotone chain convex hull algorithm implementation From 9a2a5b2a90515eda9684fc9d042deda5a0d77cb4 Mon Sep 17 00:00:00 2001 From: Anis Date: Thu, 18 Feb 2016 16:49:06 +0100 Subject: [PATCH 44/47] compile fix. --- Engine/source/gfx/sim/debugDraw.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Engine/source/gfx/sim/debugDraw.h b/Engine/source/gfx/sim/debugDraw.h index c650417b0..a07f52ca4 100644 --- a/Engine/source/gfx/sim/debugDraw.h +++ b/Engine/source/gfx/sim/debugDraw.h @@ -124,7 +124,10 @@ public: void drawLine(const Point3F &a, const Point3F &b, const ColorF &color = ColorF(1.0f,1.0f,1.0f)); void drawTri(const Point3F &a, const Point3F &b, const Point3F &c, const ColorF &color = ColorF(1.0f,1.0f,1.0f)); void drawText(const Point3F& pos, const String& text, const ColorF &color = ColorF(1.0f,1.0f,1.0f)); - + void drawCapsule(const Point3F &a, const F32 &radius, const F32 &height, const ColorF &color = ColorF(1.0f, 1.0f, 1.0f)); + void drawDirectionLine(const Point3F &a, const Point3F &b, const ColorF &color = ColorF(1.0f, 1.0f, 1.0f)); + void drawOutlinedText(const Point3F& pos, const String& text, const ColorF &color = ColorF(1.0f, 1.0f, 1.0f), const ColorF &colorOutline = ColorF(0.0f, 0.0f, 0.0f)); + /// Render a wireframe view of the given polyhedron. void drawPolyhedron( const AnyPolyhedron& polyhedron, const ColorF& color = ColorF( 1.f, 1.f, 1.f ) ); From 6f47cb7dfae34f43d88cd520310f4649005cea34 Mon Sep 17 00:00:00 2001 From: Anis Date: Fri, 19 Feb 2016 00:34:07 +0100 Subject: [PATCH 45/47] Update guiControl.h --- Engine/source/gui/core/guiControl.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Engine/source/gui/core/guiControl.h b/Engine/source/gui/core/guiControl.h index dc2653ff9..ca873878d 100644 --- a/Engine/source/gui/core/guiControl.h +++ b/Engine/source/gui/core/guiControl.h @@ -121,9 +121,9 @@ class GuiControl : public SimGroup horizResizeLeft, ///< fixed on the right and width horizResizeCenter, horizResizeRelative, ///< resize relative - horizResizeAspectLeft, ///< resize relative to hieght delta (offset Left) - horizResizeAspectRight, ///< resize relative to hieght delta (offset Right) - horizResizeAspectCenter, ///< resize relative to hieght delta (Centered) + horizResizeAspectLeft, ///< resize relative to height delta (offset Left) + horizResizeAspectRight, ///< resize relative to height delta (offset Right) + horizResizeAspectCenter, ///< resize relative to height delta (Centered) horizResizeWindowRelative ///< resize window relative }; enum vertSizingOptions From 36daca8d8e4b641e1d653fb0ebc581cb97b5ada5 Mon Sep 17 00:00:00 2001 From: rextimmy Date: Sun, 21 Feb 2016 15:10:58 +1000 Subject: [PATCH 46/47] Corrected FeatureSet::getNextFeatureIndex and ShaderFeature::getProcessIndex signed mismatch. --- Engine/source/shaderGen/featureSet.cpp | 2 +- Engine/source/shaderGen/featureSet.h | 2 +- Engine/source/shaderGen/shaderFeature.h | 2 +- Engine/source/terrain/hlsl/terrFeatureHLSL.cpp | 10 +++++----- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Engine/source/shaderGen/featureSet.cpp b/Engine/source/shaderGen/featureSet.cpp index 7189beacc..2eff50e1c 100644 --- a/Engine/source/shaderGen/featureSet.cpp +++ b/Engine/source/shaderGen/featureSet.cpp @@ -170,7 +170,7 @@ void FeatureSet::removeFeature( const FeatureType &type ) } } -U32 FeatureSet::getNextFeatureIndex( const FeatureType &type, S32 index ) const +S32 FeatureSet::getNextFeatureIndex( const FeatureType &type, S32 index ) const { for ( U32 i=0; i < mFeatures.size(); i++ ) { diff --git a/Engine/source/shaderGen/featureSet.h b/Engine/source/shaderGen/featureSet.h index e8920dc67..03b46f62a 100644 --- a/Engine/source/shaderGen/featureSet.h +++ b/Engine/source/shaderGen/featureSet.h @@ -106,7 +106,7 @@ public: void removeFeature( const FeatureType &type ); /// - U32 getNextFeatureIndex( const FeatureType &type, S32 index ) const; + S32 getNextFeatureIndex( const FeatureType &type, S32 index ) const; /// Removes features that are not in the input set. void filter( const FeatureSet &features ); diff --git a/Engine/source/shaderGen/shaderFeature.h b/Engine/source/shaderGen/shaderFeature.h index f18fae7f9..c6ac4955d 100644 --- a/Engine/source/shaderGen/shaderFeature.h +++ b/Engine/source/shaderGen/shaderFeature.h @@ -153,7 +153,7 @@ public: void setProcessIndex( S32 index ) { mProcessIndex = index; } /// - U32 getProcessIndex() const { return mProcessIndex; } + S32 getProcessIndex() const { return mProcessIndex; } //----------------------------------------------------------------------- // Virtual Functions diff --git a/Engine/source/terrain/hlsl/terrFeatureHLSL.cpp b/Engine/source/terrain/hlsl/terrFeatureHLSL.cpp index 6ef1c2009..d993f4bd8 100644 --- a/Engine/source/terrain/hlsl/terrFeatureHLSL.cpp +++ b/Engine/source/terrain/hlsl/terrFeatureHLSL.cpp @@ -298,7 +298,7 @@ TerrainDetailMapFeatHLSL::TerrainDetailMapFeatHLSL() void TerrainDetailMapFeatHLSL::processVert( Vector &componentList, const MaterialFeatureData &fd ) { - const U32 detailIndex = getProcessIndex(); + const S32 detailIndex = getProcessIndex(); // Grab incoming texture coords... the base map feature // made sure this was created. @@ -383,7 +383,7 @@ void TerrainDetailMapFeatHLSL::processVert( Vector &component void TerrainDetailMapFeatHLSL::processPix( Vector &componentList, const MaterialFeatureData &fd ) { - const U32 detailIndex = getProcessIndex(); + const S32 detailIndex = getProcessIndex(); Var *inTex = getVertTexCoord( "texCoord" ); MultiLine *meta = new MultiLine; @@ -615,7 +615,7 @@ TerrainMacroMapFeatHLSL::TerrainMacroMapFeatHLSL() void TerrainMacroMapFeatHLSL::processVert( Vector &componentList, const MaterialFeatureData &fd ) { - const U32 detailIndex = getProcessIndex(); + const S32 detailIndex = getProcessIndex(); // Grab incoming texture coords... the base map feature // made sure this was created. @@ -673,7 +673,7 @@ void TerrainMacroMapFeatHLSL::processVert( Vector &componentL void TerrainMacroMapFeatHLSL::processPix( Vector &componentList, const MaterialFeatureData &fd ) { - const U32 detailIndex = getProcessIndex(); + const S32 detailIndex = getProcessIndex(); Var *inTex = getVertTexCoord( "texCoord" ); MultiLine *meta = new MultiLine; @@ -900,7 +900,7 @@ void TerrainNormalMapFeatHLSL::processPix( Vector &component meta->addStatement( new GenOp( " @ = @[2];\r\n", new DecOp( gbNormal ), viewToTangent ) ); } - const U32 normalIndex = getProcessIndex(); + const S32 normalIndex = getProcessIndex(); Var *detailBlend = (Var*)LangElement::find( String::ToString( "detailBlend%d", normalIndex ) ); AssertFatal( detailBlend, "The detail blend is missing!" ); From 2383e8e43e306f902e234049ef0731482067e6dd Mon Sep 17 00:00:00 2001 From: rextimmy Date: Sun, 21 Feb 2016 22:24:05 +1000 Subject: [PATCH 47/47] Fix for TerrainFeatGLSL getProcessIndex() signed mismatch --- Engine/source/terrain/glsl/terrFeatureGLSL.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Engine/source/terrain/glsl/terrFeatureGLSL.cpp b/Engine/source/terrain/glsl/terrFeatureGLSL.cpp index 5f32359a8..dd67124c6 100644 --- a/Engine/source/terrain/glsl/terrFeatureGLSL.cpp +++ b/Engine/source/terrain/glsl/terrFeatureGLSL.cpp @@ -298,7 +298,7 @@ TerrainDetailMapFeatGLSL::TerrainDetailMapFeatGLSL() void TerrainDetailMapFeatGLSL::processVert( Vector &componentList, const MaterialFeatureData &fd ) { - const U32 detailIndex = getProcessIndex(); + const S32 detailIndex = getProcessIndex(); // Grab incoming texture coords... the base map feature // made sure this was created. @@ -383,7 +383,7 @@ void TerrainDetailMapFeatGLSL::processVert( Vector &component void TerrainDetailMapFeatGLSL::processPix( Vector &componentList, const MaterialFeatureData &fd ) { - const U32 detailIndex = getProcessIndex(); + const S32 detailIndex = getProcessIndex(); Var *inTex = getVertTexCoord( "texCoord" ); MultiLine *meta = new MultiLine; @@ -616,7 +616,7 @@ TerrainMacroMapFeatGLSL::TerrainMacroMapFeatGLSL() void TerrainMacroMapFeatGLSL::processVert( Vector &componentList, const MaterialFeatureData &fd ) { - const U32 detailIndex = getProcessIndex(); + const S32 detailIndex = getProcessIndex(); // Grab incoming texture coords... the base map feature // made sure this was created. @@ -674,7 +674,7 @@ void TerrainMacroMapFeatGLSL::processVert( Vector &componentL void TerrainMacroMapFeatGLSL::processPix( Vector &componentList, const MaterialFeatureData &fd ) { - const U32 detailIndex = getProcessIndex(); + const S32 detailIndex = getProcessIndex(); Var *inTex = getVertTexCoord( "texCoord" ); MultiLine *meta = new MultiLine; @@ -900,7 +900,7 @@ void TerrainNormalMapFeatGLSL::processPix( Vector &component meta->addStatement( new GenOp( " @ = tGetMatrix3Row(@, 2);\r\n", new DecOp( gbNormal ), viewToTangent ) ); } - const U32 normalIndex = getProcessIndex(); + const S32 normalIndex = getProcessIndex(); Var *detailBlend = (Var*)LangElement::find( String::ToString( "detailBlend%d", normalIndex ) ); AssertFatal( detailBlend, "The detail blend is missing!" );