From b5dfdf1fbbd7429ecc3d5c482ba9663db516f2fd Mon Sep 17 00:00:00 2001 From: Areloch Date: Thu, 12 Oct 2017 01:41:27 -0500 Subject: [PATCH 01/34] Adds functionality to automate convex proxy objects for appropriate types. Instead of having to manually convert a zone or portal or occlusion volume to convex to edit it's shape, then back again, simply entering the convex editor will automatically convert them to proxy convex shapes, with a special material to denote them. When the convex shape editor is exited, it converts them back to their original type, with the changes made to the proxy convex applied to them. --- Engine/source/T3D/convexShape.h | 2 + .../worldEditor/guiConvexShapeEditorCtrl.cpp | 297 +++++++++++++++++- .../worldEditor/guiConvexShapeEditorCtrl.h | 12 + .../images/occluderProxyImage.png | Bin 0 -> 40588 bytes .../convexEditor/images/portalProxyImage.png | Bin 0 -> 37452 bytes .../convexEditor/images/triggerProxyImage.png | Bin 0 -> 22887 bytes .../convexEditor/images/zoneProxyImage.png | Bin 0 -> 26122 bytes .../Full/game/tools/convexEditor/materials.cs | 39 +++ 8 files changed, 349 insertions(+), 1 deletion(-) create mode 100644 Templates/Full/game/tools/convexEditor/images/occluderProxyImage.png create mode 100644 Templates/Full/game/tools/convexEditor/images/portalProxyImage.png create mode 100644 Templates/Full/game/tools/convexEditor/images/triggerProxyImage.png create mode 100644 Templates/Full/game/tools/convexEditor/images/zoneProxyImage.png create mode 100644 Templates/Full/game/tools/convexEditor/materials.cs diff --git a/Engine/source/T3D/convexShape.h b/Engine/source/T3D/convexShape.h index d0f30eeaa..651ad5d01 100644 --- a/Engine/source/T3D/convexShape.h +++ b/Engine/source/T3D/convexShape.h @@ -200,6 +200,8 @@ public: /// @} + String getMaterialName() { return mMaterialName; } + protected: void _updateMaterial(); diff --git a/Engine/source/gui/worldEditor/guiConvexShapeEditorCtrl.cpp b/Engine/source/gui/worldEditor/guiConvexShapeEditorCtrl.cpp index 6bc043d09..daf4fbb6f 100644 --- a/Engine/source/gui/worldEditor/guiConvexShapeEditorCtrl.cpp +++ b/Engine/source/gui/worldEditor/guiConvexShapeEditorCtrl.cpp @@ -46,6 +46,10 @@ #include "core/volume.h" #include "gui/worldEditor/worldEditor.h" #include "T3D/prefab.h" +#include "T3D/trigger.h" +#include "T3D/zone.h" +#include "T3D/portal.h" +#include "math/mPolyhedron.impl.h" IMPLEMENT_CONOBJECT( GuiConvexEditorCtrl ); @@ -161,6 +165,35 @@ void GuiConvexEditorCtrl::setVisible( bool val ) mGizmoProfile->flags = mSavedGizmoFlags; mSavedGizmoFlags = -1; } + + SimGroup* misGroup; + if (Sim::findObject("MissionGroup", misGroup)) + { + //Make our proxy objects "real" again + for (U32 i = 0; i < mProxyObjects.size(); ++i) + { + if (!mProxyObjects[i].shapeProxy || !mProxyObjects[i].targetObject) + continue; + + AbstractClassRep* classRep = AbstractClassRep::findClassRep(mProxyObjects[i].targetObjectClass); + if (!classRep) + { + Con::errorf("WorldEditor::createPolyhedralObject - No such class: %s", mProxyObjects[i].targetObjectClass); + continue; + } + + SceneObject* polyObj = createPolyhedralObject(mProxyObjects[i].targetObjectClass.c_str(), mProxyObjects[i].shapeProxy); + + misGroup->addObject(polyObj); + + //Now, remove the convex proxy + mProxyObjects[i].shapeProxy->deleteObject(); + mProxyObjects[i].targetObject->deleteObject(); + mProxyObjects.erase(i); + --i; + } + + } } else { @@ -188,6 +221,60 @@ void GuiConvexEditorCtrl::setVisible( bool val ) } updateGizmoPos(); mSavedGizmoFlags = mGizmoProfile->flags; + + SimGroup* misGroup; + if (Sim::findObject("MissionGroup", misGroup)) + { + for (U32 c = 0; c < misGroup->size(); ++c) + { + bool isTrigger = (misGroup->at(c)->getClassName() == StringTable->insert("Trigger")); + bool isZone = (misGroup->at(c)->getClassName() == StringTable->insert("Zone")); + bool isPortal = (misGroup->at(c)->getClassName() == StringTable->insert("Portal")); + bool isOccluder = (misGroup->at(c)->getClassName() == StringTable->insert("OcclusionVolume")); + + if (isZone || isPortal || isOccluder) + { + SceneObject* sceneObj = static_cast(misGroup->at(c)); + if (!sceneObj) + { + Con::errorf("WorldEditor::createConvexShapeFrom - Invalid object"); + continue; + } + + ConvexShape* proxyShape = createConvexShapeFrom(sceneObj); + + //Set the texture to a representatory one so we know what's what + if (isTrigger) + proxyShape->mMaterialName = "TriggerProxyMaterial"; + else if (isPortal) + proxyShape->mMaterialName = "PortalProxyMaterial"; + else if (isZone) + proxyShape->mMaterialName = "ZoneProxyMaterial"; + else if (isOccluder) + proxyShape->mMaterialName = "OccluderProxyMaterial"; + + proxyShape->_updateMaterial(); + + sceneObj->setHidden(true); + + //set up the proxy object + ConvexShapeProxy newProxy; + newProxy.shapeProxy = proxyShape; + newProxy.targetObject = sceneObj; + + if (isTrigger) + newProxy.targetObjectClass = "Trigger"; + else if (isPortal) + newProxy.targetObjectClass = "Portal"; + else if (isZone) + newProxy.targetObjectClass = "Zone"; + else + newProxy.targetObjectClass = "OcclusionVolume"; + + mProxyObjects.push_back(newProxy); + } + } + } } } @@ -438,6 +525,8 @@ void GuiConvexEditorCtrl::on3DMouseDragged(const Gui3DMouseEvent & event) setupShape( newShape ); + newShape->setField("material", mConvexSEL->getMaterialName()); + submitUndo( CreateShape, newShape ); setSelection( newShape, -1 ); @@ -2033,7 +2122,8 @@ ConvexShape* ConvexEditorCreateTool::extrudeShapeFromFace( ConvexShape *inShape, surf.mulL( worldToShape ); } - newShape->setField( "material", Parent::mEditor->mMaterialName ); + //newShape->setField( "material", Parent::mEditor->mMaterialName ); + newShape->setField("material", inShape->getMaterialName()); newShape->registerObject(); mEditor->updateShape( newShape ); @@ -2179,6 +2269,211 @@ void GuiConvexEditorCtrl::splitSelectedFace() updateGizmoPos(); } +SceneObject* GuiConvexEditorCtrl::createPolyhedralObject(const char* className, SceneObject* geometryProvider) +{ + if (!geometryProvider) + { + Con::errorf("WorldEditor::createPolyhedralObject - Invalid geometry provider!"); + return NULL; + } + + if (!className || !className[0]) + { + Con::errorf("WorldEditor::createPolyhedralObject - Invalid class name"); + return NULL; + } + + AbstractClassRep* classRep = AbstractClassRep::findClassRep(className); + if (!classRep) + { + Con::errorf("WorldEditor::createPolyhedralObject - No such class: %s", className); + return NULL; + } + + // We don't want the extracted poly list to be affected by the object's + // current transform and scale so temporarily reset them. + + MatrixF savedTransform = geometryProvider->getTransform(); + Point3F savedScale = geometryProvider->getScale(); + + geometryProvider->setTransform(MatrixF::Identity); + geometryProvider->setScale(Point3F(1.f, 1.f, 1.f)); + + // Extract the geometry. Use the object-space bounding volumes + // as we have moved the object to the origin for the moment. + + OptimizedPolyList polyList; + if (!geometryProvider->buildPolyList(PLC_Export, &polyList, geometryProvider->getObjBox(), geometryProvider->getObjBox().getBoundingSphere())) + { + Con::errorf("WorldEditor::createPolyhedralObject - Failed to extract geometry!"); + return NULL; + } + + // Restore the object's original transform. + + geometryProvider->setTransform(savedTransform); + geometryProvider->setScale(savedScale); + + // Create the object. + + SceneObject* object = dynamic_cast< SceneObject* >(classRep->create()); + if (!Object) + { + Con::errorf("WorldEditor::createPolyhedralObject - Could not create SceneObject with class '%s'", className); + return NULL; + } + + // Convert the polylist to a polyhedron. + + Polyhedron polyhedron = polyList.toPolyhedron(); + + // Add the vertex data. + + const U32 numPoints = polyhedron.getNumPoints(); + const Point3F* points = polyhedron.getPoints(); + + for (U32 i = 0; i < numPoints; ++i) + { + static StringTableEntry sPoint = StringTable->insert("point"); + object->setDataField(sPoint, NULL, EngineMarshallData(points[i])); + } + + // Add the plane data. + + const U32 numPlanes = polyhedron.getNumPlanes(); + const PlaneF* planes = polyhedron.getPlanes(); + + for (U32 i = 0; i < numPlanes; ++i) + { + static StringTableEntry sPlane = StringTable->insert("plane"); + const PlaneF& plane = planes[i]; + + char buffer[1024]; + dSprintf(buffer, sizeof(buffer), "%g %g %g %g", plane.x, plane.y, plane.z, plane.d); + + object->setDataField(sPlane, NULL, buffer); + } + + // Add the edge data. + + const U32 numEdges = polyhedron.getNumEdges(); + const Polyhedron::Edge* edges = polyhedron.getEdges(); + + for (U32 i = 0; i < numEdges; ++i) + { + static StringTableEntry sEdge = StringTable->insert("edge"); + const Polyhedron::Edge& edge = edges[i]; + + char buffer[1024]; + dSprintf(buffer, sizeof(buffer), "%i %i %i %i ", + edge.face[0], edge.face[1], + edge.vertex[0], edge.vertex[1] + ); + + object->setDataField(sEdge, NULL, buffer); + } + + // Set the transform. + + object->setTransform(savedTransform); + object->setScale(savedScale); + + // Register and return the object. + + if (!object->registerObject()) + { + Con::errorf("WorldEditor::createPolyhedralObject - Failed to register object!"); + delete object; + return NULL; + } + + return object; +} + +ConvexShape* GuiConvexEditorCtrl::createConvexShapeFrom(SceneObject* polyObject) +{ + if (!polyObject) + { + Con::errorf("WorldEditor::createConvexShapeFrom - Invalid object"); + return NULL; + } + + IScenePolyhedralObject* iPoly = dynamic_cast< IScenePolyhedralObject* >(polyObject); + if (!iPoly) + { + Con::errorf("WorldEditor::createConvexShapeFrom - Not a polyhedral object!"); + return NULL; + } + + // Get polyhedron. + + AnyPolyhedron polyhedron = iPoly->ToAnyPolyhedron(); + const U32 numPlanes = polyhedron.getNumPlanes(); + if (!numPlanes) + { + Con::errorf("WorldEditor::createConvexShapeFrom - Object returned no valid polyhedron"); + return NULL; + } + + // Create a ConvexShape. + + ConvexShape* shape = new ConvexShape(); + + // Add all planes. + + for (U32 i = 0; i < numPlanes; ++i) + { + const PlaneF& plane = polyhedron.getPlanes()[i]; + + // Polyhedron planes are facing inwards so we need to + // invert the normal here. + + Point3F normal = plane.getNormal(); + normal.neg(); + + // Turn the orientation of the plane into a quaternion. + // The normal is our up vector (that's what's expected + // by ConvexShape for the surface orientation). + + MatrixF orientation(true); + MathUtils::getMatrixFromUpVector(normal, &orientation); + const QuatF quat(orientation); + + // Get the plane position. + + const Point3F position = plane.getPosition(); + + // Turn everything into a "surface" property for the ConvexShape. + + char buffer[1024]; + dSprintf(buffer, sizeof(buffer), "%g %g %g %g %g %g %g", + quat.x, quat.y, quat.z, quat.w, + position.x, position.y, position.z + ); + + // Add the surface. + + static StringTableEntry sSurface = StringTable->insert("surface"); + shape->setDataField(sSurface, NULL, buffer); + } + + // Copy the transform. + + shape->setTransform(polyObject->getTransform()); + shape->setScale(polyObject->getScale()); + + // Register the shape. + + if (!shape->registerObject()) + { + Con::errorf("WorldEditor::createConvexShapeFrom - Could not register ConvexShape!"); + delete shape; + return NULL; + } + + return shape; +} + DefineConsoleMethod( GuiConvexEditorCtrl, hollowSelection, void, (), , "" ) { object->hollowSelection(); diff --git a/Engine/source/gui/worldEditor/guiConvexShapeEditorCtrl.h b/Engine/source/gui/worldEditor/guiConvexShapeEditorCtrl.h index 0bb00c32f..dbf8f267f 100644 --- a/Engine/source/gui/worldEditor/guiConvexShapeEditorCtrl.h +++ b/Engine/source/gui/worldEditor/guiConvexShapeEditorCtrl.h @@ -114,6 +114,8 @@ public: void dropSelectionAtScreenCenter(); void splitSelectedFace(); + SceneObject* createPolyhedralObject(const char* className, SceneObject* geometryProvider); + ConvexShape* createConvexShapeFrom(SceneObject* polyObject); /// Interface with Tools. /// @{ @@ -192,6 +194,16 @@ protected: UndoAction *mLastUndo; UndoManager *mUndoManager; + struct ConvexShapeProxy + { + ConvexShape* shapeProxy; + SceneObject* targetObject; + String targetObjectClass; + bool dirty; + }; + + Vector mProxyObjects; + ConvexEditorTool *mActiveTool; ConvexEditorCreateTool *mCreateTool; }; diff --git a/Templates/Full/game/tools/convexEditor/images/occluderProxyImage.png b/Templates/Full/game/tools/convexEditor/images/occluderProxyImage.png new file mode 100644 index 0000000000000000000000000000000000000000..51fe109f4d54ed7a5424b32dca65930f0392dbff GIT binary patch literal 40588 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%0AJiROz(i;dZo;`w? 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 z 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 Z6Gs7?yh&S_p=4ghx0t| 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 literal 0 HcmV?d00001 diff --git a/Templates/Full/game/tools/convexEditor/images/zoneProxyImage.png b/Templates/Full/game/tools/convexEditor/images/zoneProxyImage.png new file mode 100644 index 0000000000000000000000000000000000000000..323e174984f9b372395718fecb4bcf085f7c8891 GIT binary patch literal 26122 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 IT Date: Fri, 19 Jan 2018 22:34:26 +1000 Subject: [PATCH 02/34] PhysX 3.4 implementation --- Engine/source/T3D/physics/physicsPlugin.cpp | 7 +- Engine/source/T3D/physics/physicsPlugin.h | 4 + Engine/source/T3D/physics/physicsWorld.cpp | 2 + Engine/source/T3D/physics/physicsWorld.h | 6 + Engine/source/T3D/physics/physx3/px3.h | 44 ++- Engine/source/T3D/physics/physx3/px3Body.cpp | 67 ++-- Engine/source/T3D/physics/physx3/px3Body.h | 3 +- .../T3D/physics/physx3/px3Collision.cpp | 206 ++++++------ .../source/T3D/physics/physx3/px3Collision.h | 3 + .../source/T3D/physics/physx3/px3Player.cpp | 13 +- .../source/T3D/physics/physx3/px3Stream.cpp | 9 +- Engine/source/T3D/physics/physx3/px3Stream.h | 4 +- Engine/source/T3D/physics/physx3/px3World.cpp | 233 ++++++------- Engine/source/T3D/physics/physx3/px3World.h | 28 +- Tools/CMake/modules/module_physx3.cmake | 316 ++++++++++++------ 15 files changed, 527 insertions(+), 418 deletions(-) diff --git a/Engine/source/T3D/physics/physicsPlugin.cpp b/Engine/source/T3D/physics/physicsPlugin.cpp index b2f06b55e..9b908a13c 100644 --- a/Engine/source/T3D/physics/physicsPlugin.cpp +++ b/Engine/source/T3D/physics/physicsPlugin.cpp @@ -35,12 +35,11 @@ #include "T3D/physics/physicsWorld.h" #include "core/util/tNamedFactory.h" - PhysicsPlugin* PhysicsPlugin::smSingleton = NULL; PhysicsResetSignal PhysicsPlugin::smPhysicsResetSignal; bool PhysicsPlugin::smSinglePlayer = false; U32 PhysicsPlugin::smThreadCount = 2; - +bool PhysicsPlugin::smGpuAccelerationAllowed = false; String PhysicsPlugin::smServerWorldName( "server" ); String PhysicsPlugin::smClientWorldName( "client" ); @@ -51,6 +50,10 @@ AFTER_MODULE_INIT( Sim ) "@brief Informs the physics simulation if only a single player exists.\n\n" "If true, optimizations will be implemented to better cater to a single player environmnent.\n\n" "@ingroup Physics\n"); + Con::addVariable("$Physics::gpuAccelerationAllowed", TypeBool, &PhysicsPlugin::smGpuAccelerationAllowed, + "@brief Informs the physics plugin if it is allowed to use gpu acceleration.\n\n" + "Not all physics implemenations or gpus can support gpu acceleration, this simply informs the plugin if it is allowed to try and use it or not.\n\n" + "@ingroup Physics\n"); Con::addVariable( "$pref::Physics::threadCount", TypeS32, &PhysicsPlugin::smThreadCount, "@brief Number of threads to use in a single pass of the physics engine.\n\n" "Defaults to 2 if not set.\n\n" diff --git a/Engine/source/T3D/physics/physicsPlugin.h b/Engine/source/T3D/physics/physicsPlugin.h index 91c187473..bf5040941 100644 --- a/Engine/source/T3D/physics/physicsPlugin.h +++ b/Engine/source/T3D/physics/physicsPlugin.h @@ -96,6 +96,10 @@ public: /// @see PHYSICSPLUGIN static PhysicsPlugin* getSingleton() { return smSingleton; } + /// Allow gpu acceleration if supported + static bool smGpuAccelerationAllowed; + static bool gpuAccelerationAllowed() { return smGpuAccelerationAllowed; } + /// static bool activate( const char *library ); diff --git a/Engine/source/T3D/physics/physicsWorld.cpp b/Engine/source/T3D/physics/physicsWorld.cpp index 65b254885..7298987c3 100644 --- a/Engine/source/T3D/physics/physicsWorld.cpp +++ b/Engine/source/T3D/physics/physicsWorld.cpp @@ -26,6 +26,8 @@ //Physics timing F32 PhysicsWorld::smPhysicsStepTime = 1.0f / 60.f; //default 60fps U32 PhysicsWorld::smPhysicsMaxSubSteps = 4; +//Gpu acceleration +bool PhysicsWorld::smGpuEnabled = false; PhysicsWorld::PhysicsWorld() : mGravity( 0, 0, -20.0f ) // NOTE: This matches the gravity used for player objects. diff --git a/Engine/source/T3D/physics/physicsWorld.h b/Engine/source/T3D/physics/physicsWorld.h index a18cffb98..e03d088c5 100644 --- a/Engine/source/T3D/physics/physicsWorld.h +++ b/Engine/source/T3D/physics/physicsWorld.h @@ -49,6 +49,9 @@ protected: /// The current gravity force. Point3F mGravity; + /// Gpu acceleration + static bool smGpuEnabled; + public: /// The constructor. @@ -115,6 +118,9 @@ public: /// Physics timing static F32 smPhysicsStepTime; static U32 smPhysicsMaxSubSteps; + + /// Gpu acceleration + static bool isGpuEnabled() { return smGpuEnabled; } }; diff --git a/Engine/source/T3D/physics/physx3/px3.h b/Engine/source/T3D/physics/physx3/px3.h index 6db611b51..ef273e009 100644 --- a/Engine/source/T3D/physics/physx3/px3.h +++ b/Engine/source/T3D/physics/physx3/px3.h @@ -33,19 +33,43 @@ #define WIN32 #endif +// macOS _DEBUG & NDEBUG +#if defined(TORQUE_OS_MAC) && defined(TORQUE_DEBUG) && !defined(_DEBUG) + #define _DEBUG +#elif defined(TORQUE_OS_MAC) && defined(TORQUE_RELEASE) && !defined(NDEBUG) + #define NDEBUG +#endif + +// Linux _DEBUG & NDEBUG +#if defined(TORQUE_OS_LINUX) && defined(TORQUE_DEBUG) && !defined(_DEBUG) +#define _DEBUG +#elif defined(TORQUE_OS_LINUX) && defined(TORQUE_RELEASE) && !defined(NDEBUG) +#define NDEBUG +#endif + //------------------------------------------------------------------------- +//safe release template +template void SafeReleasePhysx(T* a) +{ + if (a) + { + a->release(); + a = NULL; + } +} + #include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include extern physx::PxPhysics* gPhysics3SDK; diff --git a/Engine/source/T3D/physics/physx3/px3Body.cpp b/Engine/source/T3D/physics/physx3/px3Body.cpp index ec4e3b979..4bab75dc1 100644 --- a/Engine/source/T3D/physics/physx3/px3Body.cpp +++ b/Engine/source/T3D/physics/physx3/px3Body.cpp @@ -52,12 +52,9 @@ void Px3Body::_releaseActor() if ( !mActor ) return; - mWorld->releaseWriteLock(); - mActor->userData = NULL; - mActor->release(); - mActor = NULL; + SafeReleasePhysx(mActor); mBodyFlags = 0; if ( mMaterial ) @@ -80,7 +77,7 @@ bool Px3Body::init( PhysicsCollision *shape, AssertFatal( shape, "Px3Body::init - Got a null collision shape!" ); AssertFatal( dynamic_cast( shape ), "Px3Body::init - The collision shape is the wrong type!" ); AssertFatal( !((Px3Collision*)shape)->getShapes().empty(), "Px3Body::init - Got empty collision shape!" ); - + // Cleanup any previous actor. _releaseActor(); @@ -96,18 +93,20 @@ bool Px3Body::init( PhysicsCollision *shape, { mActor = gPhysics3SDK->createRigidDynamic(physx::PxTransform(physx::PxIDENTITY())); physx::PxRigidDynamic *actor = mActor->is(); - actor->setRigidDynamicFlag(physx::PxRigidDynamicFlag::eKINEMATIC, true); + actor->setRigidBodyFlag(physx::PxRigidBodyFlag::eKINEMATIC, true); actor->setMass(getMax( mass, 1.0f )); } else if ( mass > 0.0f ) { mActor = gPhysics3SDK->createRigidDynamic(physx::PxTransform(physx::PxIDENTITY())); + physx::PxRigidDynamic *actor = mActor->is(); + actor->setMaxAngularVelocity(80.f); } else { mActor = gPhysics3SDK->createRigidStatic(physx::PxTransform(physx::PxIDENTITY())); mIsStatic = true; - } + } mMaterial = gPhysics3SDK->createMaterial(0.6f,0.4f,0.1f); @@ -123,12 +122,13 @@ bool Px3Body::init( PhysicsCollision *shape, Con::errorf("PhysX3 Dynamic Triangle Mesh is not supported."); } } - physx::PxShape * pShape = mActor->createShape(*desc->pGeometry,*mMaterial); + + physx::PxShape * pShape = physx::PxRigidActorExt::createExclusiveShape(*mActor, *desc->pGeometry, *mMaterial); physx::PxFilterData colData; if(isDebris) colData.word0 = PX3_DEBRIS; else if(isTrigger) - colData.word0 = PX3_TRIGGER; + colData.word0 = PX3_TRIGGER; else colData.word0 = PX3_DEFAULT; @@ -149,10 +149,6 @@ bool Px3Body::init( PhysicsCollision *shape, physx::PxRigidBodyExt::setMassAndUpdateInertia(*actor,mass); } - // This sucks, but it has to happen if we want - // to avoid write lock errors from PhysX right now. - mWorld->releaseWriteLock(); - mWorld->getScene()->addActor(*mActor); mIsEnabled = true; @@ -178,9 +174,9 @@ void Px3Body::setMaterial( F32 restitution, actor->wakeUp(); } - mMaterial->setRestitution(restitution); - mMaterial->setStaticFriction(staticFriction); - mMaterial->setDynamicFriction(friction); + mMaterial->setRestitution(restitution); + mMaterial->setStaticFriction(staticFriction); + mMaterial->setDynamicFriction(friction); } @@ -322,15 +318,14 @@ Box3F Px3Body::getWorldBounds() physx::PxBounds3 bounds; bounds.setEmpty(); - physx::PxBounds3 shapeBounds; - + physx::PxBounds3 shapeBounds; U32 shapeCount = mActor->getNbShapes(); physx::PxShape **shapes = new physx::PxShape*[shapeCount]; mActor->getShapes(shapes, shapeCount); for ( U32 i = 0; i < shapeCount; i++ ) { - // Get the shape's bounds. + // Get the shape's bounds. shapeBounds = physx::PxShapeExt::getWorldBounds(*shapes[i],*mActor); // Combine them into the total bounds. bounds.include( shapeBounds ); @@ -350,10 +345,6 @@ void Px3Body::setSimulationEnabled( bool enabled ) if(mBodyFlags & BF_TRIGGER) return; - // This sucks, but it has to happen if we want - // to avoid write lock errors from PhysX right now. - mWorld->releaseWriteLock(); - U32 shapeCount = mActor->getNbShapes(); physx::PxShape **shapes = new physx::PxShape*[shapeCount]; mActor->getShapes(shapes, shapeCount); @@ -367,12 +358,6 @@ void Px3Body::setSimulationEnabled( bool enabled ) void Px3Body::setTransform( const MatrixF &transform ) { AssertFatal( mActor, "Px3Body::setTransform - The actor is null!" ); - - - // This sucks, but it has to happen if we want - // to avoid write lock errors from PhysX right now. - mWorld->releaseWriteLock(); - mActor->setGlobalPose(px3Cast(transform),false); @@ -380,7 +365,7 @@ void Px3Body::setTransform( const MatrixF &transform ) return; physx::PxRigidDynamic *actor = mActor->is(); - bool kinematic = actor->getRigidDynamicFlags() & physx::PxRigidDynamicFlag::eKINEMATIC; + bool kinematic = actor->getRigidBodyFlags() & physx::PxRigidBodyFlag::eKINEMATIC; // If its dynamic we have more to do. if ( isDynamic() && !kinematic ) { @@ -395,10 +380,6 @@ void Px3Body::applyCorrection( const MatrixF &transform ) AssertFatal( mActor, "Px3Body::applyCorrection - The actor is null!" ); AssertFatal( isDynamic(), "Px3Body::applyCorrection - This call is only for dynamics!" ); - // This sucks, but it has to happen if we want - // to avoid write lock errors from PhysX right now. - mWorld->releaseWriteLock(); - mActor->setGlobalPose( px3Cast(transform) ); } @@ -406,35 +387,27 @@ void Px3Body::applyImpulse( const Point3F &origin, const Point3F &force ) { AssertFatal( mActor, "Px3Body::applyImpulse - The actor is null!" ); - // This sucks, but it has to happen if we want - // to avoid write lock errors from PhysX right now. - mWorld->releaseWriteLock(); physx::PxRigidDynamic *actor = mActor->is(); if ( mIsEnabled && isDynamic() ) - physx::PxRigidBodyExt::addForceAtPos(*actor,px3Cast(force), - px3Cast(origin), - physx::PxForceMode::eIMPULSE); - + physx::PxRigidBodyExt::addForceAtPos( *actor,px3Cast(force), px3Cast(origin), physx::PxForceMode::eIMPULSE ); } -void Px3Body::applyTorque( const Point3F &torque ) +void Px3Body::applyTorque(const Point3F &torque) { AssertFatal(mActor, "Px3Body::applyImpulse - The actor is null!"); - mWorld->releaseWriteLock(); physx::PxRigidDynamic *actor = mActor->is(); if (mIsEnabled && isDynamic()) - actor->addTorque( px3Cast(torque), physx::PxForceMode::eFORCE, true); + actor->addTorque(px3Cast(torque), physx::PxForceMode::eFORCE, true); } -void Px3Body::applyForce( const Point3F &force ) +void Px3Body::applyForce(const Point3F &force) { AssertFatal(mActor, "Px3Body::applyTorque - The actor is null!"); - mWorld->releaseWriteLock(); physx::PxRigidDynamic *actor = mActor->is(); if (mIsEnabled && isDynamic()) - actor->addForce( px3Cast(force), physx::PxForceMode::eFORCE, true); + actor->addForce(px3Cast(force), physx::PxForceMode::eFORCE, true); } void Px3Body::findContact(SceneObject **contactObject, diff --git a/Engine/source/T3D/physics/physx3/px3Body.h b/Engine/source/T3D/physics/physx3/px3Body.h index 30f6f8895..ad348c122 100644 --- a/Engine/source/T3D/physics/physx3/px3Body.h +++ b/Engine/source/T3D/physics/physx3/px3Body.h @@ -40,7 +40,8 @@ class Px3World; class Px3Collision; struct Px3CollisionDesc; -namespace physx{ +namespace physx +{ class PxRigidActor; class PxMaterial; class PxShape; diff --git a/Engine/source/T3D/physics/physx3/px3Collision.cpp b/Engine/source/T3D/physics/physx3/px3Collision.cpp index e03a0f00b..ad8d8ad0b 100644 --- a/Engine/source/T3D/physics/physx3/px3Collision.cpp +++ b/Engine/source/T3D/physics/physx3/px3Collision.cpp @@ -36,136 +36,124 @@ Px3Collision::Px3Collision() } Px3Collision::~Px3Collision() -{ - - for ( U32 i=0; i < mColShapes.size(); i++ ) - { - Px3CollisionDesc *desc = mColShapes[i]; - delete desc->pGeometry; - // Delete the descriptor. - delete desc; - } +{ + for ( U32 i=0; i < mColShapes.size(); i++ ) + { + Px3CollisionDesc *desc = mColShapes[i]; + delete desc->pGeometry; + // Delete the descriptor. + delete desc; + } - mColShapes.clear(); + mColShapes.clear(); } void Px3Collision::addPlane( const PlaneF &plane ) { - physx::PxVec3 pos = px3Cast(plane.getPosition()); - Px3CollisionDesc *desc = new Px3CollisionDesc; + physx::PxVec3 pos = px3Cast(plane.getPosition()); + Px3CollisionDesc *desc = new Px3CollisionDesc; desc->pGeometry = new physx::PxPlaneGeometry(); desc->pose = physx::PxTransform(pos, physx::PxQuat(physx::PxHalfPi, physx::PxVec3(0.0f, -1.0f, 0.0f))); - mColShapes.push_back(desc); + mColShapes.push_back(desc); } void Px3Collision::addBox( const Point3F &halfWidth,const MatrixF &localXfm ) { - Px3CollisionDesc *desc = new Px3CollisionDesc; - desc->pGeometry = new physx::PxBoxGeometry(px3Cast(halfWidth)); - desc->pose = px3Cast(localXfm); - mColShapes.push_back(desc); + Px3CollisionDesc *desc = new Px3CollisionDesc; + desc->pGeometry = new physx::PxBoxGeometry(px3Cast(halfWidth)); + desc->pose = px3Cast(localXfm); + mColShapes.push_back(desc); } -void Px3Collision::addSphere( F32 radius, - const MatrixF &localXfm ) +void Px3Collision::addSphere( F32 radius, const MatrixF &localXfm ) { - Px3CollisionDesc *desc = new Px3CollisionDesc; - desc->pGeometry = new physx::PxSphereGeometry(radius); - desc->pose = px3Cast(localXfm); - mColShapes.push_back(desc); + Px3CollisionDesc *desc = new Px3CollisionDesc; + desc->pGeometry = new physx::PxSphereGeometry(radius); + desc->pose = px3Cast(localXfm); + mColShapes.push_back(desc); } -void Px3Collision::addCapsule( F32 radius, - F32 height, - const MatrixF &localXfm ) +void Px3Collision::addCapsule( F32 radius, F32 height, const MatrixF &localXfm ) { - Px3CollisionDesc *desc = new Px3CollisionDesc; - desc->pGeometry = new physx::PxCapsuleGeometry(radius,height*0.5);//uses half height - desc->pose = px3Cast(localXfm); - mColShapes.push_back(desc); + Px3CollisionDesc *desc = new Px3CollisionDesc; + desc->pGeometry = new physx::PxCapsuleGeometry(radius,height*0.5);//uses half height + desc->pose = px3Cast(localXfm); + mColShapes.push_back(desc); } -bool Px3Collision::addConvex( const Point3F *points, - U32 count, - const MatrixF &localXfm ) +bool Px3Collision::addConvex( const Point3F *points, U32 count, const MatrixF &localXfm ) { - physx::PxCooking *cooking = Px3World::getCooking(); - physx::PxConvexMeshDesc convexDesc; - convexDesc.points.data = points; - convexDesc.points.stride = sizeof(Point3F); - convexDesc.points.count = count; - convexDesc.flags = physx::PxConvexFlag::eFLIPNORMALS|physx::PxConvexFlag::eCOMPUTE_CONVEX | physx::PxConvexFlag::eINFLATE_CONVEX; + physx::PxCooking *cooking = Px3World::getCooking(); + physx::PxConvexMeshDesc convexDesc; + convexDesc.points.data = points; + convexDesc.points.stride = sizeof(Point3F); + convexDesc.points.count = count; + convexDesc.flags = physx::PxConvexFlag::eCOMPUTE_CONVEX | physx::PxConvexFlag::eCHECK_ZERO_AREA_TRIANGLES; + if(PhysicsWorld::isGpuEnabled()) + convexDesc.flags |= physx::PxConvexFlag::eGPU_COMPATIBLE; - Px3MemOutStream stream; - if(!cooking->cookConvexMesh(convexDesc,stream)) - return false; + Px3MemOutStream stream; + if(!cooking->cookConvexMesh(convexDesc,stream)) + return false; - physx::PxConvexMesh* convexMesh; - Px3MemInStream in(stream.getData(), stream.getSize()); - convexMesh = gPhysics3SDK->createConvexMesh(in); + physx::PxConvexMesh* convexMesh; + Px3MemInStream in(stream.getData(), stream.getSize()); + convexMesh = gPhysics3SDK->createConvexMesh(in); - Px3CollisionDesc *desc = new Px3CollisionDesc; + Px3CollisionDesc *desc = new Px3CollisionDesc; physx::PxVec3 scale = px3Cast(localXfm.getScale()); physx::PxQuat rotation = px3Cast(QuatF(localXfm)); physx::PxMeshScale meshScale(scale,rotation); - desc->pGeometry = new physx::PxConvexMeshGeometry(convexMesh,meshScale); - desc->pose = px3Cast(localXfm); - mColShapes.push_back(desc); - return true; + desc->pGeometry = new physx::PxConvexMeshGeometry(convexMesh,meshScale); + desc->pose = px3Cast(localXfm); + mColShapes.push_back(desc); + return true; } -bool Px3Collision::addTriangleMesh( const Point3F *vert, - U32 vertCount, - const U32 *index, - U32 triCount, - const MatrixF &localXfm ) +bool Px3Collision::addTriangleMesh( const Point3F *vert, U32 vertCount, const U32 *index, U32 triCount, const MatrixF &localXfm ) { - physx::PxCooking *cooking = Px3World::getCooking(); - physx::PxTriangleMeshDesc meshDesc; - meshDesc.points.count = vertCount; - meshDesc.points.data = vert; - meshDesc.points.stride = sizeof(Point3F); + physx::PxCooking *cooking = Px3World::getCooking(); + physx::PxTriangleMeshDesc meshDesc; + meshDesc.points.count = vertCount; + meshDesc.points.data = vert; + meshDesc.points.stride = sizeof(Point3F); - meshDesc.triangles.count = triCount; - meshDesc.triangles.data = index; - meshDesc.triangles.stride = 3*sizeof(U32); - meshDesc.flags = physx::PxMeshFlag::eFLIPNORMALS; + meshDesc.triangles.count = triCount; + meshDesc.triangles.data = index; + meshDesc.triangles.stride = 3*sizeof(U32); + meshDesc.flags = physx::PxMeshFlag::eFLIPNORMALS; - Px3MemOutStream stream; - if(!cooking->cookTriangleMesh(meshDesc,stream)) - return false; + Px3MemOutStream stream; + if(!cooking->cookTriangleMesh(meshDesc,stream)) + return false; - physx::PxTriangleMesh *mesh; - Px3MemInStream in(stream.getData(), stream.getSize()); - mesh = gPhysics3SDK->createTriangleMesh(in); + physx::PxTriangleMesh *mesh; + Px3MemInStream in(stream.getData(), stream.getSize()); + mesh = gPhysics3SDK->createTriangleMesh(in); - Px3CollisionDesc *desc = new Px3CollisionDesc; - desc->pGeometry = new physx::PxTriangleMeshGeometry(mesh); - desc->pose = px3Cast(localXfm); - mColShapes.push_back(desc); - return true; + Px3CollisionDesc *desc = new Px3CollisionDesc; + desc->pGeometry = new physx::PxTriangleMeshGeometry(mesh); + desc->pose = px3Cast(localXfm); + mColShapes.push_back(desc); + return true; } -bool Px3Collision::addHeightfield( const U16 *heights, - const bool *holes, - U32 blockSize, - F32 metersPerSample, - const MatrixF &localXfm ) +bool Px3Collision::addHeightfield( const U16 *heights, const bool *holes, U32 blockSize, F32 metersPerSample, const MatrixF &localXfm ) { - const F32 heightScale = 0.03125f; - physx::PxHeightFieldSample* samples = (physx::PxHeightFieldSample*) new physx::PxHeightFieldSample[blockSize*blockSize]; - memset(samples,0,blockSize*blockSize*sizeof(physx::PxHeightFieldSample)); + const F32 heightScale = 0.03125f; + physx::PxHeightFieldSample* samples = (physx::PxHeightFieldSample*) new physx::PxHeightFieldSample[blockSize*blockSize]; + memset(samples,0,blockSize*blockSize*sizeof(physx::PxHeightFieldSample)); - physx::PxHeightFieldDesc heightFieldDesc; - heightFieldDesc.nbColumns = blockSize; - heightFieldDesc.nbRows = blockSize; - heightFieldDesc.thickness = -10.f; - heightFieldDesc.convexEdgeThreshold = 0; - heightFieldDesc.format = physx::PxHeightFieldFormat::eS16_TM; - heightFieldDesc.samples.data = samples; - heightFieldDesc.samples.stride = sizeof(physx::PxHeightFieldSample); + physx::PxHeightFieldDesc heightFieldDesc; + heightFieldDesc.nbColumns = blockSize; + heightFieldDesc.nbRows = blockSize; + heightFieldDesc.thickness = -10.f; + heightFieldDesc.convexEdgeThreshold = 0; + heightFieldDesc.format = physx::PxHeightFieldFormat::eS16_TM; + heightFieldDesc.samples.data = samples; + heightFieldDesc.samples.stride = sizeof(physx::PxHeightFieldSample); - physx::PxU8 *currentByte = (physx::PxU8*)heightFieldDesc.samples.data; + physx::PxU8 *currentByte = (physx::PxU8*)heightFieldDesc.samples.data; for ( U32 row = 0; row < blockSize; row++ ) { const U32 tess = ( row + 1 ) % 2; @@ -177,7 +165,6 @@ bool Px3Collision::addHeightfield( const U16 *heights, U32 index = ( blockSize - row - 1 ) + ( column * blockSize ); currentSample->height = (physx::PxI16)heights[ index ]; - if ( holes && holes[ getMax( (S32)index - 1, 0 ) ] ) // row index for holes adjusted so PhysX collision shape better matches rendered terrain { currentSample->materialIndex0 = physx::PxHeightFieldMaterial::eHOLE; @@ -189,29 +176,30 @@ bool Px3Collision::addHeightfield( const U16 *heights, currentSample->materialIndex1 = 0; } - int flag = ( column + tess ) % 2; - if(flag) - currentSample->clearTessFlag(); - else - currentSample->setTessFlag(); + S32 flag = ( column + tess ) % 2; + if(flag) + currentSample->clearTessFlag(); + else + currentSample->setTessFlag(); currentByte += heightFieldDesc.samples.stride; } } - physx::PxHeightField * hf = gPhysics3SDK->createHeightField(heightFieldDesc); - physx::PxHeightFieldGeometry *geom = new physx::PxHeightFieldGeometry(hf,physx::PxMeshGeometryFlags(),heightScale,metersPerSample,metersPerSample); + physx::PxCooking *cooking = Px3World::getCooking(); + physx::PxHeightField * hf = cooking->createHeightField(heightFieldDesc,gPhysics3SDK->getPhysicsInsertionCallback()); + physx::PxHeightFieldGeometry *geom = new physx::PxHeightFieldGeometry(hf,physx::PxMeshGeometryFlags(),heightScale,metersPerSample,metersPerSample); - physx::PxTransform pose= physx::PxTransform(physx::PxQuat(Float_HalfPi, physx::PxVec3(1, 0, 0 ))); - physx::PxTransform pose1= physx::PxTransform(physx::PxQuat(Float_Pi, physx::PxVec3(0, 0, 1 ))); - physx::PxTransform pose2 = pose1 * pose; - pose2.p = physx::PxVec3(( blockSize - 1 ) * metersPerSample, 0, 0 ); - Px3CollisionDesc *desc = new Px3CollisionDesc; - desc->pGeometry = geom; - desc->pose = pose2; + physx::PxTransform pose= physx::PxTransform(physx::PxQuat(Float_HalfPi, physx::PxVec3(1, 0, 0 ))); + physx::PxTransform pose1= physx::PxTransform(physx::PxQuat(Float_Pi, physx::PxVec3(0, 0, 1 ))); + physx::PxTransform pose2 = pose1 * pose; + pose2.p = physx::PxVec3(( blockSize - 1 ) * metersPerSample, 0, 0 ); + Px3CollisionDesc *desc = new Px3CollisionDesc; + desc->pGeometry = geom; + desc->pose = pose2; - mColShapes.push_back(desc); + mColShapes.push_back(desc); SAFE_DELETE(samples); - return true; + return true; } diff --git a/Engine/source/T3D/physics/physx3/px3Collision.h b/Engine/source/T3D/physics/physx3/px3Collision.h index 69bf38778..8697b7f74 100644 --- a/Engine/source/T3D/physics/physx3/px3Collision.h +++ b/Engine/source/T3D/physics/physx3/px3Collision.h @@ -23,6 +23,9 @@ #ifndef _PX3COLLISION_H_ #define _PX3COLLISION_H_ +#ifndef _PHYSX3_H_ +#include "T3D/physics/physx3/px3.h" +#endif #ifndef _T3D_PHYSICS_PHYSICSCOLLISION_H_ #include "T3D/physics/physicsCollision.h" #endif diff --git a/Engine/source/T3D/physics/physx3/px3Player.cpp b/Engine/source/T3D/physics/physx3/px3Player.cpp index 10dc65e86..8c1d66546 100644 --- a/Engine/source/T3D/physics/physx3/px3Player.cpp +++ b/Engine/source/T3D/physics/physx3/px3Player.cpp @@ -53,7 +53,7 @@ void Px3Player::_releaseController() { mController->getActor()->userData = NULL; mWorld->getStaticChangedSignal().remove( this, &Px3Player::_onStaticChanged ); - mController->release(); + SafeReleasePhysx(mController); } } @@ -136,8 +136,6 @@ Point3F Px3Player::move( const VectorF &disp, CollisionList &outCol ) return newPos; } - mWorld->releaseWriteLock(); - mCollisionList = &outCol; physx::PxVec3 dispNx( disp.x, disp.y, disp.z ); @@ -151,8 +149,8 @@ Point3F Px3Player::move( const VectorF &disp, CollisionList &outCol ) physx::PxFilterData data; data.word0=groups; filter.mFilterData = &data; - filter.mFilterFlags = physx::PxSceneQueryFilterFlags(physx::PxControllerFlag::eCOLLISION_DOWN|physx::PxControllerFlag::eCOLLISION_SIDES|physx::PxControllerFlag::eCOLLISION_UP); - + filter.mFilterFlags = physx::PxQueryFlags(physx::PxQueryFlag::eDYNAMIC | physx::PxQueryFlag::eSTATIC); + mController->move( dispNx,0.0001f,0, filter ); Point3F newPos = px3Cast( mController->getPosition() ); @@ -272,7 +270,6 @@ void Px3Player::enableCollision() { AssertFatal( mController, "Px3Player::enableCollision - The controller is null!" ); - mWorld->releaseWriteLock(); px3GetFirstShape(mController->getActor())->setFlag(physx::PxShapeFlag::eSIMULATION_SHAPE,true); } @@ -280,7 +277,6 @@ void Px3Player::disableCollision() { AssertFatal( mController, "Px3Player::disableCollision - The controller is null!" ); - mWorld->releaseWriteLock(); px3GetFirstShape(mController->getActor())->setFlag(physx::PxShapeFlag::eSIMULATION_SHAPE,false); } @@ -293,8 +289,6 @@ void Px3Player::setTransform( const MatrixF &transform ) { AssertFatal( mController, "Px3Player::setTransform - The controller is null!" ); - mWorld->releaseWriteLock(); - Point3F newPos = transform.getPosition(); newPos.z += mOriginOffset; @@ -355,7 +349,6 @@ void Px3Player::setSpacials(const Point3F &nPos, const Point3F &nSize) F32 height = nSize.z - (radius * 2.0f); height -= mSkinWidth * 2.0f; - mWorld->releaseWriteLock(); mController->resize(height); px3GetFirstShape(mController->getActor())->getCapsuleGeometry(mGeometry); } \ No newline at end of file diff --git a/Engine/source/T3D/physics/physx3/px3Stream.cpp b/Engine/source/T3D/physics/physx3/px3Stream.cpp index f8374cf89..ec76508be 100644 --- a/Engine/source/T3D/physics/physx3/px3Stream.cpp +++ b/Engine/source/T3D/physics/physx3/px3Stream.cpp @@ -83,10 +83,7 @@ Px3ConsoleStream::~Px3ConsoleStream() { } -void Px3ConsoleStream::reportError( physx::PxErrorCode code, const char *message, const char* file, int line ) +void Px3ConsoleStream::reportError(physx::PxErrorCode::Enum code, const char* message, const char* file, int line) { - UTF8 info[1024]; - dSprintf( info, 1024, "File: %s\nLine: %d\n%s", file, line, message ); - Platform::AlertOK( "PhysX Error", info ); - // Con::printf( "PhysX Error:\n %s(%d) : %s\n", file, line, message ); -} \ No newline at end of file + Con::warnf( "PhysX Warning: %s(%d) : %s", file, line, message ); +} diff --git a/Engine/source/T3D/physics/physx3/px3Stream.h b/Engine/source/T3D/physics/physx3/px3Stream.h index b7538b5e2..bf1641a3b 100644 --- a/Engine/source/T3D/physics/physx3/px3Stream.h +++ b/Engine/source/T3D/physics/physx3/px3Stream.h @@ -62,11 +62,11 @@ protected: }; -class Px3ConsoleStream : public physx::PxDefaultErrorCallback +class Px3ConsoleStream : public physx::PxErrorCallback { protected: - virtual void reportError( physx::PxErrorCode code, const char *message, const char* file, int line ); + virtual void reportError(physx::PxErrorCode::Enum code, const char* message, const char* file, int line); public: diff --git a/Engine/source/T3D/physics/physx3/px3World.cpp b/Engine/source/T3D/physics/physx3/px3World.cpp index a3732634e..5a27e190f 100644 --- a/Engine/source/T3D/physics/physx3/px3World.cpp +++ b/Engine/source/T3D/physics/physx3/px3World.cpp @@ -41,27 +41,31 @@ #include "gfx/sim/debugDraw.h" #include "gfx/primBuilder.h" - physx::PxPhysics* gPhysics3SDK = NULL; physx::PxCooking* Px3World::smCooking = NULL; physx::PxFoundation* Px3World::smFoundation = NULL; -physx::PxProfileZoneManager* Px3World::smProfileZoneManager = NULL; -physx::PxDefaultCpuDispatcher* Px3World::smCpuDispatcher=NULL; +physx::PxDefaultCpuDispatcher* Px3World::smCpuDispatcher = NULL; +#ifndef TORQUE_OS_MAC +physx::PxCudaContextManager* Px3World::smCudaContextManager = NULL; +#endif Px3ConsoleStream* Px3World::smErrorCallback = NULL; -physx::PxVisualDebuggerConnection* Px3World::smPvdConnection=NULL; +physx::PxPvd* Px3World::smPvdConnection = NULL; +physx::PxPvdTransport* Px3World::smPvdTransport = NULL; physx::PxDefaultAllocator Px3World::smMemoryAlloc; -Px3World::Px3World(): mScene( NULL ), - mProcessList( NULL ), - mIsSimulating( false ), - mErrorReport( false ), - mTickCount( 0 ), +Px3World::Px3World() : + mScene( NULL ), mIsEnabled( false ), + mIsSimulating( false ), + mIsServer( false ), + mIsSceneLocked( false ), + mTickCount( 0 ), + mProcessList( NULL ), mEditorTimeScale( 1.0f ), - mAccumulator( 0 ), + mErrorReport( false ), mControllerManager(NULL), - mIsSceneLocked(false), - mRenderBuffer(NULL) + mRenderBuffer(NULL), + mAccumulator( 0 ) { } @@ -80,33 +84,25 @@ bool Px3World::restartSDK( bool destroyOnly, Px3World *clientWorld, Px3World *se // then we cannot reset the SDK. if ( clientWorld || serverWorld ) return false; - - if(smPvdConnection) - smPvdConnection->release(); - - if(smCooking) - smCooking->release(); - - if(smCpuDispatcher) - smCpuDispatcher->release(); +#ifndef TORQUE_OS_MAC + SafeReleasePhysx(smCudaContextManager); +#endif + SafeReleasePhysx(smCpuDispatcher); + SafeReleasePhysx(smCooking); + smGpuEnabled = false; // Destroy the existing SDK. if ( gPhysics3SDK ) { PxCloseExtensions(); - gPhysics3SDK->release(); + SafeReleasePhysx(gPhysics3SDK); } - if(smErrorCallback) - { - SAFE_DELETE(smErrorCallback); - } + SafeReleasePhysx(smPvdConnection); + SafeReleasePhysx(smPvdTransport); - if(smFoundation) - { - smFoundation->release(); - SAFE_DELETE(smErrorCallback); - } + SAFE_DELETE(smErrorCallback); + SafeReleasePhysx(smFoundation); // If we're not supposed to restart... return. if ( destroyOnly ) @@ -114,20 +110,18 @@ bool Px3World::restartSDK( bool destroyOnly, Px3World *clientWorld, Px3World *se bool memTrack = false; #ifdef TORQUE_DEBUG - memTrack = true; + memTrack = false; #endif - + smErrorCallback = new Px3ConsoleStream; - smFoundation = PxCreateFoundation(PX_PHYSICS_VERSION, smMemoryAlloc, *smErrorCallback); - smProfileZoneManager = &physx::PxProfileZoneManager::createProfileZoneManager(smFoundation); - gPhysics3SDK = PxCreatePhysics(PX_PHYSICS_VERSION, *smFoundation, physx::PxTolerancesScale(),memTrack,smProfileZoneManager); + smFoundation = PxCreateFoundation(PX_FOUNDATION_VERSION, smMemoryAlloc, *smErrorCallback); + smPvdConnection = PxCreatePvd(*smFoundation); + gPhysics3SDK = PxCreatePhysics(PX_PHYSICS_VERSION, *smFoundation, physx::PxTolerancesScale(),memTrack, smPvdConnection); if ( !gPhysics3SDK ) { Con::errorf( "PhysX3 failed to initialize!" ); - Platform::messageBox( Con::getVariable( "$appName" ), - avar("PhysX3 could not be started!\r\n"), - MBOk, MIStop ); + Platform::messageBox( Con::getVariable( "$appName" ), avar("PhysX3 could not be started!\r\n"), MBOk, MIStop ); Platform::forceShutdown( -1 ); // We shouldn't get here, but this shuts up @@ -135,33 +129,67 @@ bool Px3World::restartSDK( bool destroyOnly, Px3World *clientWorld, Px3World *se return false; } - if(!PxInitExtensions(*gPhysics3SDK)) + if(!PxInitExtensions(*gPhysics3SDK, smPvdConnection)) { Con::errorf( "PhysX3 failed to initialize extensions!" ); - Platform::messageBox( Con::getVariable( "$appName" ), - avar("PhysX3 could not be started!\r\n"), - MBOk, MIStop ); + Platform::messageBox( Con::getVariable( "$appName" ), avar("PhysX3 could not be started!\r\n"), MBOk, MIStop ); Platform::forceShutdown( -1 ); return false; } +//no gpu support on macOS +#ifndef TORQUE_OS_MAC + //check if we are allowed to use gpu acceleration + if (PhysicsPlugin::gpuAccelerationAllowed()) + { + // attempt to create a cuda context manager - only works on nvidia gpu (SM 3.0+ i.e kepler or better) + if (!smCpuDispatcher) + { + //check we have capable gpu, -1 means none found + S32 suggestedGpu = PxGetSuggestedCudaDeviceOrdinal(*smErrorCallback); + if (suggestedGpu != -1) + { + physx::PxCudaContextManagerDesc cudaContextManagerDesc; + smCudaContextManager = PxCreateCudaContextManager(*smFoundation, cudaContextManagerDesc); + if (smCudaContextManager) + smGpuEnabled = true; + } + } + } +#endif - smCooking = PxCreateCooking(PX_PHYSICS_VERSION, *smFoundation, physx::PxCookingParams(physx::PxTolerancesScale())); + //cpu dispatcher + if (!smCpuDispatcher) + smCpuDispatcher = physx::PxDefaultCpuDispatcherCreate(PHYSICSMGR->getThreadCount()); + + physx::PxCookingParams params = physx::PxCookingParams(physx::PxTolerancesScale()); + params.meshWeldTolerance = 0.001f; + params.meshPreprocessParams = physx::PxMeshPreprocessingFlags(physx::PxMeshPreprocessingFlag::eWELD_VERTICES); +#ifndef TORQUE_OS_MAC + if(smGpuEnabled) + params.buildGPUData = true; +#endif + + smCooking = PxCreateCooking(PX_PHYSICS_VERSION, *smFoundation, params); if(!smCooking) { Con::errorf( "PhysX3 failed to initialize cooking!" ); - Platform::messageBox( Con::getVariable( "$appName" ), - avar("PhysX3 could not be started!\r\n"), - MBOk, MIStop ); + Platform::messageBox( Con::getVariable( "$appName" ), avar("PhysX3 could not be started!\r\n"), MBOk, MIStop ); Platform::forceShutdown( -1 ); return false; } + //TODO: enable/disable this from script #ifdef TORQUE_DEBUG - physx::PxVisualDebuggerConnectionFlags connectionFlags(physx::PxVisualDebuggerExt::getAllConnectionFlags()); - smPvdConnection = physx::PxVisualDebuggerExt::createConnection(gPhysics3SDK->getPvdConnectionManager(), - "localhost", 5425, 100, connectionFlags); + if(!smPvdTransport) + smPvdTransport = physx::PxDefaultPvdSocketTransportCreate("localhost", 5425, 100); + + smPvdConnection->connect(*smPvdTransport, physx::PxPvdInstrumentationFlag::eALL); #endif + //use legacy heightfield + //TODO: new method causing crashes on collision in debug build (unified HeightFields) + PxRegisterLegacyHeightFields(*gPhysics3SDK); + return true; } @@ -169,8 +197,6 @@ void Px3World::destroyWorld() { getPhysicsResults(); - mRenderBuffer = NULL; - // Release the tick processing signals. if ( mProcessList ) { @@ -179,19 +205,9 @@ void Px3World::destroyWorld() mProcessList = NULL; } - if(mControllerManager) - { - mControllerManager->release(); - mControllerManager = NULL; - } - + SafeReleasePhysx(mControllerManager); // Destroy the scene. - if ( mScene ) - { - // Release the scene. - mScene->release(); - mScene = NULL; - } + SafeReleasePhysx(mScene); } bool Px3World::initWorld( bool isServer, ProcessList *processList ) @@ -203,27 +219,32 @@ bool Px3World::initWorld( bool isServer, ProcessList *processList ) } mIsServer = isServer; - + physx::PxSceneDesc sceneDesc(gPhysics3SDK->getTolerancesScale()); sceneDesc.gravity = px3Cast(mGravity); sceneDesc.userData = this; - if(!sceneDesc.cpuDispatcher) - { - //Create shared cpu dispatcher - if(!smCpuDispatcher) - smCpuDispatcher = physx::PxDefaultCpuDispatcherCreate(PHYSICSMGR->getThreadCount()); - sceneDesc.cpuDispatcher = smCpuDispatcher; - Con::printf("PhysX3 using Cpu: %d workers", smCpuDispatcher->getWorkerCount()); + sceneDesc.cpuDispatcher = smCpuDispatcher; + Con::printf("PhysX3 using Cpu: %d workers", smCpuDispatcher->getWorkerCount()); + +#ifndef TORQUE_OS_MAC + if (smGpuEnabled) + { + sceneDesc.flags |= physx::PxSceneFlag::eENABLE_GPU_DYNAMICS; + sceneDesc.flags |= physx::PxSceneFlag::eENABLE_PCM; + sceneDesc.broadPhaseType = physx::PxBroadPhaseType::eGPU; + sceneDesc.gpuDispatcher = smCudaContextManager->getGpuDispatcher(); + Con::printf("PhysX3 using Gpu: %s", smCudaContextManager->getDeviceName()); } - +#endif + sceneDesc.flags |= physx::PxSceneFlag::eENABLE_CCD; sceneDesc.flags |= physx::PxSceneFlag::eENABLE_ACTIVETRANSFORMS; sceneDesc.filterShader = physx::PxDefaultSimulationFilterShader; - mScene = gPhysics3SDK->createScene(sceneDesc); - //cache renderbuffer for use with debug drawing + mScene = gPhysics3SDK->createScene(sceneDesc); + mRenderBuffer = const_cast(&mScene->getRenderBuffer()); physx::PxDominanceGroupPair debrisDominance( 0.0f, 1.0f ); @@ -252,15 +273,16 @@ bool Px3World::_simulate(const F32 dt) if (numSimulationSubSteps) { //clamp the number of substeps, to prevent simulation grinding spiralling down to a halt - S32 clampedSimulationSteps = (numSimulationSubSteps > smPhysicsMaxSubSteps)? smPhysicsMaxSubSteps : numSimulationSubSteps; - + S32 clampedSimulationSteps = (numSimulationSubSteps > smPhysicsMaxSubSteps) ? smPhysicsMaxSubSteps : numSimulationSubSteps; + for (S32 i=0;ifetchResults(true); + if(i > 0) + mScene->fetchResults(true); mScene->simulate(smPhysicsStepTime); } } - + mIsSimulating = true; return true; @@ -299,36 +321,6 @@ void Px3World::getPhysicsResults() mScene->fetchResults(true); mIsSimulating = false; mTickCount++; - - // Con::printf( "%s PhysXWorld::getPhysicsResults!", this == smClientWorld ? "Client" : "Server" ); -} - -void Px3World::releaseWriteLocks() -{ - Px3World *world = dynamic_cast( PHYSICSMGR->getWorld( "server" ) ); - - if ( world ) - world->releaseWriteLock(); - - world = dynamic_cast( PHYSICSMGR->getWorld( "client" ) ); - - if ( world ) - world->releaseWriteLock(); -} - -void Px3World::releaseWriteLock() -{ - if ( !mScene || !mIsSimulating ) - return; - - PROFILE_SCOPE(PxWorld_ReleaseWriteLock); - - // We use checkResults here to release the write lock - // but we do not change the simulation flag or increment - // the tick count... we may have gotten results, but the - // simulation hasn't really ticked! - mScene->checkResults( true ); - //AssertFatal( mScene->isWritable(), "PhysX3World::releaseWriteLock() - We should have been writable now!" ); } void Px3World::lockScenes() @@ -388,8 +380,7 @@ void Px3World::unlockScene() } bool Px3World::castRay( const Point3F &startPnt, const Point3F &endPnt, RayInfo *ri, const Point3F &impulse ) -{ - +{ physx::PxVec3 orig = px3Cast( startPnt ); physx::PxVec3 dir = px3Cast( endPnt - startPnt ); physx::PxF32 maxDist = dir.magnitude(); @@ -398,15 +389,15 @@ bool Px3World::castRay( const Point3F &startPnt, const Point3F &endPnt, RayInfo U32 groups = 0xffffffff; groups &= ~( PX3_TRIGGER ); // No trigger shapes! - physx::PxHitFlags outFlags(physx::PxHitFlag::eDISTANCE | physx::PxHitFlag::eIMPACT | physx::PxHitFlag::eNORMAL); + physx::PxHitFlags outFlags(physx::PxHitFlag::eDISTANCE | physx::PxHitFlag::ePOSITION | physx::PxHitFlag::eNORMAL); physx::PxQueryFilterData filterData(physx::PxQueryFlag::eSTATIC|physx::PxQueryFlag::eDYNAMIC); filterData.data.word0 = groups; physx::PxRaycastBuffer buf; if(!mScene->raycast(orig,dir,maxDist,buf,outFlags,filterData)) - return false; + return false; if(!buf.hasBlock) - return false; + return false; const physx::PxRaycastHit hit = buf.block; physx::PxRigidActor *actor = hit.actor; @@ -425,8 +416,8 @@ bool Px3World::castRay( const Point3F &startPnt, const Point3F &endPnt, RayInfo } if ( impulse.isZero() || - !actor->isRigidDynamic() || - actor->is()->getRigidDynamicFlags() & physx::PxRigidDynamicFlag::eKINEMATIC ) + !actor->is() || + actor->is()->getRigidBodyFlags() & physx::PxRigidBodyFlag::eKINEMATIC ) return true; physx::PxRigidBody *body = actor->is(); @@ -453,7 +444,7 @@ PhysicsBody* Px3World::castRay( const Point3F &start, const Point3F &end, U32 bo groups &= ~( PX3_TRIGGER ); // triggers groups &= ~( PX3_DEBRIS ); // debris - physx::PxHitFlags outFlags(physx::PxHitFlag::eDISTANCE | physx::PxHitFlag::eIMPACT | physx::PxHitFlag::eNORMAL); + physx::PxHitFlags outFlags(physx::PxHitFlag::eDISTANCE | physx::PxHitFlag::ePOSITION | physx::PxHitFlag::eNORMAL); physx::PxQueryFilterData filterData; if(bodyTypes & BT_Static) filterData.flags |= physx::PxQueryFlag::eSTATIC; @@ -491,12 +482,12 @@ void Px3World::explosion( const Point3F &pos, F32 radius, F32 forceMagnitude ) { physx::PxRigidActor *actor = buffer.touches[i].actor; - bool dynamic = actor->isRigidDynamic(); + bool dynamic = actor->is(); if ( !dynamic ) continue; - bool kinematic = actor->is()->getRigidDynamicFlags() & physx::PxRigidDynamicFlag::eKINEMATIC; + bool kinematic = actor->is()->getRigidBodyFlags() & physx::PxRigidBodyFlag::eKINEMATIC; if ( kinematic ) continue; @@ -523,8 +514,6 @@ physx::PxController* Px3World::createController( physx::PxControllerDesc &desc ) if ( !mScene ) return NULL; - // We need the writelock! - releaseWriteLock(); physx::PxController* pController = mControllerManager->createController(desc); AssertFatal( pController, "Px3World::createController - Got a null!" ); return pController; @@ -543,7 +532,7 @@ static ColorI getDebugColor( physx::PxU32 packed ) void Px3World::onDebugDraw( const SceneRenderState *state ) { - if ( !mScene || !mRenderBuffer ) + if ( !mScene || !mRenderBuffer) return; mScene->setVisualizationParameter(physx::PxVisualizationParameter::eSCALE,1.0f); diff --git a/Engine/source/T3D/physics/physx3/px3World.h b/Engine/source/T3D/physics/physx3/px3World.h index 5399c3f0a..9005d2a07 100644 --- a/Engine/source/T3D/physics/physx3/px3World.h +++ b/Engine/source/T3D/physics/physx3/px3World.h @@ -23,15 +23,15 @@ #ifndef _PX3WORLD_H_ #define _PX3WORLD_H_ +#ifndef _PHYSX3_H_ +#include "T3D/physics/physx3/px3.h" +#endif #ifndef _T3D_PHYSICS_PHYSICSWORLD_H_ #include "T3D/physics/physicsWorld.h" #endif #ifndef _MMATH_H_ #include "math/mMath.h" #endif -#ifndef _PHYSX3_H_ -#include "T3D/physics/physx3/px3.h" -#endif #ifndef _TVECTOR_H_ #include "core/util/tVector.h" #endif @@ -51,26 +51,29 @@ enum Px3CollisionGroup class Px3World : public PhysicsWorld { protected: - physx::PxScene* mScene; bool mIsEnabled; bool mIsSimulating; bool mIsServer; - bool mIsSceneLocked; + bool mIsSceneLocked; U32 mTickCount; ProcessList *mProcessList; F32 mEditorTimeScale; bool mErrorReport; - physx::PxRenderBuffer *mRenderBuffer; physx::PxControllerManager* mControllerManager; + physx::PxRenderBuffer *mRenderBuffer; + F32 mAccumulator; static Px3ConsoleStream *smErrorCallback; static physx::PxDefaultAllocator smMemoryAlloc; static physx::PxFoundation* smFoundation; static physx::PxCooking *smCooking; - static physx::PxProfileZoneManager* smProfileZoneManager; static physx::PxDefaultCpuDispatcher* smCpuDispatcher; - static physx::PxVisualDebuggerConnection* smPvdConnection; - F32 mAccumulator; +#ifndef TORQUE_OS_MAC + static physx::PxCudaContextManager* smCudaContextManager; +#endif + static physx::PxPvd* smPvdConnection; + static physx::PxPvdTransport* smPvdTransport; + bool _simulate(const F32 dt); public: @@ -86,21 +89,20 @@ public: virtual PhysicsBody* castRay( const Point3F &start, const Point3F &end, U32 bodyTypes = BT_All ); virtual void explosion( const Point3F &pos, F32 radius, F32 forceMagnitude ); virtual bool isEnabled() const { return mIsEnabled; } - physx::PxScene* getScene(){ return mScene;} + physx::PxScene* getScene(){ return mScene; } void setEnabled( bool enabled ); U32 getTick() { return mTickCount; } void tickPhysics( U32 elapsedMs ); void getPhysicsResults(); void setEditorTimeScale( F32 timeScale ) { mEditorTimeScale = timeScale; } const F32 getEditorTimeScale() const { return mEditorTimeScale; } - void releaseWriteLock(); - bool isServer(){return mIsServer;} + bool isServer() { return mIsServer; } + physx::PxController* createController( physx::PxControllerDesc &desc ); void lockScene(); void unlockScene(); //static static bool restartSDK( bool destroyOnly = false, Px3World *clientWorld = NULL, Px3World *serverWorld = NULL ); - static void releaseWriteLocks(); static physx::PxCooking *getCooking(); static void lockScenes(); static void unlockScenes(); diff --git a/Tools/CMake/modules/module_physx3.cmake b/Tools/CMake/modules/module_physx3.cmake index 5545120ee..56984649f 100644 --- a/Tools/CMake/modules/module_physx3.cmake +++ b/Tools/CMake/modules/module_physx3.cmake @@ -1,5 +1,5 @@ # ----------------------------------------------------------------------------- -# Copyright (c) 2015 GarageGames, LLC +# Copyright (c) 2017 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 @@ -20,16 +20,18 @@ # IN THE SOFTWARE. # ----------------------------------------------------------------------------- -# module Physx 3.3 +# module Physx 3.4 -option(TORQUE_PHYSICS_PHYSX3 "Use PhysX 3.3 physics" OFF) +#do note the inconsistent upper/lower case nvidia use for directory names in physx + +option(TORQUE_PHYSICS_PHYSX3 "Use PhysX 3.4 physics" OFF) if( NOT TORQUE_PHYSICS_PHYSX3 ) - return() + return() endif() if("${PHYSX3_BASE_PATH}" STREQUAL "") - set(PHYSX3_BASE_PATH "" CACHE PATH "PhysX 3.3 path" FORCE) + set(PHYSX3_BASE_PATH "" CACHE PATH "PhysX 3.4 path" FORCE) endif() #still no path we can't go any further @@ -39,63 +41,177 @@ if("${PHYSX3_BASE_PATH}" STREQUAL "") endif() #set physx path -set(PHYSX3_PATH "${PHYSX3_BASE_PATH}/PhysXSDK") +set(PHYSX3_PATH "${PHYSX3_BASE_PATH}/PhysX_3.4") -# TODO linux support +# Windows/ Visual Studio if(MSVC) if(TORQUE_CPU_X32) - if(MSVC11) - set(PHYSX3_LIBPATH_PREFIX vc11win32) - elseif(MSVC12) - set(PHYSX3_LIBPATH_PREFIX vc12win32) - elseif(MSVC14) - set(PHYSX3_LIBPATH_PREFIX vc14win32) - else() - return() - endif() + if(MSVC11) + set(PHYSX3_LIBPATH_PREFIX vc11win32) + elseif(MSVC12) + set(PHYSX3_LIBPATH_PREFIX vc12win32) + elseif(MSVC14) + set(PHYSX3_LIBPATH_PREFIX vc14win32) + else() + message(FATAL_ERROR "This version of VS is not supported") + return() + endif() set(PHYSX3_LIBNAME_POSTFIX _x86) elseif(TORQUE_CPU_X64) - if(MSVC11) - set(PHYSX3_LIBPATH_PREFIX vc11win64) - elseif(MSVC12) - set(PHYSX3_LIBPATH_PREFIX vc12win64) - elseif(MSVC14) - set(PHYSX3_LIBPATH_PREFIX vc14win64) - else() - return() - endif() -set(PHYSX3_LIBNAME_POSTFIX _x64) + if(MSVC11) + set(PHYSX3_LIBPATH_PREFIX vc11win64) + elseif(MSVC12) + set(PHYSX3_LIBPATH_PREFIX vc12win64) + elseif(MSVC14) + set(PHYSX3_LIBPATH_PREFIX vc14win64) + else() + message(FATAL_ERROR "This version of VS is not supported") + return() + endif() + set(PHYSX3_LIBNAME_POSTFIX _x64) + endif() endif() -endif(MSVC) +# Only suport 64bit on macOS and linux +if(APPLE) + set(PHYSX3_LIBPATH_PREFIX osx64) + set(PHYSX3_LIBNAME_POSTFIX _x64) +elseif(UNIX) + set(PHYSX3_LIBPATH_PREFIX linux64) + set(PHYSX3_LIBNAME_POSTFIX _x64) +endif() -MACRO(FIND_PHYSX3_LIBRARY VARNAME LIBNAME WITHPOSTFIX) +MACRO(FIND_PHYSX3_LIBRARY VARNAME LIBNAME WITHPOSTFIX SEARCHDIR) - set(LIBPOSTFIX "") - if(${WITHPOSTFIX}) - set(LIBPOSTFIX ${PHYSX3_LIBNAME_POSTFIX}) - endif(${WITHPOSTFIX}) - find_library(PHYSX3_${VARNAME}_LIBRARY NAMES ${LIBNAME}${LIBPOSTFIX} - PATHS ${PHYSX3_PATH}/Lib/${PHYSX3_LIBPATH_PREFIX}) - find_library(PHYSX3_${VARNAME}_LIBRARY_DEBUG NAMES ${LIBNAME}DEBUG${LIBPOSTFIX} - PATHS ${PHYSX3_PATH}/Lib/${PHYSX3_LIBPATH_PREFIX}) + set(LIBPOSTFIX "") + if(${WITHPOSTFIX}) + set(LIBPOSTFIX ${PHYSX3_LIBNAME_POSTFIX}) + endif(${WITHPOSTFIX}) + #release + find_library(PHYSX3_${VARNAME}_LIBRARY NAMES ${LIBNAME}${LIBPOSTFIX} PATHS ${SEARCHDIR}${PHYSX3_LIBPATH_PREFIX}) + #debug + find_library(PHYSX3_${VARNAME}_LIBRARY_DEBUG NAMES ${LIBNAME}DEBUG${LIBPOSTFIX} PATHS ${SEARCHDIR}${PHYSX3_LIBPATH_PREFIX}) -ENDMACRO(FIND_PHYSX3_LIBRARY VARNAME LIBNAME) +ENDMACRO() -# Find the Libs, we just use the full path to save playing around with link_directories -FIND_PHYSX3_LIBRARY(CORE PhysX3 1) -FIND_PHYSX3_LIBRARY(COMMON PhysX3Common 1) -FIND_PHYSX3_LIBRARY(COOKING PhysX3Cooking 1) -FIND_PHYSX3_LIBRARY(CHARACTER PhysX3CharacterKinematic 1) -FIND_PHYSX3_LIBRARY(EXTENSIONS PhysX3Extensions 0) -FIND_PHYSX3_LIBRARY(TASK PxTask 0) -FIND_PHYSX3_LIBRARY(DEBUGGER PhysXVisualDebuggerSDK 0) -FIND_PHYSX3_LIBRARY(PROFILE PhysXProfileSDK 0) +# Find the Libs +if( WIN32 ) + FIND_PHYSX3_LIBRARY(CORE PhysX3 1 ${PHYSX3_PATH}/Lib/) + FIND_PHYSX3_LIBRARY(COMMON PhysX3Common 1 ${PHYSX3_PATH}/Lib/) + FIND_PHYSX3_LIBRARY(COOKING PhysX3Cooking 1 ${PHYSX3_PATH}/Lib/) + FIND_PHYSX3_LIBRARY(CHARACTER PhysX3CharacterKinematic 1 ${PHYSX3_PATH}/Lib/) + FIND_PHYSX3_LIBRARY(EXTENSIONS PhysX3Extensions 0 ${PHYSX3_PATH}/Lib/) + FIND_PHYSX3_LIBRARY(TASK PxTask 1 ${PHYSX3_BASE_PATH}/PxShared/Lib/) + FIND_PHYSX3_LIBRARY(FOUNDATION PxFoundation 1 ${PHYSX3_BASE_PATH}/PxShared/Lib/) + FIND_PHYSX3_LIBRARY(PVD PxPvdSDK 1 ${PHYSX3_BASE_PATH}/PxShared/Lib/) + + if(NOT PHYSX3_CORE_LIBRARY) + return() + endif() + + #Add the libs + set(PHYSX_LIBRARIES + ${PHYSX3_CORE_LIBRARY} + ${PHYSX3_COMMON_LIBRARY} + ${PHYSX3_EXTENSIONS_LIBRARY} + ${PHYSX3_COOKING_LIBRARY} + ${PHYSX3_CHARACTER_LIBRARY} + ${PHYSX3_TASK_LIBRARY} + ${PHYSX3_PVD_LIBRARY} + ${PHYSX3_FOUNDATION_LIBRARY} + ) + + set(PHYSX_LIBRARIES_DEBUG + ${PHYSX3_CORE_LIBRARY_DEBUG} + ${PHYSX3_COMMON_LIBRARY_DEBUG} + ${PHYSX3_EXTENSIONS_LIBRARY_DEBUG} + ${PHYSX3_COOKING_LIBRARY_DEBUG} + ${PHYSX3_CHARACTER_LIBRARY_DEBUG} + ${PHYSX3_TASK_LIBRARY_DEBUG} + ${PHYSX3_PVD_LIBRARY_DEBUG} + ${PHYSX3_FOUNDATION_LIBRARY_DEBUG} + ) +#macOS & linux +elseif(UNIX) + #common + FIND_PHYSX3_LIBRARY(EXTENSIONS PhysX3Extensions 0 ${PHYSX3_PATH}/Lib/) + FIND_PHYSX3_LIBRARY(CONTROLLER SimulationController 0 ${PHYSX3_PATH}/Lib/) + FIND_PHYSX3_LIBRARY(SCENEQUERY SceneQuery 0 ${PHYSX3_PATH}/Lib/) + FIND_PHYSX3_LIBRARY(LOWLEVEL LowLevel 0 ${PHYSX3_PATH}/Lib/) + FIND_PHYSX3_LIBRARY(LOWLEVEL_DYNAMICS LowLevelDynamics 0 ${PHYSX3_PATH}/Lib/) + FIND_PHYSX3_LIBRARY(LOWLEVEL_AABB LowLevelAABB 0 ${PHYSX3_PATH}/Lib/) + FIND_PHYSX3_LIBRARY(LOWLEVEL_CLOTH LowLevelCloth 0 ${PHYSX3_PATH}/Lib/) + FIND_PHYSX3_LIBRARY(LOWLEVEL_PARTICLES LowLevelParticles 0 ${PHYSX3_PATH}/Lib/) + FIND_PHYSX3_LIBRARY(TASK PxTask 0 ${PHYSX3_BASE_PATH}/PxShared/lib/) + #platform dependent + if(APPLE) + FIND_PHYSX3_LIBRARY(CORE PhysX3 0 ${PHYSX3_PATH}/Lib/) + FIND_PHYSX3_LIBRARY(COMMON PhysX3Common 0 ${PHYSX3_PATH}/Lib/) + FIND_PHYSX3_LIBRARY(COOKING PhysX3Cooking 0 ${PHYSX3_PATH}/Lib/) + FIND_PHYSX3_LIBRARY(CHARACTER PhysX3CharacterKinematic 0 ${PHYSX3_PATH}/Lib/) + FIND_PHYSX3_LIBRARY(FOUNDATION PxFoundation 0 ${PHYSX3_BASE_PATH}/PxShared/lib/) + FIND_PHYSX3_LIBRARY(PVD PxPvdSDK 0 ${PHYSX3_BASE_PATH}/PxShared/lib/) + elseif() #linux + FIND_PHYSX3_LIBRARY(CORE PhysX3 1 ${PHYSX3_PATH}/Bin/) + FIND_PHYSX3_LIBRARY(COMMON PhysX3Common 1 ${PHYSX3_PATH}/Bin/) + FIND_PHYSX3_LIBRARY(CHARACTER PhysX3CharacterKinematic 1 ${PHYSX3_PATH}/Bin/) + FIND_PHYSX3_LIBRARY(COOKING PhysX3Cooking 1 ${PHYSX3_PATH}/Bin/) + FIND_PHYSX3_LIBRARY(FOUNDATION PxFoundation 1 ${PHYSX3_BASE_PATH}/PxShared/bin/) + FIND_PHYSX3_LIBRARY(PVD PxPvdSDK 1 ${PHYSX3_BASE_PATH}/PxShared/bin/) + FIND_PHYSX3_LIBRARY(CUDA PxCudaContextManager 0 ${PHYSX3_BASE_PATH}/PxShared/lib/) + FIND_PHYSX3_LIBRARY(GPU PhysX3Gpu 1 ${PHYSX3_PATH}/Bin/) + FIND_PHYSX3_LIBRARY(XML PsFastXml 0 ${PHYSX3_BASE_PATH}/PxShared/lib/) + endif() + + if(NOT PHYSX3_CORE_LIBRARY) + return() + endif() + + #Add the libs + set(PHYSX_LIBRARIES + ${PHYSX3_CORE_LIBRARY} + ${PHYSX3_GPU_LIBRARY} + ${PHYSX3_CHARACTER_LIBRARY} + ${PHYSX3_COOKING_LIBRARY} + ${PHYSX3_COMMON_LIBRARY} + ${PHYSX3_EXTENSIONS_LIBRARY} + ${PHYSX3_CONTROLLER_LIBRARY} + ${PHYSX3_SCENEQUERY_LIBRARY} + ${PHYSX3_LOWLEVEL_LIBRARY} + ${PHYSX3_LOWLEVEL_AABB_LIBRARY} + ${PHYSX3_LOWLEVEL_DYNAMICS_LIBRARY} + ${PHYSX3_LOWLEVEL_CLOTH_LIBRARY} + ${PHYSX3_LOWLEVEL_PARTICLES_LIBRARY} + ${PHYSX3_CUDA_LIBRARY} + ${PHYSX3_TASK_LIBRARY} + ${PHYSX3_XML_LIBRARY} + ${PHYSX3_FOUNDATION_LIBRARY} + ${PHYSX3_PVD_LIBRARY} + ) + + set(PHYSX_LIBRARIES_DEBUG + ${PHYSX3_CORE_LIBRARY_DEBUG} + ${PHYSX3_GPU_LIBRARY_DEBUG} + ${PHYSX3_CHARACTER_LIBRARY_DEBUG} + ${PHYSX3_COOKING_LIBRARY_DEBUG} + ${PHYSX3_COMMON_LIBRARY_DEBUG} + ${PHYSX3_EXTENSIONS_LIBRARY_DEBUG} + ${PHYSX3_CONTROLLER_LIBRARY_DEBUG} + ${PHYSX3_SCENEQUERY_LIBRARY_DEBUG} + ${PHYSX3_LOWLEVEL_LIBRARY_DEBUG} + ${PHYSX3_LOWLEVEL_AABB_LIBRARY_DEBUG} + ${PHYSX3_LOWLEVEL_DYNAMICS_LIBRARY_DEBUG} + ${PHYSX3_LOWLEVEL_CLOTH_LIBRARY_DEBUG} + ${PHYSX3_LOWLEVEL_PARTICLES_LIBRARY_DEBUG} + ${PHYSX3_CUDA_LIBRARY_DEBUG} + ${PHYSX3_TASK_LIBRARY_DEBUG} + ${PHYSX3_XML_LIBRARY_DEBUG} + ${PHYSX3_FOUNDATION_LIBRARY_DEBUG} + ${PHYSX3_PVD_LIBRARY_DEBUG} + ) -if(NOT PHYSX3_CORE_LIBRARY) - return() endif() # Defines @@ -106,56 +222,64 @@ addDef( "TORQUE_PHYSICS_ENABLED" ) addPath( "${srcDir}/T3D/physics/physx3" ) # Includes +addInclude( "${PHYSX3_BASE_PATH}/PxShared/include" ) +addInclude( "${PHYSX3_BASE_PATH}/PxShared/src/foundation/include" ) +addInclude( "${PHYSX3_BASE_PATH}/PxShared/src/pvd/include" ) addInclude( "${PHYSX3_PATH}/Include" ) -addInclude( "${PHYSX3_PATH}/Include/extensions" ) -addInclude( "${PHYSX3_PATH}/Include/foundation" ) -addInclude( "${PHYSX3_PATH}/Include/characterkinematic" ) -addInclude( "${PHYSX3_PATH}/Include/common" ) -#Add the libs -set(PHYSX_LIBRARIES_DEBUG - ${PHYSX3_CORE_LIBRARY_DEBUG} - ${PHYSX3_COMMON_LIBRARY_DEBUG} - ${PHYSX3_COOKING_LIBRARY_DEBUG} - ${PHYSX3_CHARACTER_LIBRARY_DEBUG} - ${PHYSX3_EXTENSIONS_LIBRARY_DEBUG} - ${PHYSX3_TASK_LIBRARY_DEBUG} - ${PHYSX3_DEBUGGER_LIBRARY_DEBUG} - ${PHYSX3_PROFILE_LIBRARY_DEBUG} -) +# Libs +addLibRelease( "${PHYSX_LIBRARIES}" ) +addLibDebug( "${PHYSX_LIBRARIES_DEBUG}" ) -set(PHYSX_LIBRARIES - ${PHYSX3_CORE_LIBRARY} - ${PHYSX3_COMMON_LIBRARY} - ${PHYSX3_COOKING_LIBRARY} - ${PHYSX3_CHARACTER_LIBRARY} - ${PHYSX3_EXTENSIONS_LIBRARY} - ${PHYSX3_TASK_LIBRARY} - ${PHYSX3_DEBUGGER_LIBRARY} - ${PHYSX3_PROFILE_LIBRARY} -) - -addLibRelease("${PHYSX_LIBRARIES}") -addLibDebug("${PHYSX_LIBRARIES_DEBUG}") - -#Install dll files +#Install files if( WIN32 ) - # File Copy for Release - INSTALL(FILES "${PHYSX3_PATH}/Bin/${PHYSX3_LIBPATH_PREFIX}/PhysX3${PHYSX3_LIBNAME_POSTFIX}.dll" DESTINATION "${projectOutDir}" CONFIGURATIONS "Release") - INSTALL(FILES "${PHYSX3_PATH}/Bin/${PHYSX3_LIBPATH_PREFIX}/PhysX3CharacterKinematic${PHYSX3_LIBNAME_POSTFIX}.dll" DESTINATION "${projectOutDir}" CONFIGURATIONS "Release") - INSTALL(FILES "${PHYSX3_PATH}/Bin/${PHYSX3_LIBPATH_PREFIX}/PhysX3Common${PHYSX3_LIBNAME_POSTFIX}.dll" DESTINATION "${projectOutDir}" CONFIGURATIONS "Release") - INSTALL(FILES "${PHYSX3_PATH}/Bin/${PHYSX3_LIBPATH_PREFIX}/PhysX3Cooking${PHYSX3_LIBNAME_POSTFIX}.dll" DESTINATION "${projectOutDir}" CONFIGURATIONS "Release") + # File Copy for Release + INSTALL(FILES "${PHYSX3_PATH}/Bin/${PHYSX3_LIBPATH_PREFIX}/PhysX3${PHYSX3_LIBNAME_POSTFIX}.dll" DESTINATION "${projectOutDir}" CONFIGURATIONS Release) + INSTALL(FILES "${PHYSX3_PATH}/Bin/${PHYSX3_LIBPATH_PREFIX}/PhysX3Gpu${PHYSX3_LIBNAME_POSTFIX}.dll" DESTINATION "${projectOutDir}" CONFIGURATIONS Release) + INSTALL(FILES "${PHYSX3_PATH}/Bin/${PHYSX3_LIBPATH_PREFIX}/PhysX3CharacterKinematic${PHYSX3_LIBNAME_POSTFIX}.dll" DESTINATION "${projectOutDir}" CONFIGURATIONS Release) + INSTALL(FILES "${PHYSX3_PATH}/Bin/${PHYSX3_LIBPATH_PREFIX}/PhysX3Common${PHYSX3_LIBNAME_POSTFIX}.dll" DESTINATION "${projectOutDir}" CONFIGURATIONS Release) + INSTALL(FILES "${PHYSX3_PATH}/Bin/${PHYSX3_LIBPATH_PREFIX}/PhysX3Cooking${PHYSX3_LIBNAME_POSTFIX}.dll" DESTINATION "${projectOutDir}" CONFIGURATIONS Release) + INSTALL(FILES "${PHYSX3_BASE_PATH}/PxShared/bin/${PHYSX3_LIBPATH_PREFIX}/PxFoundation${PHYSX3_LIBNAME_POSTFIX}.dll" DESTINATION "${projectOutDir}" CONFIGURATIONS Release) + INSTALL(FILES "${PHYSX3_BASE_PATH}/PxShared/bin/${PHYSX3_LIBPATH_PREFIX}/PxPvdSDK${PHYSX3_LIBNAME_POSTFIX}.dll" DESTINATION "${projectOutDir}" CONFIGURATIONS Release) - # File Copy for Debug - if(TORQUE_CPU_X32) - INSTALL(FILES "${PHYSX3_PATH}/Bin/${PHYSX3_LIBPATH_PREFIX}/nvToolsExt32_1.dll" DESTINATION "${projectOutDir}" CONFIGURATIONS "Debug") - elseif(TORQUE_CPU_X64) - INSTALL(FILES "${PHYSX3_PATH}/Bin/${PHYSX3_LIBPATH_PREFIX}/nvToolsExt64_1.dll" DESTINATION "${projectOutDir}" CONFIGURATIONS "Debug") - endif() - - INSTALL(FILES "${PHYSX3_PATH}/Bin/${PHYSX3_LIBPATH_PREFIX}/PhysX3DEBUG${PHYSX3_LIBNAME_POSTFIX}.dll" DESTINATION "${projectOutDir}" CONFIGURATIONS "Debug") - INSTALL(FILES "${PHYSX3_PATH}/Bin/${PHYSX3_LIBPATH_PREFIX}/PhysX3CharacterKinematicDEBUG${PHYSX3_LIBNAME_POSTFIX}.dll" DESTINATION "${projectOutDir}" CONFIGURATIONS "Debug") - INSTALL(FILES "${PHYSX3_PATH}/Bin/${PHYSX3_LIBPATH_PREFIX}/PhysX3CommonDEBUG${PHYSX3_LIBNAME_POSTFIX}.dll" DESTINATION "${projectOutDir}" CONFIGURATIONS "Debug") - INSTALL(FILES "${PHYSX3_PATH}/Bin/${PHYSX3_LIBPATH_PREFIX}/PhysX3CookingDEBUG${PHYSX3_LIBNAME_POSTFIX}.dll" DESTINATION "${projectOutDir}" CONFIGURATIONS "Debug") - -endif(WIN32) + # File Copy + if(TORQUE_CPU_X32) + INSTALL(FILES "${PHYSX3_PATH}/Bin/${PHYSX3_LIBPATH_PREFIX}/PhysXDevice.dll" DESTINATION "${projectOutDir}") + INSTALL(FILES "${PHYSX3_PATH}/Bin/${PHYSX3_LIBPATH_PREFIX}/nvToolsExt32_1.dll" DESTINATION "${projectOutDir}" CONFIGURATIONS Debug) + elseif(TORQUE_CPU_X64) + INSTALL(FILES "${PHYSX3_PATH}/Bin/${PHYSX3_LIBPATH_PREFIX}/PhysXDevice64.dll" DESTINATION "${projectOutDir}") + INSTALL(FILES "${PHYSX3_PATH}/Bin/${PHYSX3_LIBPATH_PREFIX}/nvToolsExt64_1.dll" DESTINATION "${projectOutDir}" CONFIGURATIONS Debug) + endif() + + #File copy for Debug + INSTALL(FILES "${PHYSX3_PATH}/Bin/${PHYSX3_LIBPATH_PREFIX}/PhysX3DEBUG${PHYSX3_LIBNAME_POSTFIX}.dll" DESTINATION "${projectOutDir}" CONFIGURATIONS Debug) + INSTALL(FILES "${PHYSX3_PATH}/Bin/${PHYSX3_LIBPATH_PREFIX}/PhysX3GpuDEBUG${PHYSX3_LIBNAME_POSTFIX}.dll" DESTINATION "${projectOutDir}" CONFIGURATIONS Debug) + INSTALL(FILES "${PHYSX3_PATH}/Bin/${PHYSX3_LIBPATH_PREFIX}/PhysX3CharacterKinematicDEBUG${PHYSX3_LIBNAME_POSTFIX}.dll" DESTINATION "${projectOutDir}" CONFIGURATIONS Debug) + INSTALL(FILES "${PHYSX3_PATH}/Bin/${PHYSX3_LIBPATH_PREFIX}/PhysX3CommonDEBUG${PHYSX3_LIBNAME_POSTFIX}.dll" DESTINATION "${projectOutDir}" CONFIGURATIONS Debug) + INSTALL(FILES "${PHYSX3_PATH}/Bin/${PHYSX3_LIBPATH_PREFIX}/PhysX3CookingDEBUG${PHYSX3_LIBNAME_POSTFIX}.dll" DESTINATION "${projectOutDir}" CONFIGURATIONS Debug) + INSTALL(FILES "${PHYSX3_BASE_PATH}/PxShared/bin/${PHYSX3_LIBPATH_PREFIX}/PxFoundationDEBUG${PHYSX3_LIBNAME_POSTFIX}.dll" DESTINATION "${projectOutDir}" CONFIGURATIONS Debug) + INSTALL(FILES "${PHYSX3_BASE_PATH}/PxShared/bin/${PHYSX3_LIBPATH_PREFIX}/PxPvdSDKDEBUG${PHYSX3_LIBNAME_POSTFIX}.dll" DESTINATION "${projectOutDir}" CONFIGURATIONS Debug) + +endif() + +#linux - apple xcode physx build generates static libs +if(UNIX AND NOT APPLE) + # File Copy for Release + INSTALL(FILES "${PHYSX3_PATH}/Bin/${PHYSX3_LIBPATH_PREFIX}/libPhysX3${PHYSX3_LIBNAME_POSTFIX}.so" DESTINATION "${projectOutDir}" CONFIGURATIONS Release) + INSTALL(FILES "${PHYSX3_PATH}/Bin/${PHYSX3_LIBPATH_PREFIX}/libPhysX3CharacterKinematic${PHYSX3_LIBNAME_POSTFIX}.so" DESTINATION "${projectOutDir}" CONFIGURATIONS Release) + INSTALL(FILES "${PHYSX3_PATH}/Bin/${PHYSX3_LIBPATH_PREFIX}/libPhysX3Common${PHYSX3_LIBNAME_POSTFIX}.so" DESTINATION "${projectOutDir}" CONFIGURATIONS Release) + INSTALL(FILES "${PHYSX3_PATH}/Bin/${PHYSX3_LIBPATH_PREFIX}/libPhysX3Cooking${PHYSX3_LIBNAME_POSTFIX}.so" DESTINATION "${projectOutDir}" CONFIGURATIONS Release) + INSTALL(FILES "${PHYSX3_BASE_PATH}/PxShared/bin/${PHYSX3_LIBPATH_PREFIX}/libPxFoundation${PHYSX3_LIBNAME_POSTFIX}.so" DESTINATION "${projectOutDir}" CONFIGURATIONS Release) + INSTALL(FILES "${PHYSX3_BASE_PATH}/PxShared/bin/${PHYSX3_LIBPATH_PREFIX}/libPxPvdSDK${PHYSX3_LIBNAME_POSTFIX}.so" DESTINATION "${projectOutDir}" CONFIGURATIONS Release) + INSTALL(FILES "${PHYSX3_PATH}/Bin/${PHYSX3_LIBPATH_PREFIX}/libPhysX3Gpu${PHYSX3_LIBNAME_POSTFIX}.so" DESTINATION "${projectOutDir}" CONFIGURATIONS Release) + + # File Copy for Debug + INSTALL(FILES "${PHYSX3_PATH}/Bin/${PHYSX3_LIBPATH_PREFIX}/libPhysX3DEBUG${PHYSX3_LIBNAME_POSTFIX}.so" DESTINATION "${projectOutDir}" CONFIGURATIONS Debug) + INSTALL(FILES "${PHYSX3_PATH}/Bin/${PHYSX3_LIBPATH_PREFIX}/libPhysX3CharacterKinematicDEBUG${PHYSX3_LIBNAME_POSTFIX}.so" DESTINATION "${projectOutDir}" CONFIGURATIONS Debug) + INSTALL(FILES "${PHYSX3_PATH}/Bin/${PHYSX3_LIBPATH_PREFIX}/libPhysX3CommonDEBUG${PHYSX3_LIBNAME_POSTFIX}.so" DESTINATION "${projectOutDir}" CONFIGURATIONS Debug) + INSTALL(FILES "${PHYSX3_PATH}/Bin/${PHYSX3_LIBPATH_PREFIX}/libPhysX3CookingDEBUG${PHYSX3_LIBNAME_POSTFIX}.so" DESTINATION "${projectOutDir}" CONFIGURATIONS Debug) + INSTALL(FILES "${PHYSX3_BASE_PATH}/PxShared/bin/${PHYSX3_LIBPATH_PREFIX}/libPxFoundationDEBUG${PHYSX3_LIBNAME_POSTFIX}.so" DESTINATION "${projectOutDir}" CONFIGURATIONS Debug) + INSTALL(FILES "${PHYSX3_BASE_PATH}/PxShared/bin/${PHYSX3_LIBPATH_PREFIX}/libPxPvdSDKDEBUG${PHYSX3_LIBNAME_POSTFIX}.so" DESTINATION "${projectOutDir}" CONFIGURATIONS Debug) + INSTALL(FILES "${PHYSX3_PATH}/Bin/${PHYSX3_LIBPATH_PREFIX}/libPhysX3GpuDEBUG${PHYSX3_LIBNAME_POSTFIX}.so" DESTINATION "${projectOutDir}" CONFIGURATIONS Debug) + +endif() From c0f298e37d824187ed2fbd67db1cd5b168ee07ca Mon Sep 17 00:00:00 2001 From: Tim Date: Sat, 3 Feb 2018 13:40:33 +1000 Subject: [PATCH 03/34] Fixed physx3 linux cmake build --- Tools/CMake/modules/module_physx3.cmake | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/Tools/CMake/modules/module_physx3.cmake b/Tools/CMake/modules/module_physx3.cmake index 56984649f..a2dd3fdd3 100644 --- a/Tools/CMake/modules/module_physx3.cmake +++ b/Tools/CMake/modules/module_physx3.cmake @@ -108,6 +108,7 @@ if( WIN32 ) FIND_PHYSX3_LIBRARY(PVD PxPvdSDK 1 ${PHYSX3_BASE_PATH}/PxShared/Lib/) if(NOT PHYSX3_CORE_LIBRARY) + message(FATAL_ERROR "Could not find core PhysX lib") return() endif() @@ -153,29 +154,29 @@ elseif(UNIX) FIND_PHYSX3_LIBRARY(CHARACTER PhysX3CharacterKinematic 0 ${PHYSX3_PATH}/Lib/) FIND_PHYSX3_LIBRARY(FOUNDATION PxFoundation 0 ${PHYSX3_BASE_PATH}/PxShared/lib/) FIND_PHYSX3_LIBRARY(PVD PxPvdSDK 0 ${PHYSX3_BASE_PATH}/PxShared/lib/) - elseif() #linux + else() #linux FIND_PHYSX3_LIBRARY(CORE PhysX3 1 ${PHYSX3_PATH}/Bin/) FIND_PHYSX3_LIBRARY(COMMON PhysX3Common 1 ${PHYSX3_PATH}/Bin/) + FIND_PHYSX3_LIBRARY(GPU PhysX3Gpu 1 ${PHYSX3_PATH}/Bin/) FIND_PHYSX3_LIBRARY(CHARACTER PhysX3CharacterKinematic 1 ${PHYSX3_PATH}/Bin/) FIND_PHYSX3_LIBRARY(COOKING PhysX3Cooking 1 ${PHYSX3_PATH}/Bin/) FIND_PHYSX3_LIBRARY(FOUNDATION PxFoundation 1 ${PHYSX3_BASE_PATH}/PxShared/bin/) FIND_PHYSX3_LIBRARY(PVD PxPvdSDK 1 ${PHYSX3_BASE_PATH}/PxShared/bin/) - FIND_PHYSX3_LIBRARY(CUDA PxCudaContextManager 0 ${PHYSX3_BASE_PATH}/PxShared/lib/) - FIND_PHYSX3_LIBRARY(GPU PhysX3Gpu 1 ${PHYSX3_PATH}/Bin/) FIND_PHYSX3_LIBRARY(XML PsFastXml 0 ${PHYSX3_BASE_PATH}/PxShared/lib/) endif() if(NOT PHYSX3_CORE_LIBRARY) + message(FATAL_ERROR "Could not find core PhysX lib") return() endif() #Add the libs set(PHYSX_LIBRARIES ${PHYSX3_CORE_LIBRARY} - ${PHYSX3_GPU_LIBRARY} ${PHYSX3_CHARACTER_LIBRARY} ${PHYSX3_COOKING_LIBRARY} ${PHYSX3_COMMON_LIBRARY} + ${PHYSX3_GPU_LIBRARY} ${PHYSX3_EXTENSIONS_LIBRARY} ${PHYSX3_CONTROLLER_LIBRARY} ${PHYSX3_SCENEQUERY_LIBRARY} @@ -184,7 +185,6 @@ elseif(UNIX) ${PHYSX3_LOWLEVEL_DYNAMICS_LIBRARY} ${PHYSX3_LOWLEVEL_CLOTH_LIBRARY} ${PHYSX3_LOWLEVEL_PARTICLES_LIBRARY} - ${PHYSX3_CUDA_LIBRARY} ${PHYSX3_TASK_LIBRARY} ${PHYSX3_XML_LIBRARY} ${PHYSX3_FOUNDATION_LIBRARY} @@ -193,10 +193,10 @@ elseif(UNIX) set(PHYSX_LIBRARIES_DEBUG ${PHYSX3_CORE_LIBRARY_DEBUG} - ${PHYSX3_GPU_LIBRARY_DEBUG} ${PHYSX3_CHARACTER_LIBRARY_DEBUG} ${PHYSX3_COOKING_LIBRARY_DEBUG} ${PHYSX3_COMMON_LIBRARY_DEBUG} + ${PHYSX3_GPU_LIBRARY_DEBUG} ${PHYSX3_EXTENSIONS_LIBRARY_DEBUG} ${PHYSX3_CONTROLLER_LIBRARY_DEBUG} ${PHYSX3_SCENEQUERY_LIBRARY_DEBUG} @@ -205,7 +205,6 @@ elseif(UNIX) ${PHYSX3_LOWLEVEL_DYNAMICS_LIBRARY_DEBUG} ${PHYSX3_LOWLEVEL_CLOTH_LIBRARY_DEBUG} ${PHYSX3_LOWLEVEL_PARTICLES_LIBRARY_DEBUG} - ${PHYSX3_CUDA_LIBRARY_DEBUG} ${PHYSX3_TASK_LIBRARY_DEBUG} ${PHYSX3_XML_LIBRARY_DEBUG} ${PHYSX3_FOUNDATION_LIBRARY_DEBUG} From c0b50792f72124b8da5d5665328476e68f222dd4 Mon Sep 17 00:00:00 2001 From: Tim Date: Sun, 18 Mar 2018 16:11:07 +1000 Subject: [PATCH 04/34] physx support for vs 2017 --- Tools/CMake/modules/module_physx3.cmake | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Tools/CMake/modules/module_physx3.cmake b/Tools/CMake/modules/module_physx3.cmake index a2dd3fdd3..e8065740f 100644 --- a/Tools/CMake/modules/module_physx3.cmake +++ b/Tools/CMake/modules/module_physx3.cmake @@ -52,6 +52,9 @@ if(TORQUE_CPU_X32) set(PHYSX3_LIBPATH_PREFIX vc12win32) elseif(MSVC14) set(PHYSX3_LIBPATH_PREFIX vc14win32) + #VS 2017 uses 14.x toolchain so can't use MSVC15 + elseif(MSVC_VERSION GREATER_OR_EQUAL_TO 1910) + set(PHYSX3_LIBPATH_PREFIX vc15win32) else() message(FATAL_ERROR "This version of VS is not supported") return() @@ -65,6 +68,9 @@ elseif(TORQUE_CPU_X64) set(PHYSX3_LIBPATH_PREFIX vc12win64) elseif(MSVC14) set(PHYSX3_LIBPATH_PREFIX vc14win64) + #VS 2017 uses 14.x toolchain so can't use MSVC15 + elseif(MSVC_VERSION GREATER_OR_EQUAL_TO 1910) + set(PHYSX3_LIBPATH_PREFIX vc15win64) else() message(FATAL_ERROR "This version of VS is not supported") return() From e718841467e197c021529edd9adee75b24833769 Mon Sep 17 00:00:00 2001 From: Lukas Joergensen Date: Tue, 17 Apr 2018 16:33:56 +0200 Subject: [PATCH 05/34] Eliminate DefineConsoleFunction --- Engine/source/T3D/aiClient.cpp | 2 +- Engine/source/T3D/entity.cpp | 2 +- Engine/source/T3D/gameBase/gameProcess.cpp | 2 +- Engine/source/T3D/gameFunctions.cpp | 4 +- Engine/source/T3D/physics/physicsPlugin.cpp | 26 +-- Engine/source/app/game.cpp | 22 +-- Engine/source/app/net/serverQuery.cpp | 20 +- Engine/source/app/version.cpp | 14 +- .../source/assets/assetQuery_ScriptBinding.h | 4 +- Engine/source/cinterface/cinterface.cpp | 2 +- Engine/source/console/console.cpp | 6 +- Engine/source/console/consoleDoc.cpp | 4 +- Engine/source/console/consoleFunctions.cpp | 182 +++++++++--------- Engine/source/console/consoleXMLExport.cpp | 2 +- Engine/source/console/engineAPI.h | 18 -- Engine/source/console/sim.cpp | 24 +-- Engine/source/console/simDatablock.cpp | 4 +- Engine/source/console/telnetConsole.cpp | 2 +- Engine/source/console/telnetDebugger.cpp | 6 +- Engine/source/core/dnet.cpp | 2 +- Engine/source/core/stringBuffer.cpp | 4 +- Engine/source/core/util/str.cpp | 2 +- .../environment/VolumetricFogRTManager.cpp | 2 +- Engine/source/gfx/gfxDevice.cpp | 2 +- Engine/source/gfx/gl/gfxGLDeviceProfiler.cpp | 2 +- Engine/source/i18n/i18n.cpp | 4 +- .../advanced/advancedLightManager.cpp | 2 +- Engine/source/lighting/shadowManager.cpp | 2 +- Engine/source/materials/materialManager.cpp | 10 +- Engine/source/math/mConsoleFunctions.cpp | 70 +++---- Engine/source/math/mRotation.cpp | 20 +- Engine/source/math/mathTypes.cpp | 44 ++--- Engine/source/navigation/navMesh.cpp | 10 +- Engine/source/platform/platformFileIO.cpp | 8 +- Engine/source/platform/platformMemory.cpp | 4 +- Engine/source/platform/platformRedBook.cpp | 20 +- Engine/source/platform/platformTimer.cpp | 4 +- Engine/source/platformWin32/cardProfile.cpp | 2 +- Engine/source/platformWin32/winConsole.cpp | 2 +- .../source/platformWin32/winDirectInput.cpp | 20 +- Engine/source/platformWin32/winExec.cpp | 2 +- Engine/source/platformWin32/winInput.cpp | 6 +- Engine/source/platformWin32/winWindow.cpp | 2 +- Engine/source/scene/pathManager.cpp | 4 +- Engine/source/scene/sceneManager.cpp | 4 +- Engine/source/sfx/sfxSystem.cpp | 6 +- Engine/source/sim/netInterface.cpp | 2 +- Engine/source/terrain/terrData.cpp | 6 +- Engine/source/ts/collada/colladaImport.cpp | 2 +- Engine/source/ts/collada/colladaLights.cpp | 2 +- Engine/source/ts/loader/tsShapeLoader.cpp | 4 +- Engine/source/ts/tsLastDetail.cpp | 2 +- Engine/source/util/fpsTracker.cpp | 2 +- Engine/source/util/messaging/dispatcher.cpp | 14 +- Engine/source/util/sampler.cpp | 6 +- 55 files changed, 314 insertions(+), 332 deletions(-) diff --git a/Engine/source/T3D/aiClient.cpp b/Engine/source/T3D/aiClient.cpp index 0fab8f428..1f4be793b 100644 --- a/Engine/source/T3D/aiClient.cpp +++ b/Engine/source/T3D/aiClient.cpp @@ -526,7 +526,7 @@ DefineConsoleMethod( AIClient, getLocation, Point3F, (),, "ai.getLocation();" ) /** * Adds an AI Player to the game */ -DefineConsoleFunction( aiAddPlayer, S32, (const char * name, const char * ns), (""), "'playerName'[, 'AIClassType'] );") +DefineEngineFunction( aiAddPlayer, S32, (const char * name, const char * ns), (""), "'playerName'[, 'AIClassType'] );") { // Create the player AIClient *aiPlayer = new AIClient(); diff --git a/Engine/source/T3D/entity.cpp b/Engine/source/T3D/entity.cpp index 62c0b031f..fe0303652 100644 --- a/Engine/source/T3D/entity.cpp +++ b/Engine/source/T3D/entity.cpp @@ -2005,7 +2005,7 @@ DefineConsoleMethod(Entity, notify, void, (String signalFunction, String argA, S object->notifyComponents(signalFunction, argA, argB, argC, argD, argE); } -DefineConsoleFunction(findEntitiesByTag, const char*, (SimGroup* searchingGroup, String tags), (nullAsType(), ""), +DefineEngineFunction(findEntitiesByTag, const char*, (SimGroup* searchingGroup, String tags), (nullAsType(), ""), "Finds all entities that have the provided tags.\n" "@param searchingGroup The SimGroup to search inside. If null, we'll search the entire dictionary(this can be slow!).\n" "@param tags Word delimited list of tags to search for. If multiple tags are included, the list is eclusively parsed, requiring all tags provided to be found on an entity for a match.\n" diff --git a/Engine/source/T3D/gameBase/gameProcess.cpp b/Engine/source/T3D/gameBase/gameProcess.cpp index 2df8a850e..6aa5c0e63 100644 --- a/Engine/source/T3D/gameBase/gameProcess.cpp +++ b/Engine/source/T3D/gameBase/gameProcess.cpp @@ -34,7 +34,7 @@ ClientProcessList* ClientProcessList::smClientProcessList = NULL; ServerProcessList* ServerProcessList::smServerProcessList = NULL; static U32 gNetOrderNextId = 0; -DefineConsoleFunction( dumpProcessList, void, ( ), , +DefineEngineFunction( dumpProcessList, void, ( ), , "Dumps all ProcessObjects in ServerProcessList and ClientProcessList to the console." ) { Con::printf( "client process list:" ); diff --git a/Engine/source/T3D/gameFunctions.cpp b/Engine/source/T3D/gameFunctions.cpp index 23d048f7c..c49c75cb3 100644 --- a/Engine/source/T3D/gameFunctions.cpp +++ b/Engine/source/T3D/gameFunctions.cpp @@ -114,7 +114,7 @@ static U32 sgServerQueryIndex = 0; //SERVER FUNCTIONS ONLY ConsoleFunctionGroupBegin( Containers, "Spatial query functions. Server side only!"); -DefineConsoleFunction( containerFindFirst, const char*, (U32 typeMask, Point3F origin, Point3F size), , "(int mask, Point3F point, float x, float y, float z)" +DefineEngineFunction( containerFindFirst, const char*, (U32 typeMask, Point3F origin, Point3F size), , "(int mask, Point3F point, float x, float y, float z)" "@brief Find objects matching the bitmask type within a box centered at point, with extents x, y, z.\n\n" "@returns The first object found, or an empty string if nothing was found. Thereafter, you can get more " "results using containerFindNext()." @@ -146,7 +146,7 @@ DefineConsoleFunction( containerFindFirst, const char*, (U32 typeMask, Point3F o return buff; } -DefineConsoleFunction( containerFindNext, const char*, (), , "()" +DefineEngineFunction( containerFindNext, const char*, (), , "()" "@brief Get more results from a previous call to containerFindFirst().\n\n" "@note You must call containerFindFirst() to begin the search.\n" "@returns The next object found, or an empty string if nothing else was found.\n" diff --git a/Engine/source/T3D/physics/physicsPlugin.cpp b/Engine/source/T3D/physics/physicsPlugin.cpp index b2f06b55e..fec6f2186 100644 --- a/Engine/source/T3D/physics/physicsPlugin.cpp +++ b/Engine/source/T3D/physics/physicsPlugin.cpp @@ -124,31 +124,31 @@ void PhysicsPlugin::_debugDraw( SceneManager *graph, const SceneRenderState *sta world->onDebugDraw( state ); } -DefineConsoleFunction( physicsPluginPresent, bool, (), , "physicsPluginPresent()" +DefineEngineFunction( physicsPluginPresent, bool, (), , "physicsPluginPresent()" "@brief Returns true if a physics plugin exists and is initialized.\n\n" "@ingroup Physics" ) { return PHYSICSMGR != NULL; } -DefineConsoleFunction( physicsInit, bool, (const char * library), ("default"), "physicsInit( [string library] )") +DefineEngineFunction( physicsInit, bool, (const char * library), ("default"), "physicsInit( [string library] )") { return PhysicsPlugin::activate( library ); } -DefineConsoleFunction( physicsDestroy, void, (), , "physicsDestroy()") +DefineEngineFunction( physicsDestroy, void, (), , "physicsDestroy()") { if ( PHYSICSMGR ) PHYSICSMGR->destroyPlugin(); } -DefineConsoleFunction( physicsInitWorld, bool, (const char * worldName), , "physicsInitWorld( String worldName )") +DefineEngineFunction( physicsInitWorld, bool, (const char * worldName), , "physicsInitWorld( String worldName )") { bool res = PHYSICSMGR && PHYSICSMGR->createWorld( String( worldName ) ); return res; } -DefineConsoleFunction( physicsDestroyWorld, void, (const char * worldName), , "physicsDestroyWorld( String worldName )") +DefineEngineFunction( physicsDestroyWorld, void, (const char * worldName), , "physicsDestroyWorld( String worldName )") { if ( PHYSICSMGR ) PHYSICSMGR->destroyWorld( worldName ); @@ -157,19 +157,19 @@ DefineConsoleFunction( physicsDestroyWorld, void, (const char * worldName), , "p // Control/query of the stop/started state // of the currently running simulation. -DefineConsoleFunction( physicsStartSimulation, void, (const char * worldName), , "physicsStartSimulation( String worldName )") +DefineEngineFunction( physicsStartSimulation, void, (const char * worldName), , "physicsStartSimulation( String worldName )") { if ( PHYSICSMGR ) PHYSICSMGR->enableSimulation( String( worldName ), true ); } -DefineConsoleFunction( physicsStopSimulation, void, (const char * worldName), , "physicsStopSimulation( String worldName )") +DefineEngineFunction( physicsStopSimulation, void, (const char * worldName), , "physicsStopSimulation( String worldName )") { if ( PHYSICSMGR ) PHYSICSMGR->enableSimulation( String( worldName ), false ); } -DefineConsoleFunction( physicsSimulationEnabled, bool, (), , "physicsStopSimulation( String worldName )") +DefineEngineFunction( physicsSimulationEnabled, bool, (), , "physicsStopSimulation( String worldName )") { return PHYSICSMGR && PHYSICSMGR->isSimulationEnabled(); } @@ -177,14 +177,14 @@ DefineConsoleFunction( physicsSimulationEnabled, bool, (), , "physicsStopSimulat // Used for slowing down time on the // physics simulation, and for pausing/restarting // the simulation. -DefineConsoleFunction( physicsSetTimeScale, void, (F32 scale), , "physicsSetTimeScale( F32 scale )") +DefineEngineFunction( physicsSetTimeScale, void, (F32 scale), , "physicsSetTimeScale( F32 scale )") { if ( PHYSICSMGR ) PHYSICSMGR->setTimeScale( scale ); } // Get the currently set time scale. -DefineConsoleFunction( physicsGetTimeScale, F32, (), , "physicsGetTimeScale()") +DefineEngineFunction( physicsGetTimeScale, F32, (), , "physicsGetTimeScale()") { return PHYSICSMGR && PHYSICSMGR->getTimeScale(); } @@ -193,7 +193,7 @@ DefineConsoleFunction( physicsGetTimeScale, F32, (), , "physicsGetTimeScale()") // physics simulation that they should store // their current state for later restoration, // such as when the editor is closed. -DefineConsoleFunction( physicsStoreState, void, (), , "physicsStoreState()") +DefineEngineFunction( physicsStoreState, void, (), , "physicsStoreState()") { PhysicsPlugin::getPhysicsResetSignal().trigger( PhysicsResetEvent_Store ); } @@ -201,13 +201,13 @@ DefineConsoleFunction( physicsStoreState, void, (), , "physicsStoreState()") // Used to send a signal to objects in the // physics simulation that they should restore // their saved state, such as when the editor is opened. -DefineConsoleFunction( physicsRestoreState, void, (), , "physicsRestoreState()") +DefineEngineFunction( physicsRestoreState, void, (), , "physicsRestoreState()") { if ( PHYSICSMGR ) PHYSICSMGR->reset(); } -DefineConsoleFunction( physicsDebugDraw, void, (bool enable), , "physicsDebugDraw( bool enable )") +DefineEngineFunction( physicsDebugDraw, void, (bool enable), , "physicsDebugDraw( bool enable )") { if ( PHYSICSMGR ) PHYSICSMGR->enableDebugDraw( enable ); diff --git a/Engine/source/app/game.cpp b/Engine/source/app/game.cpp index 05f63e84c..d7a3377f6 100644 --- a/Engine/source/app/game.cpp +++ b/Engine/source/app/game.cpp @@ -67,7 +67,7 @@ bool gEditingMission = false; ConsoleFunctionGroupBegin( InputManagement, "Functions that let you deal with input from scripts" ); -DefineConsoleFunction( deactivateDirectInput, void, (), , +DefineEngineFunction( deactivateDirectInput, void, (), , "()" "@brief Disables DirectInput.\n\n" "Also deactivates any connected joysticks.\n\n" @@ -77,7 +77,7 @@ DefineConsoleFunction( deactivateDirectInput, void, (), , Input::deactivate(); } -DefineConsoleFunction( activateDirectInput, void, (), , +DefineEngineFunction( activateDirectInput, void, (), , "()" "@brief Activates DirectInput.\n\n" "Also activates any connected joysticks." @@ -91,7 +91,7 @@ ConsoleFunctionGroupEnd( InputManagement ); //-------------------------------------------------------------------------- static const U32 MaxPlayerNameLength = 16; -DefineConsoleFunction( strToPlayerName, const char*, (const char* ptr ), , "strToPlayerName(string);" ) +DefineEngineFunction( strToPlayerName, const char*, (const char* ptr ), , "strToPlayerName(string);" ) { // Strip leading spaces and underscores: @@ -147,7 +147,7 @@ DefineConsoleFunction( strToPlayerName, const char*, (const char* ptr ), , "strT ConsoleFunctionGroupBegin( Platform , "General platform functions."); -DefineConsoleFunction( lockMouse, void, (bool isLocked ), , "(bool isLocked)" +DefineEngineFunction( lockMouse, void, (bool isLocked ), , "(bool isLocked)" "@brief Lock or unlock the mouse to the window.\n\n" "When true, prevents the mouse from leaving the bounds of the game window.\n\n" "@ingroup Input") @@ -156,7 +156,7 @@ DefineConsoleFunction( lockMouse, void, (bool isLocked ), , "(bool isLocked)" } -DefineConsoleFunction( setNetPort, bool, (int port, bool bind), (true), "(int port, bool bind=true)" +DefineEngineFunction( setNetPort, bool, (int port, bool bind), (true), "(int port, bool bind=true)" "@brief Set the network port for the game to use.\n\n" "@param port The port to use.\n" @@ -171,28 +171,28 @@ DefineConsoleFunction( setNetPort, bool, (int port, bool bind), (true), "(int po return Net::openPort((S32)port, bind); } -DefineConsoleFunction(isAddressTypeAvailable, bool, (int addressType), , "(protocol id)" +DefineEngineFunction(isAddressTypeAvailable, bool, (int addressType), , "(protocol id)" "@brief Determines if a specified address type can be reached.\n\n" "@ingroup Networking") { return Net::isAddressTypeAvailable((NetAddress::Type)addressType); } -DefineConsoleFunction( closeNetPort, void, (), , "()" +DefineEngineFunction( closeNetPort, void, (), , "()" "@brief Closes the current network port\n\n" "@ingroup Networking") { Net::closePort(); } -DefineConsoleFunction( saveJournal, void, (const char * filename), , "(string filename)" +DefineEngineFunction( saveJournal, void, (const char * filename), , "(string filename)" "Save the journal to the specified file.\n\n" "@ingroup Platform") { Journal::Record(filename); } -DefineConsoleFunction( playJournal, void, (const char * filename), , "(string filename)" +DefineEngineFunction( playJournal, void, (const char * filename), , "(string filename)" "@brief Begin playback of a journal from a specified field.\n\n" "@param filename Name and path of file journal file\n" "@ingroup Platform") @@ -202,7 +202,7 @@ DefineConsoleFunction( playJournal, void, (const char * filename), , "(string fi Journal::Play(filename); } -DefineConsoleFunction( getSimTime, S32, (), , "()" +DefineEngineFunction( getSimTime, S32, (), , "()" "Return the current sim time in milliseconds.\n\n" "@brief Sim time is time since the game started.\n\n" "@ingroup Platform") @@ -210,7 +210,7 @@ DefineConsoleFunction( getSimTime, S32, (), , "()" return Sim::getCurrentTime(); } -DefineConsoleFunction( getRealTime, S32, (), , "()" +DefineEngineFunction( getRealTime, S32, (), , "()" "@brief Return the current real time in milliseconds.\n\n" "Real time is platform defined; typically time since the computer booted.\n\n" "@ingroup Platform") diff --git a/Engine/source/app/net/serverQuery.cpp b/Engine/source/app/net/serverQuery.cpp index 05d31e531..ef3f9daa9 100644 --- a/Engine/source/app/net/serverQuery.cpp +++ b/Engine/source/app/net/serverQuery.cpp @@ -429,7 +429,7 @@ void queryLanServers(U32 port, U8 flags, const char* gameType, const char* missi //----------------------------------------------------------------------------- -DefineConsoleFunction( queryAllServers +DefineEngineFunction( queryAllServers , void, ( U32 lanPort , U32 flags , const char * gameType @@ -455,7 +455,7 @@ DefineConsoleFunction( queryAllServers } -DefineConsoleFunction( queryLanServers +DefineEngineFunction( queryLanServers , void, ( U32 lanPort , U32 flags , const char * gameType @@ -560,7 +560,7 @@ void queryMasterServer(U8 flags, const char* gameType, const char* missionType, processMasterServerQuery( gPingSession ); } -DefineConsoleFunction( queryMasterServer +DefineEngineFunction( queryMasterServer , void, ( U32 flags , const char * gameType , const char * missionType @@ -582,7 +582,7 @@ DefineConsoleFunction( queryMasterServer //----------------------------------------------------------------------------- -DefineConsoleFunction( querySingleServer +DefineEngineFunction( querySingleServer , void, ( const char* addrText, U8 flags ) , (0), "querySingleServer(address, flags);" ) { @@ -668,7 +668,7 @@ void cancelServerQuery() } } -DefineConsoleFunction( cancelServerQuery, void, (), , "cancelServerQuery();" ) +DefineEngineFunction( cancelServerQuery, void, (), , "cancelServerQuery();" ) { cancelServerQuery(); } @@ -696,14 +696,14 @@ void stopServerQuery() } } -DefineConsoleFunction( stopServerQuery, void, (), , "stopServerQuery();" ) +DefineEngineFunction( stopServerQuery, void, (), , "stopServerQuery();" ) { stopServerQuery(); } //----------------------------------------------------------------------------- -DefineConsoleFunction( startHeartbeat, void, (), , "startHeartbeat();" ) +DefineEngineFunction( startHeartbeat, void, (), , "startHeartbeat();" ) { if (validateAuthenticatedServer()) { gHeartbeatSeq++; @@ -711,19 +711,19 @@ DefineConsoleFunction( startHeartbeat, void, (), , "startHeartbeat();" ) } } -DefineConsoleFunction( stopHeartbeat, void, (), , "stopHeartbeat();" ) +DefineEngineFunction( stopHeartbeat, void, (), , "stopHeartbeat();" ) { gHeartbeatSeq++; } //----------------------------------------------------------------------------- -DefineConsoleFunction( getServerCount, int, (), , "getServerCount();" ) +DefineEngineFunction( getServerCount, int, (), , "getServerCount();" ) { return gServerList.size(); } -DefineConsoleFunction( setServerInfo, bool, (U32 index), , "setServerInfo(index);" ) +DefineEngineFunction( setServerInfo, bool, (U32 index), , "setServerInfo(index);" ) { if (index < gServerList.size()) { ServerInfo& info = gServerList[index]; diff --git a/Engine/source/app/version.cpp b/Engine/source/app/version.cpp index bced8730a..7a26adb3d 100644 --- a/Engine/source/app/version.cpp +++ b/Engine/source/app/version.cpp @@ -92,44 +92,44 @@ const char* getCompileTimeString() ConsoleFunctionGroupBegin( CompileInformation, "Functions to get version information about the current executable." ); -DefineConsoleFunction( getVersionNumber, S32, (), , "Get the version of the engine build, as a string.\n\n" +DefineEngineFunction( getVersionNumber, S32, (), , "Get the version of the engine build, as a string.\n\n" "@ingroup Debugging") { return getVersionNumber(); } -DefineConsoleFunction( getAppVersionNumber, S32, (), , "Get the version of the application build, as a string.\n\n" +DefineEngineFunction( getAppVersionNumber, S32, (), , "Get the version of the application build, as a string.\n\n" "@ingroup Debugging") { return getAppVersionNumber(); } -DefineConsoleFunction( getVersionString, const char*, (), , "Get the version of the engine build, as a human readable string.\n\n" +DefineEngineFunction( getVersionString, const char*, (), , "Get the version of the engine build, as a human readable string.\n\n" "@ingroup Debugging") { return getVersionString(); } -DefineConsoleFunction( getAppVersionString, const char*, (), , "Get the version of the aplication build, as a human readable string.\n\n" +DefineEngineFunction( getAppVersionString, const char*, (), , "Get the version of the aplication build, as a human readable string.\n\n" "@ingroup Debugging") { return getAppVersionString(); } -DefineConsoleFunction( getEngineName, const char*, (), , "Get the name of the engine product that this is running from, as a string.\n\n" +DefineEngineFunction( getEngineName, const char*, (), , "Get the name of the engine product that this is running from, as a string.\n\n" "@ingroup Debugging") { return getEngineProductString(); } -DefineConsoleFunction( getCompileTimeString, const char*, (), , "Get the time of compilation.\n\n" +DefineEngineFunction( getCompileTimeString, const char*, (), , "Get the time of compilation.\n\n" "@ingroup Debugging") { return getCompileTimeString(); } -DefineConsoleFunction( getBuildString, const char*, (), , "Get the type of build, \"Debug\" or \"Release\".\n\n" +DefineEngineFunction( getBuildString, const char*, (), , "Get the type of build, \"Debug\" or \"Release\".\n\n" "@ingroup Debugging") { #ifdef TORQUE_DEBUG diff --git a/Engine/source/assets/assetQuery_ScriptBinding.h b/Engine/source/assets/assetQuery_ScriptBinding.h index 3324054e1..1656d2eb3 100644 --- a/Engine/source/assets/assetQuery_ScriptBinding.h +++ b/Engine/source/assets/assetQuery_ScriptBinding.h @@ -26,7 +26,7 @@ #include "console/engineAPI.h" -DefineConsoleMethod(AssetQuery, clear, void, (),,"Clears all asset Id results." +DefineEngineMethod(AssetQuery, clear, void, (),,"Clears all asset Id results." "Clears all asset Id results.\n" "@return () No return value.\n") { @@ -36,7 +36,7 @@ DefineConsoleMethod(AssetQuery, clear, void, (),,"Clears all asset Id results." //----------------------------------------------------------------------------- -DefineConsoleMethod(AssetQuery, set, bool, (S32 queryId), , +DefineEngineMethod(AssetQuery, set, bool, (S32 queryId), , "Sets the asset query to a copy of the specified asset query.\n" "@param assetQuery The asset query to copy.\n" "@return Whether the operation succeeded or not.\n") diff --git a/Engine/source/cinterface/cinterface.cpp b/Engine/source/cinterface/cinterface.cpp index aa0fae035..0820b3cf8 100644 --- a/Engine/source/cinterface/cinterface.cpp +++ b/Engine/source/cinterface/cinterface.cpp @@ -436,7 +436,7 @@ extern "C" { // By default, it is marked as secure by the web plugins and then can be called from // Javascript on the web page to ensure that function calls across the language // boundry are working with arguments and return values -DefineConsoleFunction( testJavaScriptBridge, const char *, (const char* arg1, const char* arg2, const char* arg3), , "testBridge(arg1, arg2, arg3)") +DefineEngineFunction( testJavaScriptBridge, const char *, (const char* arg1, const char* arg2, const char* arg3), , "testBridge(arg1, arg2, arg3)") { S32 failed = 0; if (dStrcmp(arg1,"one")) diff --git a/Engine/source/console/console.cpp b/Engine/source/console/console.cpp index dc7dde340..55880f30f 100644 --- a/Engine/source/console/console.cpp +++ b/Engine/source/console/console.cpp @@ -277,7 +277,7 @@ bool useTimestamp = false; ConsoleFunctionGroupBegin( Clipboard, "Miscellaneous functions to control the clipboard and clear the console."); -DefineConsoleFunction( cls, void, (), , "()" +DefineEngineFunction( cls, void, (), , "()" "@brief Clears the console output.\n\n" "@ingroup Console") { @@ -287,14 +287,14 @@ DefineConsoleFunction( cls, void, (), , "()" consoleLog.setSize(0); }; -DefineConsoleFunction( getClipboard, const char*, (), , "()" +DefineEngineFunction( getClipboard, const char*, (), , "()" "@brief Get text from the clipboard.\n\n" "@internal") { return Platform::getClipboard(); }; -DefineConsoleFunction( setClipboard, bool, (const char* text), , "(string text)" +DefineEngineFunction( setClipboard, bool, (const char* text), , "(string text)" "@brief Set the system clipboard.\n\n" "@internal") { diff --git a/Engine/source/console/consoleDoc.cpp b/Engine/source/console/consoleDoc.cpp index f4b74402b..59ea543a1 100644 --- a/Engine/source/console/consoleDoc.cpp +++ b/Engine/source/console/consoleDoc.cpp @@ -41,7 +41,7 @@ ConsoleFunctionGroupBegin(ConsoleDoc, "Console self-documentation functions. These output psuedo C++ suitable for feeeding through Doxygen or another auto documentation tool."); -DefineConsoleFunction( dumpConsoleClasses, void, (bool dumpScript, bool dumpEngine), ( true, true ), +DefineEngineFunction( dumpConsoleClasses, void, (bool dumpScript, bool dumpEngine), ( true, true ), "@brief Dumps all declared console classes to the console.\n\n" "@param dumpScript Optional parameter specifying whether or not classes defined in script should be dumped.\n" "@param dumpEngine Optional parameter specifying whether or not classes defined in the engine should be dumped.\n" @@ -50,7 +50,7 @@ DefineConsoleFunction( dumpConsoleClasses, void, (bool dumpScript, bool dumpEngi Namespace::dumpClasses( dumpScript, dumpEngine ); } -DefineConsoleFunction(dumpConsoleFunctions, void, ( bool dumpScript, bool dumpEngine ), ( true, true ), +DefineEngineFunction(dumpConsoleFunctions, void, ( bool dumpScript, bool dumpEngine ), ( true, true ), "@brief Dumps all declared console functions to the console.\n" "@param dumpScript Optional parameter specifying whether or not functions defined in script should be dumped.\n" "@param dumpEngine Optional parameter specitying whether or not functions defined in the engine should be dumped.\n" diff --git a/Engine/source/console/consoleFunctions.cpp b/Engine/source/console/consoleFunctions.cpp index d32b30d31..258f7911f 100644 --- a/Engine/source/console/consoleFunctions.cpp +++ b/Engine/source/console/consoleFunctions.cpp @@ -184,7 +184,7 @@ bool isValidPort(U16 port) //----------------------------------------------------------------------------- -DefineConsoleFunction( strasc, int, ( const char* chr ),, +DefineEngineFunction( strasc, int, ( const char* chr ),, "Return the integer character code value corresponding to the first character in the given string.\n" "@param chr a (one-character) string.\n" "@return the UTF32 code value for the first character in the given string.\n" @@ -195,7 +195,7 @@ DefineConsoleFunction( strasc, int, ( const char* chr ),, //----------------------------------------------------------------------------- -DefineConsoleFunction( strformat, const char*, ( const char* format, const char* value ),, +DefineEngineFunction( strformat, const char*, ( const char* format, const char* value ),, "Format the given value as a string using printf-style formatting.\n" "@param format A printf-style format string.\n" "@param value The value argument matching the given format string.\n\n" @@ -252,7 +252,7 @@ DefineConsoleFunction( strformat, const char*, ( const char* format, const char* //----------------------------------------------------------------------------- -DefineConsoleFunction( strcmp, S32, ( const char* str1, const char* str2 ),, +DefineEngineFunction( strcmp, S32, ( const char* str1, const char* str2 ),, "Compares two strings using case-sensitive comparison.\n" "@param str1 The first string.\n" "@param str2 The second string.\n" @@ -271,7 +271,7 @@ DefineConsoleFunction( strcmp, S32, ( const char* str1, const char* str2 ),, //----------------------------------------------------------------------------- -DefineConsoleFunction( stricmp, S32, ( const char* str1, const char* str2 ),, +DefineEngineFunction( stricmp, S32, ( const char* str1, const char* str2 ),, "Compares two strings using case-insensitive comparison.\n" "@param str1 The first string.\n" "@param str2 The second string.\n" @@ -290,7 +290,7 @@ DefineConsoleFunction( stricmp, S32, ( const char* str1, const char* str2 ),, //----------------------------------------------------------------------------- -DefineConsoleFunction( strnatcmp, S32, ( const char* str1, const char* str2 ),, +DefineEngineFunction( strnatcmp, S32, ( const char* str1, const char* str2 ),, "Compares two strings using \"natural order\" case-sensitive comparison.\n" "Natural order means that rather than solely comparing single character code values, strings are ordered in a " "natural way. For example, the string \"hello10\" is considered greater than the string \"hello2\" even though " @@ -325,7 +325,7 @@ DefineConsoleFunction( strnatcmp, S32, ( const char* str1, const char* str2 ),, //----------------------------------------------------------------------------- -DefineConsoleFunction( strinatcmp, S32, ( const char* str1, const char* str2 ),, +DefineEngineFunction( strinatcmp, S32, ( const char* str1, const char* str2 ),, "Compares two strings using \"natural order\" case-insensitive comparison.\n" "Natural order means that rather than solely comparing single character code values, strings are ordered in a " "natural way. For example, the string \"hello10\" is considered greater than the string \"hello2\" even though " @@ -360,7 +360,7 @@ DefineConsoleFunction( strinatcmp, S32, ( const char* str1, const char* str2 ),, //----------------------------------------------------------------------------- -DefineConsoleFunction( strlen, S32, ( const char* str ),, +DefineEngineFunction( strlen, S32, ( const char* str ),, "Get the length of the given string in bytes.\n" "@note This does not return a true character count for strings with multi-byte characters!\n" "@param str A string.\n" @@ -371,7 +371,7 @@ DefineConsoleFunction( strlen, S32, ( const char* str ),, } //----------------------------------------------------------------------------- -DefineConsoleFunction( strlenskip, S32, ( const char* str, const char* first, const char* last ),, +DefineEngineFunction( strlenskip, S32, ( const char* str, const char* first, const char* last ),, "Calculate the length of a string in characters, skipping everything between and including first and last.\n" "@param str A string.\n" "@param first First character to look for to skip block of text.\n" @@ -406,7 +406,7 @@ DefineConsoleFunction( strlenskip, S32, ( const char* str, const char* first, co //----------------------------------------------------------------------------- -DefineConsoleFunction( strstr, S32, ( const char* string, const char* substring ),, +DefineEngineFunction( strstr, S32, ( const char* string, const char* substring ),, "Find the start of @a substring in the given @a string searching from left to right.\n" "@param string The string to search.\n" "@param substring The string to search for.\n" @@ -425,7 +425,7 @@ DefineConsoleFunction( strstr, S32, ( const char* string, const char* substring //----------------------------------------------------------------------------- -DefineConsoleFunction( strpos, S32, ( const char* haystack, const char* needle, S32 offset ), ( 0 ), +DefineEngineFunction( strpos, S32, ( const char* haystack, const char* needle, S32 offset ), ( 0 ), "Find the start of @a needle in @a haystack searching from left to right beginning at the given offset.\n" "@param haystack The string to search.\n" "@param needle The string to search for.\n" @@ -450,7 +450,7 @@ DefineConsoleFunction( strpos, S32, ( const char* haystack, const char* needle, //----------------------------------------------------------------------------- -DefineConsoleFunction( strposr, S32, ( const char* haystack, const char* needle, S32 offset ), ( 0 ), +DefineEngineFunction( strposr, S32, ( const char* haystack, const char* needle, S32 offset ), ( 0 ), "Find the start of @a needle in @a haystack searching from right to left beginning at the given offset.\n" "@param haystack The string to search.\n" "@param needle The string to search for.\n" @@ -477,7 +477,7 @@ DefineConsoleFunction( strposr, S32, ( const char* haystack, const char* needle, //----------------------------------------------------------------------------- -DefineConsoleFunction( ltrim, const char*, ( const char* str ),, +DefineEngineFunction( ltrim, const char*, ( const char* str ),, "Remove leading whitespace from the string.\n" "@param str A string.\n" "@return A string that is the same as @a str but with any leading (i.e. leftmost) whitespace removed.\n\n" @@ -496,7 +496,7 @@ DefineConsoleFunction( ltrim, const char*, ( const char* str ),, //----------------------------------------------------------------------------- -DefineConsoleFunction( rtrim, const char*, ( const char* str ),, +DefineEngineFunction( rtrim, const char*, ( const char* str ),, "Remove trailing whitespace from the string.\n" "@param str A string.\n" "@return A string that is the same as @a str but with any trailing (i.e. rightmost) whitespace removed.\n\n" @@ -523,7 +523,7 @@ DefineConsoleFunction( rtrim, const char*, ( const char* str ),, //----------------------------------------------------------------------------- -DefineConsoleFunction( trim, const char*, ( const char* str ),, +DefineEngineFunction( trim, const char*, ( const char* str ),, "Remove leading and trailing whitespace from the string.\n" "@param str A string.\n" "@return A string that is the same as @a str but with any leading (i.e. leftmost) and trailing (i.e. rightmost) whitespace removed.\n\n" @@ -551,7 +551,7 @@ DefineConsoleFunction( trim, const char*, ( const char* str ),, //----------------------------------------------------------------------------- -DefineConsoleFunction( stripChars, const char*, ( const char* str, const char* chars ),, +DefineEngineFunction( stripChars, const char*, ( const char* str, const char* chars ),, "Remove all occurrences of characters contained in @a chars from @a str.\n" "@param str The string to filter characters out from.\n" "@param chars A string of characters to filter out from @a str.\n" @@ -575,7 +575,7 @@ DefineConsoleFunction( stripChars, const char*, ( const char* str, const char* c //----------------------------------------------------------------------------- -DefineConsoleFunction( strlwr, const char*, ( const char* str ),, +DefineEngineFunction( strlwr, const char*, ( const char* str ),, "Return an all lower-case version of the given string.\n" "@param str A string.\n" "@return A version of @a str with all characters converted to lower-case.\n\n" @@ -593,7 +593,7 @@ DefineConsoleFunction( strlwr, const char*, ( const char* str ),, //----------------------------------------------------------------------------- -DefineConsoleFunction( strupr, const char*, ( const char* str ),, +DefineEngineFunction( strupr, const char*, ( const char* str ),, "Return an all upper-case version of the given string.\n" "@param str A string.\n" "@return A version of @a str with all characters converted to upper-case.\n\n" @@ -611,7 +611,7 @@ DefineConsoleFunction( strupr, const char*, ( const char* str ),, //----------------------------------------------------------------------------- -DefineConsoleFunction( strchr, const char*, ( const char* str, const char* chr ),, +DefineEngineFunction( strchr, const char*, ( const char* str, const char* chr ),, "Find the first occurrence of the given character in @a str.\n" "@param str The string to search.\n" "@param chr The character to search for. Only the first character from the string is taken.\n" @@ -625,7 +625,7 @@ DefineConsoleFunction( strchr, const char*, ( const char* str, const char* chr ) //----------------------------------------------------------------------------- -DefineConsoleFunction( strrchr, const char*, ( const char* str, const char* chr ),, +DefineEngineFunction( strrchr, const char*, ( const char* str, const char* chr ),, "Find the last occurrence of the given character in @a str." "@param str The string to search.\n" "@param chr The character to search for. Only the first character from the string is taken.\n" @@ -639,7 +639,7 @@ DefineConsoleFunction( strrchr, const char*, ( const char* str, const char* chr //----------------------------------------------------------------------------- -DefineConsoleFunction( strreplace, const char*, ( const char* source, const char* from, const char* to ),, +DefineEngineFunction( strreplace, const char*, ( const char* source, const char* from, const char* to ),, "Replace all occurrences of @a from in @a source with @a to.\n" "@param source The string in which to replace the occurrences of @a from.\n" "@param from The string to replace in @a source.\n" @@ -690,7 +690,7 @@ DefineConsoleFunction( strreplace, const char*, ( const char* source, const char //----------------------------------------------------------------------------- -DefineConsoleFunction( strrepeat, const char*, ( const char* str, S32 numTimes, const char* delimiter ), ( "" ), +DefineEngineFunction( strrepeat, const char*, ( const char* str, S32 numTimes, const char* delimiter ), ( "" ), "Return a string that repeats @a str @a numTimes number of times delimiting each occurrence with @a delimiter.\n" "@param str The string to repeat multiple times.\n" "@param numTimes The number of times to repeat @a str in the result string.\n" @@ -717,7 +717,7 @@ DefineConsoleFunction( strrepeat, const char*, ( const char* str, S32 numTimes, //----------------------------------------------------------------------------- -DefineConsoleFunction( getSubStr, const char*, ( const char* str, S32 start, S32 numChars ), ( -1 ), +DefineEngineFunction( getSubStr, const char*, ( const char* str, S32 start, S32 numChars ), ( -1 ), "@brief Return a substring of @a str starting at @a start and continuing either through to the end of @a str " "(if @a numChars is -1) or for @a numChars characters (except if this would exceed the actual source " "string length).\n" @@ -758,7 +758,7 @@ DefineConsoleFunction( getSubStr, const char*, ( const char* str, S32 start, S32 //----------------------------------------------------------------------------- -DefineConsoleFunction( strIsMatchExpr, bool, ( const char* pattern, const char* str, bool caseSensitive ), ( false ), +DefineEngineFunction( strIsMatchExpr, bool, ( const char* pattern, const char* str, bool caseSensitive ), ( false ), "Match a pattern against a string.\n" "@param pattern The wildcard pattern to match against. The pattern can include characters, '*' to match " "any number of characters and '?' to match a single character.\n" @@ -777,7 +777,7 @@ DefineConsoleFunction( strIsMatchExpr, bool, ( const char* pattern, const char* //----------------------------------------------------------------------------- -DefineConsoleFunction( strIsMatchMultipleExpr, bool, ( const char* patterns, const char* str, bool caseSensitive ), ( false ), +DefineEngineFunction( strIsMatchMultipleExpr, bool, ( const char* patterns, const char* str, bool caseSensitive ), ( false ), "Match a multiple patterns against a single string.\n" "@param patterns A tab-separated list of patterns. Each pattern can include charaters, '*' to match " "any number of characters and '?' to match a single character. Each of the patterns is tried in turn.\n" @@ -796,7 +796,7 @@ DefineConsoleFunction( strIsMatchMultipleExpr, bool, ( const char* patterns, con //----------------------------------------------------------------------------- -DefineConsoleFunction( getTrailingNumber, S32, ( const char* str ),, +DefineEngineFunction( getTrailingNumber, S32, ( const char* str ),, "Get the numeric suffix of the given input string.\n" "@param str The string from which to read out the numeric suffix.\n" "@return The numeric value of the number suffix of @a str or -1 if @a str has no such suffix.\n\n" @@ -813,7 +813,7 @@ DefineConsoleFunction( getTrailingNumber, S32, ( const char* str ),, //----------------------------------------------------------------------------- -DefineConsoleFunction( stripTrailingNumber, String, ( const char* str ),, +DefineEngineFunction( stripTrailingNumber, String, ( const char* str ),, "Strip a numeric suffix from the given string.\n" "@param str The string from which to strip its numeric suffix.\n" "@return The string @a str without its number suffix or the original string @a str if it has no such suffix.\n\n" @@ -829,7 +829,7 @@ DefineConsoleFunction( stripTrailingNumber, String, ( const char* str ),, //----------------------------------------------------------------------------- -DefineConsoleFunction( getFirstNumber, String, ( const char* str ),, +DefineEngineFunction( getFirstNumber, String, ( const char* str ),, "Get the first occuring number from @a str.\n" "@param str The string from which to read out the first number.\n" "@return String representation of the number or "" if no number.\n\n") @@ -841,7 +841,7 @@ DefineConsoleFunction( getFirstNumber, String, ( const char* str ),, //---------------------------------------------------------------- -DefineConsoleFunction( isspace, bool, ( const char* str, S32 index ),, +DefineEngineFunction( isspace, bool, ( const char* str, S32 index ),, "Test whether the character at the given position is a whitespace character.\n" "Characters such as tab, space, or newline are considered whitespace.\n" "@param str The string to test.\n" @@ -858,7 +858,7 @@ DefineConsoleFunction( isspace, bool, ( const char* str, S32 index ),, //---------------------------------------------------------------- -DefineConsoleFunction( isalnum, bool, ( const char* str, S32 index ),, +DefineEngineFunction( isalnum, bool, ( const char* str, S32 index ),, "Test whether the character at the given position is an alpha-numeric character.\n" "Alpha-numeric characters are characters that are either alphabetic (a-z, A-Z) or numbers (0-9).\n" "@param str The string to test.\n" @@ -875,7 +875,7 @@ DefineConsoleFunction( isalnum, bool, ( const char* str, S32 index ),, //---------------------------------------------------------------- -DefineConsoleFunction( startsWith, bool, ( const char* str, const char* prefix, bool caseSensitive ), ( false ), +DefineEngineFunction( startsWith, bool, ( const char* str, const char* prefix, bool caseSensitive ), ( false ), "Test whether the given string begins with the given prefix.\n" "@param str The string to test.\n" "@param prefix The potential prefix of @a str.\n" @@ -924,7 +924,7 @@ DefineConsoleFunction( startsWith, bool, ( const char* str, const char* prefix, //---------------------------------------------------------------- -DefineConsoleFunction( endsWith, bool, ( const char* str, const char* suffix, bool caseSensitive ), ( false ), +DefineEngineFunction( endsWith, bool, ( const char* str, const char* suffix, bool caseSensitive ), ( false ), "@brief Test whether the given string ends with the given suffix.\n\n" "@param str The string to test.\n" "@param suffix The potential suffix of @a str.\n" @@ -978,7 +978,7 @@ DefineConsoleFunction( endsWith, bool, ( const char* str, const char* suffix, bo //---------------------------------------------------------------- -DefineConsoleFunction( strchrpos, S32, ( const char* str, const char* chr, S32 start ), ( 0 ), +DefineEngineFunction( strchrpos, S32, ( const char* str, const char* chr, S32 start ), ( 0 ), "Find the first occurrence of the given character in the given string.\n" "@param str The string to search.\n" "@param chr The character to look for. Only the first character of this string will be searched for.\n" @@ -998,7 +998,7 @@ DefineConsoleFunction( strchrpos, S32, ( const char* str, const char* chr, S32 s //---------------------------------------------------------------- -DefineConsoleFunction( strrchrpos, S32, ( const char* str, const char* chr, S32 start ), ( 0 ), +DefineEngineFunction( strrchrpos, S32, ( const char* str, const char* chr, S32 start ), ( 0 ), "Find the last occurrence of the given character in the given string.\n" "@param str The string to search.\n" "@param chr The character to look for. Only the first character of this string will be searched for.\n" @@ -1025,7 +1025,7 @@ DefineConsoleFunction( strrchrpos, S32, ( const char* str, const char* chr, S32 //---------------------------------------------------------------- -DefineConsoleFunction(ColorFloatToInt, ColorI, (LinearColorF color), , +DefineEngineFunction(ColorFloatToInt, ColorI, (LinearColorF color), , "Convert from a float color to an integer color (0.0 - 1.0 to 0 to 255).\n" "@param color Float color value to be converted in the form \"R G B A\", where R is red, G is green, B is blue, and A is alpha.\n" "@return Converted color value (0 - 255)\n\n" @@ -1037,7 +1037,7 @@ DefineConsoleFunction(ColorFloatToInt, ColorI, (LinearColorF color), , return color.toColorI(); } -DefineConsoleFunction(ColorIntToFloat, LinearColorF, (ColorI color), , +DefineEngineFunction(ColorIntToFloat, LinearColorF, (ColorI color), , "Convert from a integer color to an float color (0 to 255 to 0.0 - 1.0).\n" "@param color Integer color value to be converted in the form \"R G B A\", where R is red, G is green, B is blue, and A is alpha.\n" "@return Converted color value (0.0 - 1.0)\n\n" @@ -1049,7 +1049,7 @@ DefineConsoleFunction(ColorIntToFloat, LinearColorF, (ColorI color), , return LinearColorF(color); } -DefineConsoleFunction(ColorRGBToHEX, const char*, (ColorI color), , +DefineEngineFunction(ColorRGBToHEX, const char*, (ColorI color), , "Convert from a integer RGB (red, green, blue) color to hex color value (0 to 255 to 00 - FF).\n" "@param color Integer color value to be converted in the form \"R G B A\", where R is red, G is green, B is blue, and A is alpha. It excepts an alpha, but keep in mind this will not be converted.\n" "@return Hex color value (#000000 - #FFFFFF), alpha isn't handled/converted so it is only the RGB value\n\n" @@ -1061,7 +1061,7 @@ DefineConsoleFunction(ColorRGBToHEX, const char*, (ColorI color), , return Con::getReturnBuffer(color.getHex()); } -DefineConsoleFunction(ColorRGBToHSB, const char*, (ColorI color), , +DefineEngineFunction(ColorRGBToHSB, const char*, (ColorI color), , "Convert from a integer RGB (red, green, blue) color to HSB (hue, saturation, brightness). HSB is also know as HSL or HSV as well, with the last letter standing for lightness or value.\n" "@param color Integer color value to be converted in the form \"R G B A\", where R is red, G is green, B is blue, and A is alpha. It excepts an alpha, but keep in mind this will not be converted.\n" "@return HSB color value, alpha isn't handled/converted so it is only the RGB value\n\n" @@ -1075,7 +1075,7 @@ DefineConsoleFunction(ColorRGBToHSB, const char*, (ColorI color), , return Con::getReturnBuffer(s); } -DefineConsoleFunction(ColorHEXToRGB, ColorI, (const char* hex), , +DefineEngineFunction(ColorHEXToRGB, ColorI, (const char* hex), , "Convert from a hex color value to an integer RGB (red, green, blue) color (00 - FF to 0 to 255).\n" "@param hex Hex color value (#000000 - #FFFFFF) to be converted to an RGB (red, green, blue) value.\n" "@return Integer color value to be converted in the form \"R G B A\", where R is red, G is green, B is blue, and A is alpha. Alpha isn't handled/converted so only pay attention to the RGB value\n\n" @@ -1089,7 +1089,7 @@ DefineConsoleFunction(ColorHEXToRGB, ColorI, (const char* hex), , return color; } -DefineConsoleFunction(ColorHSBToRGB, ColorI, (Point3I hsb), , +DefineEngineFunction(ColorHSBToRGB, ColorI, (Point3I hsb), , "Convert from a HSB (hue, saturation, brightness) to an integer RGB (red, green, blue) color. HSB is also know as HSL or HSV as well, with the last letter standing for lightness or value.\n" "@param hsb HSB (hue, saturation, brightness) value to be converted.\n" "@return Integer color value to be converted in the form \"R G B A\", where R is red, G is green, B is blue, and A is alpha. Alpha isn't handled/converted so only pay attention to the RGB value\n\n" @@ -1105,7 +1105,7 @@ DefineConsoleFunction(ColorHSBToRGB, ColorI, (Point3I hsb), , //---------------------------------------------------------------- -DefineConsoleFunction( strToggleCaseToWords, const char*, ( const char* str ),, +DefineEngineFunction( strToggleCaseToWords, const char*, ( const char* str ),, "Parse a Toggle Case word into separate words.\n" "@param str The string to parse.\n" "@return new string space separated.\n\n" @@ -1130,7 +1130,7 @@ DefineConsoleFunction( strToggleCaseToWords, const char*, ( const char* str ),, //---------------------------------------------------------------- // Warning: isInt and isFloat are very 'strict' and might need to be adjusted to allow other values. //seanmc -DefineConsoleFunction( isInt, bool, ( const char* str),, +DefineEngineFunction( isInt, bool, ( const char* str),, "Returns true if the string is an integer.\n" "@param str The string to test.\n" "@return true if @a str is an integer and false if not\n\n" @@ -1144,7 +1144,7 @@ DefineConsoleFunction( isInt, bool, ( const char* str),, //---------------------------------------------------------------- -DefineConsoleFunction( isFloat, bool, ( const char* str, bool sciOk), (false), +DefineEngineFunction( isFloat, bool, ( const char* str, bool sciOk), (false), "Returns true if the string is a float.\n" "@param str The string to test.\n" "@param sciOk Test for correct scientific notation and accept it (ex. 1.2e+14)" @@ -1159,7 +1159,7 @@ DefineConsoleFunction( isFloat, bool, ( const char* str, bool sciOk), (false), //---------------------------------------------------------------- -DefineConsoleFunction( isValidPort, bool, ( const char* str),, +DefineEngineFunction( isValidPort, bool, ( const char* str),, "Returns true if the string is a valid port number.\n" "@param str The string to test.\n" "@return true if @a str is a port and false if not\n\n" @@ -1179,7 +1179,7 @@ DefineConsoleFunction( isValidPort, bool, ( const char* str),, //---------------------------------------------------------------- -DefineConsoleFunction( isValidIP, bool, ( const char* str),, +DefineEngineFunction( isValidIP, bool, ( const char* str),, "Returns true if the string is a valid ip address, excepts localhost.\n" "@param str The string to test.\n" "@return true if @a str is a valid ip address and false if not\n\n" @@ -1214,7 +1214,7 @@ ConsoleFunction(addCaseSensitiveStrings,void,2,0,"[string1, string2, ...]" //----------------------------------------------------------------------------- -DefineConsoleFunction( getWord, const char*, ( const char* text, S32 index ),, +DefineEngineFunction( getWord, const char*, ( const char* text, S32 index ),, "Extract the word at the given @a index in the whitespace-separated list in @a text.\n" "Words in @a text must be separated by newlines, spaces, and/or tabs.\n" "@param text A whitespace-separated list of words.\n" @@ -1235,7 +1235,7 @@ DefineConsoleFunction( getWord, const char*, ( const char* text, S32 index ),, //----------------------------------------------------------------------------- -DefineConsoleFunction( getWords, const char*, ( const char* text, S32 startIndex, S32 endIndex ), ( -1 ), +DefineEngineFunction( getWords, const char*, ( const char* text, S32 startIndex, S32 endIndex ), ( -1 ), "Extract a range of words from the given @a startIndex onwards thru @a endIndex.\n" "Words in @a text must be separated by newlines, spaces, and/or tabs.\n" "@param text A whitespace-separated list of words.\n" @@ -1262,7 +1262,7 @@ DefineConsoleFunction( getWords, const char*, ( const char* text, S32 startIndex //----------------------------------------------------------------------------- -DefineConsoleFunction( setWord, const char*, ( const char* text, S32 index, const char* replacement ),, +DefineEngineFunction( setWord, const char*, ( const char* text, S32 index, const char* replacement ),, "Replace the word in @a text at the given @a index with @a replacement.\n" "Words in @a text must be separated by newlines, spaces, and/or tabs.\n" "@param text A whitespace-separated list of words.\n" @@ -1284,7 +1284,7 @@ DefineConsoleFunction( setWord, const char*, ( const char* text, S32 index, cons //----------------------------------------------------------------------------- -DefineConsoleFunction( removeWord, const char*, ( const char* text, S32 index ),, +DefineEngineFunction( removeWord, const char*, ( const char* text, S32 index ),, "Remove the word in @a text at the given @a index.\n" "Words in @a text must be separated by newlines, spaces, and/or tabs.\n" "@param text A whitespace-separated list of words.\n" @@ -1304,7 +1304,7 @@ DefineConsoleFunction( removeWord, const char*, ( const char* text, S32 index ), //----------------------------------------------------------------------------- -DefineConsoleFunction( getWordCount, S32, ( const char* text ),, +DefineEngineFunction( getWordCount, S32, ( const char* text ),, "Return the number of whitespace-separated words in @a text.\n" "Words in @a text must be separated by newlines, spaces, and/or tabs.\n" "@param text A whitespace-separated list of words.\n" @@ -1365,7 +1365,7 @@ DefineEngineFunction( weekdayNumToStr, String, ( S32 num, bool abbreviate ), (fa //----------------------------------------------------------------------------- -DefineConsoleFunction( getField, const char*, ( const char* text, S32 index ),, +DefineEngineFunction( getField, const char*, ( const char* text, S32 index ),, "Extract the field at the given @a index in the newline and/or tab separated list in @a text.\n" "Fields in @a text must be separated by newlines and/or tabs.\n" "@param text A list of fields separated by newlines and/or tabs.\n" @@ -1385,7 +1385,7 @@ DefineConsoleFunction( getField, const char*, ( const char* text, S32 index ),, //----------------------------------------------------------------------------- -DefineConsoleFunction( getFields, const char*, ( const char* text, S32 startIndex, S32 endIndex ), ( -1 ), +DefineEngineFunction( getFields, const char*, ( const char* text, S32 startIndex, S32 endIndex ), ( -1 ), "Extract a range of fields from the given @a startIndex onwards thru @a endIndex.\n" "Fields in @a text must be separated by newlines and/or tabs.\n" "@param text A list of fields separated by newlines and/or tabs.\n" @@ -1411,7 +1411,7 @@ DefineConsoleFunction( getFields, const char*, ( const char* text, S32 startInde //----------------------------------------------------------------------------- -DefineConsoleFunction( setField, const char*, ( const char* text, S32 index, const char* replacement ),, +DefineEngineFunction( setField, const char*, ( const char* text, S32 index, const char* replacement ),, "Replace the field in @a text at the given @a index with @a replacement.\n" "Fields in @a text must be separated by newlines and/or tabs.\n" "@param text A list of fields separated by newlines and/or tabs.\n" @@ -1432,7 +1432,7 @@ DefineConsoleFunction( setField, const char*, ( const char* text, S32 index, con //----------------------------------------------------------------------------- -DefineConsoleFunction( removeField, const char*, ( const char* text, S32 index ),, +DefineEngineFunction( removeField, const char*, ( const char* text, S32 index ),, "Remove the field in @a text at the given @a index.\n" "Fields in @a text must be separated by newlines and/or tabs.\n" "@param text A list of fields separated by newlines and/or tabs.\n" @@ -1451,7 +1451,7 @@ DefineConsoleFunction( removeField, const char*, ( const char* text, S32 index ) //----------------------------------------------------------------------------- -DefineConsoleFunction( getFieldCount, S32, ( const char* text ),, +DefineEngineFunction( getFieldCount, S32, ( const char* text ),, "Return the number of newline and/or tab separated fields in @a text.\n" "@param text A list of fields separated by newlines and/or tabs.\n" "@return The number of newline and/or tab sepearated elements in @a text.\n\n" @@ -1467,7 +1467,7 @@ DefineConsoleFunction( getFieldCount, S32, ( const char* text ),, //----------------------------------------------------------------------------- -DefineConsoleFunction( getRecord, const char*, ( const char* text, S32 index ),, +DefineEngineFunction( getRecord, const char*, ( const char* text, S32 index ),, "Extract the record at the given @a index in the newline-separated list in @a text.\n" "Records in @a text must be separated by newlines.\n" "@param text A list of records separated by newlines.\n" @@ -1487,7 +1487,7 @@ DefineConsoleFunction( getRecord, const char*, ( const char* text, S32 index ),, //----------------------------------------------------------------------------- -DefineConsoleFunction( getRecords, const char*, ( const char* text, S32 startIndex, S32 endIndex ), ( -1 ), +DefineEngineFunction( getRecords, const char*, ( const char* text, S32 startIndex, S32 endIndex ), ( -1 ), "Extract a range of records from the given @a startIndex onwards thru @a endIndex.\n" "Records in @a text must be separated by newlines.\n" "@param text A list of records separated by newlines.\n" @@ -1513,7 +1513,7 @@ DefineConsoleFunction( getRecords, const char*, ( const char* text, S32 startInd //----------------------------------------------------------------------------- -DefineConsoleFunction( setRecord, const char*, ( const char* text, S32 index, const char* replacement ),, +DefineEngineFunction( setRecord, const char*, ( const char* text, S32 index, const char* replacement ),, "Replace the record in @a text at the given @a index with @a replacement.\n" "Records in @a text must be separated by newlines.\n" "@param text A list of records separated by newlines.\n" @@ -1534,7 +1534,7 @@ DefineConsoleFunction( setRecord, const char*, ( const char* text, S32 index, co //----------------------------------------------------------------------------- -DefineConsoleFunction( removeRecord, const char*, ( const char* text, S32 index ),, +DefineEngineFunction( removeRecord, const char*, ( const char* text, S32 index ),, "Remove the record in @a text at the given @a index.\n" "Records in @a text must be separated by newlines.\n" "@param text A list of records separated by newlines.\n" @@ -1553,7 +1553,7 @@ DefineConsoleFunction( removeRecord, const char*, ( const char* text, S32 index //----------------------------------------------------------------------------- -DefineConsoleFunction( getRecordCount, S32, ( const char* text ),, +DefineEngineFunction( getRecordCount, S32, ( const char* text ),, "Return the number of newline-separated records in @a text.\n" "@param text A list of records separated by newlines.\n" "@return The number of newline-sepearated elements in @a text.\n\n" @@ -1569,7 +1569,7 @@ DefineConsoleFunction( getRecordCount, S32, ( const char* text ),, //----------------------------------------------------------------------------- -DefineConsoleFunction( firstWord, const char*, ( const char* text ),, +DefineEngineFunction( firstWord, const char*, ( const char* text ),, "Return the first word in @a text.\n" "@param text A list of words separated by newlines, spaces, and/or tabs.\n" "@return The word at index 0 in @a text or \"\" if @a text is empty.\n\n" @@ -1585,7 +1585,7 @@ DefineConsoleFunction( firstWord, const char*, ( const char* text ),, //----------------------------------------------------------------------------- -DefineConsoleFunction( restWords, const char*, ( const char* text ),, +DefineEngineFunction( restWords, const char*, ( const char* text ),, "Return all but the first word in @a text.\n" "@param text A list of words separated by newlines, spaces, and/or tabs.\n" "@return @a text with the first word removed.\n\n" @@ -1619,7 +1619,7 @@ static bool isInSet(char c, const char *set) return false; } -DefineConsoleFunction( nextToken, const char*, ( const char* str1, const char* token, const char* delim), , "( string str, string token, string delimiters ) " +DefineEngineFunction( nextToken, const char*, ( const char* str1, const char* token, const char* delim), , "( string str, string token, string delimiters ) " "Tokenize a string using a set of delimiting characters.\n" "This function first skips all leading charaters in @a str that are contained in @a delimiters. " "From that position, it then scans for the next character in @a str that is contained in @a delimiters and stores all characters " @@ -1688,7 +1688,7 @@ DefineConsoleFunction( nextToken, const char*, ( const char* str1, const char* t //----------------------------------------------------------------------------- -DefineConsoleFunction( getToken, const char*, ( const char* text, const char* delimiters, S32 index ),, +DefineEngineFunction( getToken, const char*, ( const char* text, const char* delimiters, S32 index ),, "Extract the substring at the given @a index in the @a delimiters separated list in @a text.\n" "@param text A @a delimiters list of substrings.\n" "@param delimiters Character or characters that separate the list of substrings in @a text.\n" @@ -1709,7 +1709,7 @@ DefineConsoleFunction( getToken, const char*, ( const char* text, const char* de //----------------------------------------------------------------------------- -DefineConsoleFunction( getTokens, const char*, ( const char* text, const char* delimiters, S32 startIndex, S32 endIndex ), ( -1 ), +DefineEngineFunction( getTokens, const char*, ( const char* text, const char* delimiters, S32 startIndex, S32 endIndex ), ( -1 ), "Extract a range of substrings separated by @a delimiters at the given @a startIndex onwards thru @a endIndex.\n" "@param text A @a delimiters list of substrings.\n" "@param delimiters Character or characters that separate the list of substrings in @a text.\n" @@ -1736,7 +1736,7 @@ DefineConsoleFunction( getTokens, const char*, ( const char* text, const char* d //----------------------------------------------------------------------------- -DefineConsoleFunction( setToken, const char*, ( const char* text, const char* delimiters, S32 index, const char* replacement ),, +DefineEngineFunction( setToken, const char*, ( const char* text, const char* delimiters, S32 index, const char* replacement ),, "Replace the substring in @a text separated by @a delimiters at the given @a index with @a replacement.\n" "@param text A @a delimiters list of substrings.\n" "@param delimiters Character or characters that separate the list of substrings in @a text.\n" @@ -1758,7 +1758,7 @@ DefineConsoleFunction( setToken, const char*, ( const char* text, const char* de //----------------------------------------------------------------------------- -DefineConsoleFunction( removeToken, const char*, ( const char* text, const char* delimiters, S32 index ),, +DefineEngineFunction( removeToken, const char*, ( const char* text, const char* delimiters, S32 index ),, "Remove the substring in @a text separated by @a delimiters at the given @a index.\n" "@param text A @a delimiters list of substrings.\n" "@param delimiters Character or characters that separate the list of substrings in @a text.\n" @@ -1778,7 +1778,7 @@ DefineConsoleFunction( removeToken, const char*, ( const char* text, const char* //----------------------------------------------------------------------------- -DefineConsoleFunction( getTokenCount, S32, ( const char* text, const char* delimiters),, +DefineEngineFunction( getTokenCount, S32, ( const char* text, const char* delimiters),, "Return the number of @a delimiters substrings in @a text.\n" "@param text A @a delimiters list of substrings.\n" "@param delimiters Character or characters that separate the list of substrings in @a text.\n" @@ -1837,7 +1837,7 @@ DefineEngineFunction( detag, const char*, ( const char* str ),, return str; } -DefineConsoleFunction( getTag, const char*, ( const char* textTagString ), , "( string textTagString ) " +DefineEngineFunction( getTag, const char*, ( const char* textTagString ), , "( string textTagString ) " "@brief Extracts the tag from a tagged string\n\n" "Should only be used within the context of a function that receives a tagged " @@ -1968,7 +1968,7 @@ DefineEngineFunction( debugv, void, ( const char* variableName ),, //----------------------------------------------------------------------------- -DefineConsoleFunction( expandEscape, const char*, ( const char* text ),, +DefineEngineFunction( expandEscape, const char*, ( const char* text ),, "@brief Replace all characters in @a text that need to be escaped for the string to be a valid string literal with their " "respective escape sequences.\n\n" "All characters in @a text that cannot appear in a string literal will be replaced by an escape sequence (\\\\n, \\\\t, etc).\n\n" @@ -1990,7 +1990,7 @@ DefineConsoleFunction( expandEscape, const char*, ( const char* text ),, //----------------------------------------------------------------------------- -DefineConsoleFunction( collapseEscape, const char*, ( const char* text ),, +DefineEngineFunction( collapseEscape, const char*, ( const char* text ),, "Replace all escape sequences in @a text with their respective character codes.\n\n" "This function replaces all escape sequences (\\\\n, \\\\t, etc) in the given string " "with the respective characters they represent.\n\n" @@ -2046,7 +2046,7 @@ DefineEngineFunction( setLogMode, void, ( S32 mode ),, //----------------------------------------------------------------------------- -DefineConsoleFunction( quit, void, ( ),, +DefineEngineFunction( quit, void, ( ),, "Shut down the engine and exit its process.\n" "This function cleanly uninitializes the engine and then exits back to the system with a process " "exit status indicating a clean exit.\n\n" @@ -2059,7 +2059,7 @@ DefineConsoleFunction( quit, void, ( ),, //----------------------------------------------------------------------------- -DefineConsoleFunction( realQuit, void, (), , "") +DefineEngineFunction( realQuit, void, (), , "") { Platform::postQuitMessage(0); } @@ -2067,7 +2067,7 @@ DefineConsoleFunction( realQuit, void, (), , "") //----------------------------------------------------------------------------- -DefineConsoleFunction( quitWithErrorMessage, void, ( const char* message, S32 status ), (0), +DefineEngineFunction( quitWithErrorMessage, void, ( const char* message, S32 status ), (0), "Display an error message box showing the given @a message and then shut down the engine and exit its process.\n" "This function cleanly uninitialized the engine and then exits back to the system with a process " "exit status indicating an error.\n\n" @@ -2088,7 +2088,7 @@ DefineConsoleFunction( quitWithErrorMessage, void, ( const char* message, S32 st //----------------------------------------------------------------------------- -DefineConsoleFunction( quitWithStatus, void, ( S32 status ), (0), +DefineEngineFunction( quitWithStatus, void, ( S32 status ), (0), "Shut down the engine and exit its process.\n" "This function cleanly uninitializes the engine and then exits back to the system with a given " "return status code.\n\n" @@ -2259,7 +2259,7 @@ ConsoleFunction( call, const char *, 2, 0, "( string functionName, string args.. static U32 execDepth = 0; static U32 journalDepth = 1; -DefineConsoleFunction( getDSOPath, const char*, ( const char* scriptFileName ),, +DefineEngineFunction( getDSOPath, const char*, ( const char* scriptFileName ),, "Get the absolute path to the file in which the compiled code for the given script file will be stored.\n" "@param scriptFileName %Path to the .cs script file.\n" "@return The absolute path to the .dso file for the given script file.\n\n" @@ -2373,12 +2373,12 @@ DefineEngineFunction( exec, bool, ( const char* fileName, bool noCalls, bool jou return Con::executeFile(fileName, noCalls, journalScript); } -DefineConsoleFunction( eval, const char*, ( const char* consoleString ), , "eval(consoleString)" ) +DefineEngineFunction( eval, const char*, ( const char* consoleString ), , "eval(consoleString)" ) { return Con::evaluate(consoleString, false, NULL); } -DefineConsoleFunction( getVariable, const char*, ( const char* varName ), , "(string varName)\n" +DefineEngineFunction( getVariable, const char*, ( const char* varName ), , "(string varName)\n" "@brief Returns the value of the named variable or an empty string if not found.\n\n" "@varName Name of the variable to search for\n" "@return Value contained by varName, \"\" if the variable does not exist\n" @@ -2387,7 +2387,7 @@ DefineConsoleFunction( getVariable, const char*, ( const char* varName ), , "(st return Con::getVariable(varName); } -DefineConsoleFunction( setVariable, void, ( const char* varName, const char* value ), , "(string varName, string value)\n" +DefineEngineFunction( setVariable, void, ( const char* varName, const char* value ), , "(string varName, string value)\n" "@brief Sets the value of the named variable.\n\n" "@param varName Name of the variable to locate\n" "@param value New value of the variable\n" @@ -2397,7 +2397,7 @@ DefineConsoleFunction( setVariable, void, ( const char* varName, const char* val return Con::setVariable(varName, value); } -DefineConsoleFunction( isFunction, bool, ( const char* funcName ), , "(string funcName)" +DefineEngineFunction( isFunction, bool, ( const char* funcName ), , "(string funcName)" "@brief Determines if a function exists or not\n\n" "@param funcName String containing name of the function\n" "@return True if the function exists, false if not\n" @@ -2406,7 +2406,7 @@ DefineConsoleFunction( isFunction, bool, ( const char* funcName ), , "(string fu return Con::isFunction(funcName); } -DefineConsoleFunction( getFunctionPackage, const char*, ( const char* funcName ), , "(string funcName)" +DefineEngineFunction( getFunctionPackage, const char*, ( const char* funcName ), , "(string funcName)" "@brief Provides the name of the package the function belongs to\n\n" "@param funcName String containing name of the function\n" "@return The name of the function's package\n" @@ -2419,7 +2419,7 @@ DefineConsoleFunction( getFunctionPackage, const char*, ( const char* funcName ) return nse->mPackage; } -DefineConsoleFunction( isMethod, bool, ( const char* nameSpace, const char* method ), , "(string namespace, string method)" +DefineEngineFunction( isMethod, bool, ( const char* nameSpace, const char* method ), , "(string namespace, string method)" "@brief Determines if a class/namespace method exists\n\n" "@param namespace Class or namespace, such as Player\n" "@param method Name of the function to search for\n" @@ -2434,7 +2434,7 @@ DefineConsoleFunction( isMethod, bool, ( const char* nameSpace, const char* meth return true; } -DefineConsoleFunction( getMethodPackage, const char*, ( const char* nameSpace, const char* method ), , "(string namespace, string method)" +DefineEngineFunction( getMethodPackage, const char*, ( const char* nameSpace, const char* method ), , "(string namespace, string method)" "@brief Provides the name of the package the method belongs to\n\n" "@param namespace Class or namespace, such as Player\n" "@param method Name of the funciton to search for\n" @@ -2452,7 +2452,7 @@ DefineConsoleFunction( getMethodPackage, const char*, ( const char* nameSpace, c return nse->mPackage; } -DefineConsoleFunction( isDefined, bool, ( const char* varName, const char* varValue ), ("") , "(string varName)" +DefineEngineFunction( isDefined, bool, ( const char* varName, const char* varValue ), ("") , "(string varName)" "@brief Determines if a variable exists and contains a value\n" "@param varName Name of the variable to search for\n" "@return True if the variable was defined in script, false if not\n" @@ -2590,14 +2590,14 @@ DefineConsoleFunction( isDefined, bool, ( const char* varName, const char* varVa //----------------------------------------------------------------------------- -DefineConsoleFunction( isCurrentScriptToolScript, bool, (), , "()" +DefineEngineFunction( isCurrentScriptToolScript, bool, (), , "()" "Returns true if the calling script is a tools script.\n" "@hide") { return Con::isCurrentScriptToolScript(); } -DefineConsoleFunction( getModNameFromPath, const char *, ( const char* path ), , "(string path)" +DefineEngineFunction( getModNameFromPath, const char *, ( const char* path ), , "(string path)" "@brief Attempts to extract a mod directory from path. Returns empty string on failure.\n\n" "@param File path of mod folder\n" "@note This is no longer relevant in Torque 3D (which does not use mod folders), should be deprecated\n" @@ -2609,7 +2609,7 @@ DefineConsoleFunction( getModNameFromPath, const char *, ( const char* path ), , //----------------------------------------------------------------------------- -DefineConsoleFunction( pushInstantGroup, void, ( String group ),("") , "([group])" +DefineEngineFunction( pushInstantGroup, void, ( String group ),("") , "([group])" "@brief Pushes the current $instantGroup on a stack " "and sets it to the given value (or clears it).\n\n" "@note Currently only used for editors\n" @@ -2622,7 +2622,7 @@ DefineConsoleFunction( pushInstantGroup, void, ( String group ),("") , "([group] Con::pushInstantGroup(); } -DefineConsoleFunction( popInstantGroup, void, (), , "()" +DefineEngineFunction( popInstantGroup, void, (), , "()" "@brief Pop and restore the last setting of $instantGroup off the stack.\n\n" "@note Currently only used for editors\n\n" "@ingroup Editors\n" @@ -2633,7 +2633,7 @@ DefineConsoleFunction( popInstantGroup, void, (), , "()" //----------------------------------------------------------------------------- -DefineConsoleFunction( getPrefsPath, const char *, ( const char* relativeFileName ), (""), "([relativeFileName])" +DefineEngineFunction( getPrefsPath, const char *, ( const char* relativeFileName ), (""), "([relativeFileName])" "@note Appears to be useless in Torque 3D, should be deprecated\n" "@internal") { @@ -2670,7 +2670,7 @@ ConsoleFunction( execPrefs, bool, 2, 4, "( string relativeFileName, bool noCalls //----------------------------------------------------------------------------- -DefineConsoleFunction( export, void, ( const char* pattern, const char* filename, bool append ), ( "", false ), +DefineEngineFunction( export, void, ( const char* pattern, const char* filename, bool append ), ( "", false ), "Write out the definitions of all global variables matching the given name @a pattern.\n" "If @a fileName is not \"\", the variable definitions are written to the specified file. Otherwise the " "definitions will be printed to the console.\n\n" @@ -2723,7 +2723,7 @@ DefineEngineFunction( deleteVariables, void, ( const char* pattern ),, //----------------------------------------------------------------------------- -DefineConsoleFunction( trace, void, ( bool enable ), ( true ), +DefineEngineFunction( trace, void, ( bool enable ), ( true ), "Enable or disable tracing in the script code VM.\n\n" "When enabled, the script code runtime will trace the invocation and returns " "from all functions that are called and log them to the console. This is helpful in " @@ -2739,7 +2739,7 @@ DefineConsoleFunction( trace, void, ( bool enable ), ( true ), #if defined(TORQUE_DEBUG) || !defined(TORQUE_SHIPPING) -DefineConsoleFunction( debug, void, (),, +DefineEngineFunction( debug, void, (),, "Drops the engine into the native C++ debugger.\n\n" "This function triggers a debug break and drops the process into the IDE's debugger. If the process is not " "running with a debugger attached it will generate a runtime error on most platforms.\n\n" diff --git a/Engine/source/console/consoleXMLExport.cpp b/Engine/source/console/consoleXMLExport.cpp index 79e302595..e3431acdf 100644 --- a/Engine/source/console/consoleXMLExport.cpp +++ b/Engine/source/console/consoleXMLExport.cpp @@ -314,7 +314,7 @@ namespace Con { }; // namespace Con -DefineConsoleFunction( consoleExportXML, const char*, (), ,"Exports console definition XML representation" ) +DefineEngineFunction( consoleExportXML, const char*, (), ,"Exports console definition XML representation" ) { Con::XMLExport xmlExport; String xml; diff --git a/Engine/source/console/engineAPI.h b/Engine/source/console/engineAPI.h index 049cce54d..2eef409b6 100644 --- a/Engine/source/console/engineAPI.h +++ b/Engine/source/console/engineAPI.h @@ -860,24 +860,6 @@ public: // while being only visible in the console interop. When we drop the console system, // these macros can be removed and all definitions that make use of them can be removed // as well. -#define DefineConsoleFunction( name, returnType, args, defaultArgs, usage ) \ - static inline returnType _fn ## name ## impl args; \ - static _EngineFunctionDefaultArguments< void args > _fn ## name ## DefaultArgs defaultArgs; \ - static _EngineConsoleThunkType< returnType >::ReturnType _ ## name ## caster( SimObject*, S32 argc, ConsoleValueRef *argv ) \ - { \ - return _EngineConsoleThunkType< returnType >::ReturnType( _EngineConsoleThunk< 1, returnType args >::thunk( \ - argc, argv, &_fn ## name ## impl, _fn ## name ## DefaultArgs \ - ) ); \ - } \ - static ConsoleFunctionHeader _ ## name ## header \ - ( #returnType, #args, #defaultArgs ); \ - static ConsoleConstructor \ - _ ## name ## obj( NULL, #name, _EngineConsoleThunkType< returnType >::CallbackType( _ ## name ## caster ), usage, \ - _EngineConsoleThunk< 1, returnType args >::NUM_ARGS - _EngineConsoleThunkCountArgs() defaultArgs, \ - _EngineConsoleThunk< 1, returnType args >::NUM_ARGS, \ - false, &_ ## name ## header \ - ); \ - static inline returnType _fn ## name ## impl args #define DefineConsoleMethod( className, name, returnType, args, defaultArgs, usage ) \ struct _ ## className ## name ## frame \ diff --git a/Engine/source/console/sim.cpp b/Engine/source/console/sim.cpp index cb01e8019..6bb194db3 100644 --- a/Engine/source/console/sim.cpp +++ b/Engine/source/console/sim.cpp @@ -86,7 +86,7 @@ namespace Sim ConsoleFunctionGroupBegin ( SimFunctions, "Functions relating to Sim."); -DefineConsoleFunction( nameToID, S32, (const char * objectName), ,"nameToID(object)") +DefineEngineFunction( nameToID, S32, (const char * objectName), ,"nameToID(object)") { SimObject *obj = Sim::findObject(objectName); if(obj) @@ -95,7 +95,7 @@ DefineConsoleFunction( nameToID, S32, (const char * objectName), ,"nameToID(obje return -1; } -DefineConsoleFunction( isObject, bool, (const char * objectName), ,"isObject(object)") +DefineEngineFunction( isObject, bool, (const char * objectName), ,"isObject(object)") { if (!dStrcmp(objectName, "0") || !dStrcmp(objectName, "")) return false; @@ -133,7 +133,7 @@ ConsoleDocFragment _spawnObject1( "bool spawnObject(class [, dataBlock, name, properties, script]);" ); -DefineConsoleFunction( spawnObject, S32, ( const char * spawnClass +DefineEngineFunction( spawnObject, S32, ( const char * spawnClass , const char * spawnDataBlock , const char * spawnName , const char * spawnProperties @@ -149,33 +149,33 @@ DefineConsoleFunction( spawnObject, S32, ( const char * spawnClass return -1; } -DefineConsoleFunction( cancel, void, (S32 eventId), ,"cancel(eventId)") +DefineEngineFunction( cancel, void, (S32 eventId), ,"cancel(eventId)") { Sim::cancelEvent(eventId); } -DefineConsoleFunction( cancelAll, void, (const char * objectId), ,"cancelAll(objectId): cancel pending events on the specified object. Events will be automatically cancelled if object is deleted.") +DefineEngineFunction( cancelAll, void, (const char * objectId), ,"cancelAll(objectId): cancel pending events on the specified object. Events will be automatically cancelled if object is deleted.") { Sim::cancelPendingEvents(Sim::findObject(objectId)); } -DefineConsoleFunction( isEventPending, bool, (S32 scheduleId), ,"isEventPending(%scheduleId);") +DefineEngineFunction( isEventPending, bool, (S32 scheduleId), ,"isEventPending(%scheduleId);") { return Sim::isEventPending(scheduleId); } -DefineConsoleFunction( getEventTimeLeft, S32, (S32 scheduleId), ,"getEventTimeLeft(scheduleId) Get the time left in ms until this event will trigger.") +DefineEngineFunction( getEventTimeLeft, S32, (S32 scheduleId), ,"getEventTimeLeft(scheduleId) Get the time left in ms until this event will trigger.") { return Sim::getEventTimeLeft(scheduleId); } -DefineConsoleFunction( getScheduleDuration, S32, (S32 scheduleId), ,"getScheduleDuration(%scheduleId);" ) +DefineEngineFunction( getScheduleDuration, S32, (S32 scheduleId), ,"getScheduleDuration(%scheduleId);" ) { S32 ret = Sim::getScheduleDuration(scheduleId); return ret; } -DefineConsoleFunction( getTimeSinceStart, S32, (S32 scheduleId), ,"getTimeSinceStart(%scheduleId);" ) +DefineEngineFunction( getTimeSinceStart, S32, (S32 scheduleId), ,"getTimeSinceStart(%scheduleId);" ) { S32 ret = Sim::getTimeSinceStart(scheduleId); return ret; @@ -202,7 +202,7 @@ ConsoleFunction(schedule, S32, 4, 0, "schedule(time, refobject|0, command, isConnected(); } -DefineConsoleFunction( dbgDisconnect, void, (), , "()" +DefineEngineFunction( dbgDisconnect, void, (), , "()" "Forcibly disconnects any attached script debugging client.\n" "@internal Primarily used for Torsion and other debugging tools") { diff --git a/Engine/source/core/dnet.cpp b/Engine/source/core/dnet.cpp index a5fe53f6c..e7d1b6ae0 100644 --- a/Engine/source/core/dnet.cpp +++ b/Engine/source/core/dnet.cpp @@ -50,7 +50,7 @@ static const char *packetTypeNames[] = //----------------------------------------------------------------- //----------------------------------------------------------------- //----------------------------------------------------------------- -DefineConsoleFunction( DNetSetLogging, void, (bool enabled), , "(bool enabled)" +DefineEngineFunction( DNetSetLogging, void, (bool enabled), , "(bool enabled)" "@brief Enables logging of the connection protocols\n\n" "When enabled a lot of network debugging information is sent to the console.\n" "@param enabled True to enable, false to disable\n" diff --git a/Engine/source/core/stringBuffer.cpp b/Engine/source/core/stringBuffer.cpp index 3d15a6183..a55446885 100644 --- a/Engine/source/core/stringBuffer.cpp +++ b/Engine/source/core/stringBuffer.cpp @@ -48,12 +48,12 @@ void dumpAllStrings(); }; - DefineConsoleFunction( sbmDumpStats, void, (), , "()") + DefineEngineFunction( sbmDumpStats, void, (), , "()") { StringBufferManager::getManager().dumpStats(); } - DefineConsoleFunction( sbmDumpStrings, void, (), , "()") + DefineEngineFunction( sbmDumpStrings, void, (), , "()") { StringBufferManager::getManager().dumpAllStrings(); } diff --git a/Engine/source/core/util/str.cpp b/Engine/source/core/util/str.cpp index 63580e2b4..1a15b8b85 100644 --- a/Engine/source/core/util/str.cpp +++ b/Engine/source/core/util/str.cpp @@ -480,7 +480,7 @@ static U32 sgStringInstances; #endif -DefineConsoleFunction( dumpStringMemStats, void, (), , "()" +DefineEngineFunction( dumpStringMemStats, void, (), , "()" "@brief Dumps information about String memory usage\n\n" "@ingroup Debugging\n" "@ingroup Strings\n") diff --git a/Engine/source/environment/VolumetricFogRTManager.cpp b/Engine/source/environment/VolumetricFogRTManager.cpp index 7b7b00d50..9eca811f9 100644 --- a/Engine/source/environment/VolumetricFogRTManager.cpp +++ b/Engine/source/environment/VolumetricFogRTManager.cpp @@ -283,7 +283,7 @@ VolumetricFogRTManager* VolumetricFogRTManager::get() return gVolumetricFogRTManager; } -DefineConsoleFunction(SetFogVolumeQuality, S32, (U32 new_quality), , +DefineEngineFunction(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 ...") { diff --git a/Engine/source/gfx/gfxDevice.cpp b/Engine/source/gfx/gfxDevice.cpp index 28add7718..806cf4baf 100644 --- a/Engine/source/gfx/gfxDevice.cpp +++ b/Engine/source/gfx/gfxDevice.cpp @@ -1333,7 +1333,7 @@ DefineEngineFunction( getBestHDRFormat, GFXFormat, (),, return format; } -DefineConsoleFunction(ResetGFX, void, (), , "forces the gbuffer to be reinitialized in cases of improper/lack of buffer clears.") +DefineEngineFunction(ResetGFX, void, (), , "forces the gbuffer to be reinitialized in cases of improper/lack of buffer clears.") { GFX->beginReset(); } \ No newline at end of file diff --git a/Engine/source/gfx/gl/gfxGLDeviceProfiler.cpp b/Engine/source/gfx/gl/gfxGLDeviceProfiler.cpp index 254141b71..02155a4f1 100644 --- a/Engine/source/gfx/gl/gfxGLDeviceProfiler.cpp +++ b/Engine/source/gfx/gl/gfxGLDeviceProfiler.cpp @@ -86,7 +86,7 @@ protected: GFXProfiler gfxProfiler; -DefineConsoleFunction(printGFXGLTimers, void,(), ,"") +DefineEngineFunction(printGFXGLTimers, void,(), ,"") { gfxProfiler.printTimes(); } diff --git a/Engine/source/i18n/i18n.cpp b/Engine/source/i18n/i18n.cpp index 359c76fa4..1de738abd 100644 --- a/Engine/source/i18n/i18n.cpp +++ b/Engine/source/i18n/i18n.cpp @@ -58,7 +58,7 @@ const UTF8 *getCoreString(S32 id) //----------------------------------------------------------------------------- -DefineConsoleFunction( getCoreLangTable, S32, (), , "()" +DefineEngineFunction( getCoreLangTable, S32, (), , "()" "@brief Gets the primary LangTable used by the game\n\n" "@return ID of the core LangTable\n" "@ingroup Localization") @@ -69,7 +69,7 @@ DefineConsoleFunction( getCoreLangTable, S32, (), , "()" return 0; } -DefineConsoleFunction( setCoreLangTable, void, (const char * lgTable), , "(string LangTable)" +DefineEngineFunction( setCoreLangTable, void, (const char * lgTable), , "(string LangTable)" "@brief Sets the primary LangTable used by the game\n\n" "@param LangTable ID of the core LangTable\n" "@ingroup Localization") diff --git a/Engine/source/lighting/advanced/advancedLightManager.cpp b/Engine/source/lighting/advanced/advancedLightManager.cpp index 3c851cf81..6d251ec58 100644 --- a/Engine/source/lighting/advanced/advancedLightManager.cpp +++ b/Engine/source/lighting/advanced/advancedLightManager.cpp @@ -705,7 +705,7 @@ LightShadowMap* AdvancedLightManager::findShadowMapForObject( SimObject *object return sceneLight->getLight()->getExtended()->getShadowMap(); } -DefineConsoleFunction( setShadowVizLight, const char*, (const char* name), (""), "") +DefineEngineFunction( setShadowVizLight, const char*, (const char* name), (""), "") { static const String DebugTargetName( "AL_ShadowVizTexture" ); diff --git a/Engine/source/lighting/shadowManager.cpp b/Engine/source/lighting/shadowManager.cpp index 68a234c70..288ff54c9 100644 --- a/Engine/source/lighting/shadowManager.cpp +++ b/Engine/source/lighting/shadowManager.cpp @@ -54,7 +54,7 @@ SceneManager* ShadowManager::getSceneManager() //------------------------------------------------------------------------------ // Runtime switching of shadow systems. Requires correct world to be pushed at console. -DefineConsoleFunction( setShadowManager, bool, (const char* sShadowSystemName), (""), "string sShadowSystemName") +DefineEngineFunction( setShadowManager, bool, (const char* sShadowSystemName), (""), "string sShadowSystemName") { /* // Make sure this new one exists diff --git a/Engine/source/materials/materialManager.cpp b/Engine/source/materials/materialManager.cpp index 4b28988b7..0f8519bb5 100644 --- a/Engine/source/materials/materialManager.cpp +++ b/Engine/source/materials/materialManager.cpp @@ -454,14 +454,14 @@ bool MaterialManager::_handleGFXEvent( GFXDevice::GFXDeviceEventType event_ ) return true; } -DefineConsoleFunction( reInitMaterials, void, (),, +DefineEngineFunction( reInitMaterials, void, (),, "@brief Flushes all procedural shaders and re-initializes all active material instances.\n\n" "@ingroup Materials") { MATMGR->flushAndReInitInstances(); } -DefineConsoleFunction( addMaterialMapping, void, (const char * texName, const char * matName), , "(string texName, string matName)\n" +DefineEngineFunction( addMaterialMapping, void, (const char * texName, const char * matName), , "(string texName, string matName)\n" "@brief Maps the given texture to the given material.\n\n" "Generates a console warning before overwriting.\n\n" "Material maps are used by terrain and interiors for triggering " @@ -472,7 +472,7 @@ DefineConsoleFunction( addMaterialMapping, void, (const char * texName, const ch MATMGR->mapMaterial(texName, matName); } -DefineConsoleFunction( getMaterialMapping, const char*, (const char * texName), , "(string texName)\n" +DefineEngineFunction( getMaterialMapping, const char*, (const char * texName), , "(string texName)\n" "@brief Returns the name of the material mapped to this texture.\n\n" "If no materials are found, an empty string is returned.\n\n" "@param texName Name of the texture\n\n" @@ -481,14 +481,14 @@ DefineConsoleFunction( getMaterialMapping, const char*, (const char * texName), return MATMGR->getMapEntry(texName).c_str(); } -DefineConsoleFunction( dumpMaterialInstances, void, (), , +DefineEngineFunction( dumpMaterialInstances, void, (), , "@brief Dumps a formatted list of currently allocated material instances to the console.\n\n" "@ingroup Materials") { MATMGR->dumpMaterialInstances(); } -DefineConsoleFunction( getMapEntry, const char*, (const char * texName), , +DefineEngineFunction( getMapEntry, const char*, (const char * texName), , "@hide") { return MATMGR->getMapEntry( String(texName) ); diff --git a/Engine/source/math/mConsoleFunctions.cpp b/Engine/source/math/mConsoleFunctions.cpp index c9a1f4622..0b5541f2f 100644 --- a/Engine/source/math/mConsoleFunctions.cpp +++ b/Engine/source/math/mConsoleFunctions.cpp @@ -31,7 +31,7 @@ #include "console/engineAPI.h" -DefineConsoleFunction( mSolveQuadratic, const char*, ( F32 a, F32 b, F32 c ),, +DefineEngineFunction( mSolveQuadratic, const char*, ( F32 a, F32 b, F32 c ),, "Solve a quadratic equation (2nd degree polynomial) of form a*x^2 + b*x + c = 0.\n" "@param a First Coefficient." "@param b Second Coefficient." @@ -49,7 +49,7 @@ DefineConsoleFunction( mSolveQuadratic, const char*, ( F32 a, F32 b, F32 c ),, return retBuffer; } -DefineConsoleFunction( mSolveCubic, const char*, ( F32 a, F32 b, F32 c, F32 d ),, +DefineEngineFunction( mSolveCubic, const char*, ( F32 a, F32 b, F32 c, F32 d ),, "Solve a cubic equation (3rd degree polynomial) of form a*x^3 + b*x^2 + c*x + d = 0.\n" "@param a First Coefficient." "@param b Second Coefficient." @@ -68,7 +68,7 @@ DefineConsoleFunction( mSolveCubic, const char*, ( F32 a, F32 b, F32 c, F32 d ), return retBuffer; } -DefineConsoleFunction( mSolveQuartic, const char*, ( F32 a, F32 b, F32 c, F32 d, F32 e ),, +DefineEngineFunction( mSolveQuartic, const char*, ( F32 a, F32 b, F32 c, F32 d, F32 e ),, "Solve a quartic equation (4th degree polynomial) of form a*x^4 + b*x^3 + c*x^2 + d*x + e = 0.\n" "@param a First Coefficient." "@param b Second Coefficient." @@ -87,7 +87,7 @@ DefineConsoleFunction( mSolveQuartic, const char*, ( F32 a, F32 b, F32 c, F32 d, return retBuffer; } -DefineConsoleFunction( mFloor, S32, ( F32 v ),, +DefineEngineFunction( mFloor, S32, ( F32 v ),, "Round v down to the nearest integer.\n" "@param v Number to convert to integer." "@returns Number converted to integer." @@ -96,7 +96,7 @@ DefineConsoleFunction( mFloor, S32, ( F32 v ),, return (S32)mFloor( v ); } -DefineConsoleFunction( mRound, S32, ( F32 v ),, +DefineEngineFunction( mRound, S32, ( F32 v ),, "Round v to the nth decimal place or the nearest whole number by default." "@param v Value to roundn" "@return The rounded value as a S32." @@ -105,7 +105,7 @@ DefineConsoleFunction( mRound, S32, ( F32 v ),, return mRound(v); } -DefineConsoleFunction( mRoundColour, F32, ( F32 v, S32 n ), (0), +DefineEngineFunction( mRoundColour, F32, ( F32 v, S32 n ), (0), "Round v to the nth decimal place or the nearest whole number by default." "@param v Value to roundn" "@param n Number of decimal places to round to, 0 by defaultn" @@ -118,7 +118,7 @@ DefineConsoleFunction( mRoundColour, F32, ( F32 v, S32 n ), (0), return mRound(v, n); } -DefineConsoleFunction( mCeil, S32, ( F32 v ),, +DefineEngineFunction( mCeil, S32, ( F32 v ),, "Round v up to the nearest integer.\n" "@param v Number to convert to integer." "@returns Number converted to integer." @@ -127,7 +127,7 @@ DefineConsoleFunction( mCeil, S32, ( F32 v ),, return (S32)mCeil( v ); } -DefineConsoleFunction( mFloatLength, const char*, ( F32 v, U32 precision ),, +DefineEngineFunction( mFloatLength, const char*, ( F32 v, U32 precision ),, "Formats the specified number to the given number of decimal places.\n" "@param v Number to format." "@param precision Number of decimal places to format to (1-9)." @@ -148,7 +148,7 @@ DefineConsoleFunction( mFloatLength, const char*, ( F32 v, U32 precision ),, //------------------------------------------------------------------------------ -DefineConsoleFunction( mAbs, F32, ( F32 v ),, +DefineEngineFunction( mAbs, F32, ( F32 v ),, "Calculate absolute value of specified value.\n" "@param v Input Value." "@returns Absolute value of specified value." @@ -157,7 +157,7 @@ DefineConsoleFunction( mAbs, F32, ( F32 v ),, return mFabs( v ); } -DefineConsoleFunction( mFMod, F32, ( F32 v, F32 d ),, +DefineEngineFunction( mFMod, F32, ( F32 v, F32 d ),, "Calculate the remainder of v/d.\n" "@param v Input Value." "@param d Divisor Value." @@ -167,7 +167,7 @@ DefineConsoleFunction( mFMod, F32, ( F32 v, F32 d ),, return mFmod( v, d ); } -DefineConsoleFunction( mSqrt, F32, ( F32 v ),, +DefineEngineFunction( mSqrt, F32, ( F32 v ),, "Calculate the square-root of v.\n" "@param v Input Value." "@returns The square-root of the input value." @@ -176,7 +176,7 @@ DefineConsoleFunction( mSqrt, F32, ( F32 v ),, return mSqrt (v ); } -DefineConsoleFunction( mPow, F32, ( F32 v, F32 p ),, +DefineEngineFunction( mPow, F32, ( F32 v, F32 p ),, "Calculate b raised to the p-th power.\n" "@param v Input Value." "@param p Power to raise value by." @@ -186,7 +186,7 @@ DefineConsoleFunction( mPow, F32, ( F32 v, F32 p ),, return mPow( v, p ); } -DefineConsoleFunction( mLog, F32, ( F32 v ),, +DefineEngineFunction( mLog, F32, ( F32 v ),, "Calculate the natural logarithm of v.\n" "@param v Input Value." "@returns The natural logarithm of the input value." @@ -195,7 +195,7 @@ DefineConsoleFunction( mLog, F32, ( F32 v ),, return mLog( v ); } -DefineConsoleFunction( mSin, F32, ( F32 v ),, +DefineEngineFunction( mSin, F32, ( F32 v ),, "Calculate the sine of v.\n" "@param v Input Value (in radians)." "@returns The sine of the input value." @@ -204,7 +204,7 @@ DefineConsoleFunction( mSin, F32, ( F32 v ),, return mSin( v ); } -DefineConsoleFunction( mCos, F32, ( F32 v ),, +DefineEngineFunction( mCos, F32, ( F32 v ),, "Calculate the cosine of v.\n" "@param v Input Value (in radians)." "@returns The cosine of the input value." @@ -213,7 +213,7 @@ DefineConsoleFunction( mCos, F32, ( F32 v ),, return mCos( v ); } -DefineConsoleFunction( mTan, F32, ( F32 v ),, +DefineEngineFunction( mTan, F32, ( F32 v ),, "Calculate the tangent of v.\n" "@param v Input Value (in radians)." "@returns The tangent of the input value." @@ -222,7 +222,7 @@ DefineConsoleFunction( mTan, F32, ( F32 v ),, return mTan( v ); } -DefineConsoleFunction( mAsin, F32, ( F32 v ),, +DefineEngineFunction( mAsin, F32, ( F32 v ),, "Calculate the arc-sine of v.\n" "@param v Input Value (in radians)." "@returns The arc-sine of the input value." @@ -231,7 +231,7 @@ DefineConsoleFunction( mAsin, F32, ( F32 v ),, return mAsin( v ); } -DefineConsoleFunction( mAcos, F32, ( F32 v ),, +DefineEngineFunction( mAcos, F32, ( F32 v ),, "Calculate the arc-cosine of v.\n" "@param v Input Value (in radians)." "@returns The arc-cosine of the input value." @@ -240,7 +240,7 @@ DefineConsoleFunction( mAcos, F32, ( F32 v ),, return mAcos( v ); } -DefineConsoleFunction( mAtan, F32, ( F32 rise, F32 run ),, +DefineEngineFunction( mAtan, F32, ( F32 rise, F32 run ),, "Calculate the arc-tangent (slope) of a line defined by rise and run.\n" "@param rise of line." "@param run of line." @@ -250,7 +250,7 @@ DefineConsoleFunction( mAtan, F32, ( F32 rise, F32 run ),, return mAtan2( rise, run ); } -DefineConsoleFunction( mRadToDeg, F32, ( F32 radians ),, +DefineEngineFunction( mRadToDeg, F32, ( F32 radians ),, "Convert specified radians into degrees.\n" "@param radians Input Value (in radians)." "@returns The specified radians value converted to degrees." @@ -259,7 +259,7 @@ DefineConsoleFunction( mRadToDeg, F32, ( F32 radians ),, return mRadToDeg( radians ); } -DefineConsoleFunction( mDegToRad, F32, ( F32 degrees ),, +DefineEngineFunction( mDegToRad, F32, ( F32 degrees ),, "Convert specified degrees into radians.\n" "@param degrees Input Value (in degrees)." "@returns The specified degrees value converted to radians." @@ -268,7 +268,7 @@ DefineConsoleFunction( mDegToRad, F32, ( F32 degrees ),, return mDegToRad( degrees ); } -DefineConsoleFunction( mClamp, F32, ( F32 v, F32 min, F32 max ),, +DefineEngineFunction( mClamp, F32, ( F32 v, F32 min, F32 max ),, "Clamp the specified value between two bounds.\n" "@param v Input value." "@param min Minimum Bound." @@ -279,7 +279,7 @@ DefineConsoleFunction( mClamp, F32, ( F32 v, F32 min, F32 max ),, return mClampF( v, min, max ); } -DefineConsoleFunction( mSaturate, F32, ( F32 v ),, +DefineEngineFunction( mSaturate, F32, ( F32 v ),, "Clamp the specified value between 0 and 1 (inclusive).\n" "@param v Input value." "@returns The specified value clamped between 0 and 1 (inclusive)." @@ -288,7 +288,7 @@ DefineConsoleFunction( mSaturate, F32, ( F32 v ),, return mClampF( v, 0.0f, 1.0f ); } -DefineConsoleFunction(mWrapF, F32, (F32 v, F32 min, F32 max), , +DefineEngineFunction(mWrapF, F32, (F32 v, F32 min, F32 max), , "Wrap the specified value between two bounds.\n" "@param v Input value." "@param min Minimum Bound." @@ -299,7 +299,7 @@ DefineConsoleFunction(mWrapF, F32, (F32 v, F32 min, F32 max), , return mWrapF(v, min, max); } -DefineConsoleFunction(mWrap, S32, (S32 v, S32 min, S32 max), , +DefineEngineFunction(mWrap, S32, (S32 v, S32 min, S32 max), , "Wrap the specified value between two bounds.\n" "@param v Input value." "@param min Minimum Bound." @@ -311,7 +311,7 @@ DefineConsoleFunction(mWrap, S32, (S32 v, S32 min, S32 max), , } -DefineConsoleFunction( getMax, F32, ( F32 v1, F32 v2 ),, +DefineEngineFunction( getMax, F32, ( F32 v1, F32 v2 ),, "Calculate the greater of two specified numbers.\n" "@param v1 Input value." "@param v2 Input value." @@ -321,7 +321,7 @@ DefineConsoleFunction( getMax, F32, ( F32 v1, F32 v2 ),, return getMax( v1, v2 ); } -DefineConsoleFunction( getMin, F32, ( F32 v1, F32 v2 ),, +DefineEngineFunction( getMin, F32, ( F32 v1, F32 v2 ),, "Calculate the lesser of two specified numbers.\n" "@param v1 Input value." "@param v2 Input value." @@ -331,7 +331,7 @@ DefineConsoleFunction( getMin, F32, ( F32 v1, F32 v2 ),, return getMin( v1, v2 ); } -DefineConsoleFunction( mLerp, F32, ( F32 v1, F32 v2, F32 time ),, +DefineEngineFunction( mLerp, F32, ( F32 v1, F32 v2, F32 time ),, "Calculate linearly interpolated value between two specified numbers using specified normalized time.\n" "@param v1 Interpolate From Input value." "@param v2 Interpolate To Input value." @@ -342,7 +342,7 @@ DefineConsoleFunction( mLerp, F32, ( F32 v1, F32 v2, F32 time ),, return mLerp( v1, v2, time ); } -DefineConsoleFunction( mPi, F32, (),, +DefineEngineFunction( mPi, F32, (),, "Return the value of PI (half-circle in radians).\n" "@returns The value of PI." "@ingroup Math" ) @@ -350,7 +350,7 @@ DefineConsoleFunction( mPi, F32, (),, return M_PI_F; } -DefineConsoleFunction( m2Pi, F32, (),, +DefineEngineFunction( m2Pi, F32, (),, "Return the value of 2*PI (full-circle in radians).\n" "@returns The value of 2*PI." "@ingroup Math" ) @@ -358,7 +358,7 @@ DefineConsoleFunction( m2Pi, F32, (),, return M_2PI_F; } -DefineConsoleFunction( mIsPow2, bool, ( S32 v ),, +DefineEngineFunction( mIsPow2, bool, ( S32 v ),, "Returns whether the value is an exact power of two.\n" "@param v Input value." "@returns Whether the specified value is an exact power of two." @@ -367,7 +367,7 @@ DefineConsoleFunction( mIsPow2, bool, ( S32 v ),, return isPow2( v ); } -DefineConsoleFunction( mRandomDir, Point3F, (Point3F axis, F32 angleMin, F32 angleMax),, +DefineEngineFunction( mRandomDir, Point3F, (Point3F axis, F32 angleMin, F32 angleMax),, "Returns a randomized direction based on a starting axis and the min/max angles.\n" "@param axis Main axis to deviate the direction from." "@param angleMin minimum amount of deviation from the axis." @@ -378,7 +378,7 @@ DefineConsoleFunction( mRandomDir, Point3F, (Point3F axis, F32 angleMin, F32 ang return MathUtils::randomDir(axis, angleMin, angleMax); } -DefineConsoleFunction( mRandomPointInSphere, Point3F, (F32 radius), , +DefineEngineFunction( mRandomPointInSphere, Point3F, (F32 radius), , "Returns a randomized point inside a sphere of a given radius.\n" "@param radius The radius of the sphere to find a point in." "@returns Randomized point inside a sphere." @@ -387,7 +387,7 @@ DefineConsoleFunction( mRandomPointInSphere, Point3F, (F32 radius), , return MathUtils::randomPointInSphere(radius); } -DefineConsoleFunction( mGetAngleBetweenVectors, F32, (VectorF vecA, VectorF vecB), , +DefineEngineFunction( mGetAngleBetweenVectors, F32, (VectorF vecA, VectorF vecB), , "Returns angle between two vectors.\n" "@param vecA First input vector." "@param vecB Second input vector." @@ -397,7 +397,7 @@ DefineConsoleFunction( mGetAngleBetweenVectors, F32, (VectorF vecA, VectorF vecB return MathUtils::getAngleBetweenVectors(vecA, vecB); } -DefineConsoleFunction(mGetSignedAngleBetweenVectors, F32, (VectorF vecA, VectorF vecB, VectorF norm), (VectorF::Zero, VectorF::Zero, VectorF::Zero), +DefineEngineFunction(mGetSignedAngleBetweenVectors, F32, (VectorF vecA, VectorF vecB, VectorF norm), (VectorF::Zero, VectorF::Zero, VectorF::Zero), "Returns signed angle between two vectors, using a normal for orientation.\n" "@param vecA First input vector." "@param vecB Second input vector." diff --git a/Engine/source/math/mRotation.cpp b/Engine/source/math/mRotation.cpp index 6d9bc3b35..43b696d4a 100644 --- a/Engine/source/math/mRotation.cpp +++ b/Engine/source/math/mRotation.cpp @@ -325,7 +325,7 @@ TEST(Maths, RotationF_Calculations) }; #endif -DefineConsoleFunction(AddRotation, RotationF, (RotationF a, RotationF b), , +DefineEngineFunction(AddRotation, RotationF, (RotationF a, RotationF b), , "Adds two rotations together.\n" "@param a Rotation one." "@param b Rotation two." @@ -335,7 +335,7 @@ DefineConsoleFunction(AddRotation, RotationF, (RotationF a, RotationF b), , return a + b; } -DefineConsoleFunction(SubtractRotation, RotationF, (RotationF a, RotationF b), , +DefineEngineFunction(SubtractRotation, RotationF, (RotationF a, RotationF b), , "Subtracts two rotations.\n" "@param a Rotation one." "@param b Rotation two." @@ -345,7 +345,7 @@ DefineConsoleFunction(SubtractRotation, RotationF, (RotationF a, RotationF b), , return a - b; } -DefineConsoleFunction(InterpolateRotation, RotationF, (RotationF a, RotationF b, F32 factor), , +DefineEngineFunction(InterpolateRotation, RotationF, (RotationF a, RotationF b, F32 factor), , "Interpolates between two rotations.\n" "@param a Rotation one." "@param b Rotation two." @@ -358,7 +358,7 @@ DefineConsoleFunction(InterpolateRotation, RotationF, (RotationF a, RotationF b, return result; } -DefineConsoleFunction(RotationLookAt, RotationF, (Point3F origin, Point3F target, Point3F up), +DefineEngineFunction(RotationLookAt, RotationF, (Point3F origin, Point3F target, Point3F up), (Point3F(0, 0, 0), Point3F(0, 0, 0), Point3F(0, 0, 1)), "Provides a rotation orientation to look at a target from a given position.\n" "@param origin Position of the object doing the looking." @@ -372,7 +372,7 @@ DefineConsoleFunction(RotationLookAt, RotationF, (Point3F origin, Point3F target return result; } -DefineConsoleFunction(setRotationRightVector, RotationF, (RotationF rot, VectorF rightVec), , +DefineEngineFunction(setRotationRightVector, RotationF, (RotationF rot, VectorF rightVec), , "Sets the right vector of the rotation.\n" "@param Starting rotation." "@param New up vector." @@ -383,7 +383,7 @@ DefineConsoleFunction(setRotationRightVector, RotationF, (RotationF rot, VectorF return rot; } -DefineConsoleFunction(setRotationUpVector, RotationF, (RotationF rot, VectorF upVec), , +DefineEngineFunction(setRotationUpVector, RotationF, (RotationF rot, VectorF upVec), , "Sets the up vector of the rotation.\n" "@param Starting rotation." "@param New up vector." @@ -394,14 +394,14 @@ DefineConsoleFunction(setRotationUpVector, RotationF, (RotationF rot, VectorF up return rot; } -DefineConsoleFunction(getRotationForwardVector, VectorF, (RotationF rot), , +DefineEngineFunction(getRotationForwardVector, VectorF, (RotationF rot), , "Get the forward vector of a rotation.\n" "@ingroup Math") { return rot.asMatrixF().getForwardVector(); } -DefineConsoleFunction(getRotationRightVector, VectorF, (RotationF rot), , +DefineEngineFunction(getRotationRightVector, VectorF, (RotationF rot), , "Gets the right vector of a rotation.\n" "@param Our rotation." "@ingroup Math") @@ -409,7 +409,7 @@ DefineConsoleFunction(getRotationRightVector, VectorF, (RotationF rot), , return rot.asMatrixF().getRightVector(); } -DefineConsoleFunction(getRotationUpVector, VectorF, (RotationF rot), , +DefineEngineFunction(getRotationUpVector, VectorF, (RotationF rot), , "Gets the up vector of a rotation.\n" "@param Our rotation." "@ingroup Math") @@ -417,7 +417,7 @@ DefineConsoleFunction(getRotationUpVector, VectorF, (RotationF rot), , return rot.asMatrixF().getUpVector(); } -DefineConsoleFunction(getRotationDirection, Point3F, (RotationF rot),, +DefineEngineFunction(getRotationDirection, Point3F, (RotationF rot),, "Gets the direction from the rotation's angles.\n" "@param Our rotation." "@ingroup Math") diff --git a/Engine/source/math/mathTypes.cpp b/Engine/source/math/mathTypes.cpp index 1d1011d0f..30b550abc 100644 --- a/Engine/source/math/mathTypes.cpp +++ b/Engine/source/math/mathTypes.cpp @@ -631,7 +631,7 @@ ConsoleSetType(TypeRotationF) //----------------------------------------------------------------------------- -DefineConsoleFunction( VectorAdd, VectorF, ( VectorF a, VectorF b ),, +DefineEngineFunction( VectorAdd, VectorF, ( VectorF a, VectorF b ),, "Add two vectors.\n" "@param a The first vector.\n" "@param b The second vector.\n" @@ -659,7 +659,7 @@ DefineConsoleFunction( VectorAdd, VectorF, ( VectorF a, VectorF b ),, //----------------------------------------------------------------------------- -DefineConsoleFunction( VectorSub, VectorF, ( VectorF a, VectorF b ),, +DefineEngineFunction( VectorSub, VectorF, ( VectorF a, VectorF b ),, "Subtract two vectors.\n" "@param a The first vector.\n" "@param b The second vector.\n" @@ -689,7 +689,7 @@ DefineConsoleFunction( VectorSub, VectorF, ( VectorF a, VectorF b ),, //----------------------------------------------------------------------------- -DefineConsoleFunction( VectorScale, VectorF, ( VectorF a, F32 scalar ),, +DefineEngineFunction( VectorScale, VectorF, ( VectorF a, F32 scalar ),, "Scales a vector by a scalar.\n" "@param a The vector to scale.\n" "@param scalar The scale factor.\n" @@ -716,7 +716,7 @@ DefineConsoleFunction( VectorScale, VectorF, ( VectorF a, F32 scalar ),, { return a * scalar; } -DefineConsoleFunction( VectorMul, VectorF, ( VectorF a, VectorF b ),, +DefineEngineFunction( VectorMul, VectorF, ( VectorF a, VectorF b ),, "Multiplies two vectors.\n" "@param a The first vector.\n" "@param b The second vector.\n" @@ -744,7 +744,7 @@ DefineConsoleFunction( VectorMul, VectorF, ( VectorF a, VectorF b ),, return a * b; } -DefineConsoleFunction( VectorDiv, VectorF, ( VectorF a, VectorF b ),, +DefineEngineFunction( VectorDiv, VectorF, ( VectorF a, VectorF b ),, "Divide two vectors.\n" "@param a The first vector.\n" "@param b The second vector.\n" @@ -779,7 +779,7 @@ DefineConsoleFunction( VectorDiv, VectorF, ( VectorF a, VectorF b ),, //----------------------------------------------------------------------------- -DefineConsoleFunction( VectorNormalize, VectorF, ( VectorF v ),, +DefineEngineFunction( VectorNormalize, VectorF, ( VectorF v ),, "Brings a vector into its unit form, i.e. such that it has the magnitute 1.\n" "@param v The vector to normalize.\n" "@return The vector @a v scaled to length 1.\n\n" @@ -811,7 +811,7 @@ DefineConsoleFunction( VectorNormalize, VectorF, ( VectorF v ),, //----------------------------------------------------------------------------- -DefineConsoleFunction( VectorDot, F32, ( VectorF a, VectorF b ),, +DefineEngineFunction( VectorDot, F32, ( VectorF a, VectorF b ),, "Compute the dot product of two vectors.\n" "@param a The first vector.\n" "@param b The second vector.\n" @@ -841,7 +841,7 @@ DefineConsoleFunction( VectorDot, F32, ( VectorF a, VectorF b ),, //----------------------------------------------------------------------------- -DefineConsoleFunction( VectorCross, VectorF, ( VectorF a, VectorF b ),, +DefineEngineFunction( VectorCross, VectorF, ( VectorF a, VectorF b ),, "Calculcate the cross product of two vectors.\n" "@param a The first vector.\n" "@param b The second vector.\n" @@ -873,7 +873,7 @@ DefineConsoleFunction( VectorCross, VectorF, ( VectorF a, VectorF b ),, //----------------------------------------------------------------------------- -DefineConsoleFunction( VectorDist, F32, ( VectorF a, VectorF b ),, +DefineEngineFunction( VectorDist, F32, ( VectorF a, VectorF b ),, "Compute the distance between two vectors.\n" "@param a The first vector.\n" "@param b The second vector.\n" @@ -906,7 +906,7 @@ DefineConsoleFunction( VectorDist, F32, ( VectorF a, VectorF b ),, //----------------------------------------------------------------------------- -DefineConsoleFunction( VectorMidPoint, VectorF, ( VectorF a, VectorF b ),, +DefineEngineFunction( VectorMidPoint, VectorF, ( VectorF a, VectorF b ),, "Gets the midpoint between the two vectors.\n" "@param a The first vector.\n" "@param b The second vector.\n" @@ -934,7 +934,7 @@ DefineConsoleFunction( VectorMidPoint, VectorF, ( VectorF a, VectorF b ),, //----------------------------------------------------------------------------- -DefineConsoleFunction( VectorLen, F32, ( VectorF v ),, +DefineEngineFunction( VectorLen, F32, ( VectorF v ),, "Calculate the magnitude of the given vector.\n" "@param v A vector.\n" "@return The length of vector @a v.\n\n" @@ -963,7 +963,7 @@ DefineConsoleFunction( VectorLen, F32, ( VectorF v ),, //----------------------------------------------------------------------------- -DefineConsoleFunction( VectorOrthoBasis, MatrixF, ( AngAxisF aa ),, +DefineEngineFunction( VectorOrthoBasis, MatrixF, ( AngAxisF aa ),, "Create an orthogonal basis from the given vector.\n" "@param aaf The vector to create the orthogonal basis from.\n" "@return A matrix representing the orthogonal basis.\n" @@ -977,7 +977,7 @@ DefineConsoleFunction( VectorOrthoBasis, MatrixF, ( AngAxisF aa ),, //----------------------------------------------------------------------------- //ConsoleFunction(VectorRot, const char*, 3, 3, "(Vector3F, float) rotate a vector in 2d") -DefineConsoleFunction( VectorRot, const char*, (Point3F v, F32 angle), , "(Vector3F, float) rotate a vector in 2d") +DefineEngineFunction( VectorRot, const char*, (Point3F v, F32 angle), , "(Vector3F, float) rotate a vector in 2d") { //VectorF v(0,0,0); //dSscanf(argv[1],"%g %g %g",&v.x,&v.y,&v.z); @@ -996,7 +996,7 @@ DefineConsoleFunction( VectorRot, const char*, (Point3F v, F32 angle), , "(Vecto return returnBuffer; } -DefineConsoleFunction( VectorLerp, VectorF, ( VectorF a, VectorF b, F32 t ),, +DefineEngineFunction( VectorLerp, VectorF, ( VectorF a, VectorF b, F32 t ),, "Linearly interpolate between two vectors by @a t.\n" "@param a Vector to start interpolation from.\n" "@param b Vector to interpolate to.\n" @@ -1032,7 +1032,7 @@ DefineConsoleFunction( VectorLerp, VectorF, ( VectorF a, VectorF b, F32 t ),, return c; } -DefineConsoleFunction(VectorReflect, VectorF, (VectorF vec, VectorF normal), , +DefineEngineFunction(VectorReflect, VectorF, (VectorF vec, VectorF normal), , "Compute the reflection of a vector based on a normal.\n" "@param a The vector.\n" "@param b The normal.\n" @@ -1046,7 +1046,7 @@ DefineConsoleFunction(VectorReflect, VectorF, (VectorF vec, VectorF normal), , //----------------------------------------------------------------------------- -DefineConsoleFunction( MatrixCreate, TransformF, ( VectorF position, AngAxisF orientation ),, +DefineEngineFunction( MatrixCreate, TransformF, ( VectorF position, AngAxisF orientation ),, "Create a transform from the given translation and orientation.\n" "@param position The translation vector for the transform.\n" "@param orientation The axis and rotation that orients the transform.\n" @@ -1059,7 +1059,7 @@ DefineConsoleFunction( MatrixCreate, TransformF, ( VectorF position, AngAxisF or //----------------------------------------------------------------------------- -DefineConsoleFunction( MatrixCreateFromEuler, TransformF, ( Point3F angles ),, +DefineEngineFunction( MatrixCreateFromEuler, TransformF, ( Point3F angles ),, "@Create a matrix from the given rotations.\n\n" "@param Vector3F X, Y, and Z rotation in *radians*.\n" "@return A transform based on the given orientation.\n" @@ -1074,7 +1074,7 @@ DefineConsoleFunction( MatrixCreateFromEuler, TransformF, ( Point3F angles ),, //----------------------------------------------------------------------------- -DefineConsoleFunction( MatrixMultiply, TransformF, ( TransformF left, TransformF right ),, +DefineEngineFunction( MatrixMultiply, TransformF, ( TransformF left, TransformF right ),, "@brief Multiply the two matrices.\n\n" "@param left First transform.\n" "@param right Right transform.\n" @@ -1091,7 +1091,7 @@ DefineConsoleFunction( MatrixMultiply, TransformF, ( TransformF left, TransformF //----------------------------------------------------------------------------- -DefineConsoleFunction( MatrixMulVector, VectorF, ( TransformF transform, VectorF vector ),, +DefineEngineFunction( MatrixMulVector, VectorF, ( TransformF transform, VectorF vector ),, "@brief Multiply the vector by the transform assuming that w=0.\n\n" "This function will multiply the given vector by the given transform such that translation will " "not affect the vector.\n\n" @@ -1107,7 +1107,7 @@ DefineConsoleFunction( MatrixMulVector, VectorF, ( TransformF transform, VectorF //----------------------------------------------------------------------------- -DefineConsoleFunction( MatrixMulPoint, Point3F, ( TransformF transform, Point3F point ),, +DefineEngineFunction( MatrixMulPoint, Point3F, ( TransformF transform, Point3F point ),, "@brief Multiply the given point by the given transform assuming that w=1.\n\n" "This function will multiply the given vector such that translation with take effect.\n" "@param transform A transform.\n" @@ -1124,7 +1124,7 @@ ConsoleFunctionGroupEnd(MatrixMath); //------------------------------------------------------------------------------ -DefineConsoleFunction( getBoxCenter, Point3F, ( Box3F box ),, +DefineEngineFunction( getBoxCenter, Point3F, ( Box3F box ),, "Get the center point of an axis-aligned box.\n\n" "@param b A Box3F, in string format using \"minExtentX minExtentY minExtentZ maxExtentX maxExtentY maxExtentZ\"\n" "@return Center of the box.\n" @@ -1176,7 +1176,7 @@ F32 mRandF() return gRandGen.randF(); } -DefineConsoleFunction(getRandom, F32, (S32 a, S32 b), (S32_MAX, S32_MAX), +DefineEngineFunction(getRandom, F32, (S32 a, S32 b), (S32_MAX, S32_MAX), "( int a, int b ) " "@brief Returns a random number based on parameters passed in..\n\n" "If no parameters are passed in, getRandom() will return a float between 0.0 and 1.0. If one " diff --git a/Engine/source/navigation/navMesh.cpp b/Engine/source/navigation/navMesh.cpp index c9bbb1fa4..f4adf9992 100644 --- a/Engine/source/navigation/navMesh.cpp +++ b/Engine/source/navigation/navMesh.cpp @@ -95,13 +95,13 @@ EventManager *NavMesh::getEventManager() return smEventManager; } -DefineConsoleFunction(getNavMeshEventManager, S32, (),, +DefineEngineFunction(getNavMeshEventManager, S32, (),, "@brief Get the EventManager object for all NavMesh updates.") { return NavMesh::getEventManager()->getId(); } -DefineConsoleFunction(NavMeshUpdateAll, void, (S32 objid, bool remove), (0, false), +DefineEngineFunction(NavMeshUpdateAll, void, (S32 objid, bool remove), (0, false), "@brief Update all NavMesh tiles that intersect the given object's world box.") { SceneObject *obj; @@ -123,7 +123,7 @@ DefineConsoleFunction(NavMeshUpdateAll, void, (S32 objid, bool remove), (0, fals obj->enableCollision(); } -DefineConsoleFunction(NavMeshUpdateAroundObject, void, (S32 objid, bool remove), (0, false), +DefineEngineFunction(NavMeshUpdateAroundObject, void, (S32 objid, bool remove), (0, false), "@brief Update all NavMesh tiles that intersect the given object's world box.") { SceneObject *obj; @@ -146,7 +146,7 @@ DefineConsoleFunction(NavMeshUpdateAroundObject, void, (S32 objid, bool remove), } -DefineConsoleFunction(NavMeshIgnore, void, (S32 objid, bool _ignore), (0, true), +DefineEngineFunction(NavMeshIgnore, void, (S32 objid, bool _ignore), (0, true), "@brief Flag this object as not generating a navmesh result.") { SceneObject *obj; @@ -156,7 +156,7 @@ DefineConsoleFunction(NavMeshIgnore, void, (S32 objid, bool _ignore), (0, true), obj->mPathfindingIgnore = _ignore; } -DefineConsoleFunction(NavMeshUpdateOne, void, (S32 meshid, S32 objid, bool remove), (0, 0, false), +DefineEngineFunction(NavMeshUpdateOne, void, (S32 meshid, S32 objid, bool remove), (0, 0, false), "@brief Update all tiles in a given NavMesh that intersect the given object's world box.") { NavMesh *mesh; diff --git a/Engine/source/platform/platformFileIO.cpp b/Engine/source/platform/platformFileIO.cpp index a9ace740b..788ed4f62 100644 --- a/Engine/source/platform/platformFileIO.cpp +++ b/Engine/source/platform/platformFileIO.cpp @@ -38,7 +38,7 @@ StringTableEntry Platform::getTemporaryDirectory() return path; } -DefineConsoleFunction( getTemporaryDirectory, const char *, (), , +DefineEngineFunction( getTemporaryDirectory, const char *, (), , "@brief Returns the OS temporary directory, \"C:/Users/Mich/AppData/Local/Temp\" for example\n\n" "@note This can be useful to adhering to OS standards and practices, " "but not really used in Torque 3D right now.\n" @@ -66,7 +66,7 @@ StringTableEntry Platform::getTemporaryFileName() return StringTable->insert(buf); } -DefineConsoleFunction( getTemporaryFileName, const char *, (), , +DefineEngineFunction( getTemporaryFileName, const char *, (), , "@brief Creates a name and extension for a potential temporary file\n\n" "This does not create the actual file. It simply creates a random name " "for a file that does not exist.\n\n" @@ -611,12 +611,12 @@ StringTableEntry Platform::getPrefsPath(const char *file /* = NULL */) //----------------------------------------------------------------------------- -DefineConsoleFunction( getUserDataDirectory, const char *, (), , "getUserDataDirectory()") +DefineEngineFunction( getUserDataDirectory, const char *, (), , "getUserDataDirectory()") { return Platform::getUserDataDirectory(); } -DefineConsoleFunction( getUserHomeDirectory, const char *, (), , "getUserHomeDirectory()") +DefineEngineFunction( getUserHomeDirectory, const char *, (), , "getUserHomeDirectory()") { return Platform::getUserHomeDirectory(); } diff --git a/Engine/source/platform/platformMemory.cpp b/Engine/source/platform/platformMemory.cpp index 5f7aa926d..f10113308 100644 --- a/Engine/source/platform/platformMemory.cpp +++ b/Engine/source/platform/platformMemory.cpp @@ -885,7 +885,7 @@ void logDumpTraverse(MemDumpLog *sizes, TreeNode *header, U32 depth) } #ifdef TORQUE_DEBUG -DefineConsoleFunction( validateMemory, void, ( ),, +DefineEngineFunction( validateMemory, void, ( ),, "@brief Used to validate memory space for the game.\n\n" "@ingroup Debugging" ) { @@ -893,7 +893,7 @@ DefineConsoleFunction( validateMemory, void, ( ),, } #endif -DefineConsoleFunction( freeMemoryDump, void, ( ),, +DefineEngineFunction( freeMemoryDump, void, ( ),, "@brief Dumps some useful statistics regarding free memory.\n\n" "Dumps an analysis of \'free chunks\' of memory. " "Does not print how much memory is free.\n\n" diff --git a/Engine/source/platform/platformRedBook.cpp b/Engine/source/platform/platformRedBook.cpp index 82b1bae2d..acbc0bc7a 100644 --- a/Engine/source/platform/platformRedBook.cpp +++ b/Engine/source/platform/platformRedBook.cpp @@ -211,7 +211,7 @@ bool RedBook::setVolume(F32 volume) ConsoleFunctionGroupBegin( Redbook, "Control functions for Redbook audio (ie, CD audio)."); -DefineConsoleFunction( redbookOpen, bool, (const char * device), (""), "(string device=NULL)" +DefineEngineFunction( redbookOpen, bool, (const char * device), (""), "(string device=NULL)" "@brief Deprecated\n\n" "@internal") { @@ -221,28 +221,28 @@ DefineConsoleFunction( redbookOpen, bool, (const char * device), (""), "(string return(RedBook::open(device)); } -DefineConsoleFunction( redbookClose, bool, (), , "Close the current Redbook device." +DefineEngineFunction( redbookClose, bool, (), , "Close the current Redbook device." "@brief Deprecated\n\n" "@internal") { return(RedBook::close()); } -DefineConsoleFunction( redbookPlay, bool, (S32 track), , "(int track) Play the selected track." +DefineEngineFunction( redbookPlay, bool, (S32 track), , "(int track) Play the selected track." "@brief Deprecated\n\n" "@internal") { return(RedBook::play(track)); } -DefineConsoleFunction( redbookStop, bool, (), , "Stop playing." +DefineEngineFunction( redbookStop, bool, (), , "Stop playing." "@brief Deprecated\n\n" "@internal") { return(RedBook::stop()); } -DefineConsoleFunction( redbookGetTrackCount, S32, (), , "Return the number of tracks." +DefineEngineFunction( redbookGetTrackCount, S32, (), , "Return the number of tracks." "@brief Deprecated\n\n" "@internal") { @@ -252,7 +252,7 @@ DefineConsoleFunction( redbookGetTrackCount, S32, (), , "Return the number of tr return(trackCount); } -DefineConsoleFunction( redbookGetVolume, F32, (), , "Get the volume." +DefineEngineFunction( redbookGetVolume, F32, (), , "Get the volume." "@brief Deprecated\n\n" "@internal") { @@ -263,28 +263,28 @@ DefineConsoleFunction( redbookGetVolume, F32, (), , "Get the volume." return(vol); } -DefineConsoleFunction( redbookSetVolume, bool, (F32 volume), , "(float volume) Set playback volume." +DefineEngineFunction( redbookSetVolume, bool, (F32 volume), , "(float volume) Set playback volume." "@brief Deprecated\n\n" "@internal") { return(RedBook::setVolume(volume)); } -DefineConsoleFunction( redbookGetDeviceCount, S32, (), , "get the number of redbook devices." +DefineEngineFunction( redbookGetDeviceCount, S32, (), , "get the number of redbook devices." "@brief Deprecated\n\n" "@internal") { return(RedBook::getDeviceCount()); } -DefineConsoleFunction( redbookGetDeviceName, const char *, (S32 index), , "(int index) Get name of specified Redbook device." +DefineEngineFunction( redbookGetDeviceName, const char *, (S32 index), , "(int index) Get name of specified Redbook device." "@brief Deprecated\n\n" "@internal") { return(RedBook::getDeviceName(index)); } -DefineConsoleFunction( redbookGetLastError, const char *, (), , "Get a string explaining the last redbook error." +DefineEngineFunction( redbookGetLastError, const char *, (), , "Get a string explaining the last redbook error." "@brief Deprecated\n\n" "@internal") { diff --git a/Engine/source/platform/platformTimer.cpp b/Engine/source/platform/platformTimer.cpp index 1da010c5a..e3be91fe9 100644 --- a/Engine/source/platform/platformTimer.cpp +++ b/Engine/source/platform/platformTimer.cpp @@ -160,12 +160,12 @@ S32 ScriptTimerMan::stopTimer( S32 id ) ScriptTimerMan gScriptTimerMan; -DefineConsoleFunction( startPrecisionTimer, S32, (), , "startPrecisionTimer() - Create and start a high resolution platform timer. Returns the timer id." ) +DefineEngineFunction( startPrecisionTimer, S32, (), , "startPrecisionTimer() - Create and start a high resolution platform timer. Returns the timer id." ) { return gScriptTimerMan.startTimer(); } -DefineConsoleFunction( stopPrecisionTimer, S32, ( S32 id), , "stopPrecisionTimer( S32 id ) - Stop and destroy timer with the passed id. Returns the elapsed milliseconds." ) +DefineEngineFunction( stopPrecisionTimer, S32, ( S32 id), , "stopPrecisionTimer( S32 id ) - Stop and destroy timer with the passed id. Returns the elapsed milliseconds." ) { return gScriptTimerMan.stopTimer( id ); } \ No newline at end of file diff --git a/Engine/source/platformWin32/cardProfile.cpp b/Engine/source/platformWin32/cardProfile.cpp index a4658f98c..dbfad0fe6 100644 --- a/Engine/source/platformWin32/cardProfile.cpp +++ b/Engine/source/platformWin32/cardProfile.cpp @@ -74,7 +74,7 @@ void initDisplayDeviceInfo() Con::setVariable( "$PCI_DEV", dev ); } -DefineConsoleFunction( initDisplayDeviceInfo, void, (), , "()" +DefineEngineFunction( initDisplayDeviceInfo, void, (), , "()" "@brief Initializes variables that track device and vendor information/IDs\n\n" "@ingroup Rendering") { diff --git a/Engine/source/platformWin32/winConsole.cpp b/Engine/source/platformWin32/winConsole.cpp index cc92c2c15..66c9bb3c0 100644 --- a/Engine/source/platformWin32/winConsole.cpp +++ b/Engine/source/platformWin32/winConsole.cpp @@ -38,7 +38,7 @@ namespace Con extern bool alwaysUseDebugOutput; } -DefineConsoleFunction( enableWinConsole, void, (bool flag), , "enableWinConsole(bool);") +DefineEngineFunction( enableWinConsole, void, (bool flag), , "enableWinConsole(bool);") { WindowsConsole->enable(flag); } diff --git a/Engine/source/platformWin32/winDirectInput.cpp b/Engine/source/platformWin32/winDirectInput.cpp index 2fd8084ef..fd016496f 100644 --- a/Engine/source/platformWin32/winDirectInput.cpp +++ b/Engine/source/platformWin32/winDirectInput.cpp @@ -769,7 +769,7 @@ void DInputManager::processXInput( void ) mXInputStateReset = false; } } -DefineConsoleFunction( enableJoystick, bool, (), , "()" +DefineEngineFunction( enableJoystick, bool, (), , "()" "@brief Enables use of the joystick.\n\n" "@note DirectInput must be enabled and active to use this function.\n\n" "@ingroup Input") @@ -778,7 +778,7 @@ DefineConsoleFunction( enableJoystick, bool, (), , "()" } //------------------------------------------------------------------------------ -DefineConsoleFunction( disableJoystick, void, (), , "()" +DefineEngineFunction( disableJoystick, void, (), , "()" "@brief Disables use of the joystick.\n\n" "@note DirectInput must be enabled and active to use this function.\n\n" "@ingroup Input") @@ -787,7 +787,7 @@ DefineConsoleFunction( disableJoystick, void, (), , "()" } //------------------------------------------------------------------------------ -DefineConsoleFunction( isJoystickEnabled, bool, (), , "()" +DefineEngineFunction( isJoystickEnabled, bool, (), , "()" "@brief Queries input manager to see if a joystick is enabled\n\n" "@return 1 if a joystick exists and is enabled, 0 if it's not.\n" "@ingroup Input") @@ -796,7 +796,7 @@ DefineConsoleFunction( isJoystickEnabled, bool, (), , "()" } //------------------------------------------------------------------------------ -DefineConsoleFunction( enableXInput, bool, (), , "()" +DefineEngineFunction( enableXInput, bool, (), , "()" "@brief Enables XInput for Xbox 360 controllers.\n\n" "@note XInput is enabled by default. Disable to use an Xbox 360 " "Controller as a joystick device.\n\n" @@ -811,7 +811,7 @@ DefineConsoleFunction( enableXInput, bool, (), , "()" } //------------------------------------------------------------------------------ -DefineConsoleFunction( disableXInput, void, (), , "()" +DefineEngineFunction( disableXInput, void, (), , "()" "@brief Disables XInput for Xbox 360 controllers.\n\n" "@ingroup Input") { @@ -819,7 +819,7 @@ DefineConsoleFunction( disableXInput, void, (), , "()" } //------------------------------------------------------------------------------ -DefineConsoleFunction( resetXInput, void, (), , "()" +DefineEngineFunction( resetXInput, void, (), , "()" "@brief Rebuilds the XInput section of the InputManager\n\n" "Requests a full refresh of events for all controllers. Useful when called at the beginning " "of game code after actionMaps are set up to hook up all appropriate events.\n\n" @@ -836,7 +836,7 @@ DefineConsoleFunction( resetXInput, void, (), , "()" } //------------------------------------------------------------------------------ -DefineConsoleFunction( isXInputConnected, bool, (S32 controllerID), , "( int controllerID )" +DefineEngineFunction( isXInputConnected, bool, (S32 controllerID), , "( int controllerID )" "@brief Checks to see if an Xbox 360 controller is connected\n\n" "@param controllerID Zero-based index of the controller to check.\n" "@return 1 if the controller is connected, 0 if it isn't, and 205 if XInput " @@ -849,7 +849,7 @@ DefineConsoleFunction( isXInputConnected, bool, (S32 controllerID), , "( int con } //------------------------------------------------------------------------------ -DefineConsoleFunction( getXInputState, int, (S32 controllerID, const char * properties, bool current), (false), "( int controllerID, string property, bool currentD )" +DefineEngineFunction( getXInputState, int, (S32 controllerID, const char * properties, bool current), (false), "( int controllerID, string property, bool currentD )" "@brief Queries the current state of a connected Xbox 360 controller.\n\n" "XInput Properties:\n\n" " - XI_THUMBLX, XI_THUMBLY - X and Y axes of the left thumbstick. \n" @@ -905,7 +905,7 @@ DefineConsoleFunction( getXInputState, int, (S32 controllerID, const char * prop } //------------------------------------------------------------------------------ -DefineConsoleFunction( echoInputState, void, (), , "()" +DefineEngineFunction( echoInputState, void, (), , "()" "@brief Prints information to the console stating if DirectInput and a Joystick are enabled and active.\n\n" "@ingroup Input") { @@ -921,7 +921,7 @@ DefineConsoleFunction( echoInputState, void, (), , "()" Con::printf( "DirectInput is not enabled." ); } -DefineConsoleFunction( rumble, void, (const char * device, F32 xRumble, F32 yRumble), , "(string device, float xRumble, float yRumble)" +DefineEngineFunction( rumble, void, (const char * device, F32 xRumble, F32 yRumble), , "(string device, float xRumble, float yRumble)" "@brief Activates the vibration motors in the specified controller.\n\n" "The controller will constantly at it's xRumble and yRumble intensities until " "changed or told to stop." diff --git a/Engine/source/platformWin32/winExec.cpp b/Engine/source/platformWin32/winExec.cpp index 6ec218929..3b9ad52b9 100644 --- a/Engine/source/platformWin32/winExec.cpp +++ b/Engine/source/platformWin32/winExec.cpp @@ -136,7 +136,7 @@ void ExecuteThread::run(void *arg /* = 0 */) // Console Functions //----------------------------------------------------------------------------- -DefineConsoleFunction( shellExecute, bool, (const char * executable, const char * args, const char * directory), ("", ""), "(string executable, string args, string directory)" +DefineEngineFunction( shellExecute, bool, (const char * executable, const char * args, const char * directory), ("", ""), "(string executable, string args, string directory)" "@brief Launches an outside executable or batch file\n\n" "@param executable Name of the executable or batch file\n" "@param args Optional list of arguments, in string format, to pass to the executable\n" diff --git a/Engine/source/platformWin32/winInput.cpp b/Engine/source/platformWin32/winInput.cpp index 2424eabdb..77eb38511 100644 --- a/Engine/source/platformWin32/winInput.cpp +++ b/Engine/source/platformWin32/winInput.cpp @@ -157,13 +157,13 @@ void Input::init() } //------------------------------------------------------------------------------ -DefineConsoleFunction( isJoystickDetected, bool, (), , "isJoystickDetected()") +DefineEngineFunction( isJoystickDetected, bool, (), , "isJoystickDetected()") { return( DInputDevice::joystickDetected() ); } //------------------------------------------------------------------------------ -DefineConsoleFunction( getJoystickAxes, const char*, (U32 deviceID), , "getJoystickAxes( instance )") +DefineEngineFunction( getJoystickAxes, const char*, (U32 deviceID), , "getJoystickAxes( instance )") { DInputManager* mgr = dynamic_cast( Input::getManager() ); if ( mgr ) @@ -505,7 +505,7 @@ void Input::log( const char* format, ... ) va_end( argptr ); } -DefineConsoleFunction( inputLog, void, (const char * log), , "inputLog( string )") +DefineEngineFunction( inputLog, void, (const char * log), , "inputLog( string )") { Input::log( "%s\n", log ); } diff --git a/Engine/source/platformWin32/winWindow.cpp b/Engine/source/platformWin32/winWindow.cpp index 63fb5ea54..0ce0f7cba 100644 --- a/Engine/source/platformWin32/winWindow.cpp +++ b/Engine/source/platformWin32/winWindow.cpp @@ -643,7 +643,7 @@ bool Platform::setLoginPassword( const char* password ) // as commentary on Koreans as a nationality. Thank you for your // attention. //-------------------------------------- -DefineConsoleFunction( isKoreanBuild, bool, ( ), , "isKoreanBuild()") +DefineEngineFunction( isKoreanBuild, bool, ( ), , "isKoreanBuild()") { HKEY regKey; bool result = false; diff --git a/Engine/source/scene/pathManager.cpp b/Engine/source/scene/pathManager.cpp index 2f1c423c3..7d9c88140 100644 --- a/Engine/source/scene/pathManager.cpp +++ b/Engine/source/scene/pathManager.cpp @@ -207,12 +207,12 @@ void PathManager::clearPaths() #endif } -DefineConsoleFunction( clearServerPaths, void, ( ), , "") +DefineEngineFunction( clearServerPaths, void, ( ), , "") { gServerPathManager->clearPaths(); } -DefineConsoleFunction( clearClientPaths, void, ( ), , "") +DefineEngineFunction( clearClientPaths, void, ( ), , "") { gClientPathManager->clearPaths(); } diff --git a/Engine/source/scene/sceneManager.cpp b/Engine/source/scene/sceneManager.cpp index aeca87092..706bc0da5 100644 --- a/Engine/source/scene/sceneManager.cpp +++ b/Engine/source/scene/sceneManager.cpp @@ -720,7 +720,7 @@ RenderPassManager* SceneManager::getDefaultRenderPass() const //----------------------------------------------------------------------------- -DefineConsoleFunction( sceneDumpZoneStates, void, ( bool updateFirst ), ( true ), +DefineEngineFunction( sceneDumpZoneStates, void, ( bool updateFirst ), ( true ), "Dump the current zoning states of all zone spaces in the scene to the console.\n\n" "@param updateFirst If true, zoning states are brought up to date first; if false, the zoning states " "are dumped as is.\n\n" @@ -745,7 +745,7 @@ DefineConsoleFunction( sceneDumpZoneStates, void, ( bool updateFirst ), ( true ) //----------------------------------------------------------------------------- -DefineConsoleFunction( sceneGetZoneOwner, SceneObject*, ( U32 zoneId ),, +DefineEngineFunction( sceneGetZoneOwner, SceneObject*, ( U32 zoneId ),, "Return the SceneObject that contains the given zone.\n\n" "@param zoneId ID of zone.\n" "@return A SceneObject or NULL if the given @a zoneId is invalid.\n\n" diff --git a/Engine/source/sfx/sfxSystem.cpp b/Engine/source/sfx/sfxSystem.cpp index b02d4fc67..0377aff90 100644 --- a/Engine/source/sfx/sfxSystem.cpp +++ b/Engine/source/sfx/sfxSystem.cpp @@ -1442,7 +1442,7 @@ static ConsoleDocFragment _sfxCreateSource4( NULL, "SFXSound sfxCreateSource( SFXDescription description, string filename, float x, float y, float z );" ); -DefineConsoleFunction( sfxCreateSource, S32, ( const char * sfxType, const char * arg0, const char * arg1, const char * arg2, const char * arg3 ), ("", "", "", ""), +DefineEngineFunction( sfxCreateSource, S32, ( const char * sfxType, const char * arg0, const char * arg1, const char * arg2, const char * arg3 ), ("", "", "", ""), "( SFXTrack track | ( SFXDescription description, string filename ) [, float x, float y, float z ] ) " "Creates a new paused sound source using a profile or a description " "and filename. The return value is the source which must be " @@ -1547,7 +1547,7 @@ static ConsoleDocFragment _sfxPlay3( NULL, "void sfxPlay( SFXTrack track, float x, float y, float z );" ); -DefineConsoleFunction( sfxPlay, S32, ( const char * trackName, const char * pointOrX, const char * y, const char * z ), ( "", "", ""), +DefineEngineFunction( sfxPlay, S32, ( const char * trackName, const char * pointOrX, const char * y, const char * z ), ( "", "", ""), "Start playing the given source or create a new source for the given track and play it.\n" "@hide" ) { @@ -1657,7 +1657,7 @@ static ConsoleDocFragment _sPlayOnce4( "SFXSource sfxPlayOnce( SFXDescription description, string filename, float x, float y, float z, float fadeInTime=-1 );" ); -DefineConsoleFunction( sfxPlayOnce, S32, ( const char * sfxType, const char * arg0, const char * arg1, const char * arg2, const char * arg3, const char* arg4 ), ("", "", "", "", "-1.0f"), +DefineEngineFunction( sfxPlayOnce, S32, ( const char * sfxType, const char * arg0, const char * arg1, const char * arg2, const char * arg3, const char* arg4 ), ("", "", "", "", "-1.0f"), "SFXSource sfxPlayOnce( ( SFXTrack track | SFXDescription description, string filename ) [, float x, float y, float z, float fadeInTime=-1 ] ) " "Create a new play-once source for the given profile or description+filename and start playback of the source.\n" "@hide" ) diff --git a/Engine/source/sim/netInterface.cpp b/Engine/source/sim/netInterface.cpp index 6d312df8a..fd2c51bc4 100644 --- a/Engine/source/sim/netInterface.cpp +++ b/Engine/source/sim/netInterface.cpp @@ -638,7 +638,7 @@ void NetInterface::computeNetMD5(const NetAddress *address, U32 connectSequence, ConsoleFunctionGroupBegin(NetInterface, "Global control functions for the netInterfaces."); -DefineConsoleFunction( allowConnections, void, ( bool allow ), , "allowConnections(bool allow)" +DefineEngineFunction( allowConnections, void, ( bool allow ), , "allowConnections(bool allow)" "@brief Sets whether or not the global NetInterface allows connections from remote hosts.\n\n" "@param allow Set to true to allow remote connections.\n" diff --git a/Engine/source/terrain/terrData.cpp b/Engine/source/terrain/terrData.cpp index 37f523356..78e991b63 100644 --- a/Engine/source/terrain/terrData.cpp +++ b/Engine/source/terrain/terrData.cpp @@ -147,7 +147,7 @@ ConsoleDocFragment _getTerrainUnderWorldPoint2( "bool getTerrainUnderWorldPoint( F32 x, F32 y, F32 z);" ); -DefineConsoleFunction( getTerrainUnderWorldPoint, S32, (const char* ptOrX, const char* y, const char* z), ("", ""), +DefineEngineFunction( getTerrainUnderWorldPoint, S32, (const char* ptOrX, const char* y, const char* z), ("", ""), "(Point3F x/y/z) Gets the terrain block that is located under the given world point.\n" "@param x/y/z The world coordinates (floating point values) you wish to query at. " "These can be formatted as either a string (\"x y z\") or separately as (x, y, z)\n" @@ -1338,7 +1338,7 @@ ConsoleDocFragment _getTerrainHeight2( "bool getTerrainHeight( F32 x, F32 y);" ); -DefineConsoleFunction( getTerrainHeight, F32, (const char* ptOrX, const char* y), (""), "(Point2 pos) - gets the terrain height at the specified position." +DefineEngineFunction( getTerrainHeight, F32, (const char* ptOrX, const char* y), (""), "(Point2 pos) - gets the terrain height at the specified position." "@param pos The world space point, minus the z (height) value\n Can be formatted as either (\"x y\") or (x,y)\n" "@return Returns the terrain height at the given point as an F32 value.\n" "@hide") @@ -1383,7 +1383,7 @@ ConsoleDocFragment _getTerrainHeightBelowPosition2( "bool getTerrainHeightBelowPosition( F32 x, F32 y);" ); -DefineConsoleFunction( getTerrainHeightBelowPosition, F32, (const char* ptOrX, const char* y, const char* z), ("", ""), +DefineEngineFunction( getTerrainHeightBelowPosition, F32, (const char* ptOrX, const char* y, const char* z), ("", ""), "(Point3F pos) - gets the terrain height at the specified position." "@param pos The world space point. Can be formatted as either (\"x y z\") or (x,y,z)\n" "@note This function is useful if you simply want to grab the terrain height underneath an object.\n" diff --git a/Engine/source/ts/collada/colladaImport.cpp b/Engine/source/ts/collada/colladaImport.cpp index 1cc2909b0..465e157ec 100644 --- a/Engine/source/ts/collada/colladaImport.cpp +++ b/Engine/source/ts/collada/colladaImport.cpp @@ -126,7 +126,7 @@ static void processNode(GuiTreeViewCtrl* tree, domNode* node, S32 parentID, Scen } } -DefineConsoleFunction( enumColladaForImport, bool, (const char * shapePath, const char * ctrl), , +DefineEngineFunction( enumColladaForImport, bool, (const char * shapePath, const char * ctrl), , "(string shapePath, GuiTreeViewCtrl ctrl) Collect scene information from " "a COLLADA file and store it in a GuiTreeView control. This function is " "used by the COLLADA import gui to show a preview of the scene contents " diff --git a/Engine/source/ts/collada/colladaLights.cpp b/Engine/source/ts/collada/colladaLights.cpp index bb699e4ff..fcc4bb67d 100644 --- a/Engine/source/ts/collada/colladaLights.cpp +++ b/Engine/source/ts/collada/colladaLights.cpp @@ -139,7 +139,7 @@ static void processNodeLights(AppNode* appNode, const MatrixF& offset, SimGroup* } // Load lights from a collada file and add to the scene. -DefineConsoleFunction( loadColladaLights, bool, (const char * filename, const char * parentGroup, const char * baseObject), ("", ""), +DefineEngineFunction( loadColladaLights, bool, (const char * filename, const char * parentGroup, const char * baseObject), ("", ""), "(string filename, SimGroup parentGroup=MissionGroup, SimObject baseObject=-1)" "Load all light instances from a COLLADA (.dae) file and add to the scene.\n" "@param filename COLLADA filename to load lights from\n" diff --git a/Engine/source/ts/loader/tsShapeLoader.cpp b/Engine/source/ts/loader/tsShapeLoader.cpp index 61c183d27..2ae067627 100644 --- a/Engine/source/ts/loader/tsShapeLoader.cpp +++ b/Engine/source/ts/loader/tsShapeLoader.cpp @@ -1325,14 +1325,14 @@ String TSShapeLoader::getFormatFilters() return output.end(); } -DefineConsoleFunction( getFormatExtensions, const char*, ( ),, +DefineEngineFunction( getFormatExtensions, const char*, ( ),, "Returns a list of supported shape format extensions separated by tabs." "Example output: *.dsq TAB *.dae TAB") { return Con::getReturnBuffer(TSShapeLoader::getFormatExtensions()); } -DefineConsoleFunction( getFormatFilters, const char*, ( ),, +DefineEngineFunction( getFormatFilters, const char*, ( ),, "Returns a list of supported shape formats in filter form.\n" "Example output: DSQ Files|*.dsq|COLLADA Files|*.dae|") { diff --git a/Engine/source/ts/tsLastDetail.cpp b/Engine/source/ts/tsLastDetail.cpp index 9619903b0..21dc8b415 100644 --- a/Engine/source/ts/tsLastDetail.cpp +++ b/Engine/source/ts/tsLastDetail.cpp @@ -543,7 +543,7 @@ void TSLastDetail::updateImposterImages( bool forceUpdate ) GFX->endScene(); } -DefineConsoleFunction( tsUpdateImposterImages, void, (bool forceUpdate), (false), "tsUpdateImposterImages( bool forceupdate )") +DefineEngineFunction( tsUpdateImposterImages, void, (bool forceUpdate), (false), "tsUpdateImposterImages( bool forceupdate )") { TSLastDetail::updateImposterImages(forceUpdate); } diff --git a/Engine/source/util/fpsTracker.cpp b/Engine/source/util/fpsTracker.cpp index ebf49b458..4013344e4 100644 --- a/Engine/source/util/fpsTracker.cpp +++ b/Engine/source/util/fpsTracker.cpp @@ -88,7 +88,7 @@ void FPSTracker::update() } } -DefineConsoleFunction( resetFPSTracker, void, (), , "()" +DefineEngineFunction( resetFPSTracker, void, (), , "()" "@brief Reset FPS stats (fps::)\n\n" "@ingroup Game") { diff --git a/Engine/source/util/messaging/dispatcher.cpp b/Engine/source/util/messaging/dispatcher.cpp index 2ae20ba17..d21f0dfdb 100644 --- a/Engine/source/util/messaging/dispatcher.cpp +++ b/Engine/source/util/messaging/dispatcher.cpp @@ -331,7 +331,7 @@ extern void unlockDispatcherMutex() using namespace Dispatcher; -DefineConsoleFunction( isQueueRegistered, bool, (const char * queueName), , "(string queueName)" +DefineEngineFunction( isQueueRegistered, bool, (const char * queueName), , "(string queueName)" "@brief Determines if a dispatcher queue exists\n\n" "@param queueName String containing the name of queue\n" "@ingroup Messaging") @@ -339,7 +339,7 @@ DefineConsoleFunction( isQueueRegistered, bool, (const char * queueName), , "(st return Dispatcher::isQueueRegistered(queueName); } -DefineConsoleFunction( registerMessageQueue, void, (const char *queueName), , "(string queueName)" +DefineEngineFunction( registerMessageQueue, void, (const char *queueName), , "(string queueName)" "@brief Registeres a dispatcher queue\n\n" "@param queueName String containing the name of queue\n" "@ingroup Messaging") @@ -347,7 +347,7 @@ DefineConsoleFunction( registerMessageQueue, void, (const char *queueName), , "( return Dispatcher::registerMessageQueue(queueName); } -DefineConsoleFunction( unregisterMessageQueue, void, (const char *queueName), , "(string queueName)" +DefineEngineFunction( unregisterMessageQueue, void, (const char *queueName), , "(string queueName)" "@brief Unregisters a dispatcher queue\n\n" "@param queueName String containing the name of queue\n" "@ingroup Messaging") @@ -357,7 +357,7 @@ DefineConsoleFunction( unregisterMessageQueue, void, (const char *queueName), , //----------------------------------------------------------------------------- -DefineConsoleFunction( registerMessageListener, bool, (const char *queueName, const char *listenerName), , "(string queueName, string listener)" +DefineEngineFunction( registerMessageListener, bool, (const char *queueName, const char *listenerName), , "(string queueName, string listener)" "@brief Registers an event message\n\n" "@param queueName String containing the name of queue to attach listener to\n" "@param listener Name of event messenger\n" @@ -373,7 +373,7 @@ DefineConsoleFunction( registerMessageListener, bool, (const char *queueName, co return Dispatcher::registerMessageListener(queueName, listener); } -DefineConsoleFunction( unregisterMessageListener, void, (const char *queueName, const char *listenerName), , "(string queueName, string listener)" +DefineEngineFunction( unregisterMessageListener, void, (const char *queueName, const char *listenerName), , "(string queueName, string listener)" "@brief Unregisters an event message\n\n" "@param queueName String containing the name of queue\n" "@param listener Name of event messenger\n" @@ -391,7 +391,7 @@ DefineConsoleFunction( unregisterMessageListener, void, (const char *queueName, //----------------------------------------------------------------------------- -DefineConsoleFunction( dispatchMessage, bool, (const char *queueName, const char *message, const char *data), (""), "(string queueName, string message, string data)" +DefineEngineFunction( dispatchMessage, bool, (const char *queueName, const char *message, const char *data), (""), "(string queueName, string message, string data)" "@brief Dispatch a message to a queue\n\n" "@param queueName Queue to dispatch the message to\n" "@param message Message to dispatch\n" @@ -403,7 +403,7 @@ DefineConsoleFunction( dispatchMessage, bool, (const char *queueName, const char return Dispatcher::dispatchMessage(queueName, message, data); } -DefineConsoleFunction( dispatchMessageObject, bool, (const char *queueName, const char *message), ("", ""), "(string queueName, string message)" +DefineEngineFunction( dispatchMessageObject, bool, (const char *queueName, const char *message), ("", ""), "(string queueName, string message)" "@brief Dispatch a message object to a queue\n\n" "@param queueName Queue to dispatch the message to\n" "@param message Message to dispatch\n" diff --git a/Engine/source/util/sampler.cpp b/Engine/source/util/sampler.cpp index 7e163d004..f4d051e1e 100644 --- a/Engine/source/util/sampler.cpp +++ b/Engine/source/util/sampler.cpp @@ -394,7 +394,7 @@ SAMPLE_FUNC( const char* ); // Console Functions. //-------------------------------------------------------------------------------- -DefineConsoleFunction( beginSampling, void, (const char * location, const char * backend), ("CSV"), "(location, [backend]) -" +DefineEngineFunction( beginSampling, void, (const char * location, const char * backend), ("CSV"), "(location, [backend]) -" "@brief Takes a string informing the backend where to store " "sample data and optionally a name of the specific logging " "backend to use. The default is the CSV backend. In most " @@ -408,14 +408,14 @@ DefineConsoleFunction( beginSampling, void, (const char * location, const char * beginSampling( location, backend ); } -DefineConsoleFunction( stopSampling, void, (), , "()" +DefineEngineFunction( stopSampling, void, (), , "()" "@brief Stops the rendering sampler\n\n" "@ingroup Rendering\n") { stopSampling(); } -DefineConsoleFunction( enableSamples, void, (const char * pattern, bool state), (true), "(pattern, [state]) -" +DefineEngineFunction( enableSamples, void, (const char * pattern, bool state), (true), "(pattern, [state]) -" "@brief Enable sampling for all keys that match the given name " "pattern. Slashes are treated as separators.\n\n" "@ingroup Rendering") From 76908eae3caea80ff131c8988b96c7d73c4558e8 Mon Sep 17 00:00:00 2001 From: Lukas Joergensen Date: Tue, 17 Apr 2018 21:01:50 +0200 Subject: [PATCH 06/34] Eliminate DefineConsoleMethod --- Engine/source/T3D/aiClient.cpp | 24 +++--- Engine/source/T3D/aiConnection.cpp | 14 ++-- Engine/source/T3D/aiPlayer.cpp | 2 +- .../camera/cameraComponent_ScriptBinding.h | 10 +-- .../collisionComponent_ScriptBinding.h | 14 ++-- Engine/source/T3D/components/component.cpp | 4 +- Engine/source/T3D/entity.cpp | 20 ++--- Engine/source/T3D/lightBase.cpp | 4 +- Engine/source/T3D/missionMarker.cpp | 2 +- Engine/source/T3D/physics/physicsDebris.cpp | 2 +- Engine/source/T3D/staticShape.cpp | 4 +- .../source/assets/assetQuery_ScriptBinding.h | 4 +- Engine/source/console/SimXMLDocument.cpp | 4 +- Engine/source/console/consoleLogger.cpp | 4 +- Engine/source/console/engineAPI.h | 2 +- Engine/source/console/fieldBrushObject.cpp | 8 +- Engine/source/console/persistenceManager.cpp | 26 +++---- Engine/source/console/simDatablock.cpp | 2 +- Engine/source/console/simObject.cpp | 58 +++++++------- Engine/source/console/simPersistSet.cpp | 2 +- Engine/source/console/simSet.cpp | 6 +- Engine/source/core/fileObject.cpp | 2 +- .../editors/guiMeshRoadEditorCtrl.cpp | 30 +++---- .../editors/guiRiverEditorCtrl.cpp | 28 +++---- .../environment/editors/guiRoadEditorCtrl.cpp | 22 +++--- Engine/source/environment/skyBox.cpp | 2 +- Engine/source/environment/sun.cpp | 4 +- .../forest/editor/forestBrushElement.cpp | 2 +- .../source/forest/editor/forestBrushTool.cpp | 2 +- .../source/forest/editor/forestEditorCtrl.cpp | 12 +-- .../forest/editor/forestSelectionTool.cpp | 12 +-- Engine/source/forest/forest.cpp | 8 +- .../source/gfx/video/theoraTextureObject.cpp | 6 +- .../gui/buttons/guiToolboxButtonCtrl.cpp | 6 +- Engine/source/gui/controls/guiBitmapCtrl.cpp | 2 +- Engine/source/gui/controls/guiColorPicker.cpp | 6 +- .../source/gui/controls/guiFileTreeCtrl.cpp | 6 +- .../source/gui/controls/guiGradientCtrl.cpp | 4 +- .../source/gui/controls/guiMaterialCtrl.cpp | 2 +- Engine/source/gui/controls/guiPopUpCtrl.cpp | 38 ++++----- Engine/source/gui/controls/guiPopUpCtrlEx.cpp | 18 ++--- Engine/source/gui/core/guiCanvas.cpp | 24 +++--- Engine/source/gui/core/guiControl.cpp | 2 +- Engine/source/gui/editor/guiDebugger.cpp | 16 ++-- Engine/source/gui/editor/guiEditCtrl.cpp | 56 ++++++------- Engine/source/gui/editor/guiFilterCtrl.cpp | 4 +- Engine/source/gui/editor/guiMenuBar.cpp | 12 +-- .../gui/editor/guiParticleGraphCtrl.cpp | 60 +++++++------- .../gui/editor/inspector/componentGroup.cpp | 2 +- .../gui/editor/inspector/dynamicField.cpp | 2 +- .../gui/editor/inspector/dynamicGroup.cpp | 6 +- Engine/source/gui/editor/inspector/field.cpp | 18 ++--- .../gui/editor/inspector/variableGroup.cpp | 4 +- .../editor/inspector/variableInspector.cpp | 16 ++-- Engine/source/gui/editor/popupMenu.cpp | 20 ++--- .../gui/game/guiIdleCamFadeBitmapCtrl.cpp | 4 +- Engine/source/gui/shiny/guiTickCtrl.cpp | 2 +- Engine/source/gui/utility/messageVector.cpp | 2 +- Engine/source/gui/worldEditor/creator.cpp | 18 ++--- Engine/source/gui/worldEditor/editor.cpp | 10 +-- .../worldEditor/guiConvexShapeEditorCtrl.cpp | 16 ++-- .../gui/worldEditor/guiDecalEditorCtrl.cpp | 22 +++--- .../gui/worldEditor/guiMissionAreaEditor.cpp | 4 +- .../gui/worldEditor/guiTerrPreviewCtrl.cpp | 14 ++-- .../source/gui/worldEditor/terrainActions.cpp | 2 +- .../source/gui/worldEditor/terrainEditor.cpp | 78 +++++++++---------- Engine/source/gui/worldEditor/worldEditor.cpp | 2 +- Engine/source/i18n/lang.cpp | 14 ++-- .../source/materials/materialDefinition.cpp | 14 ++-- Engine/source/math/util/tResponseCurve.cpp | 6 +- Engine/source/scene/sceneObject.cpp | 2 +- Engine/source/sfx/sfxSource.cpp | 2 +- Engine/source/terrain/terrExport.cpp | 4 +- Engine/source/util/messaging/eventManager.cpp | 18 ++--- Engine/source/util/messaging/message.cpp | 6 +- Engine/source/util/settings.cpp | 22 +++--- Engine/source/util/undo.cpp | 34 ++++---- 77 files changed, 483 insertions(+), 483 deletions(-) diff --git a/Engine/source/T3D/aiClient.cpp b/Engine/source/T3D/aiClient.cpp index 1f4be793b..8801e3460 100644 --- a/Engine/source/T3D/aiClient.cpp +++ b/Engine/source/T3D/aiClient.cpp @@ -418,7 +418,7 @@ void AIClient::onAdd( const char *nameSpace ) { /** * Sets the move speed for an AI object */ -DefineConsoleMethod( AIClient, setMoveSpeed, void, (F32 speed), , "ai.setMoveSpeed( float );" ) +DefineEngineMethod( AIClient, setMoveSpeed, void, (F32 speed), , "ai.setMoveSpeed( float );" ) { AIClient *ai = static_cast( object ); ai->setMoveSpeed( speed ); @@ -427,7 +427,7 @@ DefineConsoleMethod( AIClient, setMoveSpeed, void, (F32 speed), , "ai.setMoveSpe /** * Stops all AI movement, halt! */ -DefineConsoleMethod( AIClient, stop, void, (),, "ai.stop();" ) +DefineEngineMethod( AIClient, stop, void, (),, "ai.stop();" ) { AIClient *ai = static_cast( object ); ai->setMoveMode( AIClient::ModeStop ); @@ -436,7 +436,7 @@ DefineConsoleMethod( AIClient, stop, void, (),, "ai.stop();" ) /** * Tells the AI to aim at the location provided */ -DefineConsoleMethod( AIClient, setAimLocation, void, (Point3F v), , "ai.setAimLocation( x y z );" ) +DefineEngineMethod( AIClient, setAimLocation, void, (Point3F v), , "ai.setAimLocation( x y z );" ) { AIClient *ai = static_cast( object ); @@ -446,7 +446,7 @@ DefineConsoleMethod( AIClient, setAimLocation, void, (Point3F v), , "ai.setAimLo /** * Tells the AI to move to the location provided */ -DefineConsoleMethod( AIClient, setMoveDestination, void, (Point3F v), , "ai.setMoveDestination( x y z );" ) +DefineEngineMethod( AIClient, setMoveDestination, void, (Point3F v), , "ai.setMoveDestination( x y z );" ) { AIClient *ai = static_cast( object ); @@ -456,7 +456,7 @@ DefineConsoleMethod( AIClient, setMoveDestination, void, (Point3F v), , "ai.setM /** * Returns the point the AI is aiming at */ -DefineConsoleMethod( AIClient, getAimLocation, Point3F, (),, "ai.getAimLocation();" ) +DefineEngineMethod( AIClient, getAimLocation, Point3F, (),, "ai.getAimLocation();" ) { AIClient *ai = static_cast( object ); return ai->getAimLocation(); @@ -465,7 +465,7 @@ DefineConsoleMethod( AIClient, getAimLocation, Point3F, (),, "ai.getAimLocation( /** * Returns the point the AI is set to move to */ -DefineConsoleMethod( AIClient, getMoveDestination, Point3F, (),, "ai.getMoveDestination();" ) +DefineEngineMethod( AIClient, getMoveDestination, Point3F, (),, "ai.getMoveDestination();" ) { AIClient *ai = static_cast( object ); return ai->getMoveDestination(); @@ -474,7 +474,7 @@ DefineConsoleMethod( AIClient, getMoveDestination, Point3F, (),, "ai.getMoveDest /** * Sets the bots target object */ -DefineConsoleMethod( AIClient, setTargetObject, void, (const char * objName), , "ai.setTargetObject( obj );" ) +DefineEngineMethod( AIClient, setTargetObject, void, (const char * objName), , "ai.setTargetObject( obj );" ) { AIClient *ai = static_cast( object ); @@ -489,7 +489,7 @@ DefineConsoleMethod( AIClient, setTargetObject, void, (const char * objName), , /** * Gets the object the AI is targeting */ -DefineConsoleMethod( AIClient, getTargetObject, S32, (),, "ai.getTargetObject();" ) +DefineEngineMethod( AIClient, getTargetObject, S32, (),, "ai.getTargetObject();" ) { AIClient *ai = static_cast( object ); @@ -499,7 +499,7 @@ DefineConsoleMethod( AIClient, getTargetObject, S32, (),, "ai.getTargetObject(); /** * Tells the bot the mission is cycling */ -DefineConsoleMethod( AIClient, missionCycleCleanup, void, (),, "ai.missionCycleCleanup();" ) +DefineEngineMethod( AIClient, missionCycleCleanup, void, (),, "ai.missionCycleCleanup();" ) { AIClient *ai = static_cast( object ); ai->missionCycleCleanup(); @@ -508,7 +508,7 @@ DefineConsoleMethod( AIClient, missionCycleCleanup, void, (),, "ai.missionCycleC /** * Sets the AI to run mode */ -DefineConsoleMethod( AIClient, move, void, (),, "ai.move();" ) +DefineEngineMethod( AIClient, move, void, (),, "ai.move();" ) { AIClient *ai = static_cast( object ); ai->setMoveMode( AIClient::ModeMove ); @@ -517,7 +517,7 @@ DefineConsoleMethod( AIClient, move, void, (),, "ai.move();" ) /** * Gets the AI's location in the world */ -DefineConsoleMethod( AIClient, getLocation, Point3F, (),, "ai.getLocation();" ) +DefineEngineMethod( AIClient, getLocation, Point3F, (),, "ai.getLocation();" ) { AIClient *ai = static_cast( object ); return ai->getLocation(); @@ -559,7 +559,7 @@ DefineEngineFunction( aiAddPlayer, S32, (const char * name, const char * ns), (" /** * Tells the AI to move forward 100 units...TEST FXN */ -DefineConsoleMethod( AIClient, moveForward, void, (),, "ai.moveForward();" ) +DefineEngineMethod( AIClient, moveForward, void, (),, "ai.moveForward();" ) { AIClient *ai = static_cast( object ); diff --git a/Engine/source/T3D/aiConnection.cpp b/Engine/source/T3D/aiConnection.cpp index af60b1d3c..21564d5eb 100644 --- a/Engine/source/T3D/aiConnection.cpp +++ b/Engine/source/T3D/aiConnection.cpp @@ -160,7 +160,7 @@ ConsoleFunction(aiConnect, S32 , 2, 20, "(...)" //----------------------------------------------------------------------------- -DefineConsoleMethod(AIConnection, setMove, void, (const char * field, F32 value), ,"(string field, float value)" +DefineEngineMethod(AIConnection, setMove, void, (const char * field, F32 value), ,"(string field, float value)" "Set a field on the current move.\n\n" "@param field One of {'x','y','z','yaw','pitch','roll'}\n" "@param value Value to set field to.") @@ -190,7 +190,7 @@ DefineConsoleMethod(AIConnection, setMove, void, (const char * field, F32 value) object->setMove(&move); } -DefineConsoleMethod(AIConnection,getMove,F32, (const char * field), ,"(string field)" +DefineEngineMethod(AIConnection,getMove,F32, (const char * field), ,"(string field)" "Get the given field of a move.\n\n" "@param field One of {'x','y','z','yaw','pitch','roll'}\n" "@returns The requested field on the current move.") @@ -212,7 +212,7 @@ DefineConsoleMethod(AIConnection,getMove,F32, (const char * field), ,"(string fi } -DefineConsoleMethod(AIConnection,setFreeLook,void,(bool isFreeLook), ,"(bool isFreeLook)" +DefineEngineMethod(AIConnection,setFreeLook,void,(bool isFreeLook), ,"(bool isFreeLook)" "Enable/disable freelook on the current move.") { Move move = object->getMove(); @@ -220,7 +220,7 @@ DefineConsoleMethod(AIConnection,setFreeLook,void,(bool isFreeLook), ,"(bool isF object->setMove(&move); } -DefineConsoleMethod(AIConnection, getFreeLook, bool, (), ,"getFreeLook()" +DefineEngineMethod(AIConnection, getFreeLook, bool, (), ,"getFreeLook()" "Is freelook on for the current move?") { return object->getMove().freeLook; @@ -229,7 +229,7 @@ DefineConsoleMethod(AIConnection, getFreeLook, bool, (), ,"getFreeLook()" //----------------------------------------------------------------------------- -DefineConsoleMethod(AIConnection,setTrigger,void, (S32 idx, bool set), ,"(int trigger, bool set)" +DefineEngineMethod(AIConnection,setTrigger,void, (S32 idx, bool set), ,"(int trigger, bool set)" "Set a trigger.") { if (idx >= 0 && idx < MaxTriggerKeys) @@ -240,7 +240,7 @@ DefineConsoleMethod(AIConnection,setTrigger,void, (S32 idx, bool set), ,"(int tr } } -DefineConsoleMethod(AIConnection,getTrigger,bool, (S32 idx), ,"(int trigger)" +DefineEngineMethod(AIConnection,getTrigger,bool, (S32 idx), ,"(int trigger)" "Is the given trigger set?") { if (idx >= 0 && idx < MaxTriggerKeys) @@ -251,7 +251,7 @@ DefineConsoleMethod(AIConnection,getTrigger,bool, (S32 idx), ,"(int trigger)" //----------------------------------------------------------------------------- -DefineConsoleMethod(AIConnection,getAddress,const char*,(), ,"") +DefineEngineMethod(AIConnection,getAddress,const char*,(), ,"") { // Override the netConnection method to return to indicate // this is an ai connection. diff --git a/Engine/source/T3D/aiPlayer.cpp b/Engine/source/T3D/aiPlayer.cpp index 6e1c39328..565bb742c 100644 --- a/Engine/source/T3D/aiPlayer.cpp +++ b/Engine/source/T3D/aiPlayer.cpp @@ -1251,7 +1251,7 @@ ConsoleDocFragment _setAimObject( "void setAimObject(GameBase targetObject, Point3F offset);" ); -DefineConsoleMethod( AIPlayer, setAimObject, void, ( const char * objName, Point3F offset ), (Point3F::Zero), "( GameBase obj, [Point3F offset] )" +DefineEngineMethod( AIPlayer, setAimObject, void, ( const char * objName, Point3F offset ), (Point3F::Zero), "( GameBase obj, [Point3F offset] )" "Sets the bot's target object. Optionally set an offset from target location." "@hide") { diff --git a/Engine/source/T3D/components/camera/cameraComponent_ScriptBinding.h b/Engine/source/T3D/components/camera/cameraComponent_ScriptBinding.h index 2c3f1dbef..d3b7f9883 100644 --- a/Engine/source/T3D/components/camera/cameraComponent_ScriptBinding.h +++ b/Engine/source/T3D/components/camera/cameraComponent_ScriptBinding.h @@ -30,7 +30,7 @@ ConsoleMethod(CameraComponent, getMode, const char*, 2, 2, "() - We get the firs return "fly"; } -DefineConsoleMethod(CameraComponent, getForwardVector, VectorF, (), , +DefineEngineMethod(CameraComponent, getForwardVector, VectorF, (), , "Get the number of static fields on the object.\n" "@return The number of static fields defined on the object.") { @@ -44,7 +44,7 @@ DefineConsoleMethod(CameraComponent, getForwardVector, VectorF, (), , return returnVec; } -DefineConsoleMethod(CameraComponent, getRightVector, VectorF, (), , +DefineEngineMethod(CameraComponent, getRightVector, VectorF, (), , "Get the number of static fields on the object.\n" "@return The number of static fields defined on the object.") { @@ -58,7 +58,7 @@ DefineConsoleMethod(CameraComponent, getRightVector, VectorF, (), , return returnVec; } -DefineConsoleMethod(CameraComponent, getUpVector, VectorF, (), , +DefineEngineMethod(CameraComponent, getUpVector, VectorF, (), , "Get the number of static fields on the object.\n" "@return The number of static fields defined on the object.") { @@ -72,14 +72,14 @@ DefineConsoleMethod(CameraComponent, getUpVector, VectorF, (), , return returnVec; } -DefineConsoleMethod(CameraComponent, setForwardVector, void, (VectorF newForward), (VectorF(0, 0, 0)), +DefineEngineMethod(CameraComponent, setForwardVector, void, (VectorF newForward), (VectorF(0, 0, 0)), "Get the number of static fields on the object.\n" "@return The number of static fields defined on the object.") { object->setForwardVector(newForward); } -DefineConsoleMethod(CameraComponent, getWorldPosition, Point3F, (), , +DefineEngineMethod(CameraComponent, getWorldPosition, Point3F, (), , "Get the number of static fields on the object.\n" "@return The number of static fields defined on the object.") { diff --git a/Engine/source/T3D/components/collision/collisionComponent_ScriptBinding.h b/Engine/source/T3D/components/collision/collisionComponent_ScriptBinding.h index 3b8e83d11..30c41da2b 100644 --- a/Engine/source/T3D/components/collision/collisionComponent_ScriptBinding.h +++ b/Engine/source/T3D/components/collision/collisionComponent_ScriptBinding.h @@ -24,21 +24,21 @@ #include "T3D/components/collision/collisionComponent.h" #include "materials/baseMatInstance.h" -DefineConsoleMethod(CollisionComponent, getNumberOfContacts, S32, (), , +DefineEngineMethod(CollisionComponent, getNumberOfContacts, S32, (), , "Gets the number of contacts this collider has hit.\n" "@return The number of static fields defined on the object.") { return object->getCollisionList()->getCount(); } -DefineConsoleMethod(CollisionComponent, getBestContact, S32, (), , +DefineEngineMethod(CollisionComponent, getBestContact, S32, (), , "Gets the number of contacts this collider has hit.\n" "@return The number of static fields defined on the object.") { return 0; } -DefineConsoleMethod(CollisionComponent, getContactNormal, Point3F, (), , +DefineEngineMethod(CollisionComponent, getContactNormal, Point3F, (), , "Gets the number of contacts this collider has hit.\n" "@return The number of static fields defined on the object.") { @@ -53,7 +53,7 @@ DefineConsoleMethod(CollisionComponent, getContactNormal, Point3F, (), , return Point3F::Zero; } -DefineConsoleMethod(CollisionComponent, getContactMaterial, S32, (), , +DefineEngineMethod(CollisionComponent, getContactMaterial, S32, (), , "Gets the number of contacts this collider has hit.\n" "@return The number of static fields defined on the object.") { @@ -69,7 +69,7 @@ DefineConsoleMethod(CollisionComponent, getContactMaterial, S32, (), , return 0; } -DefineConsoleMethod(CollisionComponent, getContactObject, S32, (), , +DefineEngineMethod(CollisionComponent, getContactObject, S32, (), , "Gets the number of contacts this collider has hit.\n" "@return The number of static fields defined on the object.") { @@ -81,7 +81,7 @@ DefineConsoleMethod(CollisionComponent, getContactObject, S32, (), , return 0; } -DefineConsoleMethod(CollisionComponent, getContactPoint, Point3F, (), , +DefineEngineMethod(CollisionComponent, getContactPoint, Point3F, (), , "Gets the number of contacts this collider has hit.\n" "@return The number of static fields defined on the object.") { @@ -96,7 +96,7 @@ DefineConsoleMethod(CollisionComponent, getContactPoint, Point3F, (), , return Point3F::Zero; } -DefineConsoleMethod(CollisionComponent, getContactTime, S32, (), , +DefineEngineMethod(CollisionComponent, getContactTime, S32, (), , "Gets the number of contacts this collider has hit.\n" "@return The number of static fields defined on the object.") { diff --git a/Engine/source/T3D/components/component.cpp b/Engine/source/T3D/components/component.cpp index c7f9dcc2c..83fc015f1 100644 --- a/Engine/source/T3D/components/component.cpp +++ b/Engine/source/T3D/components/component.cpp @@ -633,7 +633,7 @@ ConsoleMethod(Component, endGroup, void, 2, 2, "()\n" object->endFieldGroup(); } -DefineConsoleMethod(Component, addComponentField, void, (String fieldName, String fieldDesc, String fieldType, String defValue, String userData, bool hidden), +DefineEngineMethod(Component, addComponentField, void, (String fieldName, String fieldDesc, String fieldType, String defValue, String userData, bool hidden), ("", "", "", "", "", false), "Get the number of static fields on the object.\n" "@return The number of static fields defined on the object.") @@ -678,7 +678,7 @@ ConsoleMethod(Component, setComponentield, const char *, 3, 3, "(int index) - Ge return buf; } -DefineConsoleMethod(Component, getComponentFieldType, const char *, (String fieldName), , +DefineEngineMethod(Component, getComponentFieldType, const char *, (String fieldName), , "Get the number of static fields on the object.\n" "@return The number of static fields defined on the object.") { diff --git a/Engine/source/T3D/entity.cpp b/Engine/source/T3D/entity.cpp index fe0303652..587eb145b 100644 --- a/Engine/source/T3D/entity.cpp +++ b/Engine/source/T3D/entity.cpp @@ -1800,7 +1800,7 @@ DefineEngineMethod(Entity, setBox, void, } -/*DefineConsoleMethod(Entity, callOnComponents, void, (const char* functionName), , +/*DefineEngineMethod(Entity, callOnComponents, void, (const char* functionName), , "Get the number of static fields on the object.\n" "@return The number of static fields defined on the object.") { @@ -1875,7 +1875,7 @@ ConsoleMethod(Entity, getComponentByIndex, S32, 3, 3, "(int index) - Gets a part return (comp != NULL) ? comp->getId() : 0; } -DefineConsoleMethod(Entity, getComponent, S32, (String componentName), (""), +DefineEngineMethod(Entity, getComponent, S32, (String componentName), (""), "Get the number of static fields on the object.\n" "@return The number of static fields defined on the object.") { @@ -1916,7 +1916,7 @@ ConsoleMethod(Entity, getComponentCount, S32, 2, 2, "() - Get the count of behav return object->getComponentCount(); } -DefineConsoleMethod(Entity, setComponentDirty, void, (S32 componentID, bool forceUpdate), (0, false), +DefineEngineMethod(Entity, setComponentDirty, void, (S32 componentID, bool forceUpdate), (0, false), "Get the number of static fields on the object.\n" "@return The number of static fields defined on the object.") { @@ -1925,7 +1925,7 @@ DefineConsoleMethod(Entity, setComponentDirty, void, (S32 componentID, bool forc object->setComponentDirty(comp, forceUpdate);*/ } -DefineConsoleMethod(Entity, getMoveVector, VectorF, (),, +DefineEngineMethod(Entity, getMoveVector, VectorF, (),, "Get the number of static fields on the object.\n" "@return The number of static fields defined on the object.") { @@ -1939,7 +1939,7 @@ DefineConsoleMethod(Entity, getMoveVector, VectorF, (),, return VectorF::Zero; } -DefineConsoleMethod(Entity, getMoveRotation, VectorF, (), , +DefineEngineMethod(Entity, getMoveRotation, VectorF, (), , "Get the number of static fields on the object.\n" "@return The number of static fields defined on the object.") { @@ -1953,7 +1953,7 @@ DefineConsoleMethod(Entity, getMoveRotation, VectorF, (), , return VectorF::Zero; } -DefineConsoleMethod(Entity, getMoveTrigger, bool, (S32 triggerNum), (0), +DefineEngineMethod(Entity, getMoveTrigger, bool, (S32 triggerNum), (0), "Get the number of static fields on the object.\n" "@return The number of static fields defined on the object.") { @@ -1974,28 +1974,28 @@ DefineEngineMethod(Entity, getForwardVector, VectorF, (), , return forVec; } -DefineConsoleMethod(Entity, setForwardVector, void, (VectorF newForward), (VectorF(0,0,0)), +DefineEngineMethod(Entity, setForwardVector, void, (VectorF newForward), (VectorF(0,0,0)), "Get the number of static fields on the object.\n" "@return The number of static fields defined on the object.") { object->setForwardVector(newForward); } -DefineConsoleMethod(Entity, lookAt, void, (Point3F lookPosition),, +DefineEngineMethod(Entity, lookAt, void, (Point3F lookPosition),, "Get the number of static fields on the object.\n" "@return The number of static fields defined on the object.") { //object->setForwardVector(newForward); } -DefineConsoleMethod(Entity, rotateTo, void, (Point3F lookPosition, F32 degreePerSecond), (1.0), +DefineEngineMethod(Entity, rotateTo, void, (Point3F lookPosition, F32 degreePerSecond), (1.0), "Get the number of static fields on the object.\n" "@return The number of static fields defined on the object.") { //object->setForwardVector(newForward); } -DefineConsoleMethod(Entity, notify, void, (String signalFunction, String argA, String argB, String argC, String argD, String argE), +DefineEngineMethod(Entity, notify, void, (String signalFunction, String argA, String argB, String argC, String argD, String argE), ("", "", "", "", "", ""), "Triggers a signal call to all components for a certain function.") { diff --git a/Engine/source/T3D/lightBase.cpp b/Engine/source/T3D/lightBase.cpp index 6cc739ed3..007f2ca32 100644 --- a/Engine/source/T3D/lightBase.cpp +++ b/Engine/source/T3D/lightBase.cpp @@ -440,7 +440,7 @@ static ConsoleDocFragment _lbplayAnimation2( "void playAnimation(LightAnimData anim);" ); -DefineConsoleMethod( LightBase, playAnimation, void, (const char * anim), (""), "( [LightAnimData anim] )\t" +DefineEngineMethod( LightBase, playAnimation, void, (const char * anim), (""), "( [LightAnimData anim] )\t" "Plays a light animation on the light. If no LightAnimData is passed the " "existing one is played." "@hide") @@ -484,7 +484,7 @@ void LightBase::playAnimation( LightAnimData *animData ) } } -DefineConsoleMethod( LightBase, pauseAnimation, void, (), , "Stops the light animation." ) +DefineEngineMethod( LightBase, pauseAnimation, void, (), , "Stops the light animation." ) { object->pauseAnimation(); } diff --git a/Engine/source/T3D/missionMarker.cpp b/Engine/source/T3D/missionMarker.cpp index 1480e2f1f..ff4fc3c0d 100644 --- a/Engine/source/T3D/missionMarker.cpp +++ b/Engine/source/T3D/missionMarker.cpp @@ -494,7 +494,7 @@ ConsoleDocFragment _SpawnSpherespawnObject1( "bool spawnObject(string additionalProps);" ); -DefineConsoleMethod(SpawnSphere, spawnObject, S32, (String additionalProps), , +DefineEngineMethod(SpawnSphere, spawnObject, S32, (String additionalProps), , "([string additionalProps]) Spawns the object based on the SpawnSphere's " "class, datablock, properties, and script settings. Allows you to pass in " "extra properties." diff --git a/Engine/source/T3D/physics/physicsDebris.cpp b/Engine/source/T3D/physics/physicsDebris.cpp index a2e2026b3..90a225ff4 100644 --- a/Engine/source/T3D/physics/physicsDebris.cpp +++ b/Engine/source/T3D/physics/physicsDebris.cpp @@ -238,7 +238,7 @@ void PhysicsDebrisData::unpackData(BitStream* stream) shapeName = stream->readSTString(); } -DefineConsoleMethod( PhysicsDebrisData, preload, void, (), , +DefineEngineMethod( PhysicsDebrisData, preload, void, (), , "@brief Loads some information to have readily available at simulation time.\n\n" "Forces generation of shaders, materials, and other data used by the %PhysicsDebris object. " "This function should be used while a level is loading in order to shorten " diff --git a/Engine/source/T3D/staticShape.cpp b/Engine/source/T3D/staticShape.cpp index 874e31059..9bc7369e1 100644 --- a/Engine/source/T3D/staticShape.cpp +++ b/Engine/source/T3D/staticShape.cpp @@ -314,7 +314,7 @@ void StaticShape::unpackUpdate(NetConnection *connection, BitStream *bstream) // This appears to be legacy T2 stuff // Marked internal, as this is flagged to be deleted // [8/1/2010 mperry] -DefineConsoleMethod( StaticShape, setPoweredState, void, (bool isPowered), , "(bool isPowered)" +DefineEngineMethod( StaticShape, setPoweredState, void, (bool isPowered), , "(bool isPowered)" "@internal") { if(!object->isServerObject()) @@ -322,7 +322,7 @@ DefineConsoleMethod( StaticShape, setPoweredState, void, (bool isPowered), , "(b object->setPowered(isPowered); } -DefineConsoleMethod( StaticShape, getPoweredState, bool, (), , "@internal") +DefineEngineMethod( StaticShape, getPoweredState, bool, (), , "@internal") { if(!object->isServerObject()) return(false); diff --git a/Engine/source/assets/assetQuery_ScriptBinding.h b/Engine/source/assets/assetQuery_ScriptBinding.h index 1656d2eb3..71cc58f1a 100644 --- a/Engine/source/assets/assetQuery_ScriptBinding.h +++ b/Engine/source/assets/assetQuery_ScriptBinding.h @@ -59,7 +59,7 @@ DefineEngineMethod(AssetQuery, set, bool, (S32 queryId), , //----------------------------------------------------------------------------- -DefineConsoleMethod(AssetQuery, getCount, S32, (), , +DefineEngineMethod(AssetQuery, getCount, S32, (), , "Gets the count of asset Id results.\n" "@return (int)The count of asset Id results.\n") { @@ -68,7 +68,7 @@ DefineConsoleMethod(AssetQuery, getCount, S32, (), , //----------------------------------------------------------------------------- -DefineConsoleMethod(AssetQuery, getAsset, const char*, (S32 resultIndex), (-1), +DefineEngineMethod(AssetQuery, getAsset, const char*, (S32 resultIndex), (-1), "Gets the asset Id at the specified query result index.\n" "@param resultIndex The query result index to use.\n" "@return (assetId)The asset Id at the specified index or NULL if not valid.\n") diff --git a/Engine/source/console/SimXMLDocument.cpp b/Engine/source/console/SimXMLDocument.cpp index 156533503..df45888d1 100644 --- a/Engine/source/console/SimXMLDocument.cpp +++ b/Engine/source/console/SimXMLDocument.cpp @@ -571,7 +571,7 @@ DefineEngineMethod( SimXMLDocument, attribute, const char*, ( const char* attrib } // These two methods don't make a lot of sense the way TS works. Leaving them in for backwards-compatibility. -DefineConsoleMethod( SimXMLDocument, attributeF32, F32, (const char * attributeName), , "(string attributeName)" +DefineEngineMethod( SimXMLDocument, attributeF32, F32, (const char * attributeName), , "(string attributeName)" "@brief Get float attribute from the current Element on the stack.\n\n" "@param attributeName Name of attribute to retrieve.\n" "@return The value of the given attribute in the form of a float.\n" @@ -580,7 +580,7 @@ DefineConsoleMethod( SimXMLDocument, attributeF32, F32, (const char * attributeN return dAtof( object->attribute( attributeName ) ); } -DefineConsoleMethod(SimXMLDocument, attributeS32, S32, (const char * attributeName), , "(string attributeName)" +DefineEngineMethod(SimXMLDocument, attributeS32, S32, (const char * attributeName), , "(string attributeName)" "@brief Get int attribute from the current Element on the stack.\n\n" "@param attributeName Name of attribute to retrieve.\n" "@return The value of the given attribute in the form of an integer.\n" diff --git a/Engine/source/console/consoleLogger.cpp b/Engine/source/console/consoleLogger.cpp index 84347a332..fc2095eae 100644 --- a/Engine/source/console/consoleLogger.cpp +++ b/Engine/source/console/consoleLogger.cpp @@ -225,7 +225,7 @@ void ConsoleLogger::log( const char *consoleLine ) //----------------------------------------------------------------------------- -DefineConsoleMethod( ConsoleLogger, attach, bool, (), , "() Attaches the logger to the console and begins writing to file" +DefineEngineMethod( ConsoleLogger, attach, bool, (), , "() Attaches the logger to the console and begins writing to file" "@tsexample\n" "// Create the logger\n" "// Will automatically start writing to testLogging.txt with normal priority\n" @@ -247,7 +247,7 @@ DefineConsoleMethod( ConsoleLogger, attach, bool, (), , "() Attaches the logger //----------------------------------------------------------------------------- -DefineConsoleMethod( ConsoleLogger, detach, bool, (), , "() Detaches the logger from the console and stops writing to file" +DefineEngineMethod( ConsoleLogger, detach, bool, (), , "() Detaches the logger from the console and stops writing to file" "@tsexample\n" "// Create the logger\n" "// Will automatically start writing to testLogging.txt with normal priority\n" diff --git a/Engine/source/console/engineAPI.h b/Engine/source/console/engineAPI.h index 2eef409b6..ca7ca8a1d 100644 --- a/Engine/source/console/engineAPI.h +++ b/Engine/source/console/engineAPI.h @@ -861,7 +861,7 @@ public: // these macros can be removed and all definitions that make use of them can be removed // as well. -#define DefineConsoleMethod( className, name, returnType, args, defaultArgs, usage ) \ +#define DefineEngineMethod( className, name, returnType, args, defaultArgs, usage ) \ struct _ ## className ## name ## frame \ { \ typedef className ObjectType; \ diff --git a/Engine/source/console/fieldBrushObject.cpp b/Engine/source/console/fieldBrushObject.cpp index 0caf00e48..6ec9ace0d 100644 --- a/Engine/source/console/fieldBrushObject.cpp +++ b/Engine/source/console/fieldBrushObject.cpp @@ -123,7 +123,7 @@ static char* suppressSpaces(const char* in_pname) //----------------------------------------------------------------------------- // Query Groups. //----------------------------------------------------------------------------- -DefineConsoleMethod(FieldBrushObject, queryGroups, const char*, (const char* simObjName), , "(simObject) Query available static-field groups for selected object./\n" +DefineEngineMethod(FieldBrushObject, queryGroups, const char*, (const char* simObjName), , "(simObject) Query available static-field groups for selected object./\n" "@param simObject Object to query static-field groups on.\n" "@return Space-seperated static-field group list.") { @@ -191,7 +191,7 @@ DefineConsoleMethod(FieldBrushObject, queryGroups, const char*, (const char* sim //----------------------------------------------------------------------------- // Query Fields. //----------------------------------------------------------------------------- -DefineConsoleMethod(FieldBrushObject, queryFields, const char*, (const char* simObjName, const char* groupList), (""), "(simObject, [groupList]) Query available static-fields for selected object./\n" +DefineEngineMethod(FieldBrushObject, queryFields, const char*, (const char* simObjName, const char* groupList), (""), "(simObject, [groupList]) Query available static-fields for selected object./\n" "@param simObject Object to query static-fields on.\n" "@param groupList groups to filter static-fields against.\n" "@return Space-seperated static-field list.") @@ -366,7 +366,7 @@ DefineConsoleMethod(FieldBrushObject, queryFields, const char*, (const char* sim //----------------------------------------------------------------------------- // Copy Fields. //----------------------------------------------------------------------------- -DefineConsoleMethod(FieldBrushObject, copyFields, void, (const char* simObjName, const char* pFieldList), (""), "(simObject, [fieldList]) Copy selected static-fields for selected object./\n" +DefineEngineMethod(FieldBrushObject, copyFields, void, (const char* simObjName, const char* pFieldList), (""), "(simObject, [fieldList]) Copy selected static-fields for selected object./\n" "@param simObject Object to copy static-fields from.\n" "@param fieldList fields to filter static-fields against.\n" "@return No return value.") @@ -500,7 +500,7 @@ void FieldBrushObject::copyFields( SimObject* pSimObject, const char* fieldList //----------------------------------------------------------------------------- // Paste Fields. //----------------------------------------------------------------------------- -DefineConsoleMethod(FieldBrushObject, pasteFields, void, (const char* simObjName), , "(simObject) Paste copied static-fields to selected object./\n" +DefineEngineMethod(FieldBrushObject, pasteFields, void, (const char* simObjName), , "(simObject) Paste copied static-fields to selected object./\n" "@param simObject Object to paste static-fields to.\n" "@return No return value.") { diff --git a/Engine/source/console/persistenceManager.cpp b/Engine/source/console/persistenceManager.cpp index 56812cd4b..75f209237 100644 --- a/Engine/source/console/persistenceManager.cpp +++ b/Engine/source/console/persistenceManager.cpp @@ -2190,14 +2190,14 @@ void PersistenceManager::deleteObjectsFromFile(const char* fileName) clearAll(); } -DefineConsoleMethod( PersistenceManager, deleteObjectsFromFile, void, ( const char * fileName ), , "( fileName )" +DefineEngineMethod( PersistenceManager, deleteObjectsFromFile, void, ( const char * fileName ), , "( fileName )" "Delete all of the objects that are created from the given file." ) { // Delete Objects. object->deleteObjectsFromFile( fileName ); } -DefineConsoleMethod( PersistenceManager, setDirty, void, ( const char * objName, const char * fileName ), (""), "(SimObject object, [filename])" +DefineEngineMethod( PersistenceManager, setDirty, void, ( const char * objName, const char * fileName ), (""), "(SimObject object, [filename])" "Mark an existing SimObject as dirty (will be written out when saveDirty() is called).") { SimObject *dirtyObject = NULL; @@ -2226,7 +2226,7 @@ DefineConsoleMethod( PersistenceManager, setDirty, void, ( const char * objName } } -DefineConsoleMethod( PersistenceManager, removeDirty, void, ( const char * objName ), , "(SimObject object)" +DefineEngineMethod( PersistenceManager, removeDirty, void, ( const char * objName ), , "(SimObject object)" "Remove a SimObject from the dirty list.") { SimObject *dirtyObject = NULL; @@ -2243,7 +2243,7 @@ DefineConsoleMethod( PersistenceManager, removeDirty, void, ( const char * objNa object->removeDirty(dirtyObject); } -DefineConsoleMethod( PersistenceManager, isDirty, bool, ( const char * objName ), , "(SimObject object)" +DefineEngineMethod( PersistenceManager, isDirty, bool, ( const char * objName ), , "(SimObject object)" "Returns true if the SimObject is on the dirty list.") { SimObject *dirtyObject = NULL; @@ -2262,19 +2262,19 @@ DefineConsoleMethod( PersistenceManager, isDirty, bool, ( const char * objName ) return false; } -DefineConsoleMethod( PersistenceManager, hasDirty, bool, (), , "()" +DefineEngineMethod( PersistenceManager, hasDirty, bool, (), , "()" "Returns true if the manager has dirty objects to save." ) { return object->hasDirty(); } -DefineConsoleMethod( PersistenceManager, getDirtyObjectCount, S32, (), , "()" +DefineEngineMethod( PersistenceManager, getDirtyObjectCount, S32, (), , "()" "Returns the number of dirty objects." ) { return object->getDirtyList().size(); } -DefineConsoleMethod( PersistenceManager, getDirtyObject, S32, (S32 index), , "( index )" +DefineEngineMethod( PersistenceManager, getDirtyObject, S32, (S32 index), , "( index )" "Returns the ith dirty object." ) { if ( index < 0 || index >= object->getDirtyList().size() ) @@ -2290,7 +2290,7 @@ DefineConsoleMethod( PersistenceManager, getDirtyObject, S32, (S32 index), , "( return ( dirtyObject.getObject() ) ? dirtyObject.getObject()->getId() : 0; } -DefineConsoleMethod( PersistenceManager, listDirty, void, (), , "()" +DefineEngineMethod( PersistenceManager, listDirty, void, (), , "()" "Prints the dirty list to the console.") { const PersistenceManager::DirtyList dirtyList = object->getDirtyList(); @@ -2318,13 +2318,13 @@ DefineConsoleMethod( PersistenceManager, listDirty, void, (), , "()" } } -DefineConsoleMethod( PersistenceManager, saveDirty, bool, (), , "()" +DefineEngineMethod( PersistenceManager, saveDirty, bool, (), , "()" "Saves all of the SimObject's on the dirty list to their respective files.") { return object->saveDirty(); } -DefineConsoleMethod( PersistenceManager, saveDirtyObject, bool, (const char * objName), , "(SimObject object)" +DefineEngineMethod( PersistenceManager, saveDirtyObject, bool, (const char * objName), , "(SimObject object)" "Save a dirty SimObject to it's file.") { SimObject *dirtyObject = NULL; @@ -2342,13 +2342,13 @@ DefineConsoleMethod( PersistenceManager, saveDirtyObject, bool, (const char * ob return false; } -DefineConsoleMethod( PersistenceManager, clearAll, void, (), , "()" +DefineEngineMethod( PersistenceManager, clearAll, void, (), , "()" "Clears all the tracked objects without saving them." ) { object->clearAll(); } -DefineConsoleMethod( PersistenceManager, removeObjectFromFile, void, (const char * objName, const char * filename),("") , "(SimObject object, [filename])" +DefineEngineMethod( PersistenceManager, removeObjectFromFile, void, (const char * objName, const char * filename),("") , "(SimObject object, [filename])" "Remove an existing SimObject from a file (can optionally specify a different file than \ the one it was created in.") { @@ -2371,7 +2371,7 @@ DefineConsoleMethod( PersistenceManager, removeObjectFromFile, void, (const char } } -DefineConsoleMethod( PersistenceManager, removeField, void, (const char * objName, const char * fieldName), , "(SimObject object, string fieldName)" +DefineEngineMethod( PersistenceManager, removeField, void, (const char * objName, const char * fieldName), , "(SimObject object, string fieldName)" "Remove a specific field from an object declaration.") { SimObject *dirtyObject = NULL; diff --git a/Engine/source/console/simDatablock.cpp b/Engine/source/console/simDatablock.cpp index 6181fe810..771b1f039 100644 --- a/Engine/source/console/simDatablock.cpp +++ b/Engine/source/console/simDatablock.cpp @@ -428,7 +428,7 @@ void SimDataBlock::write(Stream &stream, U32 tabStop, U32 flags) //----------------------------------------------------------------------------- -DefineConsoleMethod( SimDataBlock, reloadOnLocalClient, void, (),, +DefineEngineMethod( SimDataBlock, reloadOnLocalClient, void, (),, "Reload the datablock. This can only be used with a local client configuration." ) { // Make sure we're running a local client. diff --git a/Engine/source/console/simObject.cpp b/Engine/source/console/simObject.cpp index b47448414..62ac25fd1 100644 --- a/Engine/source/console/simObject.cpp +++ b/Engine/source/console/simObject.cpp @@ -2271,7 +2271,7 @@ DefineEngineMethod( SimObject, dumpGroupHierarchy, void, (),, //----------------------------------------------------------------------------- -DefineConsoleMethod( SimObject, isMethod, bool, ( const char* methodName ),, +DefineEngineMethod( SimObject, isMethod, bool, ( const char* methodName ),, "Test whether the given method is defined on this object.\n" "@param The name of the method.\n" "@return True if the object implements the given method." ) @@ -2291,7 +2291,7 @@ DefineEngineMethod( SimObject, isChildOfGroup, bool, ( SimGroup* group ),, //----------------------------------------------------------------------------- -DefineConsoleMethod( SimObject, getClassNamespace, const char*, (),, +DefineEngineMethod( SimObject, getClassNamespace, const char*, (),, "Get the name of the class namespace assigned to this object.\n" "@return The name of the 'class' namespace." ) { @@ -2300,7 +2300,7 @@ DefineConsoleMethod( SimObject, getClassNamespace, const char*, (),, //----------------------------------------------------------------------------- -DefineConsoleMethod( SimObject, getSuperClassNamespace, const char*, (),, +DefineEngineMethod( SimObject, getSuperClassNamespace, const char*, (),, "Get the name of the superclass namespace assigned to this object.\n" "@return The name of the 'superClass' namespace." ) { @@ -2309,7 +2309,7 @@ DefineConsoleMethod( SimObject, getSuperClassNamespace, const char*, (),, //----------------------------------------------------------------------------- -DefineConsoleMethod( SimObject, setClassNamespace, void, ( const char* name ),, +DefineEngineMethod( SimObject, setClassNamespace, void, ( const char* name ),, "Assign a class namespace to this object.\n" "@param name The name of the 'class' namespace for this object." ) { @@ -2318,7 +2318,7 @@ DefineConsoleMethod( SimObject, setClassNamespace, void, ( const char* name ),, //----------------------------------------------------------------------------- -DefineConsoleMethod( SimObject, setSuperClassNamespace, void, ( const char* name ),, +DefineEngineMethod( SimObject, setSuperClassNamespace, void, ( const char* name ),, "Assign a superclass namespace to this object.\n" "@param name The name of the 'superClass' namespace for this object." ) { @@ -2345,7 +2345,7 @@ DefineEngineMethod( SimObject, setIsSelected, void, ( bool state ), ( true ), //----------------------------------------------------------------------------- -DefineConsoleMethod( SimObject, isExpanded, bool, (),, +DefineEngineMethod( SimObject, isExpanded, bool, (),, "Get whether the object has been marked as expanded. (in editor)\n" "@return True if the object is marked expanded." ) { @@ -2354,7 +2354,7 @@ DefineConsoleMethod( SimObject, isExpanded, bool, (),, //----------------------------------------------------------------------------- -DefineConsoleMethod( SimObject, setIsExpanded, void, ( bool state ), ( true ), +DefineEngineMethod( SimObject, setIsExpanded, void, ( bool state ), ( true ), "Set whether the object has been marked as expanded. (in editor)\n" "@param state True if the object is to be marked expanded; false if not." ) { @@ -2363,7 +2363,7 @@ DefineConsoleMethod( SimObject, setIsExpanded, void, ( bool state ), ( true ), //----------------------------------------------------------------------------- -DefineConsoleMethod( SimObject, getFilename, const char*, (),, +DefineEngineMethod( SimObject, getFilename, const char*, (),, "Returns the filename the object is attached to.\n" "@return The name of the file the object is associated with; usually the file the object was loaded from." ) { @@ -2372,7 +2372,7 @@ DefineConsoleMethod( SimObject, getFilename, const char*, (),, //----------------------------------------------------------------------------- -DefineConsoleMethod( SimObject, setFilename, void, ( const char* fileName ),, +DefineEngineMethod( SimObject, setFilename, void, ( const char* fileName ),, "Sets the object's file name and path\n" "@param fileName The name of the file to associate this object with." ) { @@ -2381,7 +2381,7 @@ DefineConsoleMethod( SimObject, setFilename, void, ( const char* fileName ),, //----------------------------------------------------------------------------- -DefineConsoleMethod( SimObject, getDeclarationLine, S32, (),, +DefineEngineMethod( SimObject, getDeclarationLine, S32, (),, "Get the line number at which the object is defined in its file.\n\n" "@return The line number of the object's definition in script.\n" "@see getFilename()") @@ -2418,7 +2418,7 @@ DefineEngineFunction( debugEnumInstances, void, ( const char* className, const c //----------------------------------------------------------------------------- -DefineConsoleMethod( SimObject, assignFieldsFrom, void, ( SimObject* fromObject ),, +DefineEngineMethod( SimObject, assignFieldsFrom, void, ( SimObject* fromObject ),, "Copy fields from another object onto this one. The objects must " "be of same type. Everything from the object will overwrite what's " "in this object; extra fields in this object will remain. This " @@ -2439,7 +2439,7 @@ DefineEngineMethod( SimObject, assignPersistentId, void, (),, //----------------------------------------------------------------------------- -DefineConsoleMethod( SimObject, getCanSave, bool, (),, +DefineEngineMethod( SimObject, getCanSave, bool, (),, "Get whether the object will be included in saves.\n" "@return True if the object will be saved; false otherwise." ) { @@ -2448,7 +2448,7 @@ DefineConsoleMethod( SimObject, getCanSave, bool, (),, //----------------------------------------------------------------------------- -DefineConsoleMethod( SimObject, setCanSave, void, ( bool value ), ( true ), +DefineEngineMethod( SimObject, setCanSave, void, ( bool value ), ( true ), "Set whether the object will be included in saves.\n" "@param value If true, the object will be included in saves; if false, it will be excluded." ) { @@ -2529,7 +2529,7 @@ DefineEngineMethod( SimObject, setHidden, void, ( bool value ), ( true ), //----------------------------------------------------------------------------- -DefineConsoleMethod( SimObject, dumpMethods, ArrayObject*, (),, +DefineEngineMethod( SimObject, dumpMethods, ArrayObject*, (),, "List the methods defined on this object.\n\n" "Each description is a newline-separated vector with the following elements:\n" "- Minimum number of arguments.\n" @@ -2776,7 +2776,7 @@ DefineEngineMethod( SimObject, dump, void, ( bool detailed ), ( false ), //----------------------------------------------------------------------------- -DefineConsoleMethod( SimObject, save, bool, ( const char* fileName, bool selectedOnly, const char* preAppendString ), ( false, "" ), +DefineEngineMethod( SimObject, save, bool, ( const char* fileName, bool selectedOnly, const char* preAppendString ), ( false, "" ), "Save out the object to the given file.\n" "@param fileName The name of the file to save to." "@param selectedOnly If true, only objects marked as selected will be saved out.\n" @@ -2808,7 +2808,7 @@ DefineEngineMethod( SimObject, getName, const char*, (),, //----------------------------------------------------------------------------- -DefineConsoleMethod( SimObject, getClassName, const char*, (),, +DefineEngineMethod( SimObject, getClassName, const char*, (),, "Get the name of the C++ class which the object is an instance of.\n" "@return The name of the C++ class of the object." ) { @@ -2818,7 +2818,7 @@ DefineConsoleMethod( SimObject, getClassName, const char*, (),, //----------------------------------------------------------------------------- -DefineConsoleMethod( SimObject, isField, bool, ( const char* fieldName ),, +DefineEngineMethod( SimObject, isField, bool, ( const char* fieldName ),, "Test whether the given field is defined on this object.\n" "@param fieldName The name of the field.\n" "@return True if the object implements the given field." ) @@ -2828,7 +2828,7 @@ DefineConsoleMethod( SimObject, isField, bool, ( const char* fieldName ),, //----------------------------------------------------------------------------- -DefineConsoleMethod( SimObject, getFieldValue, const char*, ( const char* fieldName, S32 index ), ( -1 ), +DefineEngineMethod( SimObject, getFieldValue, const char*, ( const char* fieldName, S32 index ), ( -1 ), "Return the value of the given field on this object.\n" "@param fieldName The name of the field. If it includes a field index, the index is parsed out.\n" "@param index Optional parameter to specify the index of an array field separately.\n" @@ -2872,7 +2872,7 @@ DefineConsoleMethod( SimObject, getFieldValue, const char*, ( const char* fieldN //----------------------------------------------------------------------------- -DefineConsoleMethod( SimObject, setFieldValue, bool, ( const char* fieldName, const char* value, S32 index ), ( -1 ), +DefineEngineMethod( SimObject, setFieldValue, bool, ( const char* fieldName, const char* value, S32 index ), ( -1 ), "Set the value of the given field on this object.\n" "@param fieldName The name of the field to assign to. If it includes an array index, the index will be parsed out.\n" "@param value The new value to assign to the field.\n" @@ -2919,7 +2919,7 @@ DefineConsoleMethod( SimObject, setFieldValue, bool, ( const char* fieldName, co //----------------------------------------------------------------------------- -DefineConsoleMethod( SimObject, getFieldType, const char*, ( const char* fieldName ),, +DefineEngineMethod( SimObject, getFieldType, const char*, ( const char* fieldName ),, "Get the console type code of the given field.\n" "@return The numeric type code for the underlying console type of the given field." ) { @@ -2934,7 +2934,7 @@ DefineConsoleMethod( SimObject, getFieldType, const char*, ( const char* fieldNa //----------------------------------------------------------------------------- -DefineConsoleMethod( SimObject, setFieldType, void, ( const char* fieldName, const char* type ),, +DefineEngineMethod( SimObject, setFieldType, void, ( const char* fieldName, const char* type ),, "Set the console type code for the given field.\n" "@param fieldName The name of the dynamic field to change to type for.\n" "@param type The name of the console type.\n" @@ -2974,7 +2974,7 @@ DefineEngineMethod( SimObject, getInternalName, const char*, (),, //----------------------------------------------------------------------------- -DefineConsoleMethod( SimObject, dumpClassHierarchy, void, (),, +DefineEngineMethod( SimObject, dumpClassHierarchy, void, (),, "Dump the native C++ class hierarchy of this object's C++ class to the console." ) { object->dumpClassHierarchy(); @@ -2982,7 +2982,7 @@ DefineConsoleMethod( SimObject, dumpClassHierarchy, void, (),, //----------------------------------------------------------------------------- -DefineConsoleMethod( SimObject, isMemberOfClass, bool, ( const char* className ),, +DefineEngineMethod( SimObject, isMemberOfClass, bool, ( const char* className ),, "Test whether this object is a member of the specified class.\n" "@param className Name of a native C++ class.\n" "@return True if this object is an instance of the given C++ class or any of its super classes." ) @@ -3004,7 +3004,7 @@ DefineConsoleMethod( SimObject, isMemberOfClass, bool, ( const char* className ) //----------------------------------------------------------------------------- -DefineConsoleMethod( SimObject, isInNamespaceHierarchy, bool, ( const char* name ),, +DefineEngineMethod( SimObject, isInNamespaceHierarchy, bool, ( const char* name ),, "Test whether the namespace of this object is a direct or indirect child to the given namespace.\n" "@param name The name of a namespace.\n" "@return True if the given namespace name is within the namespace hierarchy of this object." ) @@ -3039,7 +3039,7 @@ DefineEngineMethod( SimObject, getGroup, SimGroup*, (),, //----------------------------------------------------------------------------- -DefineConsoleMethod( SimObject, delete, void, (),, +DefineEngineMethod( SimObject, delete, void, (),, "Delete and remove the object." ) { object->deleteObject(); @@ -3067,7 +3067,7 @@ ConsoleMethod( SimObject,schedule, S32, 4, 0, "( float time, string method, stri //----------------------------------------------------------------------------- -DefineConsoleMethod( SimObject, getDynamicFieldCount, S32, (),, +DefineEngineMethod( SimObject, getDynamicFieldCount, S32, (),, "Get the number of dynamic fields defined on the object.\n" "@return The number of dynamic fields defined on the object." ) { @@ -3081,7 +3081,7 @@ DefineConsoleMethod( SimObject, getDynamicFieldCount, S32, (),, //----------------------------------------------------------------------------- -DefineConsoleMethod( SimObject, getDynamicField, const char*, ( S32 index ),, +DefineEngineMethod( SimObject, getDynamicField, const char*, ( S32 index ),, "Get a value of a dynamic field by index.\n" "@param index The index of the dynamic field.\n" "@return The value of the dynamic field at the given index or \"\"." ) @@ -3113,7 +3113,7 @@ DefineConsoleMethod( SimObject, getDynamicField, const char*, ( S32 index ),, //----------------------------------------------------------------------------- -DefineConsoleMethod( SimObject, getFieldCount, S32, (),, +DefineEngineMethod( SimObject, getFieldCount, S32, (),, "Get the number of static fields on the object.\n" "@return The number of static fields defined on the object." ) { @@ -3135,7 +3135,7 @@ DefineConsoleMethod( SimObject, getFieldCount, S32, (),, //----------------------------------------------------------------------------- -DefineConsoleMethod( SimObject, getField, const char*, ( S32 index ),, +DefineEngineMethod( SimObject, getField, const char*, ( S32 index ),, "Retrieve the value of a static field by index.\n" "@param index The index of the static field.\n" "@return The value of the static field with the given index or \"\"." ) diff --git a/Engine/source/console/simPersistSet.cpp b/Engine/source/console/simPersistSet.cpp index 2dea6416e..00840c649 100644 --- a/Engine/source/console/simPersistSet.cpp +++ b/Engine/source/console/simPersistSet.cpp @@ -187,7 +187,7 @@ void SimPersistSet::addObject( SimObject* object ) //----------------------------------------------------------------------------- -DefineConsoleMethod( SimPersistSet, resolvePersistentIds, void, (), , "() - Try to bind unresolved persistent IDs in the set." ) +DefineEngineMethod( SimPersistSet, resolvePersistentIds, void, (), , "() - Try to bind unresolved persistent IDs in the set." ) { object->resolvePIDs(); } diff --git a/Engine/source/console/simSet.cpp b/Engine/source/console/simSet.cpp index c44b09c36..545c411b7 100644 --- a/Engine/source/console/simSet.cpp +++ b/Engine/source/console/simSet.cpp @@ -954,7 +954,7 @@ DefineEngineMethod( SimSet, clear, void, (),, //----------------------------------------------------------------------------- //UNSAFE; don't want this in the new API -DefineConsoleMethod( SimSet, deleteAllObjects, void, (), , "() Delete all objects in the set." ) +DefineEngineMethod( SimSet, deleteAllObjects, void, (), , "() Delete all objects in the set." ) { object->deleteAllObjects(); } @@ -1026,7 +1026,7 @@ DEFINE_CALLIN( fnSimSet_getCountRecursive, getCountRecursive, SimSet, U32, ( Sim return set->sizeRecursive(); } -DefineConsoleMethod( SimSet, getFullCount, S32, (), , "() Get the number of direct and indirect child objects contained in the set.\n" +DefineEngineMethod( SimSet, getFullCount, S32, (), , "() Get the number of direct and indirect child objects contained in the set.\n" "@return The number of objects contained in the set as well as in other sets contained directly or indirectly in the set." ) { return object->sizeRecursive(); @@ -1122,7 +1122,7 @@ DefineEngineMethod( SimSet, pushToBack, void, ( SimObject* obj ),, //----------------------------------------------------------------------------- -DefineConsoleMethod( SimSet, sort, void, ( const char * callbackFunction ), , "( string callbackFunction ) Sort the objects in the set using the given comparison function.\n" +DefineEngineMethod( SimSet, sort, void, ( const char * callbackFunction ), , "( string callbackFunction ) Sort the objects in the set using the given comparison function.\n" "@param callbackFunction Name of a function that takes two object arguments A and B and returns -1 if A is less, 1 if B is less, and 0 if both are equal." ) { object->scriptSort( callbackFunction ); diff --git a/Engine/source/core/fileObject.cpp b/Engine/source/core/fileObject.cpp index e872d7838..c0f9b17ae 100644 --- a/Engine/source/core/fileObject.cpp +++ b/Engine/source/core/fileObject.cpp @@ -484,7 +484,7 @@ static ConsoleDocFragment _FileObjectwriteObject2( "FileObject", "void writeObject( SimObject* object, string prepend);"); -DefineConsoleMethod( FileObject, writeObject, void, (const char * simName, const char * objName), (""), "FileObject.writeObject(SimObject, object prepend)" +DefineEngineMethod( FileObject, writeObject, void, (const char * simName, const char * objName), (""), "FileObject.writeObject(SimObject, object prepend)" "@hide") { SimObject* obj = Sim::findObject( simName ); diff --git a/Engine/source/environment/editors/guiMeshRoadEditorCtrl.cpp b/Engine/source/environment/editors/guiMeshRoadEditorCtrl.cpp index e1a612b00..23b79e904 100644 --- a/Engine/source/environment/editors/guiMeshRoadEditorCtrl.cpp +++ b/Engine/source/environment/editors/guiMeshRoadEditorCtrl.cpp @@ -1185,67 +1185,67 @@ void GuiMeshRoadEditorCtrl::matchTerrainToRoad() // with the terrain underneath it. } -DefineConsoleMethod( GuiMeshRoadEditorCtrl, deleteNode, void, (), , "deleteNode()" ) +DefineEngineMethod( GuiMeshRoadEditorCtrl, deleteNode, void, (), , "deleteNode()" ) { object->deleteSelectedNode(); } -DefineConsoleMethod( GuiMeshRoadEditorCtrl, getMode, const char*, (), , "" ) +DefineEngineMethod( GuiMeshRoadEditorCtrl, getMode, const char*, (), , "" ) { return object->getMode(); } -DefineConsoleMethod( GuiMeshRoadEditorCtrl, setMode, void, (const char * mode), , "setMode( String mode )" ) +DefineEngineMethod( GuiMeshRoadEditorCtrl, setMode, void, (const char * mode), , "setMode( String mode )" ) { String newMode = ( mode ); object->setMode( newMode ); } -DefineConsoleMethod( GuiMeshRoadEditorCtrl, getNodeWidth, F32, (), , "" ) +DefineEngineMethod( GuiMeshRoadEditorCtrl, getNodeWidth, F32, (), , "" ) { return object->getNodeWidth(); } -DefineConsoleMethod( GuiMeshRoadEditorCtrl, setNodeWidth, void, ( F32 width ), , "" ) +DefineEngineMethod( GuiMeshRoadEditorCtrl, setNodeWidth, void, ( F32 width ), , "" ) { object->setNodeWidth( width ); } -DefineConsoleMethod( GuiMeshRoadEditorCtrl, getNodeDepth, F32, (), , "" ) +DefineEngineMethod( GuiMeshRoadEditorCtrl, getNodeDepth, F32, (), , "" ) { return object->getNodeDepth(); } -DefineConsoleMethod( GuiMeshRoadEditorCtrl, setNodeDepth, void, ( F32 depth ), , "" ) +DefineEngineMethod( GuiMeshRoadEditorCtrl, setNodeDepth, void, ( F32 depth ), , "" ) { object->setNodeDepth( depth ); } -DefineConsoleMethod( GuiMeshRoadEditorCtrl, getNodePosition, Point3F, (), , "" ) +DefineEngineMethod( GuiMeshRoadEditorCtrl, getNodePosition, Point3F, (), , "" ) { return object->getNodePosition(); } -DefineConsoleMethod( GuiMeshRoadEditorCtrl, setNodePosition, void, (Point3F pos), , "" ) +DefineEngineMethod( GuiMeshRoadEditorCtrl, setNodePosition, void, (Point3F pos), , "" ) { object->setNodePosition( pos ); } -DefineConsoleMethod( GuiMeshRoadEditorCtrl, getNodeNormal, Point3F, (), , "" ) +DefineEngineMethod( GuiMeshRoadEditorCtrl, getNodeNormal, Point3F, (), , "" ) { return object->getNodeNormal(); } -DefineConsoleMethod( GuiMeshRoadEditorCtrl, setNodeNormal, void, (Point3F normal), , "" ) +DefineEngineMethod( GuiMeshRoadEditorCtrl, setNodeNormal, void, (Point3F normal), , "" ) { object->setNodeNormal( normal ); } -DefineConsoleMethod( GuiMeshRoadEditorCtrl, setSelectedRoad, void, (const char * objName), (""), "" ) +DefineEngineMethod( GuiMeshRoadEditorCtrl, setSelectedRoad, void, (const char * objName), (""), "" ) { if ( String::isEmpty(objName) ) object->setSelectedRoad(NULL); @@ -1257,7 +1257,7 @@ DefineConsoleMethod( GuiMeshRoadEditorCtrl, setSelectedRoad, void, (const char * } } -DefineConsoleMethod( GuiMeshRoadEditorCtrl, getSelectedRoad, S32, (), , "" ) +DefineEngineMethod( GuiMeshRoadEditorCtrl, getSelectedRoad, S32, (), , "" ) { MeshRoad *road = object->getSelectedRoad(); if ( !road ) @@ -1266,14 +1266,14 @@ DefineConsoleMethod( GuiMeshRoadEditorCtrl, getSelectedRoad, S32, (), , "" ) return road->getId(); } -DefineConsoleMethod( GuiMeshRoadEditorCtrl, regenerate, void, (), , "" ) +DefineEngineMethod( GuiMeshRoadEditorCtrl, regenerate, void, (), , "" ) { MeshRoad *road = object->getSelectedRoad(); if ( road ) road->regenerate(); } -DefineConsoleMethod( GuiMeshRoadEditorCtrl, matchTerrainToRoad, void, (), , "" ) +DefineEngineMethod( GuiMeshRoadEditorCtrl, matchTerrainToRoad, void, (), , "" ) { object->matchTerrainToRoad(); } diff --git a/Engine/source/environment/editors/guiRiverEditorCtrl.cpp b/Engine/source/environment/editors/guiRiverEditorCtrl.cpp index 01ab745a8..1b2dd02d3 100644 --- a/Engine/source/environment/editors/guiRiverEditorCtrl.cpp +++ b/Engine/source/environment/editors/guiRiverEditorCtrl.cpp @@ -1393,66 +1393,66 @@ void GuiRiverEditorCtrl::_renderSelectedRiver( ObjectRenderInst *ri, SceneRender } } -DefineConsoleMethod( GuiRiverEditorCtrl, deleteNode, void, (), , "deleteNode()" ) +DefineEngineMethod( GuiRiverEditorCtrl, deleteNode, void, (), , "deleteNode()" ) { object->deleteSelectedNode(); } -DefineConsoleMethod( GuiRiverEditorCtrl, getMode, const char*, (), , "" ) +DefineEngineMethod( GuiRiverEditorCtrl, getMode, const char*, (), , "" ) { return object->getMode(); } -DefineConsoleMethod( GuiRiverEditorCtrl, setMode, void, ( const char * mode ), , "setMode( String mode )" ) +DefineEngineMethod( GuiRiverEditorCtrl, setMode, void, ( const char * mode ), , "setMode( String mode )" ) { String newMode = ( mode ); object->setMode( newMode ); } -DefineConsoleMethod( GuiRiverEditorCtrl, getNodeWidth, F32, (), , "" ) +DefineEngineMethod( GuiRiverEditorCtrl, getNodeWidth, F32, (), , "" ) { return object->getNodeWidth(); } -DefineConsoleMethod( GuiRiverEditorCtrl, setNodeWidth, void, ( F32 width ), , "" ) +DefineEngineMethod( GuiRiverEditorCtrl, setNodeWidth, void, ( F32 width ), , "" ) { object->setNodeWidth( width ); } -DefineConsoleMethod( GuiRiverEditorCtrl, getNodeDepth, F32, (), , "" ) +DefineEngineMethod( GuiRiverEditorCtrl, getNodeDepth, F32, (), , "" ) { return object->getNodeDepth(); } -DefineConsoleMethod( GuiRiverEditorCtrl, setNodeDepth, void, ( F32 depth ), , "" ) +DefineEngineMethod( GuiRiverEditorCtrl, setNodeDepth, void, ( F32 depth ), , "" ) { object->setNodeDepth( depth ); } -DefineConsoleMethod( GuiRiverEditorCtrl, getNodePosition, Point3F, (), , "" ) +DefineEngineMethod( GuiRiverEditorCtrl, getNodePosition, Point3F, (), , "" ) { return object->getNodePosition(); } -DefineConsoleMethod( GuiRiverEditorCtrl, setNodePosition, void, (Point3F pos), , "" ) +DefineEngineMethod( GuiRiverEditorCtrl, setNodePosition, void, (Point3F pos), , "" ) { object->setNodePosition( pos ); } -DefineConsoleMethod( GuiRiverEditorCtrl, getNodeNormal, Point3F, (), , "" ) +DefineEngineMethod( GuiRiverEditorCtrl, getNodeNormal, Point3F, (), , "" ) { return object->getNodeNormal(); } -DefineConsoleMethod( GuiRiverEditorCtrl, setNodeNormal, void, (Point3F normal), , "" ) +DefineEngineMethod( GuiRiverEditorCtrl, setNodeNormal, void, (Point3F normal), , "" ) { object->setNodeNormal( normal ); } -DefineConsoleMethod( GuiRiverEditorCtrl, setSelectedRiver, void, (const char * objName), (""), "" ) +DefineEngineMethod( GuiRiverEditorCtrl, setSelectedRiver, void, (const char * objName), (""), "" ) { if (dStrcmp( objName,"" )==0) object->setSelectedRiver(NULL); @@ -1464,7 +1464,7 @@ DefineConsoleMethod( GuiRiverEditorCtrl, setSelectedRiver, void, (const char * o } } -DefineConsoleMethod( GuiRiverEditorCtrl, getSelectedRiver, S32, (), , "" ) +DefineEngineMethod( GuiRiverEditorCtrl, getSelectedRiver, S32, (), , "" ) { River *river = object->getSelectedRiver(); if ( !river ) @@ -1473,7 +1473,7 @@ DefineConsoleMethod( GuiRiverEditorCtrl, getSelectedRiver, S32, (), , "" ) return river->getId(); } -DefineConsoleMethod( GuiRiverEditorCtrl, regenerate, void, (), , "" ) +DefineEngineMethod( GuiRiverEditorCtrl, regenerate, void, (), , "" ) { River *river = object->getSelectedRiver(); if ( river ) diff --git a/Engine/source/environment/editors/guiRoadEditorCtrl.cpp b/Engine/source/environment/editors/guiRoadEditorCtrl.cpp index 167a5db45..7a2ec8a96 100644 --- a/Engine/source/environment/editors/guiRoadEditorCtrl.cpp +++ b/Engine/source/environment/editors/guiRoadEditorCtrl.cpp @@ -1037,45 +1037,45 @@ void GuiRoadEditorCtrl::submitUndo( const UTF8 *name ) undoMan->addAction( action ); } -DefineConsoleMethod( GuiRoadEditorCtrl, deleteNode, void, (), , "deleteNode()" ) +DefineEngineMethod( GuiRoadEditorCtrl, deleteNode, void, (), , "deleteNode()" ) { object->deleteSelectedNode(); } -DefineConsoleMethod( GuiRoadEditorCtrl, getMode, const char*, (), , "" ) +DefineEngineMethod( GuiRoadEditorCtrl, getMode, const char*, (), , "" ) { return object->getMode(); } -DefineConsoleMethod( GuiRoadEditorCtrl, setMode, void, ( const char * mode ), , "setMode( String mode )" ) +DefineEngineMethod( GuiRoadEditorCtrl, setMode, void, ( const char * mode ), , "setMode( String mode )" ) { String newMode = ( mode ); object->setMode( newMode ); } -DefineConsoleMethod( GuiRoadEditorCtrl, getNodeWidth, F32, (), , "" ) +DefineEngineMethod( GuiRoadEditorCtrl, getNodeWidth, F32, (), , "" ) { return object->getNodeWidth(); } -DefineConsoleMethod( GuiRoadEditorCtrl, setNodeWidth, void, ( F32 width ), , "" ) +DefineEngineMethod( GuiRoadEditorCtrl, setNodeWidth, void, ( F32 width ), , "" ) { object->setNodeWidth( width ); } -DefineConsoleMethod( GuiRoadEditorCtrl, getNodePosition, Point3F, (), , "" ) +DefineEngineMethod( GuiRoadEditorCtrl, getNodePosition, Point3F, (), , "" ) { return object->getNodePosition(); } -DefineConsoleMethod( GuiRoadEditorCtrl, setNodePosition, void, ( Point3F pos ), , "" ) +DefineEngineMethod( GuiRoadEditorCtrl, setNodePosition, void, ( Point3F pos ), , "" ) { object->setNodePosition( pos ); } -DefineConsoleMethod( GuiRoadEditorCtrl, setSelectedRoad, void, ( const char * pathRoad ), (""), "" ) +DefineEngineMethod( GuiRoadEditorCtrl, setSelectedRoad, void, ( const char * pathRoad ), (""), "" ) { if (dStrcmp( pathRoad,"")==0 ) object->setSelectedRoad(NULL); @@ -1087,7 +1087,7 @@ DefineConsoleMethod( GuiRoadEditorCtrl, setSelectedRoad, void, ( const char * pa } } -DefineConsoleMethod( GuiRoadEditorCtrl, getSelectedRoad, S32, (), , "" ) +DefineEngineMethod( GuiRoadEditorCtrl, getSelectedRoad, S32, (), , "" ) { DecalRoad *road = object->getSelectedRoad(); if ( road ) @@ -1096,12 +1096,12 @@ DefineConsoleMethod( GuiRoadEditorCtrl, getSelectedRoad, S32, (), , "" ) return NULL; } -DefineConsoleMethod( GuiRoadEditorCtrl, getSelectedNode, S32, (), , "" ) +DefineEngineMethod( GuiRoadEditorCtrl, getSelectedNode, S32, (), , "" ) { return object->getSelectedNode(); } -DefineConsoleMethod( GuiRoadEditorCtrl, deleteRoad, void, (), , "" ) +DefineEngineMethod( GuiRoadEditorCtrl, deleteRoad, void, (), , "" ) { object->deleteSelectedRoad(); } diff --git a/Engine/source/environment/skyBox.cpp b/Engine/source/environment/skyBox.cpp index daadcf885..8aca8d266 100644 --- a/Engine/source/environment/skyBox.cpp +++ b/Engine/source/environment/skyBox.cpp @@ -640,7 +640,7 @@ BaseMatInstance* SkyBox::_getMaterialInstance() return mMatInstance; } -DefineConsoleMethod( SkyBox, postApply, void, (), , "") +DefineEngineMethod( SkyBox, postApply, void, (), , "") { object->inspectPostApply(); } \ No newline at end of file diff --git a/Engine/source/environment/sun.cpp b/Engine/source/environment/sun.cpp index d83d7078b..7063e1a27 100644 --- a/Engine/source/environment/sun.cpp +++ b/Engine/source/environment/sun.cpp @@ -558,12 +558,12 @@ void Sun::_onUnselected() Parent::_onUnselected(); } -DefineConsoleMethod(Sun, apply, void, (), , "") +DefineEngineMethod(Sun, apply, void, (), , "") { object->inspectPostApply(); } -DefineConsoleMethod(Sun, animate, void, ( F32 duration, F32 startAzimuth, F32 endAzimuth, F32 startElevation, F32 endElevation ), , "animate( F32 duration, F32 startAzimuth, F32 endAzimuth, F32 startElevation, F32 endElevation )") +DefineEngineMethod(Sun, animate, void, ( F32 duration, F32 startAzimuth, F32 endAzimuth, F32 startElevation, F32 endElevation ), , "animate( F32 duration, F32 startAzimuth, F32 endAzimuth, F32 startElevation, F32 endElevation )") { object->animate(duration, startAzimuth, endAzimuth, startElevation, endElevation); diff --git a/Engine/source/forest/editor/forestBrushElement.cpp b/Engine/source/forest/editor/forestBrushElement.cpp index f61834c9e..bbee91e5a 100644 --- a/Engine/source/forest/editor/forestBrushElement.cpp +++ b/Engine/source/forest/editor/forestBrushElement.cpp @@ -187,7 +187,7 @@ bool ForestBrush::containsItemData( const ForestItemData *inData ) return false; } -DefineConsoleMethod( ForestBrush, containsItemData, bool, ( const char * obj ), , "( ForestItemData obj )" ) +DefineEngineMethod( ForestBrush, containsItemData, bool, ( const char * obj ), , "( ForestItemData obj )" ) { ForestItemData *data = NULL; if ( !Sim::findObject( obj, data ) ) diff --git a/Engine/source/forest/editor/forestBrushTool.cpp b/Engine/source/forest/editor/forestBrushTool.cpp index ae71951b5..d0d64d517 100644 --- a/Engine/source/forest/editor/forestBrushTool.cpp +++ b/Engine/source/forest/editor/forestBrushTool.cpp @@ -682,7 +682,7 @@ bool ForestBrushTool::getGroundAt( const Point3F &worldPt, F32 *zValueOut, Vecto return true; } -DefineConsoleMethod( ForestBrushTool, collectElements, void, (), , "" ) +DefineEngineMethod( ForestBrushTool, collectElements, void, (), , "" ) { object->collectElements(); } \ No newline at end of file diff --git a/Engine/source/forest/editor/forestEditorCtrl.cpp b/Engine/source/forest/editor/forestEditorCtrl.cpp index d8b54ba9c..db8a58f3c 100644 --- a/Engine/source/forest/editor/forestEditorCtrl.cpp +++ b/Engine/source/forest/editor/forestEditorCtrl.cpp @@ -370,24 +370,24 @@ bool ForestEditorCtrl::isDirty() return foundDirty; } -DefineConsoleMethod( ForestEditorCtrl, updateActiveForest, void, (), , "()" ) +DefineEngineMethod( ForestEditorCtrl, updateActiveForest, void, (), , "()" ) { object->updateActiveForest( true ); } -DefineConsoleMethod( ForestEditorCtrl, setActiveTool, void, ( const char * toolName ), , "( ForestTool tool )" ) +DefineEngineMethod( ForestEditorCtrl, setActiveTool, void, ( const char * toolName ), , "( ForestTool tool )" ) { ForestTool *tool = dynamic_cast( Sim::findObject( toolName ) ); object->setActiveTool( tool ); } -DefineConsoleMethod( ForestEditorCtrl, getActiveTool, S32, (), , "()" ) +DefineEngineMethod( ForestEditorCtrl, getActiveTool, S32, (), , "()" ) { ForestTool *tool = object->getActiveTool(); return tool ? tool->getId() : 0; } -DefineConsoleMethod( ForestEditorCtrl, deleteMeshSafe, void, ( const char * obj ), , "( ForestItemData obj )" ) +DefineEngineMethod( ForestEditorCtrl, deleteMeshSafe, void, ( const char * obj ), , "( ForestItemData obj )" ) { ForestItemData *db; if ( !Sim::findObject( obj, db ) ) @@ -396,12 +396,12 @@ DefineConsoleMethod( ForestEditorCtrl, deleteMeshSafe, void, ( const char * obj object->deleteMeshSafe( db ); } -DefineConsoleMethod( ForestEditorCtrl, isDirty, bool, (), , "" ) +DefineEngineMethod( ForestEditorCtrl, isDirty, bool, (), , "" ) { return object->isDirty(); } -DefineConsoleMethod(ForestEditorCtrl, setActiveForest, void, (const char * obj), , "( Forest obj )") +DefineEngineMethod(ForestEditorCtrl, setActiveForest, void, (const char * obj), , "( Forest obj )") { Forest *forestObject; if (!Sim::findObject(obj, forestObject)) diff --git a/Engine/source/forest/editor/forestSelectionTool.cpp b/Engine/source/forest/editor/forestSelectionTool.cpp index a453f4e99..f6689c9b8 100644 --- a/Engine/source/forest/editor/forestSelectionTool.cpp +++ b/Engine/source/forest/editor/forestSelectionTool.cpp @@ -563,32 +563,32 @@ void ForestSelectionTool::onUndoAction() mBounds.intersect( mSelection[i].getWorldBox() ); } -DefineConsoleMethod( ForestSelectionTool, getSelectionCount, S32, (), , "" ) +DefineEngineMethod( ForestSelectionTool, getSelectionCount, S32, (), , "" ) { return object->getSelectionCount(); } -DefineConsoleMethod( ForestSelectionTool, deleteSelection, void, (), , "" ) +DefineEngineMethod( ForestSelectionTool, deleteSelection, void, (), , "" ) { object->deleteSelection(); } -DefineConsoleMethod( ForestSelectionTool, clearSelection, void, (), , "" ) +DefineEngineMethod( ForestSelectionTool, clearSelection, void, (), , "" ) { object->clearSelection(); } -DefineConsoleMethod( ForestSelectionTool, cutSelection, void, (), , "" ) +DefineEngineMethod( ForestSelectionTool, cutSelection, void, (), , "" ) { object->cutSelection(); } -DefineConsoleMethod( ForestSelectionTool, copySelection, void, (), , "" ) +DefineEngineMethod( ForestSelectionTool, copySelection, void, (), , "" ) { object->copySelection(); } -DefineConsoleMethod( ForestSelectionTool, pasteSelection, void, (), , "" ) +DefineEngineMethod( ForestSelectionTool, pasteSelection, void, (), , "" ) { object->pasteSelection(); } diff --git a/Engine/source/forest/forest.cpp b/Engine/source/forest/forest.cpp index e6b2fd8bd..985f34151 100644 --- a/Engine/source/forest/forest.cpp +++ b/Engine/source/forest/forest.cpp @@ -361,22 +361,22 @@ void Forest::saveDataFile( const char *path ) mData->write( mDataFileName ); } -DefineConsoleMethod( Forest, saveDataFile, void, (const char * path), (""), "saveDataFile( [path] )" ) +DefineEngineMethod( Forest, saveDataFile, void, (const char * path), (""), "saveDataFile( [path] )" ) { object->saveDataFile( path ); } -DefineConsoleMethod(Forest, isDirty, bool, (), , "()") +DefineEngineMethod(Forest, isDirty, bool, (), , "()") { return object->getData() && object->getData()->isDirty(); } -DefineConsoleMethod(Forest, regenCells, void, (), , "()") +DefineEngineMethod(Forest, regenCells, void, (), , "()") { object->getData()->regenCells(); } -DefineConsoleMethod(Forest, clear, void, (), , "()" ) +DefineEngineMethod(Forest, clear, void, (), , "()" ) { object->clear(); } diff --git a/Engine/source/gfx/video/theoraTextureObject.cpp b/Engine/source/gfx/video/theoraTextureObject.cpp index 13e73402b..e83314870 100644 --- a/Engine/source/gfx/video/theoraTextureObject.cpp +++ b/Engine/source/gfx/video/theoraTextureObject.cpp @@ -191,7 +191,7 @@ void TheoraTextureObject::play() //----------------------------------------------------------------------------- -DefineConsoleMethod( TheoraTextureObject, play, void, (),, +DefineEngineMethod( TheoraTextureObject, play, void, (),, "Start playback of the video." ) { object->play(); @@ -199,7 +199,7 @@ DefineConsoleMethod( TheoraTextureObject, play, void, (),, //----------------------------------------------------------------------------- -DefineConsoleMethod( TheoraTextureObject, stop, void, (),, +DefineEngineMethod( TheoraTextureObject, stop, void, (),, "Stop playback of the video." ) { object->stop(); @@ -207,7 +207,7 @@ DefineConsoleMethod( TheoraTextureObject, stop, void, (),, //----------------------------------------------------------------------------- -DefineConsoleMethod( TheoraTextureObject, pause, void, (),, +DefineEngineMethod( TheoraTextureObject, pause, void, (),, "Pause playback of the video." ) { object->pause(); diff --git a/Engine/source/gui/buttons/guiToolboxButtonCtrl.cpp b/Engine/source/gui/buttons/guiToolboxButtonCtrl.cpp index fb2b9a5f9..c3e7cf8a2 100644 --- a/Engine/source/gui/buttons/guiToolboxButtonCtrl.cpp +++ b/Engine/source/gui/buttons/guiToolboxButtonCtrl.cpp @@ -92,17 +92,17 @@ void GuiToolboxButtonCtrl::onSleep() //------------------------------------- -DefineConsoleMethod( GuiToolboxButtonCtrl, setNormalBitmap, void, ( const char * name ), , "( filepath name ) sets the bitmap that shows when the button is active") +DefineEngineMethod( GuiToolboxButtonCtrl, setNormalBitmap, void, ( const char * name ), , "( filepath name ) sets the bitmap that shows when the button is active") { object->setNormalBitmap(name); } -DefineConsoleMethod( GuiToolboxButtonCtrl, setLoweredBitmap, void, ( const char * name ), , "( filepath name ) sets the bitmap that shows when the button is disabled") +DefineEngineMethod( GuiToolboxButtonCtrl, setLoweredBitmap, void, ( const char * name ), , "( filepath name ) sets the bitmap that shows when the button is disabled") { object->setLoweredBitmap(name); } -DefineConsoleMethod( GuiToolboxButtonCtrl, setHoverBitmap, void, ( const char * name ), , "( filepath name ) sets the bitmap that shows when the button is disabled") +DefineEngineMethod( GuiToolboxButtonCtrl, setHoverBitmap, void, ( const char * name ), , "( filepath name ) sets the bitmap that shows when the button is disabled") { object->setHoverBitmap(name); } diff --git a/Engine/source/gui/controls/guiBitmapCtrl.cpp b/Engine/source/gui/controls/guiBitmapCtrl.cpp index 769445dc3..855b78900 100644 --- a/Engine/source/gui/controls/guiBitmapCtrl.cpp +++ b/Engine/source/gui/controls/guiBitmapCtrl.cpp @@ -261,7 +261,7 @@ static ConsoleDocFragment _sGuiBitmapCtrlSetBitmap2( //"Set the bitmap displayed in the control. Note that it is limited in size, to 256x256." -DefineConsoleMethod( GuiBitmapCtrl, setBitmap, void, ( const char * fileRoot, bool resize), ( false), +DefineEngineMethod( GuiBitmapCtrl, setBitmap, void, ( const char * fileRoot, bool resize), ( false), "( String filename | String filename, bool resize ) Assign an image to the control.\n\n" "@hide" ) { diff --git a/Engine/source/gui/controls/guiColorPicker.cpp b/Engine/source/gui/controls/guiColorPicker.cpp index 98f9620b3..d0e3034b6 100644 --- a/Engine/source/gui/controls/guiColorPicker.cpp +++ b/Engine/source/gui/controls/guiColorPicker.cpp @@ -658,17 +658,17 @@ void GuiColorPickerCtrl::setScriptValue(const char *value) setValue(newValue); } -DefineConsoleMethod(GuiColorPickerCtrl, getSelectorPos, Point2I, (), , "Gets the current position of the selector") +DefineEngineMethod(GuiColorPickerCtrl, getSelectorPos, Point2I, (), , "Gets the current position of the selector") { return object->getSelectorPos(); } -DefineConsoleMethod(GuiColorPickerCtrl, setSelectorPos, void, (Point2I newPos), , "Sets the current position of the selector") +DefineEngineMethod(GuiColorPickerCtrl, setSelectorPos, void, (Point2I newPos), , "Sets the current position of the selector") { object->setSelectorPos(newPos); } -DefineConsoleMethod(GuiColorPickerCtrl, updateColor, void, (), , "Forces update of pick color") +DefineEngineMethod(GuiColorPickerCtrl, updateColor, void, (), , "Forces update of pick color") { object->updateColor(); } diff --git a/Engine/source/gui/controls/guiFileTreeCtrl.cpp b/Engine/source/gui/controls/guiFileTreeCtrl.cpp index b6531fbaa..8513fb82b 100644 --- a/Engine/source/gui/controls/guiFileTreeCtrl.cpp +++ b/Engine/source/gui/controls/guiFileTreeCtrl.cpp @@ -379,18 +379,18 @@ void GuiFileTreeCtrl::recurseInsert( Item* parent, StringTableEntry path ) } -DefineConsoleMethod( GuiFileTreeCtrl, getSelectedPath, const char*, (), , "getSelectedPath() - returns the currently selected path in the tree") +DefineEngineMethod( GuiFileTreeCtrl, getSelectedPath, const char*, (), , "getSelectedPath() - returns the currently selected path in the tree") { const String& path = object->getSelectedPath(); return Con::getStringArg( path ); } -DefineConsoleMethod( GuiFileTreeCtrl, setSelectedPath, bool, (const char * path), , "setSelectedPath(path) - expands the tree to the specified path") +DefineEngineMethod( GuiFileTreeCtrl, setSelectedPath, bool, (const char * path), , "setSelectedPath(path) - expands the tree to the specified path") { return object->setSelectedPath( path ); } -DefineConsoleMethod( GuiFileTreeCtrl, reload, void, (), , "() - Reread the directory tree hierarchy." ) +DefineEngineMethod( GuiFileTreeCtrl, reload, void, (), , "() - Reread the directory tree hierarchy." ) { object->updateTree(); } diff --git a/Engine/source/gui/controls/guiGradientCtrl.cpp b/Engine/source/gui/controls/guiGradientCtrl.cpp index 20454b73d..112f3859d 100644 --- a/Engine/source/gui/controls/guiGradientCtrl.cpp +++ b/Engine/source/gui/controls/guiGradientCtrl.cpp @@ -601,7 +601,7 @@ void GuiGradientCtrl::sortColorRange() dQsort( mAlphaRange.address(), mAlphaRange.size(), sizeof(ColorRange), _numIncreasing); } -DefineConsoleMethod(GuiGradientCtrl, getColorCount, S32, (), , "Get color count") +DefineEngineMethod(GuiGradientCtrl, getColorCount, S32, (), , "Get color count") { if( object->getDisplayMode() == GuiGradientCtrl::pHorizColorRange ) return object->mColorRange.size(); @@ -611,7 +611,7 @@ DefineConsoleMethod(GuiGradientCtrl, getColorCount, S32, (), , "Get color count" return 0; } -DefineConsoleMethod(GuiGradientCtrl, getColor, LinearColorF, (S32 idx), , "Get color value") +DefineEngineMethod(GuiGradientCtrl, getColor, LinearColorF, (S32 idx), , "Get color value") { if( object->getDisplayMode() == GuiGradientCtrl::pHorizColorRange ) diff --git a/Engine/source/gui/controls/guiMaterialCtrl.cpp b/Engine/source/gui/controls/guiMaterialCtrl.cpp index edfb12e76..d6e5cf833 100644 --- a/Engine/source/gui/controls/guiMaterialCtrl.cpp +++ b/Engine/source/gui/controls/guiMaterialCtrl.cpp @@ -167,7 +167,7 @@ void GuiMaterialCtrl::onRender( Point2I offset, const RectI &updateRect ) GFX->setTexture( 0, NULL ); } -DefineConsoleMethod( GuiMaterialCtrl, setMaterial, bool, ( const char * materialName ), , "( string materialName )" +DefineEngineMethod( GuiMaterialCtrl, setMaterial, bool, ( const char * materialName ), , "( string materialName )" "Set the material to be displayed in the control." ) { return object->setMaterial( materialName ); diff --git a/Engine/source/gui/controls/guiPopUpCtrl.cpp b/Engine/source/gui/controls/guiPopUpCtrl.cpp index 0697c6a36..88eb5c59f 100644 --- a/Engine/source/gui/controls/guiPopUpCtrl.cpp +++ b/Engine/source/gui/controls/guiPopUpCtrl.cpp @@ -300,82 +300,82 @@ void GuiPopUpMenuCtrl::initPersistFields(void) } //------------------------------------------------------------------------------ -DefineConsoleMethod( GuiPopUpMenuCtrl, add, void, (const char * name, S32 idNum, U32 scheme), ("", -1, 0), "(string name, int idNum, int scheme=0)") +DefineEngineMethod( GuiPopUpMenuCtrl, add, void, (const char * name, S32 idNum, U32 scheme), ("", -1, 0), "(string name, int idNum, int scheme=0)") { object->addEntry(name, idNum, scheme); } -DefineConsoleMethod( GuiPopUpMenuCtrl, addScheme, void, (U32 id, ColorI fontColor, ColorI fontColorHL, ColorI fontColorSEL), , +DefineEngineMethod( GuiPopUpMenuCtrl, addScheme, void, (U32 id, ColorI fontColor, ColorI fontColorHL, ColorI fontColorSEL), , "(int id, ColorI fontColor, ColorI fontColorHL, ColorI fontColorSEL)") { object->addScheme( id, fontColor, fontColorHL, fontColorSEL ); } -DefineConsoleMethod( GuiPopUpMenuCtrl, getText, const char*, (), , "") +DefineEngineMethod( GuiPopUpMenuCtrl, getText, const char*, (), , "") { return object->getText(); } -DefineConsoleMethod( GuiPopUpMenuCtrl, clear, void, (), , "Clear the popup list.") +DefineEngineMethod( GuiPopUpMenuCtrl, clear, void, (), , "Clear the popup list.") { object->clear(); } //FIXME: clashes with SimSet.sort -DefineConsoleMethod(GuiPopUpMenuCtrl, sort, void, (), , "Sort the list alphabetically.") +DefineEngineMethod(GuiPopUpMenuCtrl, sort, void, (), , "Sort the list alphabetically.") { object->sort(); } // Added to sort the entries by ID -DefineConsoleMethod(GuiPopUpMenuCtrl, sortID, void, (), , "Sort the list by ID.") +DefineEngineMethod(GuiPopUpMenuCtrl, sortID, void, (), , "Sort the list by ID.") { object->sortID(); } -DefineConsoleMethod( GuiPopUpMenuCtrl, forceOnAction, void, (), , "") +DefineEngineMethod( GuiPopUpMenuCtrl, forceOnAction, void, (), , "") { object->onAction(); } -DefineConsoleMethod( GuiPopUpMenuCtrl, forceClose, void, (), , "") +DefineEngineMethod( GuiPopUpMenuCtrl, forceClose, void, (), , "") { object->closePopUp(); } -DefineConsoleMethod( GuiPopUpMenuCtrl, getSelected, S32, (), , "Gets the selected index") +DefineEngineMethod( GuiPopUpMenuCtrl, getSelected, S32, (), , "Gets the selected index") { return object->getSelected(); } -DefineConsoleMethod( GuiPopUpMenuCtrl, setSelected, void, (S32 id, bool scriptCallback), (true), "(int id, [scriptCallback=true])") +DefineEngineMethod( GuiPopUpMenuCtrl, setSelected, void, (S32 id, bool scriptCallback), (true), "(int id, [scriptCallback=true])") { object->setSelected( id, scriptCallback ); } -DefineConsoleMethod( GuiPopUpMenuCtrl, setFirstSelected, void, (bool scriptCallback), (true), "([scriptCallback=true])") +DefineEngineMethod( GuiPopUpMenuCtrl, setFirstSelected, void, (bool scriptCallback), (true), "([scriptCallback=true])") { object->setFirstSelected( scriptCallback ); } -DefineConsoleMethod( GuiPopUpMenuCtrl, setNoneSelected, void, (), , "") +DefineEngineMethod( GuiPopUpMenuCtrl, setNoneSelected, void, (), , "") { object->setNoneSelected(); } -DefineConsoleMethod( GuiPopUpMenuCtrl, getTextById, const char*, (S32 id), , "(int id)") +DefineEngineMethod( GuiPopUpMenuCtrl, getTextById, const char*, (S32 id), , "(int id)") { return(object->getTextById(id)); } -DefineConsoleMethod( GuiPopUpMenuCtrl, changeTextById, void, ( S32 id, const char * text ), , "( int id, string text )" ) +DefineEngineMethod( GuiPopUpMenuCtrl, changeTextById, void, ( S32 id, const char * text ), , "( int id, string text )" ) { object->setEntryText( id, text ); } -DefineConsoleMethod( GuiPopUpMenuCtrl, setEnumContent, void, (const char * className, const char * enumName), , "(string class, string enum)" +DefineEngineMethod( GuiPopUpMenuCtrl, setEnumContent, void, (const char * className, const char * enumName), , "(string class, string enum)" "This fills the popup with a classrep's field enumeration type info.\n\n" "More of a helper function than anything. If console access to the field list is added, " "at least for the enumerated types, then this should go away..") @@ -429,20 +429,20 @@ DefineConsoleMethod( GuiPopUpMenuCtrl, setEnumContent, void, (const char * class } //------------------------------------------------------------------------------ -DefineConsoleMethod( GuiPopUpMenuCtrl, findText, S32, (const char * text), , "(string text)" +DefineEngineMethod( GuiPopUpMenuCtrl, findText, S32, (const char * text), , "(string text)" "Returns the position of the first entry containing the specified text or -1 if not found.") { return( object->findText( text ) ); } //------------------------------------------------------------------------------ -DefineConsoleMethod( GuiPopUpMenuCtrl, size, S32, (), , "Get the size of the menu - the number of entries in it.") +DefineEngineMethod( GuiPopUpMenuCtrl, size, S32, (), , "Get the size of the menu - the number of entries in it.") { return( object->getNumEntries() ); } //------------------------------------------------------------------------------ -DefineConsoleMethod( GuiPopUpMenuCtrl, replaceText, void, (bool doReplaceText), , "(bool doReplaceText)") +DefineEngineMethod( GuiPopUpMenuCtrl, replaceText, void, (bool doReplaceText), , "(bool doReplaceText)") { object->replaceText(S32(doReplaceText)); } @@ -532,7 +532,7 @@ void GuiPopUpMenuCtrl::clearEntry( S32 entry ) } //------------------------------------------------------------------------------ -DefineConsoleMethod( GuiPopUpMenuCtrl, clearEntry, void, (S32 entry), , "(S32 entry)") +DefineEngineMethod( GuiPopUpMenuCtrl, clearEntry, void, (S32 entry), , "(S32 entry)") { object->clearEntry(entry); } diff --git a/Engine/source/gui/controls/guiPopUpCtrlEx.cpp b/Engine/source/gui/controls/guiPopUpCtrlEx.cpp index 2c8f5342a..1a39c95af 100644 --- a/Engine/source/gui/controls/guiPopUpCtrlEx.cpp +++ b/Engine/source/gui/controls/guiPopUpCtrlEx.cpp @@ -364,7 +364,7 @@ ConsoleDocFragment _GuiPopUpMenuCtrlExAdd( "void add(string name, S32 idNum, S32 scheme=0);" ); -DefineConsoleMethod( GuiPopUpMenuCtrlEx, add, void, (const char * name, S32 idNum, U32 scheme), ("", -1, 0), "(string name, int idNum, int scheme=0)") +DefineEngineMethod( GuiPopUpMenuCtrlEx, add, void, (const char * name, S32 idNum, U32 scheme), ("", -1, 0), "(string name, int idNum, int scheme=0)") { object->addEntry(name, idNum, scheme); } @@ -525,7 +525,7 @@ ConsoleDocFragment _GuiPopUpMenuCtrlExsetSelected( "setSelected(int id, bool scriptCallback=true);" ); -DefineConsoleMethod( GuiPopUpMenuCtrlEx, setSelected, void, (S32 id, bool scriptCallback), (true), "(int id, [scriptCallback=true])" +DefineEngineMethod( GuiPopUpMenuCtrlEx, setSelected, void, (S32 id, bool scriptCallback), (true), "(int id, [scriptCallback=true])" "@hide") { object->setSelected( id, scriptCallback ); @@ -539,7 +539,7 @@ ConsoleDocFragment _GuiPopUpMenuCtrlExsetFirstSelected( ); -DefineConsoleMethod( GuiPopUpMenuCtrlEx, setFirstSelected, void, (bool scriptCallback), (true), "([scriptCallback=true])" +DefineEngineMethod( GuiPopUpMenuCtrlEx, setFirstSelected, void, (bool scriptCallback), (true), "([scriptCallback=true])" "@hide") { object->setFirstSelected( scriptCallback ); @@ -561,7 +561,7 @@ DefineEngineMethod( GuiPopUpMenuCtrlEx, getTextById, const char*, (S32 id),, } -DefineConsoleMethod( GuiPopUpMenuCtrlEx, getColorById, ColorI, (S32 id), , +DefineEngineMethod( GuiPopUpMenuCtrlEx, getColorById, ColorI, (S32 id), , "@brief Get color of an entry's box\n\n" "@param id ID number of entry to query\n\n" "@return ColorI in the format of \"Red Green Blue Alpha\", each of with is a value between 0 - 255") @@ -572,7 +572,7 @@ DefineConsoleMethod( GuiPopUpMenuCtrlEx, getColorById, ColorI, (S32 id), , } -DefineConsoleMethod( GuiPopUpMenuCtrlEx, setEnumContent, void, ( const char * className, const char * enumName ), , +DefineEngineMethod( GuiPopUpMenuCtrlEx, setEnumContent, void, ( const char * className, const char * enumName ), , "@brief This fills the popup with a classrep's field enumeration type info.\n\n" "More of a helper function than anything. If console access to the field list is added, " "at least for the enumerated types, then this should go away.\n\n" @@ -628,7 +628,7 @@ DefineConsoleMethod( GuiPopUpMenuCtrlEx, setEnumContent, void, ( const char * cl } //------------------------------------------------------------------------------ -DefineConsoleMethod( GuiPopUpMenuCtrlEx, findText, S32, (const char * text), , "(string text)" +DefineEngineMethod( GuiPopUpMenuCtrlEx, findText, S32, (const char * text), , "(string text)" "Returns the id of the first entry containing the specified text or -1 if not found." "@param text String value used for the query\n\n" "@return Numerical ID of entry containing the text.") @@ -637,7 +637,7 @@ DefineConsoleMethod( GuiPopUpMenuCtrlEx, findText, S32, (const char * text), , " } //------------------------------------------------------------------------------ -DefineConsoleMethod( GuiPopUpMenuCtrlEx, size, S32, (), , +DefineEngineMethod( GuiPopUpMenuCtrlEx, size, S32, (), , "@brief Get the size of the menu\n\n" "@return Number of entries in the menu\n") { @@ -645,7 +645,7 @@ DefineConsoleMethod( GuiPopUpMenuCtrlEx, size, S32, (), , } //------------------------------------------------------------------------------ -DefineConsoleMethod( GuiPopUpMenuCtrlEx, replaceText, void, (S32 boolVal), , +DefineEngineMethod( GuiPopUpMenuCtrlEx, replaceText, void, (S32 boolVal), , "@brief Flag that causes each new text addition to replace the current entry\n\n" "@param True to turn on replacing, false to disable it") { @@ -737,7 +737,7 @@ void GuiPopUpMenuCtrlEx::clearEntry( S32 entry ) } //------------------------------------------------------------------------------ -DefineConsoleMethod( GuiPopUpMenuCtrlEx, clearEntry, void, (S32 entry), , "(S32 entry)") +DefineEngineMethod( GuiPopUpMenuCtrlEx, clearEntry, void, (S32 entry), , "(S32 entry)") { object->clearEntry(entry); } diff --git a/Engine/source/gui/core/guiCanvas.cpp b/Engine/source/gui/core/guiCanvas.cpp index efb0674ea..885d157a0 100644 --- a/Engine/source/gui/core/guiCanvas.cpp +++ b/Engine/source/gui/core/guiCanvas.cpp @@ -2139,7 +2139,7 @@ ConsoleDocFragment _pushDialog( "void pushDialog( GuiControl ctrl, int layer=0, bool center=false);" ); -DefineConsoleMethod( GuiCanvas, pushDialog, void, (const char * ctrlName, S32 layer, bool center), ( 0, false), "(GuiControl ctrl, int layer=0, bool center=false)" +DefineEngineMethod( GuiCanvas, pushDialog, void, (const char * ctrlName, S32 layer, bool center), ( 0, false), "(GuiControl ctrl, int layer=0, bool center=false)" "@hide") { GuiControl *gui; @@ -2176,7 +2176,7 @@ ConsoleDocFragment _popDialog2( "void popDialog();" ); -DefineConsoleMethod( GuiCanvas, popDialog, void, (GuiControl * gui), (nullAsType()), "(GuiControl ctrl=NULL)" +DefineEngineMethod( GuiCanvas, popDialog, void, (GuiControl * gui), (nullAsType()), "(GuiControl ctrl=NULL)" "@hide") { if (gui) @@ -2204,7 +2204,7 @@ ConsoleDocFragment _popLayer2( "void popLayer(S32 layer);" ); -DefineConsoleMethod( GuiCanvas, popLayer, void, (S32 layer), (0), "(int layer)" +DefineEngineMethod( GuiCanvas, popLayer, void, (S32 layer), (0), "(int layer)" "@hide") { @@ -2362,7 +2362,7 @@ ConsoleDocFragment _setCursorPos2( "bool setCursorPos( F32 posX, F32 posY);" ); -DefineConsoleMethod( GuiCanvas, setCursorPos, void, (Point2I pos), , "(Point2I pos)" +DefineEngineMethod( GuiCanvas, setCursorPos, void, (Point2I pos), , "(Point2I pos)" "@hide") { @@ -2647,7 +2647,7 @@ DefineEngineMethod( GuiCanvas, setWindowPosition, void, ( Point2I position ),, object->getPlatformWindow()->setPosition( position ); } -DefineConsoleMethod( GuiCanvas, isFullscreen, bool, (), , "() - Is this canvas currently fullscreen?" ) +DefineEngineMethod( GuiCanvas, isFullscreen, bool, (), , "() - Is this canvas currently fullscreen?" ) { if (Platform::getWebDeployment()) return false; @@ -2658,14 +2658,14 @@ DefineConsoleMethod( GuiCanvas, isFullscreen, bool, (), , "() - Is this canvas c return object->getPlatformWindow()->getVideoMode().fullScreen; } -DefineConsoleMethod( GuiCanvas, minimizeWindow, void, (), , "() - minimize this canvas' window." ) +DefineEngineMethod( GuiCanvas, minimizeWindow, void, (), , "() - minimize this canvas' window." ) { PlatformWindow* window = object->getPlatformWindow(); if ( window ) window->minimize(); } -DefineConsoleMethod( GuiCanvas, isMinimized, bool, (), , "()" ) +DefineEngineMethod( GuiCanvas, isMinimized, bool, (), , "()" ) { PlatformWindow* window = object->getPlatformWindow(); if ( window ) @@ -2674,7 +2674,7 @@ DefineConsoleMethod( GuiCanvas, isMinimized, bool, (), , "()" ) return false; } -DefineConsoleMethod( GuiCanvas, isMaximized, bool, (), , "()" ) +DefineEngineMethod( GuiCanvas, isMaximized, bool, (), , "()" ) { PlatformWindow* window = object->getPlatformWindow(); if ( window ) @@ -2683,21 +2683,21 @@ DefineConsoleMethod( GuiCanvas, isMaximized, bool, (), , "()" ) return false; } -DefineConsoleMethod( GuiCanvas, maximizeWindow, void, (), , "() - maximize this canvas' window." ) +DefineEngineMethod( GuiCanvas, maximizeWindow, void, (), , "() - maximize this canvas' window." ) { PlatformWindow* window = object->getPlatformWindow(); if ( window ) window->maximize(); } -DefineConsoleMethod( GuiCanvas, restoreWindow, void, (), , "() - restore this canvas' window." ) +DefineEngineMethod( GuiCanvas, restoreWindow, void, (), , "() - restore this canvas' window." ) { PlatformWindow* window = object->getPlatformWindow(); if( window ) window->restore(); } -DefineConsoleMethod( GuiCanvas, setFocus, void, (), , "() - Claim OS input focus for this canvas' window.") +DefineEngineMethod( GuiCanvas, setFocus, void, (), , "() - Claim OS input focus for this canvas' window.") { PlatformWindow* window = object->getPlatformWindow(); if( window ) @@ -2712,7 +2712,7 @@ DefineEngineMethod( GuiCanvas, setMenuBar, void, ( GuiControl* menu ),, return object->setMenuBar( menu ); } -DefineConsoleMethod( GuiCanvas, setVideoMode, void, +DefineEngineMethod( GuiCanvas, setVideoMode, void, (U32 width, U32 height, bool fullscreen, U32 bitDepth, U32 refreshRate, U32 antialiasLevel), ( false, 0, 0, 0), "(int width, int height, bool fullscreen, [int bitDepth], [int refreshRate], [int antialiasLevel] )\n" diff --git a/Engine/source/gui/core/guiControl.cpp b/Engine/source/gui/core/guiControl.cpp index 6fded2e92..5526c2cc6 100644 --- a/Engine/source/gui/core/guiControl.cpp +++ b/Engine/source/gui/core/guiControl.cpp @@ -2898,7 +2898,7 @@ static ConsoleDocFragment _sGuiControlSetExtent2( "GuiControl", // The class to place the method in; use NULL for functions. "void setExtent( Point2I p );" ); // The definition string. -DefineConsoleMethod( GuiControl, setExtent, void, ( const char* extOrX, const char* y ), (""), +DefineEngineMethod( GuiControl, setExtent, void, ( const char* extOrX, const char* y ), (""), "( Point2I p | int x, int y ) Set the width and height of the control.\n\n" "@hide" ) { diff --git a/Engine/source/gui/editor/guiDebugger.cpp b/Engine/source/gui/editor/guiDebugger.cpp index fb888538a..7c60d4359 100644 --- a/Engine/source/gui/editor/guiDebugger.cpp +++ b/Engine/source/gui/editor/guiDebugger.cpp @@ -66,13 +66,13 @@ DbgFileView::DbgFileView() mSize.set(1, 0); } -DefineConsoleMethod(DbgFileView, setCurrentLine, void, (S32 line, bool selected), , "(int line, bool selected)" +DefineEngineMethod(DbgFileView, setCurrentLine, void, (S32 line, bool selected), , "(int line, bool selected)" "Set the current highlighted line.") { object->setCurrentLine(line, selected); } -DefineConsoleMethod(DbgFileView, getCurrentLine, const char *, (), , "()" +DefineEngineMethod(DbgFileView, getCurrentLine, const char *, (), , "()" "Get the currently executing file and line, if any.\n\n" "@returns A string containing the file, a tab, and then the line number." " Use getField() with this.") @@ -84,38 +84,38 @@ DefineConsoleMethod(DbgFileView, getCurrentLine, const char *, (), , "()" return ret; } -DefineConsoleMethod(DbgFileView, open, bool, (const char * filename), , "(string filename)" +DefineEngineMethod(DbgFileView, open, bool, (const char * filename), , "(string filename)" "Open a file for viewing.\n\n" "@note This loads the file from the local system.") { return object->openFile(filename); } -DefineConsoleMethod(DbgFileView, clearBreakPositions, void, (), , "()" +DefineEngineMethod(DbgFileView, clearBreakPositions, void, (), , "()" "Clear all break points in the current file.") { object->clearBreakPositions(); } -DefineConsoleMethod(DbgFileView, setBreakPosition, void, (U32 line), , "(int line)" +DefineEngineMethod(DbgFileView, setBreakPosition, void, (U32 line), , "(int line)" "Set a breakpoint at the specified line.") { object->setBreakPosition(line); } -DefineConsoleMethod(DbgFileView, setBreak, void, (U32 line), , "(int line)" +DefineEngineMethod(DbgFileView, setBreak, void, (U32 line), , "(int line)" "Set a breakpoint at the specified line.") { object->setBreakPointStatus(line, true); } -DefineConsoleMethod(DbgFileView, removeBreak, void, (U32 line), , "(int line)" +DefineEngineMethod(DbgFileView, removeBreak, void, (U32 line), , "(int line)" "Remove a breakpoint from the specified line.") { object->setBreakPointStatus(line, false); } -DefineConsoleMethod(DbgFileView, findString, bool, (const char * findThis), , "(string findThis)" +DefineEngineMethod(DbgFileView, findString, bool, (const char * findThis), , "(string findThis)" "Find the specified string in the currently viewed file and " "scroll it into view.") { diff --git a/Engine/source/gui/editor/guiEditCtrl.cpp b/Engine/source/gui/editor/guiEditCtrl.cpp index 6eb290142..be4179421 100644 --- a/Engine/source/gui/editor/guiEditCtrl.cpp +++ b/Engine/source/gui/editor/guiEditCtrl.cpp @@ -2468,7 +2468,7 @@ void GuiEditCtrl::startMouseGuideDrag( guideAxis axis, U32 guideIndex, bool lock //----------------------------------------------------------------------------- -DefineConsoleMethod( GuiEditCtrl, getContentControl, S32, (), , "() - Return the toplevel control edited inside the GUI editor." ) +DefineEngineMethod( GuiEditCtrl, getContentControl, S32, (), , "() - Return the toplevel control edited inside the GUI editor." ) { GuiControl* ctrl = object->getContentControl(); if( ctrl ) @@ -2479,7 +2479,7 @@ DefineConsoleMethod( GuiEditCtrl, getContentControl, S32, (), , "() - Return the //----------------------------------------------------------------------------- -DefineConsoleMethod( GuiEditCtrl, setContentControl, void, (GuiControl *ctrl ), , "( GuiControl ctrl ) - Set the toplevel control to edit in the GUI editor." ) +DefineEngineMethod( GuiEditCtrl, setContentControl, void, (GuiControl *ctrl ), , "( GuiControl ctrl ) - Set the toplevel control to edit in the GUI editor." ) { if (ctrl) object->setContentControl(ctrl); @@ -2487,7 +2487,7 @@ DefineConsoleMethod( GuiEditCtrl, setContentControl, void, (GuiControl *ctrl ), //----------------------------------------------------------------------------- -DefineConsoleMethod( GuiEditCtrl, addNewCtrl, void, (GuiControl *ctrl), , "(GuiControl ctrl)") +DefineEngineMethod( GuiEditCtrl, addNewCtrl, void, (GuiControl *ctrl), , "(GuiControl ctrl)") { if (ctrl) object->addNewControl(ctrl); @@ -2495,28 +2495,28 @@ DefineConsoleMethod( GuiEditCtrl, addNewCtrl, void, (GuiControl *ctrl), , "(GuiC //----------------------------------------------------------------------------- -DefineConsoleMethod( GuiEditCtrl, addSelection, void, (S32 id), , "selects a control.") +DefineEngineMethod( GuiEditCtrl, addSelection, void, (S32 id), , "selects a control.") { object->addSelection(id); } //----------------------------------------------------------------------------- -DefineConsoleMethod( GuiEditCtrl, removeSelection, void, (S32 id), , "deselects a control.") +DefineEngineMethod( GuiEditCtrl, removeSelection, void, (S32 id), , "deselects a control.") { object->removeSelection(id); } //----------------------------------------------------------------------------- -DefineConsoleMethod( GuiEditCtrl, clearSelection, void, (), , "Clear selected controls list.") +DefineEngineMethod( GuiEditCtrl, clearSelection, void, (), , "Clear selected controls list.") { object->clearSelection(); } //----------------------------------------------------------------------------- -DefineConsoleMethod( GuiEditCtrl, select, void, (GuiControl *ctrl), , "(GuiControl ctrl)") +DefineEngineMethod( GuiEditCtrl, select, void, (GuiControl *ctrl), , "(GuiControl ctrl)") { if (ctrl) object->setSelection(ctrl, false); @@ -2524,7 +2524,7 @@ DefineConsoleMethod( GuiEditCtrl, select, void, (GuiControl *ctrl), , "(GuiContr //----------------------------------------------------------------------------- -DefineConsoleMethod( GuiEditCtrl, setCurrentAddSet, void, (GuiControl *addSet), , "(GuiControl ctrl)") +DefineEngineMethod( GuiEditCtrl, setCurrentAddSet, void, (GuiControl *addSet), , "(GuiControl ctrl)") { if (addSet) object->setCurrentAddSet(addSet); @@ -2532,7 +2532,7 @@ DefineConsoleMethod( GuiEditCtrl, setCurrentAddSet, void, (GuiControl *addSet), //----------------------------------------------------------------------------- -DefineConsoleMethod( GuiEditCtrl, getCurrentAddSet, S32, (), , "Returns the set to which new controls will be added") +DefineEngineMethod( GuiEditCtrl, getCurrentAddSet, S32, (), , "Returns the set to which new controls will be added") { const GuiControl* add = object->getCurrentAddSet(); return add ? add->getId() : 0; @@ -2540,49 +2540,49 @@ DefineConsoleMethod( GuiEditCtrl, getCurrentAddSet, S32, (), , "Returns the set //----------------------------------------------------------------------------- -DefineConsoleMethod( GuiEditCtrl, toggle, void, (), , "Toggle activation.") +DefineEngineMethod( GuiEditCtrl, toggle, void, (), , "Toggle activation.") { object->setEditMode( !object->isActive() ); } //----------------------------------------------------------------------------- -DefineConsoleMethod( GuiEditCtrl, justify, void, (U32 mode), , "(int mode)" ) +DefineEngineMethod( GuiEditCtrl, justify, void, (U32 mode), , "(int mode)" ) { object->justifySelection( (GuiEditCtrl::Justification)mode ); } //----------------------------------------------------------------------------- -DefineConsoleMethod( GuiEditCtrl, bringToFront, void, (), , "") +DefineEngineMethod( GuiEditCtrl, bringToFront, void, (), , "") { object->bringToFront(); } //----------------------------------------------------------------------------- -DefineConsoleMethod( GuiEditCtrl, pushToBack, void, (), , "") +DefineEngineMethod( GuiEditCtrl, pushToBack, void, (), , "") { object->pushToBack(); } //----------------------------------------------------------------------------- -DefineConsoleMethod( GuiEditCtrl, deleteSelection, void, (), , "() - Delete the selected controls.") +DefineEngineMethod( GuiEditCtrl, deleteSelection, void, (), , "() - Delete the selected controls.") { object->deleteSelection(); } //----------------------------------------------------------------------------- -DefineConsoleMethod( GuiEditCtrl, moveSelection, void, (S32 dx, S32 dy), , "Move all controls in the selection by (dx,dy) pixels.") +DefineEngineMethod( GuiEditCtrl, moveSelection, void, (S32 dx, S32 dy), , "Move all controls in the selection by (dx,dy) pixels.") { object->moveAndSnapSelection(Point2I(dx, dy)); } //----------------------------------------------------------------------------- -DefineConsoleMethod( GuiEditCtrl, saveSelection, void, (const char * filename), (nullAsType()), "( string fileName=null ) - Save selection to file or clipboard.") +DefineEngineMethod( GuiEditCtrl, saveSelection, void, (const char * filename), (nullAsType()), "( string fileName=null ) - Save selection to file or clipboard.") { object->saveSelection( filename ); @@ -2590,7 +2590,7 @@ DefineConsoleMethod( GuiEditCtrl, saveSelection, void, (const char * filename), //----------------------------------------------------------------------------- -DefineConsoleMethod( GuiEditCtrl, loadSelection, void, (const char * filename), (nullAsType()), "( string fileName=null ) - Load selection from file or clipboard.") +DefineEngineMethod( GuiEditCtrl, loadSelection, void, (const char * filename), (nullAsType()), "( string fileName=null ) - Load selection from file or clipboard.") { object->loadSelection( filename ); @@ -2598,7 +2598,7 @@ DefineConsoleMethod( GuiEditCtrl, loadSelection, void, (const char * filename), //----------------------------------------------------------------------------- -DefineConsoleMethod( GuiEditCtrl, selectAll, void, (), , "()") +DefineEngineMethod( GuiEditCtrl, selectAll, void, (), , "()") { object->selectAll(); } @@ -2613,14 +2613,14 @@ DefineEngineMethod( GuiEditCtrl, getSelection, SimSet*, (),, //----------------------------------------------------------------------------- -DefineConsoleMethod( GuiEditCtrl, getNumSelected, S32, (), , "() - Return the number of controls currently selected." ) +DefineEngineMethod( GuiEditCtrl, getNumSelected, S32, (), , "() - Return the number of controls currently selected." ) { return object->getNumSelected(); } //----------------------------------------------------------------------------- -DefineConsoleMethod( GuiEditCtrl, getSelectionGlobalBounds, const char*, (), , "() - Returns global bounds of current selection as vector 'x y width height'." ) +DefineEngineMethod( GuiEditCtrl, getSelectionGlobalBounds, const char*, (), , "() - Returns global bounds of current selection as vector 'x y width height'." ) { RectI bounds = object->getSelectionGlobalBounds(); String str = String::ToString( "%i %i %i %i", bounds.point.x, bounds.point.y, bounds.extent.x, bounds.extent.y ); @@ -2633,7 +2633,7 @@ DefineConsoleMethod( GuiEditCtrl, getSelectionGlobalBounds, const char*, (), , " //----------------------------------------------------------------------------- -DefineConsoleMethod( GuiEditCtrl, selectParents, void, ( bool addToSelection ), (false), "( bool addToSelection=false ) - Select parents of currently selected controls." ) +DefineEngineMethod( GuiEditCtrl, selectParents, void, ( bool addToSelection ), (false), "( bool addToSelection=false ) - Select parents of currently selected controls." ) { object->selectParents( addToSelection ); @@ -2641,7 +2641,7 @@ DefineConsoleMethod( GuiEditCtrl, selectParents, void, ( bool addToSelection ), //----------------------------------------------------------------------------- -DefineConsoleMethod( GuiEditCtrl, selectChildren, void, ( bool addToSelection ), (false), "( bool addToSelection=false ) - Select children of currently selected controls." ) +DefineEngineMethod( GuiEditCtrl, selectChildren, void, ( bool addToSelection ), (false), "( bool addToSelection=false ) - Select children of currently selected controls." ) { object->selectChildren( addToSelection ); @@ -2657,14 +2657,14 @@ DefineEngineMethod( GuiEditCtrl, getTrash, SimGroup*, (),, //----------------------------------------------------------------------------- -DefineConsoleMethod(GuiEditCtrl, setSnapToGrid, void, (U32 gridsize), , "GuiEditCtrl.setSnapToGrid(gridsize)") +DefineEngineMethod(GuiEditCtrl, setSnapToGrid, void, (U32 gridsize), , "GuiEditCtrl.setSnapToGrid(gridsize)") { object->setSnapToGrid(gridsize); } //----------------------------------------------------------------------------- -DefineConsoleMethod( GuiEditCtrl, readGuides, void, ( GuiControl* ctrl, S32 axis ), (-1), "( GuiControl ctrl [, int axis ] ) - Read the guides from the given control." ) +DefineEngineMethod( GuiEditCtrl, readGuides, void, ( GuiControl* ctrl, S32 axis ), (-1), "( GuiControl ctrl [, int axis ] ) - Read the guides from the given control." ) { // Find the control. @@ -2694,7 +2694,7 @@ DefineConsoleMethod( GuiEditCtrl, readGuides, void, ( GuiControl* ctrl, S32 axis //----------------------------------------------------------------------------- -DefineConsoleMethod( GuiEditCtrl, writeGuides, void, ( GuiControl* ctrl, S32 axis ), ( -1), "( GuiControl ctrl [, int axis ] ) - Write the guides to the given control." ) +DefineEngineMethod( GuiEditCtrl, writeGuides, void, ( GuiControl* ctrl, S32 axis ), ( -1), "( GuiControl ctrl [, int axis ] ) - Write the guides to the given control." ) { // Find the control. @@ -2724,7 +2724,7 @@ DefineConsoleMethod( GuiEditCtrl, writeGuides, void, ( GuiControl* ctrl, S32 axi //----------------------------------------------------------------------------- -DefineConsoleMethod( GuiEditCtrl, clearGuides, void, ( S32 axis ), (-1), "( [ int axis ] ) - Clear all currently set guide lines." ) +DefineEngineMethod( GuiEditCtrl, clearGuides, void, ( S32 axis ), (-1), "( [ int axis ] ) - Clear all currently set guide lines." ) { if( axis != -1 ) { @@ -2745,7 +2745,7 @@ DefineConsoleMethod( GuiEditCtrl, clearGuides, void, ( S32 axis ), (-1), "( [ in //----------------------------------------------------------------------------- -DefineConsoleMethod( GuiEditCtrl, fitIntoParents, void, (bool width, bool height), (true, true), "( bool width=true, bool height=true ) - Fit selected controls into their parents." ) +DefineEngineMethod( GuiEditCtrl, fitIntoParents, void, (bool width, bool height), (true, true), "( bool width=true, bool height=true ) - Fit selected controls into their parents." ) { object->fitIntoParents( width, height ); @@ -2753,7 +2753,7 @@ DefineConsoleMethod( GuiEditCtrl, fitIntoParents, void, (bool width, bool height //----------------------------------------------------------------------------- -DefineConsoleMethod( GuiEditCtrl, getMouseMode, const char*, (), , "() - Return the current mouse mode." ) +DefineEngineMethod( GuiEditCtrl, getMouseMode, const char*, (), , "() - Return the current mouse mode." ) { switch( object->getMouseMode() ) { diff --git a/Engine/source/gui/editor/guiFilterCtrl.cpp b/Engine/source/gui/editor/guiFilterCtrl.cpp index 67a0232ae..c0d9c2a72 100644 --- a/Engine/source/gui/editor/guiFilterCtrl.cpp +++ b/Engine/source/gui/editor/guiFilterCtrl.cpp @@ -60,7 +60,7 @@ void GuiFilterCtrl::initPersistFields() Parent::initPersistFields(); } -DefineConsoleMethod( GuiFilterCtrl, getValue, const char*, (), , "Return a tuple containing all the values in the filter." +DefineEngineMethod( GuiFilterCtrl, getValue, const char*, (), , "Return a tuple containing all the values in the filter." "@internal") { static char buffer[512]; @@ -89,7 +89,7 @@ ConsoleMethod( GuiFilterCtrl, setValue, void, 3, 20, "(f1, f2, ...)" object->set(filter); } -DefineConsoleMethod( GuiFilterCtrl, identity, void, (), , "Reset the filtering." +DefineEngineMethod( GuiFilterCtrl, identity, void, (), , "Reset the filtering." "@internal") { object->identity(); diff --git a/Engine/source/gui/editor/guiMenuBar.cpp b/Engine/source/gui/editor/guiMenuBar.cpp index dc168436b..efe534358 100644 --- a/Engine/source/gui/editor/guiMenuBar.cpp +++ b/Engine/source/gui/editor/guiMenuBar.cpp @@ -1486,7 +1486,7 @@ PopupMenu* GuiMenuBar::findMenu(StringTableEntry barTitle) //----------------------------------------------------------------------------- // Console Methods //----------------------------------------------------------------------------- -DefineConsoleMethod(GuiMenuBar, attachToCanvas, void, (const char *canvas, S32 pos), , "(GuiCanvas, pos)") +DefineEngineMethod(GuiMenuBar, attachToCanvas, void, (const char *canvas, S32 pos), , "(GuiCanvas, pos)") { GuiCanvas* canv = dynamic_cast(Sim::findObject(canvas)); if (canv) @@ -1495,7 +1495,7 @@ DefineConsoleMethod(GuiMenuBar, attachToCanvas, void, (const char *canvas, S32 p } } -DefineConsoleMethod(GuiMenuBar, removeFromCanvas, void, (), , "()") +DefineEngineMethod(GuiMenuBar, removeFromCanvas, void, (), , "()") { GuiCanvas* canvas = object->getRoot(); @@ -1503,23 +1503,23 @@ DefineConsoleMethod(GuiMenuBar, removeFromCanvas, void, (), , "()") canvas->setMenuBar(nullptr); } -DefineConsoleMethod(GuiMenuBar, getMenuCount, S32, (), , "()") +DefineEngineMethod(GuiMenuBar, getMenuCount, S32, (), , "()") { return object->getMenuListCount(); } -DefineConsoleMethod(GuiMenuBar, getMenu, S32, (S32 index), (0), "(Index)") +DefineEngineMethod(GuiMenuBar, getMenu, S32, (S32 index), (0), "(Index)") { return object->getMenu(index)->getId(); } //----------------------------------------------------------------------------- -DefineConsoleMethod(GuiMenuBar, insert, void, (SimObject* pObject, S32 pos), (nullAsType(), -1), "(object, pos) insert object at position") +DefineEngineMethod(GuiMenuBar, insert, void, (SimObject* pObject, S32 pos), (nullAsType(), -1), "(object, pos) insert object at position") { object->insert(pObject, pos); } -DefineConsoleMethod(GuiMenuBar, findMenu, S32, (const char* barTitle), (""), "(barTitle)") +DefineEngineMethod(GuiMenuBar, findMenu, S32, (const char* barTitle), (""), "(barTitle)") { StringTableEntry barTitleStr = StringTable->insert(barTitle); PopupMenu* menu = object->findMenu(barTitleStr); diff --git a/Engine/source/gui/editor/guiParticleGraphCtrl.cpp b/Engine/source/gui/editor/guiParticleGraphCtrl.cpp index 342646fb1..4b71a1518 100644 --- a/Engine/source/gui/editor/guiParticleGraphCtrl.cpp +++ b/Engine/source/gui/editor/guiParticleGraphCtrl.cpp @@ -1004,7 +1004,7 @@ bool GuiParticleGraphCtrl::renderGraphTooltip(Point2I cursorPos, StringTableEntr return true; } -DefineConsoleMethod(GuiParticleGraphCtrl, setSelectedPoint, void, (S32 point), , "(int point)" +DefineEngineMethod(GuiParticleGraphCtrl, setSelectedPoint, void, (S32 point), , "(int point)" "Set the selected point on the graph.\n" "@return No return value") { @@ -1016,7 +1016,7 @@ DefineConsoleMethod(GuiParticleGraphCtrl, setSelectedPoint, void, (S32 point), , object->setSelectedPoint( point ); } -DefineConsoleMethod(GuiParticleGraphCtrl, setSelectedPlot, void, (S32 plotID), , "(int plotID)" +DefineEngineMethod(GuiParticleGraphCtrl, setSelectedPlot, void, (S32 plotID), , "(int plotID)" "Set the selected plot (a.k.a. graph)." "@return No return value" ) { @@ -1028,7 +1028,7 @@ DefineConsoleMethod(GuiParticleGraphCtrl, setSelectedPlot, void, (S32 plotID), , object->setSelectedPlot( plotID ); } -DefineConsoleMethod(GuiParticleGraphCtrl, clearGraph, void, (S32 plotID), , "(int plotID)" +DefineEngineMethod(GuiParticleGraphCtrl, clearGraph, void, (S32 plotID), , "(int plotID)" "Clear the graph of the given plot." "@return No return value") { @@ -1040,14 +1040,14 @@ DefineConsoleMethod(GuiParticleGraphCtrl, clearGraph, void, (S32 plotID), , "(in object->clearGraph( plotID ); } -DefineConsoleMethod(GuiParticleGraphCtrl, clearAllGraphs, void, (), , "()" +DefineEngineMethod(GuiParticleGraphCtrl, clearAllGraphs, void, (), , "()" "Clear all of the graphs." "@return No return value") { object->clearAllGraphs(); } -DefineConsoleMethod(GuiParticleGraphCtrl, addPlotPoint, S32, (S32 plotID, F32 x, F32 y, bool setAdded), (true), "(int plotID, float x, float y, bool setAdded = true;)" +DefineEngineMethod(GuiParticleGraphCtrl, addPlotPoint, S32, (S32 plotID, F32 x, F32 y, bool setAdded), (true), "(int plotID, float x, float y, bool setAdded = true;)" "Add a data point to the given plot." "@return") { @@ -1060,7 +1060,7 @@ DefineConsoleMethod(GuiParticleGraphCtrl, addPlotPoint, S32, (S32 plotID, F32 x, return object->addPlotPoint( plotID, Point2F(x, y), setAdded); } -DefineConsoleMethod(GuiParticleGraphCtrl, insertPlotPoint, void, (S32 plotID, S32 i, F32 x, F32 y), , "(int plotID, int i, float x, float y)\n" +DefineEngineMethod(GuiParticleGraphCtrl, insertPlotPoint, void, (S32 plotID, S32 i, F32 x, F32 y), , "(int plotID, int i, float x, float y)\n" "Insert a data point to the given plot and plot position.\n" "@param plotID The plot you want to access\n" "@param i The data point.\n" @@ -1075,7 +1075,7 @@ DefineConsoleMethod(GuiParticleGraphCtrl, insertPlotPoint, void, (S32 plotID, S3 object->insertPlotPoint( plotID, i, Point2F(x, y)); } -DefineConsoleMethod(GuiParticleGraphCtrl, changePlotPoint, S32, (S32 plotID, S32 i, F32 x, F32 y), , "(int plotID, int i, float x, float y)" +DefineEngineMethod(GuiParticleGraphCtrl, changePlotPoint, S32, (S32 plotID, S32 i, F32 x, F32 y), , "(int plotID, int i, float x, float y)" "Change a data point to the given plot and plot position.\n" "@param plotID The plot you want to access\n" "@param i The data point.\n" @@ -1090,21 +1090,21 @@ DefineConsoleMethod(GuiParticleGraphCtrl, changePlotPoint, S32, (S32 plotID, S32 return object->changePlotPoint( plotID, i, Point2F(x, y)); } -DefineConsoleMethod(GuiParticleGraphCtrl, getSelectedPlot, S32, (), , "() " +DefineEngineMethod(GuiParticleGraphCtrl, getSelectedPlot, S32, (), , "() " "Gets the selected Plot (a.k.a. graph).\n" "@return The plot's ID.") { return object->getSelectedPlot(); } -DefineConsoleMethod(GuiParticleGraphCtrl, getSelectedPoint, S32, (), , "()" +DefineEngineMethod(GuiParticleGraphCtrl, getSelectedPoint, S32, (), , "()" "Gets the selected Point on the Plot (a.k.a. graph)." "@return The last selected point ID") { return object->getSelectedPoint(); } -DefineConsoleMethod(GuiParticleGraphCtrl, isExistingPoint, bool, (S32 plotID, S32 samples), , "(int plotID, int samples)" +DefineEngineMethod(GuiParticleGraphCtrl, isExistingPoint, bool, (S32 plotID, S32 samples), , "(int plotID, int samples)" "@return Returns true or false whether or not the point in the plot passed is an existing point.") { @@ -1119,7 +1119,7 @@ DefineConsoleMethod(GuiParticleGraphCtrl, isExistingPoint, bool, (S32 plotID, S3 return object->isExistingPoint(plotID, samples); } -DefineConsoleMethod(GuiParticleGraphCtrl, getPlotPoint, Point2F, (S32 plotID, S32 samples), , "(int plotID, int samples)" +DefineEngineMethod(GuiParticleGraphCtrl, getPlotPoint, Point2F, (S32 plotID, S32 samples), , "(int plotID, int samples)" "Get a data point from the plot specified, samples from the start of the graph." "@return The data point ID") { @@ -1137,7 +1137,7 @@ DefineConsoleMethod(GuiParticleGraphCtrl, getPlotPoint, Point2F, (S32 plotID, S3 return object->getPlotPoint(plotID, samples); } -DefineConsoleMethod(GuiParticleGraphCtrl, getPlotIndex, S32, (S32 plotID, F32 x, F32 y), , "(int plotID, float x, float y)\n" +DefineEngineMethod(GuiParticleGraphCtrl, getPlotIndex, S32, (S32 plotID, F32 x, F32 y), , "(int plotID, float x, float y)\n" "Gets the index of the point passed on the plotID passed (graph ID).\n" "@param plotID The plot you wish to check.\n" "@param x,y The coordinates of the point to get.\n" @@ -1151,7 +1151,7 @@ DefineConsoleMethod(GuiParticleGraphCtrl, getPlotIndex, S32, (S32 plotID, F32 x, return object->getPlotIndex(plotID, x, y); } -DefineConsoleMethod(GuiParticleGraphCtrl, getGraphColor, LinearColorF, (S32 plotID), , "(int plotID)" +DefineEngineMethod(GuiParticleGraphCtrl, getGraphColor, LinearColorF, (S32 plotID), , "(int plotID)" "Get the color of the graph passed." "@return Returns the color of the graph as a string of RGB values formatted as \"R G B\"") { @@ -1165,7 +1165,7 @@ DefineConsoleMethod(GuiParticleGraphCtrl, getGraphColor, LinearColorF, (S32 plot } -DefineConsoleMethod(GuiParticleGraphCtrl, getGraphMin, Point2F, (S32 plotID), , "(int plotID) " +DefineEngineMethod(GuiParticleGraphCtrl, getGraphMin, Point2F, (S32 plotID), , "(int plotID) " "Get the minimum values of the graph ranges.\n" "@return Returns the minimum of the range formatted as \"x-min y-min\"") { @@ -1177,7 +1177,7 @@ DefineConsoleMethod(GuiParticleGraphCtrl, getGraphMin, Point2F, (S32 plotID), , return object->getGraphMin(plotID); } -DefineConsoleMethod(GuiParticleGraphCtrl, getGraphMax, Point2F, (S32 plotID), , "(int plotID) " +DefineEngineMethod(GuiParticleGraphCtrl, getGraphMax, Point2F, (S32 plotID), , "(int plotID) " "Get the maximum values of the graph ranges.\n" "@return Returns the maximum of the range formatted as \"x-max y-max\"") { @@ -1190,7 +1190,7 @@ DefineConsoleMethod(GuiParticleGraphCtrl, getGraphMax, Point2F, (S32 plotID), , } -DefineConsoleMethod(GuiParticleGraphCtrl, getGraphName, const char*, (S32 plotID), , "(int plotID) " +DefineEngineMethod(GuiParticleGraphCtrl, getGraphName, const char*, (S32 plotID), , "(int plotID) " "Get the name of the graph passed.\n" "@return Returns the name of the plot") { @@ -1207,7 +1207,7 @@ DefineConsoleMethod(GuiParticleGraphCtrl, getGraphName, const char*, (S32 plotID return retBuffer; } -DefineConsoleMethod(GuiParticleGraphCtrl, setGraphMin, void, (S32 plotID, F32 minX, F32 minY), , "(int plotID, float minX, float minY) " +DefineEngineMethod(GuiParticleGraphCtrl, setGraphMin, void, (S32 plotID, F32 minX, F32 minY), , "(int plotID, float minX, float minY) " "Set the min values of the graph of plotID.\n" "@param plotID The plot to modify\n" "@param minX,minY The minimum bound of the value range.\n" @@ -1223,7 +1223,7 @@ DefineConsoleMethod(GuiParticleGraphCtrl, setGraphMin, void, (S32 plotID, F32 mi object->setGraphMin(plotID, Point2F(minX, minY)); } -DefineConsoleMethod(GuiParticleGraphCtrl, setGraphMinX, void, (S32 plotID, F32 minX), , "(int plotID, float minX) " +DefineEngineMethod(GuiParticleGraphCtrl, setGraphMinX, void, (S32 plotID, F32 minX), , "(int plotID, float minX) " "Set the min X value of the graph of plotID.\n" "@param plotID The plot to modify.\n" "@param minX The minimum x value.\n" @@ -1239,7 +1239,7 @@ DefineConsoleMethod(GuiParticleGraphCtrl, setGraphMinX, void, (S32 plotID, F32 m object->setGraphMinX(plotID, minX); } -DefineConsoleMethod(GuiParticleGraphCtrl, setGraphMinY, void, (S32 plotID, F32 minX), , "(int plotID, float minY) " +DefineEngineMethod(GuiParticleGraphCtrl, setGraphMinY, void, (S32 plotID, F32 minX), , "(int plotID, float minY) " "Set the min Y value of the graph of plotID." "@param plotID The plot to modify.\n" "@param minY The minimum y value.\n" @@ -1255,7 +1255,7 @@ DefineConsoleMethod(GuiParticleGraphCtrl, setGraphMinY, void, (S32 plotID, F32 m object->setGraphMinY(plotID, minX); } -DefineConsoleMethod(GuiParticleGraphCtrl, setGraphMax, void, (S32 plotID, F32 maxX, F32 maxY), , "(int plotID, float maxX, float maxY) " +DefineEngineMethod(GuiParticleGraphCtrl, setGraphMax, void, (S32 plotID, F32 maxX, F32 maxY), , "(int plotID, float maxX, float maxY) " "Set the max values of the graph of plotID." "@param plotID The plot to modify\n" "@param maxX,maxY The maximum bound of the value range.\n" @@ -1271,7 +1271,7 @@ DefineConsoleMethod(GuiParticleGraphCtrl, setGraphMax, void, (S32 plotID, F32 ma object->setGraphMax(plotID, Point2F(maxX, maxY)); } -DefineConsoleMethod(GuiParticleGraphCtrl, setGraphMaxX, void, (S32 plotID, F32 maxX), , "(int plotID, float maxX)" +DefineEngineMethod(GuiParticleGraphCtrl, setGraphMaxX, void, (S32 plotID, F32 maxX), , "(int plotID, float maxX)" "Set the max X value of the graph of plotID." "@param plotID The plot to modify.\n" "@param maxX The maximum x value.\n" @@ -1287,7 +1287,7 @@ DefineConsoleMethod(GuiParticleGraphCtrl, setGraphMaxX, void, (S32 plotID, F32 m object->setGraphMaxX(plotID, maxX); } -DefineConsoleMethod(GuiParticleGraphCtrl, setGraphMaxY, void, (S32 plotID, F32 maxX), , "(int plotID, float maxY)" +DefineEngineMethod(GuiParticleGraphCtrl, setGraphMaxY, void, (S32 plotID, F32 maxX), , "(int plotID, float maxY)" "Set the max Y value of the graph of plotID." "@param plotID The plot to modify.\n" "@param maxY The maximum y value.\n" @@ -1303,7 +1303,7 @@ DefineConsoleMethod(GuiParticleGraphCtrl, setGraphMaxY, void, (S32 plotID, F32 m object->setGraphMaxY(plotID, maxX); } -DefineConsoleMethod(GuiParticleGraphCtrl, setGraphHidden, void, (S32 plotID, bool isHidden), , "(int plotID, bool isHidden)" +DefineEngineMethod(GuiParticleGraphCtrl, setGraphHidden, void, (S32 plotID, bool isHidden), , "(int plotID, bool isHidden)" "Set whether the graph number passed is hidden or not." "@return No return value.") { @@ -1317,7 +1317,7 @@ DefineConsoleMethod(GuiParticleGraphCtrl, setGraphHidden, void, (S32 plotID, boo object->setGraphHidden(plotID, isHidden); } -DefineConsoleMethod(GuiParticleGraphCtrl, setAutoGraphMax, void, (bool autoMax), , "(bool autoMax) " +DefineEngineMethod(GuiParticleGraphCtrl, setAutoGraphMax, void, (bool autoMax), , "(bool autoMax) " "Set whether the max will automatically be set when adding points " "(ie if you add a value over the current max, the max is increased to that value).\n" "@return No return value.") @@ -1325,35 +1325,35 @@ DefineConsoleMethod(GuiParticleGraphCtrl, setAutoGraphMax, void, (bool autoMax), object->setAutoGraphMax(autoMax); } -DefineConsoleMethod(GuiParticleGraphCtrl, setAutoRemove, void, (bool autoRemove), , "(bool autoRemove) " +DefineEngineMethod(GuiParticleGraphCtrl, setAutoRemove, void, (bool autoRemove), , "(bool autoRemove) " "Set whether or not a point should be deleted when you drag another one over it." "@return No return value.") { object->setAutoRemove(autoRemove); } -DefineConsoleMethod(GuiParticleGraphCtrl, setRenderAll, void, (bool autoRemove), , "(bool renderAll)" +DefineEngineMethod(GuiParticleGraphCtrl, setRenderAll, void, (bool autoRemove), , "(bool renderAll)" "Set whether or not a position should be rendered on every point or just the last selected." "@return No return value.") { object->setRenderAll(autoRemove); } -DefineConsoleMethod(GuiParticleGraphCtrl, setPointXMovementClamped, void, (bool autoRemove), , "(bool clamped)" +DefineEngineMethod(GuiParticleGraphCtrl, setPointXMovementClamped, void, (bool autoRemove), , "(bool clamped)" "Set whether the x position of the selected graph point should be clamped" "@return No return value.") { object->setPointXMovementClamped(autoRemove); } -DefineConsoleMethod(GuiParticleGraphCtrl, setRenderGraphTooltip, void, (bool autoRemove), , "(bool renderGraphTooltip)" +DefineEngineMethod(GuiParticleGraphCtrl, setRenderGraphTooltip, void, (bool autoRemove), , "(bool renderGraphTooltip)" "Set whether or not to render the graph tooltip." "@return No return value.") { object->setRenderGraphTooltip(autoRemove); } -DefineConsoleMethod(GuiParticleGraphCtrl, setGraphName, void, (S32 plotID, const char * graphName), , "(int plotID, string graphName) " +DefineEngineMethod(GuiParticleGraphCtrl, setGraphName, void, (S32 plotID, const char * graphName), , "(int plotID, string graphName) " "Set the name of the given plot.\n" "@param plotID The plot to modify.\n" "@param graphName The name to set on the plot.\n" @@ -1369,7 +1369,7 @@ DefineConsoleMethod(GuiParticleGraphCtrl, setGraphName, void, (S32 plotID, const object->setGraphName(plotID, graphName); } -DefineConsoleMethod(GuiParticleGraphCtrl, resetSelectedPoint, void, (), , "()" +DefineEngineMethod(GuiParticleGraphCtrl, resetSelectedPoint, void, (), , "()" "This will reset the currently selected point to nothing." "@return No return value.") { diff --git a/Engine/source/gui/editor/inspector/componentGroup.cpp b/Engine/source/gui/editor/inspector/componentGroup.cpp index 6e16db173..27aec03fa 100644 --- a/Engine/source/gui/editor/inspector/componentGroup.cpp +++ b/Engine/source/gui/editor/inspector/componentGroup.cpp @@ -524,7 +524,7 @@ ConsoleMethod(GuiInspectorComponentGroup, removeDynamicField, void, 3, 3, "") { } -DefineConsoleMethod(GuiInspectorComponentGroup, getComponent, S32, (), ,"") +DefineEngineMethod(GuiInspectorComponentGroup, getComponent, S32, (), ,"") { return object->getComponent()->getId(); } diff --git a/Engine/source/gui/editor/inspector/dynamicField.cpp b/Engine/source/gui/editor/inspector/dynamicField.cpp index d028a6c7a..092af36f4 100644 --- a/Engine/source/gui/editor/inspector/dynamicField.cpp +++ b/Engine/source/gui/editor/inspector/dynamicField.cpp @@ -316,7 +316,7 @@ void GuiInspectorDynamicField::_executeSelectedCallback() Con::executef( mInspector, "onFieldSelected", mDynField->slotName, "TypeDynamicField" ); } -DefineConsoleMethod( GuiInspectorDynamicField, renameField, void, (const char* newDynamicFieldName),, "field.renameField(newDynamicFieldName);" ) +DefineEngineMethod( GuiInspectorDynamicField, renameField, void, (const char* newDynamicFieldName),, "field.renameField(newDynamicFieldName);" ) { object->renameField( newDynamicFieldName ); } diff --git a/Engine/source/gui/editor/inspector/dynamicGroup.cpp b/Engine/source/gui/editor/inspector/dynamicGroup.cpp index 3d9879919..931a00836 100644 --- a/Engine/source/gui/editor/inspector/dynamicGroup.cpp +++ b/Engine/source/gui/editor/inspector/dynamicGroup.cpp @@ -188,7 +188,7 @@ void GuiInspectorDynamicGroup::updateAllFields() inspectGroup(); } -DefineConsoleMethod(GuiInspectorDynamicGroup, inspectGroup, bool, (), , "Refreshes the dynamic fields in the inspector.") +DefineEngineMethod(GuiInspectorDynamicGroup, inspectGroup, bool, (), , "Refreshes the dynamic fields in the inspector.") { return object->inspectGroup(); } @@ -263,11 +263,11 @@ void GuiInspectorDynamicGroup::addDynamicField() instantExpand(); } -DefineConsoleMethod( GuiInspectorDynamicGroup, addDynamicField, void, (), , "obj.addDynamicField();" ) +DefineEngineMethod( GuiInspectorDynamicGroup, addDynamicField, void, (), , "obj.addDynamicField();" ) { object->addDynamicField(); } -DefineConsoleMethod( GuiInspectorDynamicGroup, removeDynamicField, void, (), , "" ) +DefineEngineMethod( GuiInspectorDynamicGroup, removeDynamicField, void, (), , "" ) { } diff --git a/Engine/source/gui/editor/inspector/field.cpp b/Engine/source/gui/editor/inspector/field.cpp index f8efaca02..2808ee140 100644 --- a/Engine/source/gui/editor/inspector/field.cpp +++ b/Engine/source/gui/editor/inspector/field.cpp @@ -688,59 +688,59 @@ void GuiInspectorField::_setFieldDocs( StringTableEntry docs ) //----------------------------------------------------------------------------- -DefineConsoleMethod( GuiInspectorField, getInspector, S32, (), , "() - Return the GuiInspector to which this field belongs." ) +DefineEngineMethod( GuiInspectorField, getInspector, S32, (), , "() - Return the GuiInspector to which this field belongs." ) { return object->getInspector()->getId(); } //----------------------------------------------------------------------------- -DefineConsoleMethod( GuiInspectorField, getInspectedFieldName, const char*, (), , "() - Return the name of the field edited by this inspector field." ) +DefineEngineMethod( GuiInspectorField, getInspectedFieldName, const char*, (), , "() - Return the name of the field edited by this inspector field." ) { return object->getFieldName(); } //----------------------------------------------------------------------------- -DefineConsoleMethod( GuiInspectorField, getInspectedFieldType, const char*, (), , "() - Return the type of the field edited by this inspector field." ) +DefineEngineMethod( GuiInspectorField, getInspectedFieldType, const char*, (), , "() - Return the type of the field edited by this inspector field." ) { return object->getFieldType(); } //----------------------------------------------------------------------------- -DefineConsoleMethod( GuiInspectorField, apply, void, ( const char * newValue, bool callbacks ), (true), "( string newValue, bool callbacks=true ) - Set the field's value. Suppress callbacks for undo if callbacks=false." ) +DefineEngineMethod( GuiInspectorField, apply, void, ( const char * newValue, bool callbacks ), (true), "( string newValue, bool callbacks=true ) - Set the field's value. Suppress callbacks for undo if callbacks=false." ) { object->setData( newValue, callbacks ); } //----------------------------------------------------------------------------- -DefineConsoleMethod( GuiInspectorField, applyWithoutUndo, void, (const char * data), , "() - Set field value without recording undo (same as 'apply( value, false )')." ) +DefineEngineMethod( GuiInspectorField, applyWithoutUndo, void, (const char * data), , "() - Set field value without recording undo (same as 'apply( value, false )')." ) { object->setData( data, false ); } //----------------------------------------------------------------------------- -DefineConsoleMethod( GuiInspectorField, getData, const char*, (), , "() - Return the value currently displayed on the field." ) +DefineEngineMethod( GuiInspectorField, getData, const char*, (), , "() - Return the value currently displayed on the field." ) { return object->getData(); } //----------------------------------------------------------------------------- -DefineConsoleMethod( GuiInspectorField, reset, void, (), , "() - Reset to default value." ) +DefineEngineMethod( GuiInspectorField, reset, void, (), , "() - Reset to default value." ) { object->resetData(); } -DefineConsoleMethod(GuiInspectorField, setCaption, void, (String newCaption),, "() - Reset to default value.") +DefineEngineMethod(GuiInspectorField, setCaption, void, (String newCaption),, "() - Reset to default value.") { object->setCaption(StringTable->insert(newCaption.c_str())); } -DefineConsoleMethod(GuiInspectorField, setEditControl, void, (GuiControl* editCtrl), (nullAsType()), "() - Reset to default value.") +DefineEngineMethod(GuiInspectorField, setEditControl, void, (GuiControl* editCtrl), (nullAsType()), "() - Reset to default value.") { object->setEditControl(editCtrl); } diff --git a/Engine/source/gui/editor/inspector/variableGroup.cpp b/Engine/source/gui/editor/inspector/variableGroup.cpp index 83e4f3c32..cb23d9c6e 100644 --- a/Engine/source/gui/editor/inspector/variableGroup.cpp +++ b/Engine/source/gui/editor/inspector/variableGroup.cpp @@ -250,12 +250,12 @@ GuiInspectorField* GuiInspectorVariableGroup::createInspectorField() return NULL; } -DefineConsoleMethod(GuiInspectorVariableGroup, createInspectorField, GuiInspectorField*, (),, "createInspectorField()") +DefineEngineMethod(GuiInspectorVariableGroup, createInspectorField, GuiInspectorField*, (),, "createInspectorField()") { return object->createInspectorField(); } -DefineConsoleMethod(GuiInspectorVariableGroup, addInspectorField, void, (GuiInspectorField* field), (nullAsType()), "addInspectorField( GuiInspectorFieldObject )") +DefineEngineMethod(GuiInspectorVariableGroup, addInspectorField, void, (GuiInspectorField* field), (nullAsType()), "addInspectorField( GuiInspectorFieldObject )") { object->addInspectorField(field); } \ No newline at end of file diff --git a/Engine/source/gui/editor/inspector/variableInspector.cpp b/Engine/source/gui/editor/inspector/variableInspector.cpp index 115e48b83..10d640fc9 100644 --- a/Engine/source/gui/editor/inspector/variableInspector.cpp +++ b/Engine/source/gui/editor/inspector/variableInspector.cpp @@ -216,17 +216,17 @@ void GuiVariableInspector::setFieldEnabled(const char* name, bool enabled) } } -DefineConsoleMethod(GuiVariableInspector, startGroup, void, (const char* name),, "startGroup( groupName )") +DefineEngineMethod(GuiVariableInspector, startGroup, void, (const char* name),, "startGroup( groupName )") { object->startGroup(name); } -DefineConsoleMethod(GuiVariableInspector, endGroup, void, (),, "endGroup()") +DefineEngineMethod(GuiVariableInspector, endGroup, void, (),, "endGroup()") { object->endGroup(); } -DefineConsoleMethod(GuiVariableInspector, addField, void, (const char* name, const char* label, const char* typeName, +DefineEngineMethod(GuiVariableInspector, addField, void, (const char* name, const char* label, const char* typeName, const char* description, const char* defaultValue, const char* dataValues, SimObject* ownerObj), ("","","","","", "", nullAsType()), "addField( fieldName/varName, fieldLabel, fieldTypeName, description, defaultValue, defaultValues, ownerObject )") { @@ -236,7 +236,7 @@ DefineConsoleMethod(GuiVariableInspector, addField, void, (const char* name, con object->addField(name, label, typeName, description, defaultValue, dataValues, ownerObj); } -DefineConsoleMethod(GuiVariableInspector, addCallbackField, void, (const char* name, const char* label, const char* typeName, +DefineEngineMethod(GuiVariableInspector, addCallbackField, void, (const char* name, const char* label, const char* typeName, const char* description, const char* defaultValue, const char* dataValues, const char* callbackName, SimObject* ownerObj), ("", "", "", "", "", "", nullAsType()), "addField( fieldName/varName, fieldLabel, fieldTypeName, description, defaultValue, defaultValues, callbackName, ownerObject )") { @@ -246,22 +246,22 @@ DefineConsoleMethod(GuiVariableInspector, addCallbackField, void, (const char* n object->addCallbackField(name, label, typeName, description, defaultValue, dataValues, callbackName, ownerObj); } -DefineConsoleMethod(GuiVariableInspector, update, void, (), , "update()") +DefineEngineMethod(GuiVariableInspector, update, void, (), , "update()") { object->update(); } -DefineConsoleMethod(GuiVariableInspector, clearFields, void, (), , "clearFields()") +DefineEngineMethod(GuiVariableInspector, clearFields, void, (), , "clearFields()") { object->clearFields(); } -DefineConsoleMethod(GuiVariableInspector, setFieldEnabled, void, (const char* fieldName, bool isEnabled), (true), "setFieldEnabled( fieldName, isEnabled )") +DefineEngineMethod(GuiVariableInspector, setFieldEnabled, void, (const char* fieldName, bool isEnabled), (true), "setFieldEnabled( fieldName, isEnabled )") { object->setFieldEnabled(fieldName, isEnabled); } -DefineConsoleMethod( GuiVariableInspector, loadVars, void, ( const char * searchString ), , "loadVars( searchString )" ) +DefineEngineMethod( GuiVariableInspector, loadVars, void, ( const char * searchString ), , "loadVars( searchString )" ) { object->loadVars( searchString ); } \ No newline at end of file diff --git a/Engine/source/gui/editor/popupMenu.cpp b/Engine/source/gui/editor/popupMenu.cpp index 0e5db18da..4dac1525e 100644 --- a/Engine/source/gui/editor/popupMenu.cpp +++ b/Engine/source/gui/editor/popupMenu.cpp @@ -445,17 +445,17 @@ void PopupMenu::hidePopupSubmenus() //----------------------------------------------------------------------------- // Console Methods //----------------------------------------------------------------------------- -DefineConsoleMethod(PopupMenu, insertItem, S32, (S32 pos, const char * title, const char * accelerator, const char* cmd), ("", "", ""), "(pos[, title][, accelerator][, cmd])") +DefineEngineMethod(PopupMenu, insertItem, S32, (S32 pos, const char * title, const char * accelerator, const char* cmd), ("", "", ""), "(pos[, title][, accelerator][, cmd])") { return object->insertItem(pos, title, accelerator, cmd); } -DefineConsoleMethod(PopupMenu, removeItem, void, (S32 pos), , "(pos)") +DefineEngineMethod(PopupMenu, removeItem, void, (S32 pos), , "(pos)") { object->removeItem(pos); } -DefineConsoleMethod(PopupMenu, insertSubMenu, S32, (S32 pos, String title, String subMenu), , "(pos, title, subMenu)") +DefineEngineMethod(PopupMenu, insertSubMenu, S32, (S32 pos, String title, String subMenu), , "(pos, title, subMenu)") { PopupMenu *mnu = dynamic_cast(Sim::findObject(subMenu)); if(mnu == NULL) @@ -466,40 +466,40 @@ DefineConsoleMethod(PopupMenu, insertSubMenu, S32, (S32 pos, String title, Strin return object->insertSubMenu(pos, title, mnu); } -DefineConsoleMethod(PopupMenu, setItem, bool, (S32 pos, const char * title, const char * accelerator, const char *cmd), (""), "(pos, title[, accelerator][, cmd])") +DefineEngineMethod(PopupMenu, setItem, bool, (S32 pos, const char * title, const char * accelerator, const char *cmd), (""), "(pos, title[, accelerator][, cmd])") { return object->setItem(pos, title, accelerator, cmd); } //----------------------------------------------------------------------------- -DefineConsoleMethod(PopupMenu, enableItem, void, (S32 pos, bool enabled), , "(pos, enabled)") +DefineEngineMethod(PopupMenu, enableItem, void, (S32 pos, bool enabled), , "(pos, enabled)") { object->enableItem(pos, enabled); } -DefineConsoleMethod(PopupMenu, checkItem, void, (S32 pos, bool checked), , "(pos, checked)") +DefineEngineMethod(PopupMenu, checkItem, void, (S32 pos, bool checked), , "(pos, checked)") { object->checkItem(pos, checked); } -DefineConsoleMethod(PopupMenu, checkRadioItem, void, (S32 firstPos, S32 lastPos, S32 checkPos), , "(firstPos, lastPos, checkPos)") +DefineEngineMethod(PopupMenu, checkRadioItem, void, (S32 firstPos, S32 lastPos, S32 checkPos), , "(firstPos, lastPos, checkPos)") { object->checkRadioItem(firstPos, lastPos, checkPos); } -DefineConsoleMethod(PopupMenu, isItemChecked, bool, (S32 pos), , "(pos)") +DefineEngineMethod(PopupMenu, isItemChecked, bool, (S32 pos), , "(pos)") { return object->isItemChecked(pos); } -DefineConsoleMethod(PopupMenu, getItemCount, S32, (), , "()") +DefineEngineMethod(PopupMenu, getItemCount, S32, (), , "()") { return object->getItemCount(); } //----------------------------------------------------------------------------- -DefineConsoleMethod(PopupMenu, showPopup, void, (const char * canvasName, S32 x, S32 y), ( -1, -1), "(Canvas,[x, y])") +DefineEngineMethod(PopupMenu, showPopup, void, (const char * canvasName, S32 x, S32 y), ( -1, -1), "(Canvas,[x, y])") { GuiCanvas *pCanvas = dynamic_cast(Sim::findObject(canvasName)); object->showPopup(pCanvas, x, y); diff --git a/Engine/source/gui/game/guiIdleCamFadeBitmapCtrl.cpp b/Engine/source/gui/game/guiIdleCamFadeBitmapCtrl.cpp index 17cc97548..e53d70486 100644 --- a/Engine/source/gui/game/guiIdleCamFadeBitmapCtrl.cpp +++ b/Engine/source/gui/game/guiIdleCamFadeBitmapCtrl.cpp @@ -177,13 +177,13 @@ ConsoleDocClass( GuiIdleCamFadeBitmapCtrl, "This is going to be deprecated, and any useful code ported to FadeinBitmap\n\n" "@internal"); -DefineConsoleMethod(GuiIdleCamFadeBitmapCtrl, fadeIn, void, (), , "()" +DefineEngineMethod(GuiIdleCamFadeBitmapCtrl, fadeIn, void, (), , "()" "@internal") { object->fadeIn(); } -DefineConsoleMethod(GuiIdleCamFadeBitmapCtrl, fadeOut, void, (), , "()" +DefineEngineMethod(GuiIdleCamFadeBitmapCtrl, fadeOut, void, (), , "()" "@internal") { object->fadeOut(); diff --git a/Engine/source/gui/shiny/guiTickCtrl.cpp b/Engine/source/gui/shiny/guiTickCtrl.cpp index fa788ea7b..02eca4599 100644 --- a/Engine/source/gui/shiny/guiTickCtrl.cpp +++ b/Engine/source/gui/shiny/guiTickCtrl.cpp @@ -59,7 +59,7 @@ static ConsoleDocFragment _setProcessTicks( "void setProcessTicks( bool tick )" ); -DefineConsoleMethod( GuiTickCtrl, setProcessTicks, void, (bool tick), (true), "( [tick = true] ) - This will set this object to either be processing ticks or not" ) +DefineEngineMethod( GuiTickCtrl, setProcessTicks, void, (bool tick), (true), "( [tick = true] ) - This will set this object to either be processing ticks or not" ) { object->setProcessTicks(tick); } \ No newline at end of file diff --git a/Engine/source/gui/utility/messageVector.cpp b/Engine/source/gui/utility/messageVector.cpp index 19255e38b..97fd33382 100644 --- a/Engine/source/gui/utility/messageVector.cpp +++ b/Engine/source/gui/utility/messageVector.cpp @@ -258,7 +258,7 @@ static ConsoleDocFragment _MessageVectordump2( "MessageVector", "void dump( string filename, string header);"); -DefineConsoleMethod( MessageVector, dump, void, (const char * filename, const char * header), (""), "(string filename, string header=NULL)" +DefineEngineMethod( MessageVector, dump, void, (const char * filename, const char * header), (""), "(string filename, string header=NULL)" "Dump the message vector to a file, optionally prefixing a header." "@hide") { diff --git a/Engine/source/gui/worldEditor/creator.cpp b/Engine/source/gui/worldEditor/creator.cpp index 28fc15e84..99264f4ba 100644 --- a/Engine/source/gui/worldEditor/creator.cpp +++ b/Engine/source/gui/worldEditor/creator.cpp @@ -219,7 +219,7 @@ void CreatorTree::sort() } //------------------------------------------------------------------------------ -DefineConsoleMethod( CreatorTree, addGroup, S32, (S32 group, const char * name, const char * value), , "(string group, string name, string value)") +DefineEngineMethod( CreatorTree, addGroup, S32, (S32 group, const char * name, const char * value), , "(string group, string name, string value)") { CreatorTree::Node * grp = object->findNode(group); @@ -236,7 +236,7 @@ DefineConsoleMethod( CreatorTree, addGroup, S32, (S32 group, const char * name, return(node ? node->getId() : -1); } -DefineConsoleMethod( CreatorTree, addItem, S32, (S32 group, const char * name, const char * value), , "(Node group, string name, string value)") +DefineEngineMethod( CreatorTree, addItem, S32, (S32 group, const char * name, const char * value), , "(Node group, string name, string value)") { CreatorTree::Node * grp = object->findNode(group); @@ -249,7 +249,7 @@ DefineConsoleMethod( CreatorTree, addItem, S32, (S32 group, const char * name, c } //------------------------------------------------------------------------------ -DefineConsoleMethod( CreatorTree, fileNameMatch, bool, (const char * world, const char * type, const char * filename), , "(string world, string type, string filename)") +DefineEngineMethod( CreatorTree, fileNameMatch, bool, (const char * world, const char * type, const char * filename), , "(string world, string type, string filename)") { // argv[2] - world short // argv[3] - type short @@ -269,12 +269,12 @@ DefineConsoleMethod( CreatorTree, fileNameMatch, bool, (const char * world, cons return(!dStrnicmp(filename+1, type, typeLen)); } -DefineConsoleMethod( CreatorTree, getSelected, S32, (), , "Return a handle to the currently selected item.") +DefineEngineMethod( CreatorTree, getSelected, S32, (), , "Return a handle to the currently selected item.") { return(object->getSelected()); } -DefineConsoleMethod( CreatorTree, isGroup, bool, (const char * group), , "(Group g)") +DefineEngineMethod( CreatorTree, isGroup, bool, (const char * group), , "(Group g)") { CreatorTree::Node * node = object->findNode(dAtoi(group)); if(node && node->isGroup()) @@ -282,24 +282,24 @@ DefineConsoleMethod( CreatorTree, isGroup, bool, (const char * group), , "(Group return(false); } -DefineConsoleMethod( CreatorTree, getName, const char*, (const char * item), , "(Node item)") +DefineEngineMethod( CreatorTree, getName, const char*, (const char * item), , "(Node item)") { CreatorTree::Node * node = object->findNode(dAtoi(item)); return(node ? node->mName : 0); } -DefineConsoleMethod( CreatorTree, getValue, const char*, (S32 nodeValue), , "(Node n)") +DefineEngineMethod( CreatorTree, getValue, const char*, (S32 nodeValue), , "(Node n)") { CreatorTree::Node * node = object->findNode(nodeValue); return(node ? node->mValue : 0); } -DefineConsoleMethod( CreatorTree, clear, void, (), , "Clear the tree.") +DefineEngineMethod( CreatorTree, clear, void, (), , "Clear the tree.") { object->clear(); } -DefineConsoleMethod( CreatorTree, getParent, S32, (S32 nodeValue), , "(Node n)") +DefineEngineMethod( CreatorTree, getParent, S32, (S32 nodeValue), , "(Node n)") { CreatorTree::Node * node = object->findNode(nodeValue); if(node && node->mParent) diff --git a/Engine/source/gui/worldEditor/editor.cpp b/Engine/source/gui/worldEditor/editor.cpp index 2f05c96ad..c60127540 100644 --- a/Engine/source/gui/worldEditor/editor.cpp +++ b/Engine/source/gui/worldEditor/editor.cpp @@ -128,7 +128,7 @@ static GameBase * getControlObj() return(control); } -DefineConsoleMethod( EditManager, setBookmark, void, (S32 val), , "(int slot)") +DefineEngineMethod( EditManager, setBookmark, void, (S32 val), , "(int slot)") { if(val < 0 || val > 9) return; @@ -138,7 +138,7 @@ DefineConsoleMethod( EditManager, setBookmark, void, (S32 val), , "(int slot)") object->mBookmarks[val] = control->getTransform(); } -DefineConsoleMethod( EditManager, gotoBookmark, void, (S32 val), , "(int slot)") +DefineEngineMethod( EditManager, gotoBookmark, void, (S32 val), , "(int slot)") { if(val < 0 || val > 9) return; @@ -148,17 +148,17 @@ DefineConsoleMethod( EditManager, gotoBookmark, void, (S32 val), , "(int slot)") control->setTransform(object->mBookmarks[val]); } -DefineConsoleMethod( EditManager, editorEnabled, void, (), , "Perform the onEditorEnabled callback on all SimObjects and set gEditingMission true" ) +DefineEngineMethod( EditManager, editorEnabled, void, (), , "Perform the onEditorEnabled callback on all SimObjects and set gEditingMission true" ) { object->editorEnabled(); } -DefineConsoleMethod( EditManager, editorDisabled, void, (), , "Perform the onEditorDisabled callback on all SimObjects and set gEditingMission false" ) +DefineEngineMethod( EditManager, editorDisabled, void, (), , "Perform the onEditorDisabled callback on all SimObjects and set gEditingMission false" ) { object->editorDisabled(); } -DefineConsoleMethod( EditManager, isEditorEnabled, bool, (), , "Return the value of gEditingMission." ) +DefineEngineMethod( EditManager, isEditorEnabled, bool, (), , "Return the value of gEditingMission." ) { return gEditingMission; } \ No newline at end of file diff --git a/Engine/source/gui/worldEditor/guiConvexShapeEditorCtrl.cpp b/Engine/source/gui/worldEditor/guiConvexShapeEditorCtrl.cpp index 6bc043d09..02c2138e3 100644 --- a/Engine/source/gui/worldEditor/guiConvexShapeEditorCtrl.cpp +++ b/Engine/source/gui/worldEditor/guiConvexShapeEditorCtrl.cpp @@ -2179,43 +2179,43 @@ void GuiConvexEditorCtrl::splitSelectedFace() updateGizmoPos(); } -DefineConsoleMethod( GuiConvexEditorCtrl, hollowSelection, void, (), , "" ) +DefineEngineMethod( GuiConvexEditorCtrl, hollowSelection, void, (), , "" ) { object->hollowSelection(); } -DefineConsoleMethod( GuiConvexEditorCtrl, recenterSelection, void, (), , "" ) +DefineEngineMethod( GuiConvexEditorCtrl, recenterSelection, void, (), , "" ) { object->recenterSelection(); } -DefineConsoleMethod( GuiConvexEditorCtrl, hasSelection, S32, (), , "" ) +DefineEngineMethod( GuiConvexEditorCtrl, hasSelection, S32, (), , "" ) { return object->hasSelection(); } -DefineConsoleMethod( GuiConvexEditorCtrl, handleDelete, void, (), , "" ) +DefineEngineMethod( GuiConvexEditorCtrl, handleDelete, void, (), , "" ) { object->handleDelete(); } -DefineConsoleMethod( GuiConvexEditorCtrl, handleDeselect, void, (), , "" ) +DefineEngineMethod( GuiConvexEditorCtrl, handleDeselect, void, (), , "" ) { object->handleDeselect(); } -DefineConsoleMethod( GuiConvexEditorCtrl, dropSelectionAtScreenCenter, void, (), , "" ) +DefineEngineMethod( GuiConvexEditorCtrl, dropSelectionAtScreenCenter, void, (), , "" ) { object->dropSelectionAtScreenCenter(); } -DefineConsoleMethod( GuiConvexEditorCtrl, selectConvex, void, (ConvexShape *convex), , "( ConvexShape )" ) +DefineEngineMethod( GuiConvexEditorCtrl, selectConvex, void, (ConvexShape *convex), , "( ConvexShape )" ) { if (convex) object->setSelection( convex, -1 ); } -DefineConsoleMethod( GuiConvexEditorCtrl, splitSelectedFace, void, (), , "" ) +DefineEngineMethod( GuiConvexEditorCtrl, splitSelectedFace, void, (), , "" ) { object->splitSelectedFace(); } \ No newline at end of file diff --git a/Engine/source/gui/worldEditor/guiDecalEditorCtrl.cpp b/Engine/source/gui/worldEditor/guiDecalEditorCtrl.cpp index 6712d7762..1d76d3d30 100644 --- a/Engine/source/gui/worldEditor/guiDecalEditorCtrl.cpp +++ b/Engine/source/gui/worldEditor/guiDecalEditorCtrl.cpp @@ -784,12 +784,12 @@ void GuiDecalEditorCtrl::setMode( String mode, bool sourceShortcut = false ) Con::executef( this, "paletteSync", mMode ); } -DefineConsoleMethod( GuiDecalEditorCtrl, deleteSelectedDecal, void, (), , "deleteSelectedDecal()" ) +DefineEngineMethod( GuiDecalEditorCtrl, deleteSelectedDecal, void, (), , "deleteSelectedDecal()" ) { object->deleteSelectedDecal(); } -DefineConsoleMethod( GuiDecalEditorCtrl, deleteDecalDatablock, void, ( const char * datablock ), , "deleteSelectedDecalDatablock( String datablock )" ) +DefineEngineMethod( GuiDecalEditorCtrl, deleteDecalDatablock, void, ( const char * datablock ), , "deleteSelectedDecalDatablock( String datablock )" ) { String lookupName( datablock ); if( lookupName == String::EmptyString ) @@ -798,22 +798,22 @@ DefineConsoleMethod( GuiDecalEditorCtrl, deleteDecalDatablock, void, ( const cha object->deleteDecalDatablock( lookupName ); } -DefineConsoleMethod( GuiDecalEditorCtrl, setMode, void, ( String newMode ), , "setMode( String mode )()" ) +DefineEngineMethod( GuiDecalEditorCtrl, setMode, void, ( String newMode ), , "setMode( String mode )()" ) { object->setMode( newMode ); } -DefineConsoleMethod( GuiDecalEditorCtrl, getMode, const char*, (), , "getMode()" ) +DefineEngineMethod( GuiDecalEditorCtrl, getMode, const char*, (), , "getMode()" ) { return object->mMode; } -DefineConsoleMethod( GuiDecalEditorCtrl, getDecalCount, S32, (), , "getDecalCount()" ) +DefineEngineMethod( GuiDecalEditorCtrl, getDecalCount, S32, (), , "getDecalCount()" ) { return gDecalManager->mDecalInstanceVec.size(); } -DefineConsoleMethod( GuiDecalEditorCtrl, getDecalTransform, const char*, ( U32 id ), , "getDecalTransform()" ) +DefineEngineMethod( GuiDecalEditorCtrl, getDecalTransform, const char*, ( U32 id ), , "getDecalTransform()" ) { DecalInstance *decalInstance = gDecalManager->mDecalInstanceVec[id]; @@ -835,7 +835,7 @@ DefineConsoleMethod( GuiDecalEditorCtrl, getDecalTransform, const char*, ( U32 i return returnBuffer; } -DefineConsoleMethod( GuiDecalEditorCtrl, getDecalLookupName, const char*, ( U32 id ), , "getDecalLookupName( S32 )()" ) +DefineEngineMethod( GuiDecalEditorCtrl, getDecalLookupName, const char*, ( U32 id ), , "getDecalLookupName( S32 )()" ) { DecalInstance *decalInstance = gDecalManager->mDecalInstanceVec[id]; if( decalInstance == NULL ) @@ -844,7 +844,7 @@ DefineConsoleMethod( GuiDecalEditorCtrl, getDecalLookupName, const char*, ( U32 return decalInstance->mDataBlock->lookupName; } -DefineConsoleMethod( GuiDecalEditorCtrl, selectDecal, void, ( U32 id ), , "selectDecal( S32 )()" ) +DefineEngineMethod( GuiDecalEditorCtrl, selectDecal, void, ( U32 id ), , "selectDecal( S32 )()" ) { DecalInstance *decalInstance = gDecalManager->mDecalInstanceVec[id]; if( decalInstance == NULL ) @@ -853,7 +853,7 @@ DefineConsoleMethod( GuiDecalEditorCtrl, selectDecal, void, ( U32 id ), , "selec object->selectDecal( decalInstance ); } -DefineConsoleMethod( GuiDecalEditorCtrl, editDecalDetails, void, ( U32 id, Point3F pos, Point3F tan,F32 size ), , "editDecalDetails( S32 )()" ) +DefineEngineMethod( GuiDecalEditorCtrl, editDecalDetails, void, ( U32 id, Point3F pos, Point3F tan,F32 size ), , "editDecalDetails( S32 )()" ) { DecalInstance *decalInstance = gDecalManager->mDecalInstanceVec[id]; if( decalInstance == NULL ) @@ -872,14 +872,14 @@ DefineConsoleMethod( GuiDecalEditorCtrl, editDecalDetails, void, ( U32 id, Point gDecalManager->notifyDecalModified( decalInstance ); } -DefineConsoleMethod( GuiDecalEditorCtrl, getSelectionCount, S32, (), , "" ) +DefineEngineMethod( GuiDecalEditorCtrl, getSelectionCount, S32, (), , "" ) { if ( object->mSELDecal != NULL ) return 1; return 0; } -DefineConsoleMethod( GuiDecalEditorCtrl, retargetDecalDatablock, void, ( const char * dbFrom, const char * dbTo ), , "" ) +DefineEngineMethod( GuiDecalEditorCtrl, retargetDecalDatablock, void, ( const char * dbFrom, const char * dbTo ), , "" ) { if( dStrcmp( dbFrom, "" ) != 0 && dStrcmp( dbTo, "" ) != 0 ) object->retargetDecalDatablock( dbFrom, dbTo ); diff --git a/Engine/source/gui/worldEditor/guiMissionAreaEditor.cpp b/Engine/source/gui/worldEditor/guiMissionAreaEditor.cpp index 411fd074a..839d39017 100644 --- a/Engine/source/gui/worldEditor/guiMissionAreaEditor.cpp +++ b/Engine/source/gui/worldEditor/guiMissionAreaEditor.cpp @@ -95,7 +95,7 @@ void GuiMissionAreaEditorCtrl::setSelectedMissionArea( MissionArea *missionArea Con::executef( this, "onMissionAreaSelected" ); } -DefineConsoleMethod( GuiMissionAreaEditorCtrl, setSelectedMissionArea, void, (const char * missionAreaName), (""), "" ) +DefineEngineMethod( GuiMissionAreaEditorCtrl, setSelectedMissionArea, void, (const char * missionAreaName), (""), "" ) { if ( dStrcmp( missionAreaName, "" )==0 ) object->setSelectedMissionArea(NULL); @@ -107,7 +107,7 @@ DefineConsoleMethod( GuiMissionAreaEditorCtrl, setSelectedMissionArea, void, (co } } -DefineConsoleMethod( GuiMissionAreaEditorCtrl, getSelectedMissionArea, const char*, (), , "" ) +DefineEngineMethod( GuiMissionAreaEditorCtrl, getSelectedMissionArea, const char*, (), , "" ) { MissionArea *missionArea = object->getSelectedMissionArea(); if ( !missionArea ) diff --git a/Engine/source/gui/worldEditor/guiTerrPreviewCtrl.cpp b/Engine/source/gui/worldEditor/guiTerrPreviewCtrl.cpp index 18db8de5f..0d3c988bf 100644 --- a/Engine/source/gui/worldEditor/guiTerrPreviewCtrl.cpp +++ b/Engine/source/gui/worldEditor/guiTerrPreviewCtrl.cpp @@ -88,35 +88,35 @@ void GuiTerrPreviewCtrl::initPersistFields() } -DefineConsoleMethod( GuiTerrPreviewCtrl, reset, void, (), , "Reset the view of the terrain.") +DefineEngineMethod( GuiTerrPreviewCtrl, reset, void, (), , "Reset the view of the terrain.") { object->reset(); } -DefineConsoleMethod( GuiTerrPreviewCtrl, setRoot, void, (), , "Add the origin to the root and reset the origin.") +DefineEngineMethod( GuiTerrPreviewCtrl, setRoot, void, (), , "Add the origin to the root and reset the origin.") { object->setRoot(); } -DefineConsoleMethod( GuiTerrPreviewCtrl, getRoot, Point2F, (), , "Return a Point2F representing the position of the root.") +DefineEngineMethod( GuiTerrPreviewCtrl, getRoot, Point2F, (), , "Return a Point2F representing the position of the root.") { return object->getRoot(); } -DefineConsoleMethod( GuiTerrPreviewCtrl, setOrigin, void, (Point2F pos), , "(float x, float y)" +DefineEngineMethod( GuiTerrPreviewCtrl, setOrigin, void, (Point2F pos), , "(float x, float y)" "Set the origin of the view.") { object->setOrigin( pos ); } -DefineConsoleMethod( GuiTerrPreviewCtrl, getOrigin, Point2F, (), , "Return a Point2F containing the position of the origin.") +DefineEngineMethod( GuiTerrPreviewCtrl, getOrigin, Point2F, (), , "Return a Point2F containing the position of the origin.") { return object->getOrigin(); } -DefineConsoleMethod( GuiTerrPreviewCtrl, getValue, const char*, (), , "Returns a 4-tuple containing: root_x root_y origin_x origin_y") +DefineEngineMethod( GuiTerrPreviewCtrl, getValue, const char*, (), , "Returns a 4-tuple containing: root_x root_y origin_x origin_y") { Point2F r = object->getRoot(); Point2F o = object->getOrigin(); @@ -126,7 +126,7 @@ DefineConsoleMethod( GuiTerrPreviewCtrl, getValue, const char*, (), , "Returns a return valuebuf; } -DefineConsoleMethod( GuiTerrPreviewCtrl, setValue, void, (const char * tuple), , "Accepts a 4-tuple in the same form as getValue returns.\n\n" +DefineEngineMethod( GuiTerrPreviewCtrl, setValue, void, (const char * tuple), , "Accepts a 4-tuple in the same form as getValue returns.\n\n" "@see GuiTerrPreviewCtrl::getValue()") { Point2F r,o; diff --git a/Engine/source/gui/worldEditor/terrainActions.cpp b/Engine/source/gui/worldEditor/terrainActions.cpp index 11360f82d..b64cade26 100644 --- a/Engine/source/gui/worldEditor/terrainActions.cpp +++ b/Engine/source/gui/worldEditor/terrainActions.cpp @@ -795,7 +795,7 @@ void TerrainSmoothAction::smooth( TerrainBlock *terrain, F32 factor, U32 steps ) redo(); } -DefineConsoleMethod( TerrainSmoothAction, smooth, void, ( TerrainBlock *terrain, F32 factor, U32 steps ), , "( TerrainBlock obj, F32 factor, U32 steps )") +DefineEngineMethod( TerrainSmoothAction, smooth, void, ( TerrainBlock *terrain, F32 factor, U32 steps ), , "( TerrainBlock obj, F32 factor, U32 steps )") { if (terrain) object->smooth( terrain, factor, mClamp( steps, 1, 13 ) ); diff --git a/Engine/source/gui/worldEditor/terrainEditor.cpp b/Engine/source/gui/worldEditor/terrainEditor.cpp index 8e81d84e3..f1bf5fd58 100644 --- a/Engine/source/gui/worldEditor/terrainEditor.cpp +++ b/Engine/source/gui/worldEditor/terrainEditor.cpp @@ -2403,7 +2403,7 @@ void TerrainEditor::reorderMaterial( S32 index, S32 orderPos ) //------------------------------------------------------------------------------ -DefineConsoleMethod( TerrainEditor, attachTerrain, void, (const char * terrain), (""), "(TerrainBlock terrain)") +DefineEngineMethod( TerrainEditor, attachTerrain, void, (const char * terrain), (""), "(TerrainBlock terrain)") { SimSet * missionGroup = dynamic_cast(Sim::findObject("MissionGroup")); if (!missionGroup) @@ -2459,12 +2459,12 @@ DefineConsoleMethod( TerrainEditor, attachTerrain, void, (const char * terrain), } } -DefineConsoleMethod( TerrainEditor, getTerrainBlockCount, S32, (), , "()") +DefineEngineMethod( TerrainEditor, getTerrainBlockCount, S32, (), , "()") { return object->getTerrainBlockCount(); } -DefineConsoleMethod( TerrainEditor, getTerrainBlock, S32, (S32 index), , "(S32 index)") +DefineEngineMethod( TerrainEditor, getTerrainBlock, S32, (S32 index), , "(S32 index)") { TerrainBlock* tb = object->getTerrainBlock(index); if(!tb) @@ -2473,7 +2473,7 @@ DefineConsoleMethod( TerrainEditor, getTerrainBlock, S32, (S32 index), , "(S32 i return tb->getId(); } -DefineConsoleMethod(TerrainEditor, getTerrainBlocksMaterialList, const char *, (), , "() gets the list of current terrain materials for all terrain blocks.") +DefineEngineMethod(TerrainEditor, getTerrainBlocksMaterialList, const char *, (), , "() gets the list of current terrain materials for all terrain blocks.") { Vector list; object->getTerrainBlocksMaterialList(list); @@ -2502,23 +2502,23 @@ DefineConsoleMethod(TerrainEditor, getTerrainBlocksMaterialList, const char *, ( return ret; } -DefineConsoleMethod( TerrainEditor, setBrushType, void, (String type), , "(string type)" +DefineEngineMethod( TerrainEditor, setBrushType, void, (String type), , "(string type)" "One of box, ellipse, selection.") { object->setBrushType(type); } -DefineConsoleMethod( TerrainEditor, getBrushType, const char*, (), , "()") +DefineEngineMethod( TerrainEditor, getBrushType, const char*, (), , "()") { return object->getBrushType(); } -DefineConsoleMethod( TerrainEditor, setBrushSize, void, ( S32 w, S32 h), (0), "(int w [, int h])") +DefineEngineMethod( TerrainEditor, setBrushSize, void, ( S32 w, S32 h), (0), "(int w [, int h])") { object->setBrushSize( w, h==0?w:h ); } -DefineConsoleMethod( TerrainEditor, getBrushSize, const char*, (), , "()") +DefineEngineMethod( TerrainEditor, getBrushSize, const char*, (), , "()") { Point2I size = object->getBrushSize(); @@ -2528,74 +2528,74 @@ DefineConsoleMethod( TerrainEditor, getBrushSize, const char*, (), , "()") return ret; } -DefineConsoleMethod( TerrainEditor, setBrushPressure, void, (F32 pressure), , "(float pressure)") +DefineEngineMethod( TerrainEditor, setBrushPressure, void, (F32 pressure), , "(float pressure)") { object->setBrushPressure( pressure ); } -DefineConsoleMethod( TerrainEditor, getBrushPressure, F32, (), , "()") +DefineEngineMethod( TerrainEditor, getBrushPressure, F32, (), , "()") { return object->getBrushPressure(); } -DefineConsoleMethod( TerrainEditor, setBrushSoftness, void, (F32 softness), , "(float softness)") +DefineEngineMethod( TerrainEditor, setBrushSoftness, void, (F32 softness), , "(float softness)") { object->setBrushSoftness( softness ); } -DefineConsoleMethod( TerrainEditor, getBrushSoftness, F32, (), , "()") +DefineEngineMethod( TerrainEditor, getBrushSoftness, F32, (), , "()") { return object->getBrushSoftness(); } -DefineConsoleMethod( TerrainEditor, getBrushPos, const char*, (), , "Returns a Point2I.") +DefineEngineMethod( TerrainEditor, getBrushPos, const char*, (), , "Returns a Point2I.") { return object->getBrushPos(); } -DefineConsoleMethod( TerrainEditor, setBrushPos, void, (Point2I pos), , "Location") +DefineEngineMethod( TerrainEditor, setBrushPos, void, (Point2I pos), , "Location") { object->setBrushPos(pos); } -DefineConsoleMethod( TerrainEditor, setAction, void, (const char * action_name), , "(string action_name)") +DefineEngineMethod( TerrainEditor, setAction, void, (const char * action_name), , "(string action_name)") { object->setAction(action_name); } -DefineConsoleMethod( TerrainEditor, getActionName, const char*, (U32 index), , "(int num)") +DefineEngineMethod( TerrainEditor, getActionName, const char*, (U32 index), , "(int num)") { return (object->getActionName(index)); } -DefineConsoleMethod( TerrainEditor, getNumActions, S32, (), , "") +DefineEngineMethod( TerrainEditor, getNumActions, S32, (), , "") { return(object->getNumActions()); } -DefineConsoleMethod( TerrainEditor, getCurrentAction, const char*, (), , "") +DefineEngineMethod( TerrainEditor, getCurrentAction, const char*, (), , "") { return object->getCurrentAction(); } -DefineConsoleMethod( TerrainEditor, resetSelWeights, void, (bool clear), , "(bool clear)") +DefineEngineMethod( TerrainEditor, resetSelWeights, void, (bool clear), , "(bool clear)") { object->resetSelWeights(clear); } -DefineConsoleMethod( TerrainEditor, clearSelection, void, (), , "") +DefineEngineMethod( TerrainEditor, clearSelection, void, (), , "") { object->clearSelection(); } -DefineConsoleMethod( TerrainEditor, processAction, void, (String action), (""), "(string action=NULL)") +DefineEngineMethod( TerrainEditor, processAction, void, (String action), (""), "(string action=NULL)") { object->processAction(action); } -DefineConsoleMethod( TerrainEditor, getActiveTerrain, S32, (), , "") +DefineEngineMethod( TerrainEditor, getActiveTerrain, S32, (), , "") { S32 ret = 0; @@ -2607,27 +2607,27 @@ DefineConsoleMethod( TerrainEditor, getActiveTerrain, S32, (), , "") return ret; } -DefineConsoleMethod( TerrainEditor, getNumTextures, S32, (), , "") +DefineEngineMethod( TerrainEditor, getNumTextures, S32, (), , "") { return object->getNumTextures(); } -DefineConsoleMethod( TerrainEditor, markEmptySquares, void, (), , "") +DefineEngineMethod( TerrainEditor, markEmptySquares, void, (), , "") { object->markEmptySquares(); } -DefineConsoleMethod( TerrainEditor, mirrorTerrain, void, (S32 mirrorIndex), , "") +DefineEngineMethod( TerrainEditor, mirrorTerrain, void, (S32 mirrorIndex), , "") { object->mirrorTerrain(mirrorIndex); } -DefineConsoleMethod(TerrainEditor, setTerraformOverlay, void, (bool overlayEnable), , "(bool overlayEnable) - sets the terraformer current heightmap to draw as an overlay over the current terrain.") +DefineEngineMethod(TerrainEditor, setTerraformOverlay, void, (bool overlayEnable), , "(bool overlayEnable) - sets the terraformer current heightmap to draw as an overlay over the current terrain.") { // XA: This one needs to be implemented :) } -DefineConsoleMethod(TerrainEditor, updateMaterial, bool, ( U32 index, String matName ), , +DefineEngineMethod(TerrainEditor, updateMaterial, bool, ( U32 index, String matName ), , "( int index, string matName )\n" "Changes the material name at the index." ) { @@ -2645,7 +2645,7 @@ DefineConsoleMethod(TerrainEditor, updateMaterial, bool, ( U32 index, String mat return true; } -DefineConsoleMethod(TerrainEditor, addMaterial, S32, ( String matName ), , +DefineEngineMethod(TerrainEditor, addMaterial, S32, ( String matName ), , "( string matName )\n" "Adds a new material." ) { @@ -2660,7 +2660,7 @@ DefineConsoleMethod(TerrainEditor, addMaterial, S32, ( String matName ), , return true; } -DefineConsoleMethod( TerrainEditor, removeMaterial, void, ( S32 index ), , "( int index ) - Remove the material at the given index." ) +DefineEngineMethod( TerrainEditor, removeMaterial, void, ( S32 index ), , "( int index ) - Remove the material at the given index." ) { TerrainBlock *terr = object->getClientTerrain(); if ( !terr ) @@ -2689,7 +2689,7 @@ DefineConsoleMethod( TerrainEditor, removeMaterial, void, ( S32 index ), , "( in object->setGridUpdateMinMax(); } -DefineConsoleMethod(TerrainEditor, getMaterialCount, S32, (), , +DefineEngineMethod(TerrainEditor, getMaterialCount, S32, (), , "Returns the current material count." ) { TerrainBlock *terr = object->getClientTerrain(); @@ -2699,7 +2699,7 @@ DefineConsoleMethod(TerrainEditor, getMaterialCount, S32, (), , return 0; } -DefineConsoleMethod(TerrainEditor, getMaterials, const char *, (), , "() gets the list of current terrain materials.") +DefineEngineMethod(TerrainEditor, getMaterials, const char *, (), , "() gets the list of current terrain materials.") { TerrainBlock *terr = object->getClientTerrain(); if ( !terr ) @@ -2716,7 +2716,7 @@ DefineConsoleMethod(TerrainEditor, getMaterials, const char *, (), , "() gets th return ret; } -DefineConsoleMethod( TerrainEditor, getMaterialName, const char*, (S32 index), , "( int index ) - Returns the name of the material at the given index." ) +DefineEngineMethod( TerrainEditor, getMaterialName, const char*, (S32 index), , "( int index ) - Returns the name of the material at the given index." ) { TerrainBlock *terr = object->getClientTerrain(); if ( !terr ) @@ -2732,7 +2732,7 @@ DefineConsoleMethod( TerrainEditor, getMaterialName, const char*, (S32 index), , return Con::getReturnBuffer( name ); } -DefineConsoleMethod( TerrainEditor, getMaterialIndex, S32, ( String name ), , "( string name ) - Returns the index of the material with the given name or -1." ) +DefineEngineMethod( TerrainEditor, getMaterialIndex, S32, ( String name ), , "( string name ) - Returns the index of the material with the given name or -1." ) { TerrainBlock *terr = object->getClientTerrain(); if ( !terr ) @@ -2747,13 +2747,13 @@ DefineConsoleMethod( TerrainEditor, getMaterialIndex, S32, ( String name ), , "( return -1; } -DefineConsoleMethod( TerrainEditor, reorderMaterial, void, ( S32 index, S32 orderPos ), , "( int index, int order ) " +DefineEngineMethod( TerrainEditor, reorderMaterial, void, ( S32 index, S32 orderPos ), , "( int index, int order ) " "- Reorder material at the given index to the new position, changing the order in which it is rendered / blended." ) { object->reorderMaterial( index, orderPos ); } -DefineConsoleMethod(TerrainEditor, getTerrainUnderWorldPoint, S32, (const char * ptOrX, const char * Y, const char * Z), ("", "", ""), +DefineEngineMethod(TerrainEditor, getTerrainUnderWorldPoint, S32, (const char * ptOrX, const char * Y, const char * Z), ("", "", ""), "(x/y/z) Gets the terrain block that is located under the given world point.\n" "@param x/y/z The world coordinates (floating point values) you wish to query at. " "These can be formatted as either a string (\"x y z\") or separately as (x, y, z)\n" @@ -2822,12 +2822,12 @@ void TerrainEditor::initPersistFields() Parent::initPersistFields(); } -DefineConsoleMethod( TerrainEditor, getSlopeLimitMinAngle, F32, (), , "") +DefineEngineMethod( TerrainEditor, getSlopeLimitMinAngle, F32, (), , "") { return object->mSlopeMinAngle; } -DefineConsoleMethod( TerrainEditor, setSlopeLimitMinAngle, F32, (F32 angle), , "") +DefineEngineMethod( TerrainEditor, setSlopeLimitMinAngle, F32, (F32 angle), , "") { if ( angle < 0.0f ) angle = 0.0f; @@ -2838,12 +2838,12 @@ DefineConsoleMethod( TerrainEditor, setSlopeLimitMinAngle, F32, (F32 angle), , " return angle; } -DefineConsoleMethod( TerrainEditor, getSlopeLimitMaxAngle, F32, (), , "") +DefineEngineMethod( TerrainEditor, getSlopeLimitMaxAngle, F32, (), , "") { return object->mSlopeMaxAngle; } -DefineConsoleMethod( TerrainEditor, setSlopeLimitMaxAngle, F32, (F32 angle), , "") +DefineEngineMethod( TerrainEditor, setSlopeLimitMaxAngle, F32, (F32 angle), , "") { if ( angle > 90.0f ) angle = 90.0f; diff --git a/Engine/source/gui/worldEditor/worldEditor.cpp b/Engine/source/gui/worldEditor/worldEditor.cpp index b66ead790..24e710091 100644 --- a/Engine/source/gui/worldEditor/worldEditor.cpp +++ b/Engine/source/gui/worldEditor/worldEditor.cpp @@ -3252,7 +3252,7 @@ DefineEngineMethod( WorldEditor, getActiveSelection, S32, (),, return object->getActiveSelectionSet()->getId(); } -DefineConsoleMethod( WorldEditor, setActiveSelection, void, ( WorldEditorSelection* selection), , +DefineEngineMethod( WorldEditor, setActiveSelection, void, ( WorldEditorSelection* selection), , "Set the currently active WorldEditorSelection object.\n" "@param selection A WorldEditorSelectionSet object to use for the selection container.") { diff --git a/Engine/source/i18n/lang.cpp b/Engine/source/i18n/lang.cpp index 7e1efe4a5..b1fa76c6a 100644 --- a/Engine/source/i18n/lang.cpp +++ b/Engine/source/i18n/lang.cpp @@ -329,7 +329,7 @@ void LangTable::setCurrentLanguage(S32 langid) -DefineConsoleMethod(LangTable, addLanguage, S32, (String filename, String languageName), ("", ""), +DefineEngineMethod(LangTable, addLanguage, S32, (String filename, String languageName), ("", ""), "(string filename, [string languageName])" "@brief Adds a language to the table\n\n" "@param filename Name and path to the language file\n" @@ -343,7 +343,7 @@ DefineConsoleMethod(LangTable, addLanguage, S32, (String filename, String langua return object->addLanguage(scriptFilenameBuffer, (const UTF8*)languageName); } -DefineConsoleMethod(LangTable, getString, const char *, (U32 id), , +DefineEngineMethod(LangTable, getString, const char *, (U32 id), , "(string filename)" "@brief Grabs a string from the specified table\n\n" "If an invalid is passed, the function will attempt to " @@ -363,14 +363,14 @@ DefineConsoleMethod(LangTable, getString, const char *, (U32 id), , return ""; } -DefineConsoleMethod(LangTable, setDefaultLanguage, void, (S32 langId), , "(int language)" +DefineEngineMethod(LangTable, setDefaultLanguage, void, (S32 langId), , "(int language)" "@brief Sets the default language table\n\n" "@param language ID of the table\n") { object->setDefaultLanguage(langId); } -DefineConsoleMethod(LangTable, setCurrentLanguage, void, (S32 langId), , +DefineEngineMethod(LangTable, setCurrentLanguage, void, (S32 langId), , "(int language)" "@brief Sets the current language table for grabbing text\n\n" "@param language ID of the table\n") @@ -378,14 +378,14 @@ DefineConsoleMethod(LangTable, setCurrentLanguage, void, (S32 langId), , object->setCurrentLanguage(langId); } -DefineConsoleMethod(LangTable, getCurrentLanguage, S32, (), , "()" +DefineEngineMethod(LangTable, getCurrentLanguage, S32, (), , "()" "@brief Get the ID of the current language table\n\n" "@return Numerical ID of the current language table") { return object->getCurrentLanguage(); } -DefineConsoleMethod(LangTable, getLangName, const char *, (S32 langId), , "(int language)" +DefineEngineMethod(LangTable, getLangName, const char *, (S32 langId), , "(int language)" "@brief Return the readable name of the language table\n\n" "@param language Numerical ID of the language table to access\n\n" "@return String containing the name of the table, NULL if ID was invalid or name was never specified") @@ -402,7 +402,7 @@ DefineConsoleMethod(LangTable, getLangName, const char *, (S32 langId), , "(int return ""; } -DefineConsoleMethod(LangTable, getNumLang, S32, (), , "()" +DefineEngineMethod(LangTable, getNumLang, S32, (), , "()" "@brief Used to find out how many languages are in the table\n\n" "@return Size of the vector containing the languages, numerical") { diff --git a/Engine/source/materials/materialDefinition.cpp b/Engine/source/materials/materialDefinition.cpp index 3ef1b1d01..9fd3f857a 100644 --- a/Engine/source/materials/materialDefinition.cpp +++ b/Engine/source/materials/materialDefinition.cpp @@ -629,25 +629,25 @@ void Material::StageData::getFeatureSet( FeatureSet *outFeatures ) const } } -DefineConsoleMethod( Material, flush, void, (),, +DefineEngineMethod( Material, flush, void, (),, "Flushes all material instances that use this material." ) { object->flush(); } -DefineConsoleMethod( Material, reload, void, (),, +DefineEngineMethod( Material, reload, void, (),, "Reloads all material instances that use this material." ) { object->reload(); } -DefineConsoleMethod( Material, dumpInstances, void, (),, +DefineEngineMethod( Material, dumpInstances, void, (),, "Dumps a formatted list of the currently allocated material instances for this material to the console." ) { MATMGR->dumpMaterialInstances( object ); } -DefineConsoleMethod( Material, getAnimFlags, const char*, (U32 id), , "" ) +DefineEngineMethod( Material, getAnimFlags, const char*, (U32 id), , "" ) { char * animFlags = Con::getReturnBuffer(512); @@ -688,19 +688,19 @@ DefineConsoleMethod( Material, getAnimFlags, const char*, (U32 id), , "" ) return animFlags; } -DefineConsoleMethod(Material, getFilename, const char*, (),, "Get filename of material") +DefineEngineMethod(Material, getFilename, const char*, (),, "Get filename of material") { SimObject *material = static_cast(object); return material->getFilename(); } -DefineConsoleMethod( Material, isAutoGenerated, bool, (),, +DefineEngineMethod( Material, isAutoGenerated, bool, (),, "Returns true if this Material was automatically generated by MaterialList::mapMaterials()" ) { return object->isAutoGenerated(); } -DefineConsoleMethod( Material, setAutoGenerated, void, (bool isAutoGenerated), , +DefineEngineMethod( Material, setAutoGenerated, void, (bool isAutoGenerated), , "setAutoGenerated(bool isAutoGenerated): Set whether or not the Material is autogenerated." ) { object->setAutoGenerated(isAutoGenerated); diff --git a/Engine/source/math/util/tResponseCurve.cpp b/Engine/source/math/util/tResponseCurve.cpp index 2c1d5c53c..f6c7cfb74 100644 --- a/Engine/source/math/util/tResponseCurve.cpp +++ b/Engine/source/math/util/tResponseCurve.cpp @@ -64,17 +64,17 @@ void SimResponseCurve::clear() mCurve.clear(); } -DefineConsoleMethod( SimResponseCurve, addPoint, void, ( F32 value, F32 time ), , "addPoint( F32 value, F32 time )" ) +DefineEngineMethod( SimResponseCurve, addPoint, void, ( F32 value, F32 time ), , "addPoint( F32 value, F32 time )" ) { object->addPoint( value, time ); } -DefineConsoleMethod( SimResponseCurve, getValue, F32, ( F32 time ), , "getValue( F32 time )" ) +DefineEngineMethod( SimResponseCurve, getValue, F32, ( F32 time ), , "getValue( F32 time )" ) { return object->getValue( time ); } -DefineConsoleMethod( SimResponseCurve, clear, void, (), , "clear()" ) +DefineEngineMethod( SimResponseCurve, clear, void, (), , "clear()" ) { object->clear(); } \ No newline at end of file diff --git a/Engine/source/scene/sceneObject.cpp b/Engine/source/scene/sceneObject.cpp index a6be00320..ff7b6496c 100644 --- a/Engine/source/scene/sceneObject.cpp +++ b/Engine/source/scene/sceneObject.cpp @@ -1517,7 +1517,7 @@ DefineEngineMethod( SceneObject, isGlobalBounds, bool, (),, return object->isGlobalBounds(); } -DefineConsoleMethod(SceneObject, setForwardVector, void, (VectorF newForward, VectorF upVector), (VectorF(0, 0, 0), VectorF(0, 0, 1)), +DefineEngineMethod(SceneObject, setForwardVector, void, (VectorF newForward, VectorF upVector), (VectorF(0, 0, 0), VectorF(0, 0, 1)), "Sets the forward vector of a scene object, making it face Y+ along the new vector.\n" "@param The new forward vector to set.\n" "@param (Optional) The up vector to use to help orient the rotation.") diff --git a/Engine/source/sfx/sfxSource.cpp b/Engine/source/sfx/sfxSource.cpp index e40dd5073..2beb34634 100644 --- a/Engine/source/sfx/sfxSource.cpp +++ b/Engine/source/sfx/sfxSource.cpp @@ -1569,7 +1569,7 @@ static ConsoleDocFragment _sSetTransform2( "void setTransform( Point3F position, Point3F direction )" ); -DefineConsoleMethod( SFXSource, setTransform, void, ( const char * position, const char * direction ), ( "" ), +DefineEngineMethod( SFXSource, setTransform, void, ( const char * position, const char * direction ), ( "" ), "( vector position [, vector direction ] ) " "Set the position and orientation of a 3D sound source.\n" "@hide" ) diff --git a/Engine/source/terrain/terrExport.cpp b/Engine/source/terrain/terrExport.cpp index 8941c8b26..78b63eeb1 100644 --- a/Engine/source/terrain/terrExport.cpp +++ b/Engine/source/terrain/terrExport.cpp @@ -137,7 +137,7 @@ bool TerrainBlock::exportLayerMaps( const UTF8 *filePrefix, const String &format return true; } -DefineConsoleMethod( TerrainBlock, exportHeightMap, bool, (const char * fileNameStr, const char * format), ( "png"), "(string filename, [string format]) - export the terrain block's heightmap to a bitmap file (default: png)" ) +DefineEngineMethod( TerrainBlock, exportHeightMap, bool, (const char * fileNameStr, const char * format), ( "png"), "(string filename, [string format]) - export the terrain block's heightmap to a bitmap file (default: png)" ) { UTF8 fileName[1024]; Con::expandScriptFilename( fileName, sizeof( fileName ), fileNameStr ); @@ -145,7 +145,7 @@ DefineConsoleMethod( TerrainBlock, exportHeightMap, bool, (const char * fileName return object->exportHeightMap( fileName, format ); } -DefineConsoleMethod( TerrainBlock, exportLayerMaps, bool, (const char * filePrefixStr, const char * format), ( "png"), "(string filePrefix, [string format]) - export the terrain block's layer maps to bitmap files (default: png)" ) +DefineEngineMethod( TerrainBlock, exportLayerMaps, bool, (const char * filePrefixStr, const char * format), ( "png"), "(string filePrefix, [string format]) - export the terrain block's layer maps to bitmap files (default: png)" ) { UTF8 filePrefix[1024]; Con::expandScriptFilename( filePrefix, sizeof( filePrefix ), filePrefixStr ); diff --git a/Engine/source/util/messaging/eventManager.cpp b/Engine/source/util/messaging/eventManager.cpp index 0edfa98fc..03b03228e 100644 --- a/Engine/source/util/messaging/eventManager.cpp +++ b/Engine/source/util/messaging/eventManager.cpp @@ -420,7 +420,7 @@ void EventManager::dumpSubscribers() //----------------------------------------------------------------------------- // Console Methods //----------------------------------------------------------------------------- -DefineConsoleMethod( EventManager, registerEvent, bool, ( const char * evt ), , "( String event )\n" +DefineEngineMethod( EventManager, registerEvent, bool, ( const char * evt ), , "( String event )\n" "Register an event with the event manager.\n" "@param event The event to register.\n" "@return Whether or not the event was registered successfully." ) @@ -428,14 +428,14 @@ DefineConsoleMethod( EventManager, registerEvent, bool, ( const char * evt ), , return object->registerEvent( evt ); } -DefineConsoleMethod( EventManager, unregisterEvent, void, ( const char * evt ), , "( String event )\n" +DefineEngineMethod( EventManager, unregisterEvent, void, ( const char * evt ), , "( String event )\n" "Remove an event from the EventManager.\n" "@param event The event to remove.\n" ) { object->unregisterEvent( evt ); } -DefineConsoleMethod( EventManager, isRegisteredEvent, bool, ( const char * evt ), , "( String event )\n" +DefineEngineMethod( EventManager, isRegisteredEvent, bool, ( const char * evt ), , "( String event )\n" "Check if an event is registered or not.\n" "@param event The event to check.\n" "@return Whether or not the event exists." ) @@ -443,7 +443,7 @@ DefineConsoleMethod( EventManager, isRegisteredEvent, bool, ( const char * evt ) return object->isRegisteredEvent( evt ); } -DefineConsoleMethod( EventManager, postEvent, bool, ( const char * evt, const char * data ), (""), "( String event, String data )\n" +DefineEngineMethod( EventManager, postEvent, bool, ( const char * evt, const char * data ), (""), "( String event, String data )\n" "~Trigger an event.\n" "@param event The event to trigger.\n" "@param data The data associated with the event.\n" @@ -458,7 +458,7 @@ DefineConsoleMethod( EventManager, postEvent, bool, ( const char * evt, const ch return object->postEvent( evt, data ); } -DefineConsoleMethod( EventManager, subscribe, bool, ( const char * listenerName, const char * evt, const char * callback ), (""), "( SimObject listener, String event, String callback )\n\n" +DefineEngineMethod( EventManager, subscribe, bool, ( const char * listenerName, const char * evt, const char * callback ), (""), "( SimObject listener, String event, String callback )\n\n" "Subscribe a listener to an event.\n" "@param listener The listener to subscribe.\n" "@param event The event to subscribe to.\n" @@ -476,7 +476,7 @@ DefineConsoleMethod( EventManager, subscribe, bool, ( const char * listenerName, return object->subscribe( cbObj, evt, callback ); } -DefineConsoleMethod( EventManager, remove, void, ( const char * listenerName, const char * evt), , "( SimObject listener, String event )\n\n" +DefineEngineMethod( EventManager, remove, void, ( const char * listenerName, const char * evt), , "( SimObject listener, String event )\n\n" "Remove a listener from an event.\n" "@param listener The listener to remove.\n" "@param event The event to be removed from.\n") @@ -487,7 +487,7 @@ DefineConsoleMethod( EventManager, remove, void, ( const char * listenerName, co object->remove( listener, evt ); } -DefineConsoleMethod( EventManager, removeAll, void, ( const char * listenerName ), , "( SimObject listener )\n\n" +DefineEngineMethod( EventManager, removeAll, void, ( const char * listenerName ), , "( SimObject listener )\n\n" "Remove a listener from all events.\n" "@param listener The listener to remove.\n") { @@ -498,13 +498,13 @@ DefineConsoleMethod( EventManager, removeAll, void, ( const char * listenerName object->removeAll( listener ); } -DefineConsoleMethod( EventManager, dumpEvents, void, (), , "()\n\n" +DefineEngineMethod( EventManager, dumpEvents, void, (), , "()\n\n" "Print all registered events to the console." ) { object->dumpEvents(); } -DefineConsoleMethod( EventManager, dumpSubscribers, void, ( const char * listenerName ), (""), "( String event )\n\n" +DefineEngineMethod( EventManager, dumpSubscribers, void, ( const char * listenerName ), (""), "( String event )\n\n" "Print all subscribers to an event to the console.\n" "@param event The event whose subscribers are to be printed. If this parameter isn't specified, all events will be dumped." ) { diff --git a/Engine/source/util/messaging/message.cpp b/Engine/source/util/messaging/message.cpp index 7e2b7af08..137242c56 100644 --- a/Engine/source/util/messaging/message.cpp +++ b/Engine/source/util/messaging/message.cpp @@ -155,19 +155,19 @@ const char *Message::getType() // Console Methods //----------------------------------------------------------------------------- -DefineConsoleMethod(Message, getType, const char *, (), , "() Get message type (script class name or C++ class name if no script defined class)") +DefineEngineMethod(Message, getType, const char *, (), , "() Get message type (script class name or C++ class name if no script defined class)") { return object->getType(); } //----------------------------------------------------------------------------- -DefineConsoleMethod(Message, addReference, void, (), , "() Increment the reference count for this message") +DefineEngineMethod(Message, addReference, void, (), , "() Increment the reference count for this message") { object->addReference(); } -DefineConsoleMethod(Message, freeReference, void, (), , "() Decrement the reference count for this message") +DefineEngineMethod(Message, freeReference, void, (), , "() Decrement the reference count for this message") { object->freeReference(); } diff --git a/Engine/source/util/settings.cpp b/Engine/source/util/settings.cpp index b57b77bb4..60f58966e 100644 --- a/Engine/source/util/settings.cpp +++ b/Engine/source/util/settings.cpp @@ -482,12 +482,12 @@ const char* Settings::findNextValue() } // make sure to replace the strings -DefineConsoleMethod(Settings, findFirstValue, const char*, ( const char* pattern, bool deepSearch, bool includeDefaults ), ("", false, false), "settingObj.findFirstValue();") +DefineEngineMethod(Settings, findFirstValue, const char*, ( const char* pattern, bool deepSearch, bool includeDefaults ), ("", false, false), "settingObj.findFirstValue();") { return object->findFirstValue( pattern, deepSearch, includeDefaults ); } -DefineConsoleMethod(Settings, findNextValue, const char*, (), , "settingObj.findNextValue();") +DefineEngineMethod(Settings, findNextValue, const char*, (), , "settingObj.findNextValue();") { return object->findNextValue(); } @@ -644,7 +644,7 @@ void SettingSaveNode::buildDocument(SimXMLDocument *document, bool skipWrite) document->popElement(); } -DefineConsoleMethod(Settings, setValue, void, (const char * settingName, const char * value), (""), "settingObj.setValue(settingName, value);") +DefineEngineMethod(Settings, setValue, void, (const char * settingName, const char * value), (""), "settingObj.setValue(settingName, value);") { StringTableEntry fieldName = StringTable->insert( settingName ); @@ -654,13 +654,13 @@ DefineConsoleMethod(Settings, setValue, void, (const char * settingName, const c object->setValue( fieldName ); } -DefineConsoleMethod(Settings, setDefaultValue, void, (const char * settingName, const char * value), , "settingObj.setDefaultValue(settingName, value);") +DefineEngineMethod(Settings, setDefaultValue, void, (const char * settingName, const char * value), , "settingObj.setDefaultValue(settingName, value);") { StringTableEntry fieldName = StringTable->insert( settingName ); object->setDefaultValue( fieldName, value ); } -DefineConsoleMethod(Settings, value, const char*, (const char * settingName, const char * defaultValue), (""), "settingObj.value(settingName, defaultValue);") +DefineEngineMethod(Settings, value, const char*, (const char * settingName, const char * defaultValue), (""), "settingObj.value(settingName, defaultValue);") { StringTableEntry fieldName = StringTable->insert( settingName ); @@ -672,7 +672,7 @@ DefineConsoleMethod(Settings, value, const char*, (const char * settingName, con return ""; } -DefineConsoleMethod(Settings, remove, void, (const char * settingName, bool includeDefaults), (false), "settingObj.remove(settingName, includeDefaults = false);") +DefineEngineMethod(Settings, remove, void, (const char * settingName, bool includeDefaults), (false), "settingObj.remove(settingName, includeDefaults = false);") { // there's a problem with some fields not being removed properly, but works if you run it twice, // a temporary solution for now is simply to call the remove twice @@ -687,27 +687,27 @@ ConsoleMethod(Settings, write, bool, 2, 2, "%success = settingObj.write();") return object->write(); } -DefineConsoleMethod(Settings, read, bool, (), , "%success = settingObj.read();") +DefineEngineMethod(Settings, read, bool, (), , "%success = settingObj.read();") { return object->read(); } -DefineConsoleMethod(Settings, beginGroup, void, (const char * groupName, bool includeDefaults), (false), "settingObj.beginGroup(groupName, fromStart = false);") +DefineEngineMethod(Settings, beginGroup, void, (const char * groupName, bool includeDefaults), (false), "settingObj.beginGroup(groupName, fromStart = false);") { object->beginGroup( groupName, includeDefaults ); } -DefineConsoleMethod(Settings, endGroup, void, (), , "settingObj.endGroup();") +DefineEngineMethod(Settings, endGroup, void, (), , "settingObj.endGroup();") { object->endGroup(); } -DefineConsoleMethod(Settings, clearGroups, void, (), , "settingObj.clearGroups();") +DefineEngineMethod(Settings, clearGroups, void, (), , "settingObj.clearGroups();") { object->clearGroups(); } -DefineConsoleMethod(Settings, getCurrentGroups, const char*, (), , "settingObj.getCurrentGroups();") +DefineEngineMethod(Settings, getCurrentGroups, const char*, (), , "settingObj.getCurrentGroups();") { return object->getCurrentGroups(); } \ No newline at end of file diff --git a/Engine/source/util/undo.cpp b/Engine/source/util/undo.cpp index 7ea0acc8c..ae6163774 100644 --- a/Engine/source/util/undo.cpp +++ b/Engine/source/util/undo.cpp @@ -145,7 +145,7 @@ void CompoundUndoAction::onDeleteNotify( SimObject* object ) Parent::onDeleteNotify( object ); } -DefineConsoleMethod( CompoundUndoAction, addAction, void, (const char * objName), , "addAction( UndoAction )" ) +DefineEngineMethod( CompoundUndoAction, addAction, void, (const char * objName), , "addAction( UndoAction )" ) { UndoAction *action; if ( Sim::findObject( objName, action ) ) @@ -206,7 +206,7 @@ UndoManager& UndoManager::getDefaultManager() return *defaultMan; } -DefineConsoleMethod(UndoManager, clearAll, void, (),, "Clears the undo manager.") +DefineEngineMethod(UndoManager, clearAll, void, (),, "Clears the undo manager.") { object->clearAll(); } @@ -344,7 +344,7 @@ void UndoManager::redo() (*react).redo(); } -DefineConsoleMethod(UndoManager, getUndoCount, S32, (),, "") +DefineEngineMethod(UndoManager, getUndoCount, S32, (),, "") { return object->getUndoCount(); } @@ -354,7 +354,7 @@ S32 UndoManager::getUndoCount() return mUndoStack.size(); } -DefineConsoleMethod(UndoManager, getUndoName, const char*, (S32 index), , "(index)") +DefineEngineMethod(UndoManager, getUndoName, const char*, (S32 index), , "(index)") { return object->getUndoName(index); } @@ -367,7 +367,7 @@ const char* UndoManager::getUndoName(S32 index) return NULL; } -DefineConsoleMethod(UndoManager, getUndoAction, S32, (S32 index), , "(index)") +DefineEngineMethod(UndoManager, getUndoAction, S32, (S32 index), , "(index)") { UndoAction * action = object->getUndoAction(index); if ( !action ) @@ -386,7 +386,7 @@ UndoAction* UndoManager::getUndoAction(S32 index) return NULL; } -DefineConsoleMethod(UndoManager, getRedoCount, S32, (),, "") +DefineEngineMethod(UndoManager, getRedoCount, S32, (),, "") { return object->getRedoCount(); } @@ -396,7 +396,7 @@ S32 UndoManager::getRedoCount() return mRedoStack.size(); } -DefineConsoleMethod(UndoManager, getRedoName, const char*, (S32 index), , "(index)") +DefineEngineMethod(UndoManager, getRedoName, const char*, (S32 index), , "(index)") { return object->getRedoName(index); } @@ -409,7 +409,7 @@ const char* UndoManager::getRedoName(S32 index) return NULL; } -DefineConsoleMethod(UndoManager, getRedoAction, S32, (S32 index), , "(index)") +DefineEngineMethod(UndoManager, getRedoAction, S32, (S32 index), , "(index)") { UndoAction * action = object->getRedoAction(index); @@ -501,7 +501,7 @@ void UndoManager::popCompound( bool discard ) } //----------------------------------------------------------------------------- -DefineConsoleMethod(UndoAction, addToManager, void, (const char * undoManager), (""), "action.addToManager([undoManager])") +DefineEngineMethod(UndoAction, addToManager, void, (const char * undoManager), (""), "action.addToManager([undoManager])") { UndoManager *theMan = NULL; if (!String::isEmpty(undoManager)) @@ -515,32 +515,32 @@ DefineConsoleMethod(UndoAction, addToManager, void, (const char * undoManager), //----------------------------------------------------------------------------- -DefineConsoleMethod( UndoAction, undo, void, (),, "() - Undo action contained in undo." ) +DefineEngineMethod( UndoAction, undo, void, (),, "() - Undo action contained in undo." ) { object->undo(); } //----------------------------------------------------------------------------- -DefineConsoleMethod( UndoAction, redo, void, (),, "() - Reo action contained in undo." ) +DefineEngineMethod( UndoAction, redo, void, (),, "() - Reo action contained in undo." ) { object->redo(); } //----------------------------------------------------------------------------- -DefineConsoleMethod(UndoManager, undo, void, (),, "UndoManager.undo();") +DefineEngineMethod(UndoManager, undo, void, (),, "UndoManager.undo();") { object->undo(); } //----------------------------------------------------------------------------- -DefineConsoleMethod(UndoManager, redo, void, (),, "UndoManager.redo();") +DefineEngineMethod(UndoManager, redo, void, (),, "UndoManager.redo();") { object->redo(); } //----------------------------------------------------------------------------- -DefineConsoleMethod(UndoManager, getNextUndoName, const char *, (),, "UndoManager.getNextUndoName();") +DefineEngineMethod(UndoManager, getNextUndoName, const char *, (),, "UndoManager.getNextUndoName();") { const char *name = object->getNextUndoName(); if(!name) @@ -552,7 +552,7 @@ DefineConsoleMethod(UndoManager, getNextUndoName, const char *, (),, "UndoManage } //----------------------------------------------------------------------------- -DefineConsoleMethod(UndoManager, getNextRedoName, const char *, (),, "UndoManager.getNextRedoName();") +DefineEngineMethod(UndoManager, getNextRedoName, const char *, (),, "UndoManager.getNextRedoName();") { const char *name = object->getNextRedoName(); if(!name) @@ -565,7 +565,7 @@ DefineConsoleMethod(UndoManager, getNextRedoName, const char *, (),, "UndoManage //----------------------------------------------------------------------------- -DefineConsoleMethod( UndoManager, pushCompound, const char*, ( String name ), ("\"\""), "( string name=\"\" ) - Push a CompoundUndoAction onto the compound stack for assembly." ) +DefineEngineMethod( UndoManager, pushCompound, const char*, ( String name ), ("\"\""), "( string name=\"\" ) - Push a CompoundUndoAction onto the compound stack for assembly." ) { CompoundUndoAction* action = object->pushCompound( name ); @@ -580,7 +580,7 @@ DefineConsoleMethod( UndoManager, pushCompound, const char*, ( String name ), (" //----------------------------------------------------------------------------- -DefineConsoleMethod( UndoManager, popCompound, void, ( bool discard ), (false), "( bool discard=false ) - Pop the current CompoundUndoAction off the stack." ) +DefineEngineMethod( UndoManager, popCompound, void, ( bool discard ), (false), "( bool discard=false ) - Pop the current CompoundUndoAction off the stack." ) { if( !object->getCompoundStackDepth() ) { From 6be736ff85c896b88c0bad2fcc8f93e1b8f4365d Mon Sep 17 00:00:00 2001 From: Lukas Joergensen Date: Tue, 17 Apr 2018 21:03:16 +0200 Subject: [PATCH 07/34] Eliminate DefineConsoleStaticMethod --- Engine/source/console/engineAPI.h | 54 ------------------------------- Engine/source/gfx/gfxInit.cpp | 2 +- 2 files changed, 1 insertion(+), 55 deletions(-) diff --git a/Engine/source/console/engineAPI.h b/Engine/source/console/engineAPI.h index ca7ca8a1d..6d0484171 100644 --- a/Engine/source/console/engineAPI.h +++ b/Engine/source/console/engineAPI.h @@ -855,60 +855,6 @@ public: ); \ static inline returnType _fn ## className ## name ## impl args - -// Convenience macros to allow defining functions that use the new marshalling features -// while being only visible in the console interop. When we drop the console system, -// these macros can be removed and all definitions that make use of them can be removed -// as well. - -#define DefineEngineMethod( className, name, returnType, args, defaultArgs, usage ) \ - struct _ ## className ## name ## frame \ - { \ - typedef className ObjectType; \ - className* object; \ - inline returnType _exec args const; \ - }; \ - static _EngineFunctionDefaultArguments< _EngineMethodTrampoline< _ ## className ## name ## frame, void args >::FunctionType > \ - _fn ## className ## name ## DefaultArgs defaultArgs; \ - static _EngineConsoleThunkType< returnType >::ReturnType _ ## className ## name ## caster( SimObject* object, S32 argc, ConsoleValueRef *argv ) \ - { \ - _ ## className ## name ## frame frame; \ - frame.object = static_cast< className* >( object ); \ - return _EngineConsoleThunkType< returnType >::ReturnType( _EngineConsoleThunk< 2, returnType args >::thunk( \ - argc, argv, &_ ## className ## name ## frame::_exec, &frame, _fn ## className ## name ## DefaultArgs \ - ) ); \ - } \ - static ConsoleFunctionHeader _ ## className ## name ## header \ - ( #returnType, #args, #defaultArgs ); \ - static ConsoleConstructor \ - className ## name ## obj( #className, #name, \ - _EngineConsoleThunkType< returnType >::CallbackType( _ ## className ## name ## caster ), usage, \ - _EngineConsoleThunk< 2, returnType args >::NUM_ARGS - _EngineConsoleThunkCountArgs() defaultArgs, \ - _EngineConsoleThunk< 2, returnType args >::NUM_ARGS, \ - false, &_ ## className ## name ## header \ - ); \ - returnType _ ## className ## name ## frame::_exec args const - -#define DefineConsoleStaticMethod( className, name, returnType, args, defaultArgs, usage ) \ - static inline returnType _fn ## className ## name ## impl args; \ - static _EngineFunctionDefaultArguments< void args > _fn ## className ## name ## DefaultArgs defaultArgs; \ - static _EngineConsoleThunkType< returnType >::ReturnType _ ## className ## name ## caster( SimObject*, S32 argc, ConsoleValueRef *argv )\ - { \ - return _EngineConsoleThunkType< returnType >::ReturnType( _EngineConsoleThunk< 1, returnType args >::thunk( \ - argc, argv, &_fn ## className ## name ## impl, _fn ## className ## name ## DefaultArgs \ - ) ); \ - } \ - static ConsoleFunctionHeader _ ## className ## name ## header \ - ( #returnType, #args, #defaultArgs, true ); \ - static ConsoleConstructor \ - _ ## className ## name ## obj( #className, #name, _EngineConsoleThunkType< returnType >::CallbackType( _ ## className ## name ## caster ), usage, \ - _EngineConsoleThunk< 1, returnType args >::NUM_ARGS - _EngineConsoleThunkCountArgs() defaultArgs, \ - _EngineConsoleThunk< 1, returnType args >::NUM_ARGS, \ - false, &_ ## className ## name ## header \ - ); \ - static inline returnType _fn ## className ## name ## impl args - - // The following three macros are only temporary. They allow to define engineAPI functions using the framework // here in this file while being visible only in the new API. When the console interop is removed, these macros // can be removed and all their uses be replaced with their corresponding versions that now still include support diff --git a/Engine/source/gfx/gfxInit.cpp b/Engine/source/gfx/gfxInit.cpp index 21572b957..cc7f897bb 100644 --- a/Engine/source/gfx/gfxInit.cpp +++ b/Engine/source/gfx/gfxInit.cpp @@ -536,7 +536,7 @@ DefineEngineStaticMethod( GFXInit, getAdapterModeCount, S32, ( S32 index ),, return adapters[index]->mAvailableModes.size(); } -DefineConsoleStaticMethod( GFXInit, getAdapterMode, String, ( S32 index, S32 modeIndex ),, +DefineEngineStaticMethod( GFXInit, getAdapterMode, String, ( S32 index, S32 modeIndex ),, "Gets the details of the specified adapter mode.\n\n" "@param index Index of the adapter to query.\n" "@param modeIndex Index of the mode to get data from.\n" From 2bbc716db67f2e52d7e190c9cc8deec9256268f0 Mon Sep 17 00:00:00 2001 From: Lukas Joergensen Date: Tue, 17 Apr 2018 21:41:29 +0200 Subject: [PATCH 08/34] Eliminate unnecessary uses of ConsoleFunction --- Engine/source/T3D/gameBase/gameConnection.cpp | 30 ++++---- Engine/source/afx/arcaneFX.cpp | 70 +++++-------------- Engine/source/app/game.cpp | 6 +- Engine/source/console/consoleFunctions.cpp | 25 +++---- Engine/source/console/scriptFilename.cpp | 30 ++++---- Engine/source/core/color.cpp | 59 ++++++---------- Engine/source/core/frameAllocator.cpp | 4 +- Engine/source/core/resourceManager.cpp | 11 ++- Engine/source/gfx/gl/gfxGLDevice.cpp | 2 +- Engine/source/i18n/lang.cpp | 6 +- Engine/source/platform/platformAssert.cpp | 8 +-- Engine/source/platformSDL/sdlInput.cpp | 10 +-- 12 files changed, 103 insertions(+), 158 deletions(-) diff --git a/Engine/source/T3D/gameBase/gameConnection.cpp b/Engine/source/T3D/gameBase/gameConnection.cpp index cfe87de6d..7c5effdc5 100644 --- a/Engine/source/T3D/gameBase/gameConnection.cpp +++ b/Engine/source/T3D/gameBase/gameConnection.cpp @@ -2722,33 +2722,32 @@ void GameConnection::resetDatablockCache() afx_saved_db_cache_CRC = 0xffffffff; } -ConsoleFunction(resetDatablockCache, void, 1, 1, "resetDatablockCache()") +DefineEngineFunction(resetDatablockCache, void, (),,"") { GameConnection::resetDatablockCache(); } -ConsoleFunction(isDatablockCacheSaved, bool, 1, 1, "resetDatablockCache()") +DefineEngineFunction(isDatablockCacheSaved, bool, (),,"") { return afx_saved_db_cache; } -ConsoleFunction(getDatablockCacheCRC, S32, 1, 1, "getDatablockCacheCRC()") +DefineEngineFunction(getDatablockCacheCRC, S32, (),,"") { return (S32)afx_saved_db_cache_CRC; } -ConsoleFunction(extractDatablockCacheCRC, S32, 2, 2, "extractDatablockCacheCRC(filename)") +DefineEngineFunction(extractDatablockCacheCRC, S32, (const char* fileName),,"") { FileStream f_stream; - const char* fileName = argv[1]; - if(!f_stream.open(fileName, Torque::FS::File::Read)) + if (!f_stream.open(fileName, Torque::FS::File::Read)) { Con::errorf("Failed to open file '%s'.", fileName); return -1; } U32 stream_sz = f_stream.getStreamSize(); - if (stream_sz < 4*32) + if (stream_sz < 4 * 32) { Con::errorf("File '%s' is not a valid datablock cache.", fileName); f_stream.close(); @@ -2777,17 +2776,16 @@ ConsoleFunction(extractDatablockCacheCRC, S32, 2, 2, "extractDatablockCacheCRC(f return (S32)crc_code; } -ConsoleFunction(setDatablockCacheCRC, void, 2, 2, "setDatablockCacheCRC(crc)") +DefineEngineFunction(setDatablockCacheCRC, void, (U32 crc), , "") { GameConnection *conn = GameConnection::getConnectionToServer(); - if(!conn) + if (!conn) return; - U32 crc_u = (U32)dAtoi(argv[1]); - conn->setServerCacheCRC(crc_u); + conn->setServerCacheCRC(crc); } -ConsoleMethod( GameConnection, saveDatablockCache, void, 2, 2, "saveDatablockCache()") +DefineEngineMethod(GameConnection, saveDatablockCache, void, (),, "") { if (GameConnection::serverCacheEnabled() && !afx_saved_db_cache) { @@ -2802,14 +2800,14 @@ ConsoleMethod( GameConnection, saveDatablockCache, void, 2, 2, "saveDatablockCac Con::expandScriptFilename(filename_buffer, sizeof(filename_buffer), filename.c_str()); Torque::Path givenPath(Torque::Path::CompressPath(filename_buffer)); Torque::FS::FileNodeRef fileRef = Torque::FS::GetFileNode(givenPath); - if ( fileRef == NULL ) + if (fileRef == NULL) Con::errorf("saveDatablockCache() failed to get CRC for file '%s'.", filename.c_str()); else afx_saved_db_cache_CRC = (S32)fileRef->getChecksum(); } } -ConsoleMethod( GameConnection, loadDatablockCache, void, 2, 2, "loadDatablockCache()") +DefineEngineMethod(GameConnection, loadDatablockCache, void, (),, "") { if (GameConnection::clientCacheEnabled()) { @@ -2817,7 +2815,7 @@ ConsoleMethod( GameConnection, loadDatablockCache, void, 2, 2, "loadDatablockCac } } -ConsoleMethod( GameConnection, loadDatablockCache_Begin, bool, 2, 2, "loadDatablockCache_Begin()") +DefineEngineMethod(GameConnection, loadDatablockCache_Begin, bool, (),, "") { if (GameConnection::clientCacheEnabled()) { @@ -2827,7 +2825,7 @@ ConsoleMethod( GameConnection, loadDatablockCache_Begin, bool, 2, 2, "loadDatabl return false; } -ConsoleMethod( GameConnection, loadDatablockCache_Continue, bool, 2, 2, "loadDatablockCache_Continue()") +DefineEngineMethod(GameConnection, loadDatablockCache_Continue, bool, (),, "") { if (GameConnection::clientCacheEnabled()) { diff --git a/Engine/source/afx/arcaneFX.cpp b/Engine/source/afx/arcaneFX.cpp index cec0c870a..4252183c1 100644 --- a/Engine/source/afx/arcaneFX.cpp +++ b/Engine/source/afx/arcaneFX.cpp @@ -584,69 +584,33 @@ DefineEngineFunction(getRandomDir, Point3F, (Point3F axis, float thetaMin, float return MathUtils::randomDir(axis, thetaMin, thetaMax, phiMin, phiMax); } -ConsoleFunction( MatrixInverseMulVector, const char*, 3, 3, "(MatrixF xfrm, Point3F vector)" - "@brief Multiply the vector by the affine inverse of the transform.\n\n" - "@ingroup AFX") +DefineEngineFunction(MatrixInverseMulVector, Point3F, (MatrixF xfrm, Point3F vector),, + "@brief Multiply the vector by the affine inverse of the transform.\n\n" + "@ingroup AFX") { - Point3F pos1(0.0f,0.0f,0.0f); - AngAxisF aa1(Point3F(0.0f,0.0f,0.0f),0.0f); - dSscanf(argv[1], "%g %g %g %g %g %g %g", &pos1.x, &pos1.y, &pos1.z, &aa1.axis.x, &aa1.axis.y, &aa1.axis.z, &aa1.angle); - - MatrixF temp1(true); - aa1.setMatrix(&temp1); - temp1.setColumn(3, pos1); - - Point3F vec1(0.0f,0.0f,0.0f); - dSscanf(argv[2], "%g %g %g", &vec1.x, &vec1.y, &vec1.z); - - temp1.affineInverse(); + xfrm.affineInverse(); Point3F result; - temp1.mulV(vec1, &result); + xfrm.mulV(vector, &result); - char* ret = Con::getReturnBuffer(256); - dSprintf(ret, 255, "%g %g %g", result.x, result.y, result.z); - return ret; + return result; } -ConsoleFunction(moveTransformAbs, const char*, 3, 3, "(MatrixF xfrm, Point3F pos)" - "@brief Move the transform to the new absolute position.\n\n" - "@ingroup AFX") +DefineEngineFunction(moveTransformAbs, MatrixF, (MatrixF xfrm, Point3F pos),, + "@brief Move the transform to the new absolute position.\n\n" + "@ingroup AFX") { - Point3F pos1(0.0f,0.0f,0.0f); - AngAxisF aa1(Point3F(0.0f,0.0f,0.0f),0.0f); - dSscanf(argv[1], "%g %g %g %g %g %g %g", &pos1.x, &pos1.y, &pos1.z, &aa1.axis.x, &aa1.axis.y, &aa1.axis.z, &aa1.angle); - - Point3F pos2(0.0f,0.0f,0.0f); - dSscanf(argv[2], "%g %g %g", &pos2.x, &pos2.y, &pos2.z); - - char* returnBuffer = Con::getReturnBuffer(256); - dSprintf(returnBuffer, 255, "%g %g %g %g %g %g %g", - pos2.x, pos2.y, pos2.z, - aa1.axis.x, aa1.axis.y, aa1.axis.z, - aa1.angle); - return returnBuffer; + xfrm.setPosition(pos); + return xfrm; } -ConsoleFunction(moveTransformRel, const char*, 3, 3, "(MatrixF xfrm, Point3F pos)" - "@brief Move the transform to the new relative position.\n\n" - "@ingroup AFX") +DefineEngineFunction(moveTransformRel, MatrixF, (MatrixF xfrm, Point3F pos),, + "@brief Move the transform to the new relative position.\n\n" + "@ingroup AFX") { - Point3F pos1(0.0f,0.0f,0.0f); - AngAxisF aa1(Point3F(0.0f,0.0f,0.0f),0.0f); - dSscanf(argv[1], "%g %g %g %g %g %g %g", &pos1.x, &pos1.y, &pos1.z, &aa1.axis.x, &aa1.axis.y, &aa1.axis.z, &aa1.angle); - - Point3F pos2(0.0f,0.0f,0.0f); - dSscanf(argv[2], "%g %g %g", &pos2.x, &pos2.y, &pos2.z); - - pos2 += pos1; - - char* returnBuffer = Con::getReturnBuffer(256); - dSprintf(returnBuffer, 255, "%g %g %g %g %g %g %g", - pos2.x, pos2.y, pos2.z, - aa1.axis.x, aa1.axis.y, aa1.axis.z, - aa1.angle); - return returnBuffer; + pos += xfrm.getPosition(); + xfrm.setPosition(pos); + return xfrm; } DefineEngineFunction(getFreeTargetPosition, Point3F, (),, diff --git a/Engine/source/app/game.cpp b/Engine/source/app/game.cpp index d7a3377f6..5878accd6 100644 --- a/Engine/source/app/game.cpp +++ b/Engine/source/app/game.cpp @@ -218,8 +218,10 @@ DefineEngineFunction( getRealTime, S32, (), , "()" return Platform::getRealMilliseconds(); } -ConsoleFunction( getLocalTime, const char *, 1, 1, "Return the current local time as: weekday month day year hour min sec.\n\n" - "Local time is platform defined.") +DefineEngineFunction(getLocalTime, const char*, (),, + "@brief Return the current local time as: weekday month day year hour min sec.\n\n" + "Local time is platform defined." + "@ingroup Platform") { Platform::LocalTime lt; Platform::getLocalTime(lt); diff --git a/Engine/source/console/consoleFunctions.cpp b/Engine/source/console/consoleFunctions.cpp index 258f7911f..565c79206 100644 --- a/Engine/source/console/consoleFunctions.cpp +++ b/Engine/source/console/consoleFunctions.cpp @@ -2646,26 +2646,23 @@ DefineEngineFunction( getPrefsPath, const char *, ( const char* relativeFileName //----------------------------------------------------------------------------- -ConsoleFunction( execPrefs, bool, 2, 4, "( string relativeFileName, bool noCalls=false, bool journalScript=false )" - "@brief Manually execute a special script file that contains game or editor preferences\n\n" - "@param relativeFileName Name and path to file from project folder\n" - "@param noCalls Deprecated\n" - "@param journalScript Deprecated\n" - "@return True if script was successfully executed\n" - "@note Appears to be useless in Torque 3D, should be deprecated\n" - "@ingroup Scripting") +DefineEngineFunction(execPrefs, bool, (const char* relativeFileName, bool noCalls, bool journalScript),(false, false), + "@brief Manually execute a special script file that contains game or editor preferences\n\n" + "@param relativeFileName Name and path to file from project folder\n" + "@param noCalls Deprecated\n" + "@param journalScript Deprecated\n" + "@return True if script was successfully executed\n" + "@note Appears to be useless in Torque 3D, should be deprecated\n" + "@ingroup Scripting") { - const char *filename = Platform::getPrefsPath(argv[1]); - if(filename == NULL || *filename == 0) + if (relativeFileName == NULL || *relativeFileName == 0) return false; // Scripts do this a lot, so we may as well help them out - if(! Platform::isFile(filename) && ! Torque::FS::IsFile(filename)) + if (!Platform::isFile(relativeFileName) && !Torque::FS::IsFile(relativeFileName)) return true; - argv[0] = "exec"; - argv[1] = filename; - return dAtob(Con::execute(argc, argv)); + return Con::executeFile(relativeFileName, noCalls, journalScript); } //----------------------------------------------------------------------------- diff --git a/Engine/source/console/scriptFilename.cpp b/Engine/source/console/scriptFilename.cpp index 332f01d26..b0cacf2bc 100644 --- a/Engine/source/console/scriptFilename.cpp +++ b/Engine/source/console/scriptFilename.cpp @@ -27,7 +27,7 @@ #include "core/tSimpleHashTable.h" #include "core/strings/stringFunctions.h" #include "core/stringTable.h" -#include "console/console.h" +#include "console/engineAPI.h" #include "console/compiler.h" @@ -342,28 +342,26 @@ bool collapseScriptFilename(char *filename, U32 size, const char *src) // Console Functions //----------------------------------------------------------------------------- -ConsoleFunction(expandFilename, const char*, 2, 2, "(string filename)" - "@brief Grabs the full path of a specified file\n\n" - "@param filename Name of the local file to locate\n" - "@return String containing the full filepath on disk\n" - "@ingroup FileSystem") +DefineEngineFunction(expandFilename, const char*, (const char* filename),, + "@brief Grabs the full path of a specified file\n\n" + "@param filename Name of the local file to locate\n" + "@return String containing the full filepath on disk\n" + "@ingroup FileSystem") { - TORQUE_UNUSED(argc); static const U32 bufSize = 1024; - char* ret = Con::getReturnBuffer( bufSize ); - Con::expandScriptFilename(ret, bufSize, argv[1]); + char* ret = Con::getReturnBuffer(bufSize); + Con::expandScriptFilename(ret, bufSize, filename); return ret; } -ConsoleFunction(expandOldFilename, const char*, 2, 2, "(string filename)" - "@brief Retrofits a filepath that uses old Torque style\n\n" - "@return String containing filepath with new formatting\n" - "@ingroup FileSystem") +DefineEngineFunction(expandOldFilename, const char*, (const char* filename),, + "@brief Retrofits a filepath that uses old Torque style\n\n" + "@return String containing filepath with new formatting\n" + "@ingroup FileSystem") { - TORQUE_UNUSED(argc); static const U32 bufSize = 1024; - char* ret = Con::getReturnBuffer( bufSize ); - Con::expandOldScriptFilename(ret, bufSize, argv[1]); + char* ret = Con::getReturnBuffer(bufSize); + Con::expandOldScriptFilename(ret, bufSize, filename); return ret; } diff --git a/Engine/source/core/color.cpp b/Engine/source/core/color.cpp index 273a2a658..1fea8cfec 100644 --- a/Engine/source/core/color.cpp +++ b/Engine/source/core/color.cpp @@ -536,80 +536,67 @@ float LinearColorF::sSrgbToLinear[256] = #endif //----------------------------------------------------------------------------- -ConsoleFunction( getStockColorCount, S32, 1, 1, "() - Gets a count of available stock colors.\n" - "@return A count of available stock colors." ) +DefineEngineFunction(getStockColorCount, S32, (),, + "@brief Gets a count of available stock colors.\n" + "@return A count of available stock colors.") { return StockColor::getCount(); } //----------------------------------------------------------------------------- -ConsoleFunction( getStockColorName, const char*, 2, 2, "(stockColorIndex) - Gets the stock color name at the specified index.\n" +DefineEngineFunction(getStockColorName, const char*, (S32 stockColorIndex),, + "@brief Gets the stock color name at the specified index.\n" "@param stockColorIndex The zero-based index of the stock color name to retrieve.\n" - "@return The stock color name at the specified index or nothing if the string is invalid." ) + "@return The stock color name at the specified index or nothing if the string is invalid.") { - // Fetch stock color index. - const S32 stockColorIndex = dAtoi(argv[1]); - // Fetch the color item. - const StockColorItem* pColorItem = StockColor::getColorItem( stockColorIndex ); + const StockColorItem* pColorItem = StockColor::getColorItem(stockColorIndex); return pColorItem == NULL ? NULL : pColorItem->getColorName(); } //----------------------------------------------------------------------------- -ConsoleFunction( isStockColor, bool, 2, 2, "(stockColorName) - Gets whether the specified name is a stock color or not.\n" +DefineEngineFunction(isStockColor, bool, (const char* stockColorName),, + "@brief Gets whether the specified name is a stock color or not.\n" "@param stockColorName - The stock color name to test for.\n" - "@return Whether the specified name is a stock color or not.\n" ) + "@return Whether the specified name is a stock color or not.\n") { - // Fetch stock color name. - const char* pStockColorName = argv[1]; - // Return whether this is a stock color name or not. - return StockColor::isColor( pStockColorName ); + return StockColor::isColor(stockColorName); } //----------------------------------------------------------------------------- -ConsoleFunction( getStockColorF, const char*, 2, 2, "(stockColorName) - Gets a floating-point-based stock color by name.\n" +DefineEngineFunction(getStockColorF, LinearColorF, (const char* stockColorName),, + "@brief Gets a floating-point-based stock color by name.\n" "@param stockColorName - The stock color name to retrieve.\n" - "@return The stock color that matches the specified color name. Returns nothing if the color name is not found.\n" ) + "@return The stock color that matches the specified color name. Returns nothing if the color name is not found.\n") { - // Fetch stock color name. - const char* pStockColorName = argv[1]; - // Return nothing if stock color name is invalid. - if ( !StockColor::isColor( pStockColorName ) ) + if (!StockColor::isColor(stockColorName)) return StringTable->EmptyString(); // Fetch stock color. - const LinearColorF& color = StockColor::colorF( pStockColorName ); + const LinearColorF& color = StockColor::colorF(stockColorName); - // Format stock color. - char* returnBuffer = Con::getReturnBuffer(256); - dSprintf(returnBuffer, 256, "%g %g %g %g", color.red, color.green, color.blue, color.alpha); - return(returnBuffer); + return color; } //----------------------------------------------------------------------------- -ConsoleFunction( getStockColorI, const char*, 2, 2, "(stockColorName) - Gets a byte-based stock color by name.\n" +DefineEngineFunction(getStockColorI, ColorI, (const char* stockColorName),, + "@brief Gets a byte-based stock color by name.\n" "@param stockColorName - The stock color name to retrieve.\n" - "@return The stock color that matches the specified color name. Returns nothing if the color name is not found.\n" ) + "@return The stock color that matches the specified color name. Returns nothing if the color name is not found.\n") { - // Fetch stock color name. - const char* pStockColorName = argv[1]; - // Return nothing if stock color name is invalid. - if ( !StockColor::isColor( pStockColorName ) ) + if (!StockColor::isColor(stockColorName)) return StringTable->EmptyString(); // Fetch stock color. - const ColorI& color = StockColor::colorI( pStockColorName ); + const ColorI& color = StockColor::colorI(stockColorName); - // Format stock color. - char* returnBuffer = Con::getReturnBuffer(256); - dSprintf(returnBuffer, 256, "%d %d %d %d", color.red, color.green, color.blue, color.alpha); - return(returnBuffer); + return color; } \ No newline at end of file diff --git a/Engine/source/core/frameAllocator.cpp b/Engine/source/core/frameAllocator.cpp index 846328290..5c9530271 100644 --- a/Engine/source/core/frameAllocator.cpp +++ b/Engine/source/core/frameAllocator.cpp @@ -21,7 +21,7 @@ //----------------------------------------------------------------------------- #include "core/frameAllocator.h" -#include "console/console.h" +#include "console/engineAPI.h" U8* FrameAllocator::smBuffer = NULL; U32 FrameAllocator::smWaterMark = 0; @@ -30,7 +30,7 @@ U32 FrameAllocator::smHighWaterMark = 0; #ifdef TORQUE_DEBUG U32 FrameAllocator::smMaxFrameAllocation = 0; -ConsoleFunction(getMaxFrameAllocation, S32, 1,1, "getMaxFrameAllocation();") +DefineEngineFunction(getMaxFrameAllocation, S32, (),,"") { return FrameAllocator::getMaxFrameAllocation(); } diff --git a/Engine/source/core/resourceManager.cpp b/Engine/source/core/resourceManager.cpp index 09b889f95..c5b6e0fa6 100644 --- a/Engine/source/core/resourceManager.cpp +++ b/Engine/source/core/resourceManager.cpp @@ -222,18 +222,17 @@ ResourceBase ResourceManager::nextResource() ConsoleFunctionGroupBegin(ResourceManagerFunctions, "Resource management functions."); -ConsoleFunction(resourceDump, void, 1, 1, "()" - "@brief List the currently managed resources\n\n" - "Currently used by editors only, internal\n" - "@ingroup Editors\n" - "@internal") +DefineEngineFunction(resourceDump, void, (),, + "@brief List the currently managed resources\n\n" + "Currently used by editors only, internal\n" + "@ingroup Editors\n" + "@internal") { #ifdef TORQUE_DEBUG ResourceManager::get().dumpToConsole(); #endif } - DefineEngineFunction( reloadResource, void, ( const char* path ),, "Force the resource at specified input path to be reloaded\n" "@param path Path to the resource to be reloaded\n\n" diff --git a/Engine/source/gfx/gl/gfxGLDevice.cpp b/Engine/source/gfx/gl/gfxGLDevice.cpp index d2a1853ee..9eda76ebc 100644 --- a/Engine/source/gfx/gl/gfxGLDevice.cpp +++ b/Engine/source/gfx/gl/gfxGLDevice.cpp @@ -992,7 +992,7 @@ public: static GFXGLRegisterDevice pGLRegisterDevice; -ConsoleFunction(cycleResources, void, 1, 1, "") +DefineEngineFunction(cycleResources, void, (),, "") { static_cast(GFX)->zombify(); static_cast(GFX)->resurrect(); diff --git a/Engine/source/i18n/lang.cpp b/Engine/source/i18n/lang.cpp index b1fa76c6a..724d88abe 100644 --- a/Engine/source/i18n/lang.cpp +++ b/Engine/source/i18n/lang.cpp @@ -508,14 +508,15 @@ bool compiledFileNeedsUpdate(UTF8* filename) return false; } -ConsoleFunction(CompileLanguage, void, 2, 3, "(string inputFile, [bool createMap]) Compiles a LSO language file." +DefineEngineFunction(CompileLanguage, void, (const char* inputFile, bool createMap), (false), + "@brief Compiles a LSO language file." " if createIndex is true, will also create languageMap.cs with" " the global variables for each string index." " The input file must follow this example layout:" " TXT_HELLO_WORLD = Hello world in english!") { UTF8 scriptFilenameBuffer[1024]; - Con::expandScriptFilename((char*)scriptFilenameBuffer, sizeof(scriptFilenameBuffer), argv[1]); + Con::expandScriptFilename((char*)scriptFilenameBuffer, sizeof(scriptFilenameBuffer), inputFile); if (!Torque::FS::IsFile(scriptFilenameBuffer)) { @@ -532,7 +533,6 @@ ConsoleFunction(CompileLanguage, void, 2, 3, "(string inputFile, [bool createMap if (compiledFileNeedsUpdate(scriptFilenameBuffer)) { - bool createMap = argc > 2 ? dAtob(argv[2]) : false; FileStream *mapStream = NULL; if (createMap) { diff --git a/Engine/source/platform/platformAssert.cpp b/Engine/source/platform/platformAssert.cpp index 5fe428fad..1a4b08694 100644 --- a/Engine/source/platform/platformAssert.cpp +++ b/Engine/source/platform/platformAssert.cpp @@ -23,7 +23,7 @@ #include #include "core/strings/stringFunctions.h" -#include "console/console.h" +#include "console/engineAPI.h" //-------------------------------------- STATIC Declaration @@ -167,8 +167,8 @@ const char* avar(const char *message, ...) //----------------------------------------------------------------------------- -ConsoleFunction( Assert, void, 3, 3, "(condition, message) - Fatal Script Assertion" ) +DefineEngineFunction(Assert, void, (bool condition, const char* message),, "Fatal Script Assertion") { - // Process Assertion. - AssertISV( dAtob(argv[1]), argv[2] ); + // Process Assertion. + AssertISV(condition, message); } diff --git a/Engine/source/platformSDL/sdlInput.cpp b/Engine/source/platformSDL/sdlInput.cpp index 69ef30b20..eb9e3dd8e 100644 --- a/Engine/source/platformSDL/sdlInput.cpp +++ b/Engine/source/platformSDL/sdlInput.cpp @@ -21,7 +21,7 @@ //----------------------------------------------------------------------------- #include "platform/platformInput.h" -#include "console/console.h" +#include "console/engineAPI.h" #include "core/util/journal/process.h" #include "windowManager/platformWindowMgr.h" @@ -97,16 +97,16 @@ void Input::init() } //------------------------------------------------------------------------------ -ConsoleFunction( isJoystickDetected, bool, 1, 1, "isJoystickDetected()" ) +DefineEngineFunction(isJoystickDetected, bool, (),, "") { - return( SDL_NumJoysticks() > 0 ); + return(SDL_NumJoysticks() > 0); } //------------------------------------------------------------------------------ -ConsoleFunction( getJoystickAxes, const char*, 2, 2, "getJoystickAxes( instance )" ) +DefineEngineFunction(getJoystickAxes, const char*, (const char* instance), , "") { // TODO SDL - return( "" ); + return(""); } //------------------------------------------------------------------------------ From 0fff33869cd6cc2828c35408067200c1d9b837d4 Mon Sep 17 00:00:00 2001 From: Lukas Joergensen Date: Tue, 17 Apr 2018 22:36:32 +0200 Subject: [PATCH 09/34] Eliminate unnecessary uses of ConsoleMethod --- Engine/source/T3D/assets/MaterialAsset.cpp | 2 +- .../camera/cameraComponent_ScriptBinding.h | 3 +- Engine/source/T3D/components/component.cpp | 41 ++++--- Engine/source/T3D/entity.cpp | 31 ++--- Engine/source/T3D/gameBase/gameConnection.cpp | 22 ++-- Engine/source/T3D/player.cpp | 20 ++-- Engine/source/afx/afxCamera.cpp | 110 ++++++++---------- Engine/source/gui/core/guiCanvas.cpp | 23 ++-- .../source/gui/editor/guiInspectorTypes.cpp | 13 +-- .../gui/editor/inspector/componentGroup.cpp | 9 +- .../gui/editor/inspector/entityGroup.cpp | 8 +- .../gui/editor/inspector/mountingGroup.cpp | 8 +- .../gui/worldEditor/worldEditorSelection.cpp | 45 +++---- Engine/source/navigation/guiNavEditorCtrl.cpp | 7 +- Engine/source/util/settings.cpp | 3 +- 15 files changed, 155 insertions(+), 190 deletions(-) diff --git a/Engine/source/T3D/assets/MaterialAsset.cpp b/Engine/source/T3D/assets/MaterialAsset.cpp index 697f21e37..6cf3561a1 100644 --- a/Engine/source/T3D/assets/MaterialAsset.cpp +++ b/Engine/source/T3D/assets/MaterialAsset.cpp @@ -157,7 +157,7 @@ void MaterialAsset::copyTo(SimObject* object) Parent::copyTo(object); } -ConsoleMethod(MaterialAsset, compileShader, void, 2, 2, "() - Compiles the material's generated shader, if any. Not yet implemented\n") +DefineEngineMethod(MaterialAsset, compileShader, void, (), , "Compiles the material's generated shader, if any. Not yet implemented\n") { object->compileShader(); } diff --git a/Engine/source/T3D/components/camera/cameraComponent_ScriptBinding.h b/Engine/source/T3D/components/camera/cameraComponent_ScriptBinding.h index d3b7f9883..412d8e5b6 100644 --- a/Engine/source/T3D/components/camera/cameraComponent_ScriptBinding.h +++ b/Engine/source/T3D/components/camera/cameraComponent_ScriptBinding.h @@ -24,7 +24,8 @@ #include "T3D/components/camera/cameraComponent.h" //Basically, this only exists for backwards compatibility for parts of the editors -ConsoleMethod(CameraComponent, getMode, const char*, 2, 2, "() - We get the first behavior of the requested type on our owner object.\n" +DefineEngineMethod(CameraComponent, getMode, const char*, (),, + "@brief We get the first behavior of the requested type on our owner object.\n" "@return (string name) The type of the behavior we're requesting") { return "fly"; diff --git a/Engine/source/T3D/components/component.cpp b/Engine/source/T3D/components/component.cpp index 83fc015f1..92c9dda44 100644 --- a/Engine/source/T3D/components/component.cpp +++ b/Engine/source/T3D/components/component.cpp @@ -605,8 +605,8 @@ void Component::addDependency(StringTableEntry name) ////////////////////////////////////////////////////////////////////////// // Console Methods ////////////////////////////////////////////////////////////////////////// -ConsoleMethod(Component, beginGroup, void, 3, 3, "(groupName)\n" - "Starts the grouping for following fields being added to be grouped into\n" +DefineEngineMethod(Component, beginGroup, void, (String groupName),, + "@brief Starts the grouping for following fields being added to be grouped into\n" "@param groupName The name of this group\n" "@param desc The Description of this field\n" "@param type The DataType for this field (default, int, float, Point2F, bool, enum, Object, keybind, color)\n" @@ -616,11 +616,11 @@ ConsoleMethod(Component, beginGroup, void, 3, 3, "(groupName)\n" "-object: the T2D object type that are valid choices for the field. The object types observe inheritance, so if you have a t2dSceneObject field you will be able to choose t2dStaticSrpites, t2dAnimatedSprites, etc.\n" "@return Nothing\n") { - object->beginFieldGroup(argv[2]); + object->beginFieldGroup(groupName); } -ConsoleMethod(Component, endGroup, void, 2, 2, "()\n" - "Ends the grouping for prior fields being added to be grouped into\n" +DefineEngineMethod(Component, endGroup, void, (),, + "@brief Ends the grouping for prior fields being added to be grouped into\n" "@param groupName The name of this group\n" "@param desc The Description of this field\n" "@param type The DataType for this field (default, int, float, Point2F, bool, enum, Object, keybind, color)\n" @@ -641,7 +641,8 @@ DefineEngineMethod(Component, addComponentField, void, (String fieldName, String object->addComponentField(fieldName, fieldDesc, fieldType, defValue, userData, hidden); } -ConsoleMethod(Component, getComponentFieldCount, S32, 2, 2, "() - Get the number of ComponentField's on this object\n" +DefineEngineMethod(Component, getComponentFieldCount, S32, (),, + "@brief Get the number of ComponentField's on this object\n" "@return Returns the number of BehaviorFields as a nonnegative integer\n") { return object->getComponentFieldCount(); @@ -650,11 +651,12 @@ ConsoleMethod(Component, getComponentFieldCount, S32, 2, 2, "() - Get the number // [tom, 1/12/2007] Field accessors split into multiple methods to allow space // for long descriptions and type data. -ConsoleMethod(Component, getComponentField, const char *, 3, 3, "(int index) - Gets a Tab-Delimited list of information about a ComponentField specified by Index\n" +DefineEngineMethod(Component, getComponentField, const char *, (S32 index),, + "@brief Gets a Tab-Delimited list of information about a ComponentField specified by Index\n" "@param index The index of the behavior\n" "@return FieldName, FieldType and FieldDefaultValue, each separated by a TAB character.\n") { - ComponentField *field = object->getComponentField(dAtoi(argv[2])); + ComponentField *field = object->getComponentField(index); if (field == NULL) return ""; @@ -664,11 +666,12 @@ ConsoleMethod(Component, getComponentField, const char *, 3, 3, "(int index) - G return buf; } -ConsoleMethod(Component, setComponentield, const char *, 3, 3, "(int index) - Gets a Tab-Delimited list of information about a ComponentField specified by Index\n" +DefineEngineMethod(Component, setComponentield, const char *, (S32 index),, + "@brief Gets a Tab-Delimited list of information about a ComponentField specified by Index\n" "@param index The index of the behavior\n" "@return FieldName, FieldType and FieldDefaultValue, each separated by a TAB character.\n") { - ComponentField *field = object->getComponentField(dAtoi(argv[2])); + ComponentField *field = object->getComponentField(index); if (field == NULL) return ""; @@ -689,36 +692,40 @@ DefineEngineMethod(Component, getComponentFieldType, const char *, (String field return field->mFieldTypeName;; } -ConsoleMethod(Component, getBehaviorFieldUserData, const char *, 3, 3, "(int index) - Gets the UserData associated with a field by index in the field list\n" +DefineEngineMethod(Component, getBehaviorFieldUserData, const char *, (S32 index),, + "@brief Gets the UserData associated with a field by index in the field list\n" "@param index The index of the behavior\n" "@return Returns a string representing the user data of this field\n") { - ComponentField *field = object->getComponentField(dAtoi(argv[2])); + ComponentField *field = object->getComponentField(index); if (field == NULL) return ""; return field->mUserData; } -ConsoleMethod(Component, getComponentFieldDescription, const char *, 3, 3, "(int index) - Gets a field description by index\n" +DefineEngineMethod(Component, getComponentFieldDescription, const char *, (S32 index),, + "@brief Gets a field description by index\n" "@param index The index of the behavior\n" "@return Returns a string representing the description of this field\n") { - ComponentField *field = object->getComponentField(dAtoi(argv[2])); + ComponentField *field = object->getComponentField(index); if (field == NULL) return ""; return field->mFieldDescription ? field->mFieldDescription : ""; } -ConsoleMethod(Component, addDependency, void, 3, 3, "(string behaviorName) - Gets a field description by index\n" +DefineEngineMethod(Component, addDependency, void, (String behaviorName),, + "@brief Gets a field description by index\n" "@param index The index of the behavior\n" "@return Returns a string representing the description of this field\n") { - object->addDependency(argv[2]); + object->addDependency(behaviorName); } -ConsoleMethod(Component, setDirty, void, 2, 2, "() - Gets a field description by index\n" +DefineEngineMethod(Component, setDirty, void, (),, + "@brief Gets a field description by index\n" "@param index The index of the behavior\n" "@return Returns a string representing the description of this field\n") { diff --git a/Engine/source/T3D/entity.cpp b/Engine/source/T3D/entity.cpp index 587eb145b..c13eb61fa 100644 --- a/Engine/source/T3D/entity.cpp +++ b/Engine/source/T3D/entity.cpp @@ -1823,12 +1823,11 @@ ConsoleMethod(Entity, addComponents, void, 2, 2, "() - Add all fielded behaviors object->addComponents(); }*/ -ConsoleMethod(Entity, addComponent, bool, 3, 3, "(ComponentInstance bi) - Add a behavior to the object\n" +DefineEngineMethod(Entity, addComponent, bool, (Component* comp),, + "@brief Add a behavior to the object\n" "@param bi The behavior instance to add" "@return (bool success) Whether or not the behavior was successfully added") { - Component *comp = dynamic_cast(Sim::findObject(argv[2])); - if (comp != NULL) { bool success = object->addComponent(comp); @@ -1848,40 +1847,33 @@ ConsoleMethod(Entity, addComponent, bool, 3, 3, "(ComponentInstance bi) - Add a return false; } -ConsoleMethod(Entity, removeComponent, bool, 3, 4, "(ComponentInstance bi, [bool deleteBehavior = true])\n" +DefineEngineMethod(Entity, removeComponent, bool, (Component* comp, bool deleteComponent), (true), "@param bi The behavior instance to remove\n" "@param deleteBehavior Whether or not to delete the behavior\n" "@return (bool success) Whether the behavior was successfully removed") { - bool deleteComponent = true; - if (argc > 3) - deleteComponent = dAtob(argv[3]); - - return object->removeComponent(dynamic_cast(Sim::findObject(argv[2])), deleteComponent); + return object->removeComponent(comp, deleteComponent); } -ConsoleMethod(Entity, clearComponents, void, 2, 2, "() - Clear all behavior instances\n" +DefineEngineMethod(Entity, clearComponents, void, (),, "Clear all behavior instances\n" "@return No return value") { object->clearComponents(); } -ConsoleMethod(Entity, getComponentByIndex, S32, 3, 3, "(int index) - Gets a particular behavior\n" +DefineEngineMethod(Entity, getComponentByIndex, Component*, (S32 index),, + "@brief Gets a particular behavior\n" "@param index The index of the behavior to get\n" "@return (ComponentInstance bi) The behavior instance you requested") { - Component *comp = object->getComponent(dAtoi(argv[2])); - - return (comp != NULL) ? comp->getId() : 0; + return object->getComponent(index); } -DefineEngineMethod(Entity, getComponent, S32, (String componentName), (""), +DefineEngineMethod(Entity, getComponent, Component*, (String componentName), (""), "Get the number of static fields on the object.\n" "@return The number of static fields defined on the object.") { - Component *comp = object->getComponent(componentName); - - return (comp != NULL) ? comp->getId() : 0; + return object->getComponent(componentName); } /*ConsoleMethod(Entity, getBehaviorByType, S32, 3, 3, "(string BehaviorTemplateName) - gets a behavior\n" @@ -1910,7 +1902,8 @@ DefineEngineMethod(Entity, getComponent, S32, (String componentName), (""), return object->reOrder(inst, idx); }*/ -ConsoleMethod(Entity, getComponentCount, S32, 2, 2, "() - Get the count of behaviors on an object\n" +DefineEngineMethod(Entity, getComponentCount, S32, (),, + "@brief Get the count of behaviors on an object\n" "@return (int count) The number of behaviors on an object") { return object->getComponentCount(); diff --git a/Engine/source/T3D/gameBase/gameConnection.cpp b/Engine/source/T3D/gameBase/gameConnection.cpp index 7c5effdc5..2376e7180 100644 --- a/Engine/source/T3D/gameBase/gameConnection.cpp +++ b/Engine/source/T3D/gameBase/gameConnection.cpp @@ -2451,41 +2451,37 @@ DefineEngineMethod( GameConnection, getVisibleGhostDistance, F32, (),, // Object Selection in Torque by Dave Myers // http://www.garagegames.com/index.php?sec=mg&mod=resource&page=view&qid=7335 -ConsoleMethod(GameConnection, setSelectedObj, bool, 3, 4, "(object, [propagate_to_client])") +DefineEngineMethod(GameConnection, setSelectedObj, bool, (SceneObject* obj, bool propagate_to_client), (false), "") { - SceneObject* pending_selection; - if (!Sim::findObject(argv[2], pending_selection)) + if (!obj) return false; - bool propagate_to_client = (argc > 3) ? dAtob(argv[3]) : false; - object->setSelectedObj(pending_selection, propagate_to_client); + object->setSelectedObj(obj, propagate_to_client); return true; } -ConsoleMethod(GameConnection, getSelectedObj, S32, 2, 2, "()") +DefineEngineMethod(GameConnection, getSelectedObj, SimObject*, (),, "") { - SimObject* selected = object->getSelectedObj(); - return (selected) ? selected->getId(): -1; + return object->getSelectedObj(); } -ConsoleMethod(GameConnection, clearSelectedObj, void, 2, 3, "([propagate_to_client])") +DefineEngineMethod(GameConnection, clearSelectedObj, void, (bool propagate_to_client), (false), "") { - bool propagate_to_client = (argc > 2) ? dAtob(argv[2]) : false; object->setSelectedObj(NULL, propagate_to_client); } -ConsoleMethod(GameConnection, setPreSelectedObjFromRollover, void, 2, 2, "()") +DefineEngineMethod(GameConnection, setPreSelectedObjFromRollover, void, (),, "") { object->setPreSelectedObjFromRollover(); } -ConsoleMethod(GameConnection, clearPreSelectedObj, void, 2, 2, "()") +DefineEngineMethod(GameConnection, clearPreSelectedObj, void, (),, "") { object->clearPreSelectedObj(); } -ConsoleMethod(GameConnection, setSelectedObjFromPreSelected, void, 2, 2, "()") +DefineEngineMethod(GameConnection, setSelectedObjFromPreSelected, void, (),, "") { object->setSelectedObjFromPreSelected(); } diff --git a/Engine/source/T3D/player.cpp b/Engine/source/T3D/player.cpp index 15b57046a..fa43394ca 100644 --- a/Engine/source/T3D/player.cpp +++ b/Engine/source/T3D/player.cpp @@ -7517,7 +7517,7 @@ U32 Player::lockAnimation() return last_anim_lock_tag; } -ConsoleMethod(Player, isAnimationLocked, bool, 2, 2, "isAnimationLocked()") +DefineEngineMethod(Player, isAnimationLocked, bool, (),, "") { return object->isAnimationLocked(); } @@ -7533,14 +7533,13 @@ void Player::setLookAnimationOverride(bool flag) #endif } -ConsoleMethod(Player, setLookAnimationOverride, void, 3, 3, "setLookAnimationOverride(flag)") +DefineEngineMethod(Player, setLookAnimationOverride, void, (bool flag),, "") { - object->setLookAnimationOverride(dAtob(argv[2])); + object->setLookAnimationOverride(flag); } -ConsoleMethod(Player, copyHeadRotation, void, 3, 3, "copyHeadRotation(other_player)") +DefineEngineMethod(Player, copyHeadRotation, void, (Player* other_player),, "") { - Player* other_player = dynamic_cast(Sim::findObject(argv[2])); if (other_player) object->copyHeadRotation(other_player); } @@ -7609,9 +7608,9 @@ void Player::restoreMovement(U32 tag) } } -ConsoleMethod(Player, setMovementSpeedBias, void, 3, 3, "setMovementSpeedBias(F32 bias)") +DefineEngineMethod(Player, setMovementSpeedBias, void, (F32 bias),, "setMovementSpeedBias(F32 bias)") { - object->setMovementSpeedBias(dAtof(argv[2])); + object->setMovementSpeedBias(bias); } void Player::overrideFootfallFX(bool decals, bool sounds, bool dust) @@ -7642,12 +7641,11 @@ void Player::setControllers(Vector controllerList) mControllers[1] = controllerList.size() > 1 ? controllerList[1] : NULL; } -ConsoleMethod(Player, setVRControllers, void, 4, 4, "") +DefineEngineMethod(Player, setVRControllers, void, (OpenVRTrackedObject* controllerL, OpenVRTrackedObject* controllerR,, "") { - OpenVRTrackedObject *controllerL, *controllerR; Vector list; - if (Sim::findObject(argv[2], controllerL)) + if (controllerL) { list.push_back(controllerL); } @@ -7656,7 +7654,7 @@ ConsoleMethod(Player, setVRControllers, void, 4, 4, "") list.push_back(NULL); } - if (Sim::findObject(argv[3], controllerR)) + if (controllerR) { list.push_back(controllerR); } diff --git a/Engine/source/afx/afxCamera.cpp b/Engine/source/afx/afxCamera.cpp index 63ad635ac..1aad5f455 100644 --- a/Engine/source/afx/afxCamera.cpp +++ b/Engine/source/afx/afxCamera.cpp @@ -483,105 +483,91 @@ ConsoleMethod(afxCamera, setOrbitMode, void, 7, 8, object->setOrbitMode(orbitObject, pos, aa, minDis, maxDis, curDis, (argc == 8) ? dAtob(argv[7]) : false); } -ConsoleMethod( afxCamera, setFlyMode, void, 2, 2, "()" "Set the camera to be able to fly freely.") +DefineEngineMethod(afxCamera, setFlyMode, void, (),, + "@brief Set the camera to be able to fly freely.") { - object->setFlyMode(); + object->setFlyMode(); } -ConsoleMethod( afxCamera, getPosition, const char *, 2, 2, "()" - "Get the position of the camera.\n\n" - "@returns A string of form \"x y z\".") -{ - Point3F& pos = object->getPosition(); - dSprintf(buffer, sizeof(buffer),"%f %f %f",pos.x,pos.y,pos.z); - return buffer; +DefineEngineMethod(afxCamera, getPosition, Point3F, (),, + "@brief Get the position of the camera.\n\n" + "@returns The position of the camera.") +{ + return object->getPosition(); } -ConsoleMethod(afxCamera, setCameraSubject, bool, 3, 3, "") -{ - SceneObject* subject; - if (!Sim::findObject(argv[2], subject)) - { - Con::errorf("Camera subject \"%s\" not found.", argv[2].getStringValue()); - return false; - } - - object->setCameraSubject(subject); - - return true; +DefineEngineMethod(afxCamera, setCameraSubject, bool, (SceneObject* subject),, "") +{ + if (!subject) + { + Con::errorf("Camera subject not found."); + return false; + } + + object->setCameraSubject(subject); + + return true; } -ConsoleMethod(afxCamera, setThirdPersonDistance, bool, 3, 3, "") -{ - F32 distance; - dSscanf(argv[2], "%f", &distance); +DefineEngineMethod(afxCamera, setThirdPersonDistance, bool, (F32 distance),, "") +{ + object->setThirdPersonDistance(distance); - object->setThirdPersonDistance(distance); - - return true; + return true; } -ConsoleMethod(afxCamera, getThirdPersonDistance, F32, 2, 2, "") +DefineEngineMethod(afxCamera, getThirdPersonDistance, F32, (),, "") { return object->getThirdPersonDistance(); } -ConsoleMethod(afxCamera, setThirdPersonAngle, bool, 3, 3, "") -{ - F32 angle; - dSscanf(argv[2], "%f", &angle); +DefineEngineMethod(afxCamera, setThirdPersonAngle, bool, (F32 distance),, "") +{ + object->setThirdPersonAngle(distance); - object->setThirdPersonAngle(angle); - - return true; + return true; } -ConsoleMethod(afxCamera, getThirdPersonAngle, F32, 2, 2, "") +DefineEngineMethod(afxCamera, getThirdPersonAngle, F32, (),, "") { return object->getThirdPersonAngle(); } -ConsoleMethod(afxCamera, setThirdPersonOffset, void, 3, 4, "(Point3F offset [, Point3F coi_offset])") +DefineEngineMethod(afxCamera, setThirdPersonOffset, void, (Point3F offset, Point3F coi_offset), (Point3F::Max), "") { - Point3F offset; - dSscanf(argv[2], "%f %f %f", &offset.x, &offset.y, &offset.z); - if (argc > 3) - { - Point3F coi_offset; - dSscanf(argv[3], "%f %f %f", &coi_offset.x, &coi_offset.y, &coi_offset.z); - object->setThirdPersonOffset(offset, coi_offset); - } - else - object->setThirdPersonOffset(offset); + if (coi_offset == Point3F::Max) + { + object->setThirdPersonOffset(offset); + } + else + { + object->setThirdPersonOffset(offset, coi_offset); + } } -ConsoleMethod(afxCamera, getThirdPersonOffset, const char *, 2, 2, "()") +DefineEngineMethod(afxCamera, getThirdPersonOffset, Point3F, (),, "") { - const Point3F& pos = object->getThirdPersonOffset(); - dSprintf(buffer, sizeof(buffer),"%f %f %f",pos.x,pos.y,pos.z); - return buffer; + return object->getThirdPersonOffset(); } -ConsoleMethod(afxCamera, getThirdPersonCOIOffset, const char *, 2, 2, "()") +DefineEngineMethod(afxCamera, getThirdPersonCOIOffset, Point3F, (),, "") { - const Point3F& pos = object->getThirdPersonCOIOffset(); - dSprintf(buffer, sizeof(buffer),"%f %f %f",pos.x,pos.y,pos.z); - return buffer; + return object->getThirdPersonCOIOffset(); } -ConsoleMethod(afxCamera, setThirdPersonMode, void, 2, 2, "()") +DefineEngineMethod(afxCamera, setThirdPersonMode, void, (),, "") { - object->setThirdPersonMode(); + object->setThirdPersonMode(); } -ConsoleMethod(afxCamera, setThirdPersonSnap, void, 2, 2, "()") +DefineEngineMethod(afxCamera, setThirdPersonSnap, void, (),, "") { - object->setThirdPersonSnap(); + object->setThirdPersonSnap(); } -ConsoleMethod(afxCamera, getMode, const char *, 2, 2, "()") +DefineEngineMethod(afxCamera, getMode, const char*, (),, "") { - return object->getMode(); + return object->getMode(); } //~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~// diff --git a/Engine/source/gui/core/guiCanvas.cpp b/Engine/source/gui/core/guiCanvas.cpp index 885d157a0..5b5ca637b 100644 --- a/Engine/source/gui/core/guiCanvas.cpp +++ b/Engine/source/gui/core/guiCanvas.cpp @@ -2812,7 +2812,7 @@ DefineEngineMethod( GuiCanvas, setVideoMode, void, Con::setVariable( "$pref::Video::mode", vm.toString() ); } -ConsoleMethod( GuiCanvas, showWindow, void, 2, 2, "" ) +DefineEngineMethod(GuiCanvas, showWindow, void, (),, "") { if (!object->getPlatformWindow()) return; @@ -2822,7 +2822,7 @@ ConsoleMethod( GuiCanvas, showWindow, void, 2, 2, "" ) object->getPlatformWindow()->setDisplayWindow(true); } -ConsoleMethod( GuiCanvas, hideWindow, void, 2, 2, "" ) +DefineEngineMethod(GuiCanvas, hideWindow, void, (),, "") { if (!object->getPlatformWindow()) return; @@ -2832,30 +2832,29 @@ ConsoleMethod( GuiCanvas, hideWindow, void, 2, 2, "" ) object->getPlatformWindow()->setDisplayWindow(false); } -ConsoleMethod( GuiCanvas, cursorClick, void, 4, 4, "button, isDown" ) +DefineEngineMethod(GuiCanvas, cursorClick, void, (S32 buttonId, bool isDown), , "") { - const S32 buttonId = dAtoi(argv[2]); - const bool isDown = dAtob(argv[3]); - object->cursorClick(buttonId, isDown); } -ConsoleMethod( GuiCanvas, cursorNudge, void, 4, 4, "x, y" ) +DefineEngineMethod(GuiCanvas, cursorNudge, void, (F32 x, F32 y), , "") { - object->cursorNudge(dAtof(argv[2]), dAtof(argv[3])); + object->cursorNudge(x, y); } + // This function allows resetting of the video-mode from script. It was motivated by // the need to temporarily disable vsync during datablock cache load to avoid a // significant slowdown. bool AFX_forceVideoReset = false; -ConsoleMethod( GuiCanvas, resetVideoMode, void, 2,2, "()") + +DefineEngineMethod(GuiCanvas, resetVideoMode, void, (), , "") { PlatformWindow* window = object->getPlatformWindow(); - if( window ) + if (window) { - GFXWindowTarget* gfx_target = window->getGFXTarget(); - if ( gfx_target ) + GFXWindowTarget* gfx_target = window->getGFXTarget(); + if (gfx_target) { AFX_forceVideoReset = true; gfx_target->resetMode(); diff --git a/Engine/source/gui/editor/guiInspectorTypes.cpp b/Engine/source/gui/editor/guiInspectorTypes.cpp index f31d4facd..4c07f4959 100644 --- a/Engine/source/gui/editor/guiInspectorTypes.cpp +++ b/Engine/source/gui/editor/guiInspectorTypes.cpp @@ -601,13 +601,12 @@ void GuiInspectorTypeFileName::updateValue() } } -ConsoleMethod( GuiInspectorTypeFileName, apply, void, 3,3, "apply(newValue);" ) +DefineEngineMethod(GuiInspectorTypeFileName, apply, void, (String path), , "") { - String path( (const char*)argv[2] ); - if ( path.isNotEmpty() ) - path = Platform::makeRelativePathName( path, Platform::getMainDotCsDir() ); - - object->setData( path.c_str() ); + if (path.isNotEmpty()) + path = Platform::makeRelativePathName(path, Platform::getMainDotCsDir()); + + object->setData(path.c_str()); } @@ -1502,7 +1501,7 @@ void GuiInspectorTypeBitMask32::updateData() setData( data ); } -ConsoleMethod( GuiInspectorTypeBitMask32, applyBit, void, 2,2, "apply();" ) +DefineEngineMethod( GuiInspectorTypeBitMask32, applyBit, void, (),, "" ) { object->updateData(); } diff --git a/Engine/source/gui/editor/inspector/componentGroup.cpp b/Engine/source/gui/editor/inspector/componentGroup.cpp index 27aec03fa..e81eec63d 100644 --- a/Engine/source/gui/editor/inspector/componentGroup.cpp +++ b/Engine/source/gui/editor/inspector/componentGroup.cpp @@ -469,7 +469,7 @@ void GuiInspectorComponentGroup::onRightMouseUp(const GuiEvent &event) Con::executef(this, "onRightMouseUp", event.mousePoint); } -ConsoleMethod(GuiInspectorComponentGroup, inspectGroup, bool, 2, 2, "Refreshes the dynamic fields in the inspector.") +DefineEngineMethod(GuiInspectorComponentGroup, inspectGroup, bool, (),, "Refreshes the dynamic fields in the inspector.") { return object->inspectGroup(); } @@ -515,16 +515,17 @@ AbstractClassRep::Field* GuiInspectorComponentGroup::findObjectBehaviorField(Com } return NULL; } -ConsoleMethod(GuiInspectorComponentGroup, addDynamicField, void, 2, 2, "obj.addDynamicField();") + +DefineEngineMethod(GuiInspectorComponentGroup, addDynamicField, void, (), , "obj.addDynamicField();") { object->addDynamicField(); } -ConsoleMethod(GuiInspectorComponentGroup, removeDynamicField, void, 3, 3, "") +DefineEngineMethod(GuiInspectorComponentGroup, removeDynamicField, void, (), , "") { } -DefineEngineMethod(GuiInspectorComponentGroup, getComponent, S32, (), ,"") +DefineEngineMethod(GuiInspectorComponentGroup, getComponent, S32, (), , "") { return object->getComponent()->getId(); } diff --git a/Engine/source/gui/editor/inspector/entityGroup.cpp b/Engine/source/gui/editor/inspector/entityGroup.cpp index 7b7559833..de4897165 100644 --- a/Engine/source/gui/editor/inspector/entityGroup.cpp +++ b/Engine/source/gui/editor/inspector/entityGroup.cpp @@ -87,7 +87,8 @@ void GuiInspectorEntityGroup::onMouseMove(const GuiEvent &event) { //mParent->mOverDivider = false; } -ConsoleMethod(GuiInspectorEntityGroup, inspectGroup, bool, 2, 2, "Refreshes the dynamic fields in the inspector.") + +DefineEngineMethod(GuiInspectorEntityGroup, inspectGroup, bool, (),, "Refreshes the dynamic fields in the inspector.") { return object->inspectGroup(); } @@ -128,11 +129,12 @@ AbstractClassRep::Field* GuiInspectorEntityGroup::findObjectBehaviorField(Compon } return NULL; } -ConsoleMethod(GuiInspectorEntityGroup, addDynamicField, void, 2, 2, "obj.addDynamicField();") + +DefineEngineMethod(GuiInspectorEntityGroup, addDynamicField, void, (), , "obj.addDynamicField();") { object->addDynamicField(); } -ConsoleMethod(GuiInspectorEntityGroup, removeDynamicField, void, 3, 3, "") +DefineEngineMethod(GuiInspectorEntityGroup, removeDynamicField, void, (), , "") { } diff --git a/Engine/source/gui/editor/inspector/mountingGroup.cpp b/Engine/source/gui/editor/inspector/mountingGroup.cpp index 7afa53105..759139658 100644 --- a/Engine/source/gui/editor/inspector/mountingGroup.cpp +++ b/Engine/source/gui/editor/inspector/mountingGroup.cpp @@ -242,7 +242,8 @@ void GuiInspectorMountingGroup::onMouseMove(const GuiEvent &event) //mParent->mOverDivider = false; bool test = false; } -ConsoleMethod(GuiInspectorMountingGroup, inspectGroup, bool, 2, 2, "Refreshes the dynamic fields in the inspector.") + +DefineEngineMethod(GuiInspectorMountingGroup, inspectGroup, bool, (),, "Refreshes the dynamic fields in the inspector.") { return object->inspectGroup(); } @@ -319,12 +320,13 @@ AbstractClassRep::Field* GuiInspectorMountingGroup::findObjectComponentField(Com } return NULL; } -ConsoleMethod( GuiInspectorMountingGroup, addDynamicField, void, 2, 2, "obj.addDynamicField();" ) + +DefineEngineMethod(GuiInspectorMountingGroup, addDynamicField, void, (), , "obj.addDynamicField();") { object->addDynamicField(); } -ConsoleMethod( GuiInspectorMountingGroup, removeDynamicField, void, 3, 3, "" ) +DefineEngineMethod(GuiInspectorMountingGroup, removeDynamicField, void, (), , "") { } diff --git a/Engine/source/gui/worldEditor/worldEditorSelection.cpp b/Engine/source/gui/worldEditor/worldEditorSelection.cpp index 00311adea..472ac46ef 100644 --- a/Engine/source/gui/worldEditor/worldEditorSelection.cpp +++ b/Engine/source/gui/worldEditor/worldEditorSelection.cpp @@ -657,58 +657,42 @@ void WorldEditorSelection::setSize(const VectorF & newsize) //----------------------------------------------------------------------------- -ConsoleMethod( WorldEditorSelection, containsGlobalBounds, bool, 2, 2, "() - True if an object with global bounds is contained in the selection." ) +DefineEngineMethod( WorldEditorSelection, containsGlobalBounds, bool, (),, "True if an object with global bounds is contained in the selection." ) { return object->containsGlobalBounds(); } //----------------------------------------------------------------------------- -ConsoleMethod( WorldEditorSelection, getCentroid, const char*, 2, 2, "() - Return the median of all object positions in the selection." ) +DefineEngineMethod( WorldEditorSelection, getCentroid, Point3F, (),, "Return the median of all object positions in the selection." ) { - static const U32 bufSize = 256; - char* buffer = Con::getReturnBuffer( bufSize ); const Point3F& centroid = object->getCentroid(); - - dSprintf( buffer, bufSize, "%g %g %g", centroid.x, centroid.y, centroid.z ); - return buffer; + return centroid; } //----------------------------------------------------------------------------- -ConsoleMethod( WorldEditorSelection, getBoxCentroid, const char*, 2, 2, "() - Return the center of the bounding box around the selection." ) +DefineEngineMethod( WorldEditorSelection, getBoxCentroid, Point3F, (),, "Return the center of the bounding box around the selection." ) { - static const U32 bufSize = 256; - char* buffer = Con::getReturnBuffer( bufSize ); const Point3F& boxCentroid = object->getBoxCentroid(); - - dSprintf( buffer, bufSize, "%g %g %g", boxCentroid.x, boxCentroid.y, boxCentroid.z ); - return buffer; + return boxCentroid; } //----------------------------------------------------------------------------- -ConsoleMethod( WorldEditorSelection, offset, void, 3, 4, "( vector delta, float gridSnap=0 ) - Move all objects in the selection by the given delta." ) -{ - F32 x, y, z; - dSscanf( argv[ 3 ], "%g %g %g", &x, &y, &z ); - - F32 gridSnap = 0.f; - if( argc > 3 ) - gridSnap = dAtof( argv[ 3 ] ); - - object->offset( Point3F( x, y, z ), gridSnap ); +DefineEngineMethod(WorldEditorSelection, offset, void, (Point3F delta, F32 gridSnap), (0.0f), "Move all objects in the selection by the given delta.") +{ + object->offset( delta, gridSnap ); WorldEditor::updateClientTransforms( object ); } //----------------------------------------------------------------------------- -ConsoleMethod( WorldEditorSelection, union, void, 3, 3, "( SimSet set ) - Add all objects in the given set to this selection." ) +DefineEngineMethod( WorldEditorSelection, union, void, (SimSet* selection),, "Add all objects in the given set to this selection." ) { - SimSet* selection; - if( !Sim::findObject( argv[ 2 ], selection ) ) + if( !selection) { - Con::errorf( "WorldEditorSelection::union - no SimSet '%s'", (const char*)argv[ 2 ] ); + Con::errorf( "WorldEditorSelection::union - no SimSet"); return; } @@ -719,12 +703,11 @@ ConsoleMethod( WorldEditorSelection, union, void, 3, 3, "( SimSet set ) - Add al //----------------------------------------------------------------------------- -ConsoleMethod( WorldEditorSelection, subtract, void, 3, 3, "( SimSet ) - Remove all objects in the given set from this selection." ) +DefineEngineMethod( WorldEditorSelection, subtract, void, (SimSet* selection),, "Remove all objects in the given set from this selection." ) { - SimSet* selection; - if( !Sim::findObject( argv[ 2 ], selection ) ) + if( !selection ) { - Con::errorf( "WorldEditorSelection::subtract - no SimSet '%s'", (const char*)argv[ 2 ] ); + Con::errorf( "WorldEditorSelection::subtract - no SimSet" ); return; } diff --git a/Engine/source/navigation/guiNavEditorCtrl.cpp b/Engine/source/navigation/guiNavEditorCtrl.cpp index bc605c054..7ef0fb87e 100644 --- a/Engine/source/navigation/guiNavEditorCtrl.cpp +++ b/Engine/source/navigation/guiNavEditorCtrl.cpp @@ -627,13 +627,12 @@ void GuiNavEditorCtrl::_prepRenderImage(SceneManager* sceneGraph, const SceneRen }*/ } -ConsoleMethod(GuiNavEditorCtrl, getMode, const char*, 2, 2, "") +DefineEngineMethod(GuiNavEditorCtrl, getMode, const char*, (), , "") { return object->getMode(); } -ConsoleMethod(GuiNavEditorCtrl, setMode, void, 3, 3, "setMode(String mode)") +DefineEngineMethod(GuiNavEditorCtrl, setMode, void, (String mode),, "setMode(String mode)") { - String newMode = (argv[2]); - object->setMode(newMode); + object->setMode(mode); } diff --git a/Engine/source/util/settings.cpp b/Engine/source/util/settings.cpp index 60f58966e..96fd2d5c8 100644 --- a/Engine/source/util/settings.cpp +++ b/Engine/source/util/settings.cpp @@ -681,9 +681,8 @@ DefineEngineMethod(Settings, remove, void, (const char * settingName, bool inclu object->remove( settingName, includeDefaults ); } -ConsoleMethod(Settings, write, bool, 2, 2, "%success = settingObj.write();") +DefineEngineMethod(Settings, write, bool, (),, "%success = settingObj.write();") { - TORQUE_UNUSED(argc); TORQUE_UNUSED(argv); return object->write(); } From 6b524ae58a678a3610de036eaa5004d90687acf9 Mon Sep 17 00:00:00 2001 From: Lukas Joergensen Date: Wed, 18 Apr 2018 14:19:07 +0200 Subject: [PATCH 10/34] Eliminate ConsoleStaticMethod --- Engine/source/console/console.h | 18 --------- .../gui/worldEditor/editorIconRegistry.cpp | 35 +++++++--------- .../gui/worldEditor/editorIconRegistry.h | 3 ++ Engine/source/postFx/postEffectVis.cpp | 25 ++++++------ Engine/source/postFx/postEffectVis.h | 5 +++ Engine/source/terrain/terrImport.cpp | 40 ++++++------------- 6 files changed, 47 insertions(+), 79 deletions(-) diff --git a/Engine/source/console/console.h b/Engine/source/console/console.h index a734cefbf..358b738f9 100644 --- a/Engine/source/console/console.h +++ b/Engine/source/console/console.h @@ -1220,15 +1220,6 @@ public: ConsoleConstructor cc_##className##_##name##_obj(#className,#name,cm_##className##_##name##_caster,usage1,minArgs,maxArgs); \ inline returnType cm_##className##_##name(className *object, S32 argc, ConsoleValueRef *argv) -# define ConsoleStaticMethod(className,name,returnType,minArgs,maxArgs,usage1) \ - inline returnType cm_##className##_##name(S32, ConsoleValueRef *); \ - returnType cm_##className##_##name##_caster(SimObject *object, S32 argc, ConsoleValueRef *argv) { \ - conmethod_return_##returnType ) cm_##className##_##name(argc,argv); \ - }; \ - ConsoleConstructor \ - cc_##className##_##name##_obj(#className,#name,cm_##className##_##name##_caster,usage1,minArgs,maxArgs); \ - inline returnType cm_##className##_##name(S32 argc, ConsoleValueRef *argv) - # define ConsoleMethodGroupEnd(className, groupName) \ static ConsoleConstructor cc_##className##_##groupName##_GroupEnd(#className,#groupName,NULL) @@ -1268,15 +1259,6 @@ public: className##name##obj(#className,#name,c##className##name##caster,"",minArgs,maxArgs); \ static inline returnType c##className##name(className *object, S32 argc, ConsoleValueRef *argv) -# define ConsoleStaticMethod(className,name,returnType,minArgs,maxArgs,usage1) \ - static inline returnType c##className##name(S32, ConsoleValueRef*); \ - static returnType c##className##name##caster(SimObject *object, S32 argc, ConsoleValueRef *argv) { \ - conmethod_return_##returnType ) c##className##name(argc,argv); \ - }; \ - static ConsoleConstructor \ - className##name##obj(#className,#name,c##className##name##caster,"",minArgs,maxArgs); \ - static inline returnType c##className##name(S32 argc, ConsoleValueRef *argv) - #define ConsoleDoc( text ) #endif diff --git a/Engine/source/gui/worldEditor/editorIconRegistry.cpp b/Engine/source/gui/worldEditor/editorIconRegistry.cpp index 8507d2ad2..b75a28335 100644 --- a/Engine/source/gui/worldEditor/editorIconRegistry.cpp +++ b/Engine/source/gui/worldEditor/editorIconRegistry.cpp @@ -23,7 +23,7 @@ #include "platform/platform.h" #include "gui/worldEditor/editorIconRegistry.h" -#include "console/console.h" +#include "console/engineAPI.h" #include "console/simBase.h" @@ -36,6 +36,8 @@ ConsoleDoc( "@internal" ); +IMPLEMENT_STATIC_CLASS(EditorIconRegistry,, ""); + EditorIconRegistry::EditorIconRegistry() { } @@ -168,51 +170,42 @@ void EditorIconRegistry::clear() mDefaultIcon.free(); } -ConsoleStaticMethod( EditorIconRegistry, add, void, 3, 4, "( String className, String imageFile [, bool overwrite = true] )" +DefineEngineStaticMethod( EditorIconRegistry, add, void, (String className, String imageFile, bool overwrite), (true), "@internal") { - bool overwrite = true; - if ( argc > 3 ) - overwrite = dAtob( argv[3] ); - - gEditorIcons.add( argv[1], argv[2], overwrite ); + gEditorIcons.add( className, imageFile, overwrite ); } -ConsoleStaticMethod( EditorIconRegistry, loadFromPath, void, 2, 3, "( String imagePath [, bool overwrite = true] )" +DefineEngineStaticMethod( EditorIconRegistry, loadFromPath, void, (String imagePath, bool overwrite), (true), "@internal") { - bool overwrite = true; - if ( argc > 2 ) - overwrite = dAtob( argv[2] ); - - gEditorIcons.loadFromPath( argv[1], overwrite ); + gEditorIcons.loadFromPath( imagePath, overwrite ); } -ConsoleStaticMethod( EditorIconRegistry, clear, void, 1, 1, "" +DefineEngineStaticMethod( EditorIconRegistry, clear, void, (),, "@internal") { gEditorIcons.clear(); } -ConsoleStaticMethod( EditorIconRegistry, findIconByClassName, const char*, 2, 2, "( String className )\n" - "Returns the file path to the icon file if found." +DefineEngineStaticMethod( EditorIconRegistry, findIconByClassName, const char*, (String className),, + "@brief Returns the file path to the icon file if found." "@internal") { - GFXTexHandle icon = gEditorIcons.findIcon( argv[1] ); + GFXTexHandle icon = gEditorIcons.findIcon( className ); if ( icon.isNull() ) return NULL; return icon->mPath; } -ConsoleStaticMethod( EditorIconRegistry, findIconBySimObject, const char*, 2, 2, "( SimObject )\n" +DefineEngineStaticMethod( EditorIconRegistry, findIconBySimObject, const char*, (SimObject* obj),, "Returns the file path to the icon file if found." "@internal") { - SimObject *obj = NULL; - if ( !Sim::findObject( argv[1], obj ) ) + if ( !obj ) { - Con::warnf( "EditorIconRegistry::findIcon, parameter %d was not a SimObject!", (const char*)argv[1] ); + Con::warnf( "EditorIconRegistry::findIcon, parameter was not a SimObject!"); return NULL; } diff --git a/Engine/source/gui/worldEditor/editorIconRegistry.h b/Engine/source/gui/worldEditor/editorIconRegistry.h index 35580d74c..a058b7ae7 100644 --- a/Engine/source/gui/worldEditor/editorIconRegistry.h +++ b/Engine/source/gui/worldEditor/editorIconRegistry.h @@ -30,6 +30,8 @@ #include "core/util/tDictionary.h" #endif +#include "console/engineAPI.h" + class SimObject; class AbstractClassRep; @@ -40,6 +42,7 @@ class AbstractClassRep; class EditorIconRegistry { public: + DECLARE_STATIC_CLASS(EditorIconRegistry); EditorIconRegistry(); ~EditorIconRegistry(); diff --git a/Engine/source/postFx/postEffectVis.cpp b/Engine/source/postFx/postEffectVis.cpp index bf507e162..b00ee55ae 100644 --- a/Engine/source/postFx/postEffectVis.cpp +++ b/Engine/source/postFx/postEffectVis.cpp @@ -41,6 +41,8 @@ ConsoleDoc( "@ingroup GFX\n" ); +IMPLEMENT_STATIC_CLASS(PfxVis, , "") + MODULE_BEGIN( PostEffectVis ) MODULE_INIT @@ -374,7 +376,8 @@ static ConsoleDocFragment _PfxVisclear( "PfxVis", "void clear();" ); -ConsoleStaticMethod( PfxVis, clear, void, 1, 1, "()" + +DefineEngineStaticMethod( PfxVis, clear, void, (),, "@hide") { PFXVIS->clear(); @@ -391,16 +394,15 @@ static ConsoleDocFragment _PfxVisopen( "PfxVis", "void open(PostEffect effect, bool clear);" ); -ConsoleStaticMethod( PfxVis, open, void, 2, 3, "( PostEffect, [bool clear = false] )" +DefineEngineStaticMethod( PfxVis, open, void, (PostEffect* pfx, bool clear), (false), "( PostEffect, [bool clear = false] )" "@hide") { - if ( argc == 3 && dAtob( argv[2] ) ) + if ( clear ) PFXVIS->clear(); - PostEffect *pfx; - if ( !Sim::findObject( argv[1], pfx ) ) + if ( !pfx ) { - Con::errorf( "PfxVis::add, argument %s was not a PostEffect", (const char*)argv[1] ); + Con::errorf( "PfxVis::add, argument was not a PostEffect"); return; } @@ -415,7 +417,7 @@ static ConsoleDocFragment _PfxVishide( "PfxVis", "void hide();" ); -ConsoleStaticMethod( PfxVis, hide, void, 1, 1, "()" +DefineEngineStaticMethod( PfxVis, hide, void, (),, "@hide") { PFXVIS->setVisible( false ); @@ -429,7 +431,7 @@ static ConsoleDocFragment _PfxVisshow( "PfxVis", "void show();" ); -ConsoleStaticMethod( PfxVis, show, void, 1, 1, "()" +DefineEngineStaticMethod( PfxVis, show, void, (),, "@hide") { PFXVIS->setVisible( true ); @@ -444,13 +446,12 @@ static ConsoleDocFragment _PfxVisonWindowClosed( "PfxVis", "void onWindowClosed(GuiWindowCtrl *ctrl);" ); -ConsoleStaticMethod( PfxVis, onWindowClosed, void, 2, 2, "( GuiWindowCtrl )" +DefineEngineStaticMethod( PfxVis, onWindowClosed, void, (GuiWindowCtrl* ctrl),, "@hide") { - GuiWindowCtrl *ctrl; - if ( !Sim::findObject( argv[1], ctrl ) ) + if ( !ctrl ) { - Con::errorf( "PfxVis::onWindowClosed, argument %s was not a GuiWindowCtrl", (const char*)argv[1] ); + Con::errorf( "PfxVis::onWindowClosed, argument was not a GuiWindowCtrl"); return; } diff --git a/Engine/source/postFx/postEffectVis.h b/Engine/source/postFx/postEffectVis.h index 972a7ea78..0ef807a58 100644 --- a/Engine/source/postFx/postEffectVis.h +++ b/Engine/source/postFx/postEffectVis.h @@ -104,6 +104,11 @@ public: static const char* getSingletonName() { return "PostEffectVis"; } }; +class PfxVis +{ + DECLARE_STATIC_CLASS(PfxVis) +}; + /// Returns the PostEffectVis singleton. #define PFXVIS ManagedSingleton::instance() diff --git a/Engine/source/terrain/terrImport.cpp b/Engine/source/terrain/terrImport.cpp index ad9a8d98b..063a80c93 100644 --- a/Engine/source/terrain/terrImport.cpp +++ b/Engine/source/terrain/terrImport.cpp @@ -33,15 +33,9 @@ using namespace Torque; -ConsoleStaticMethod( TerrainBlock, createNew, S32, 5, 5, - "TerrainBlock.create( String terrainName, U32 resolution, String materialName, bool genNoise )\n" +DefineEngineStaticMethod( TerrainBlock, createNew, S32, (String terrainName, U32 resolution, String materialName, bool genNoise),, "" ) { - const UTF8 *terrainName = argv[1]; - U32 resolution = dAtoi( argv[2] ); - const UTF8 *materialName = argv[3]; - bool genNoise = dAtob( argv[4] ); - Vector materials; materials.push_back( materialName ); @@ -82,17 +76,17 @@ ConsoleStaticMethod( TerrainBlock, createNew, S32, 5, 5, noise.setSeed( 134208587 ); // Set up some defaults. - F32 octaves = 3.0f; - U32 freq = 4; - F32 roughness = 0.0f; + const F32 octaves = 3.0f; + const U32 freq = 4; + const F32 roughness = 0.0f; noise.fBm( &floatHeights, blockSize, freq, 1.0f - roughness, octaves ); F32 height = 0; F32 omax, omin; noise.getMinMax( &floatHeights, &omin, &omax, blockSize ); - - F32 terrscale = 300.0f / (omax - omin); + + const F32 terrscale = 300.0f / (omax - omin); for ( S32 y = 0; y < blockSize; y++ ) { for ( S32 x = 0; x < blockSize; x++ ) @@ -111,7 +105,7 @@ ConsoleStaticMethod( TerrainBlock, createNew, S32, 5, 5, terrain->updateGridMaterials( Point2I::Zero, Point2I( blockSize, blockSize ) ); } - terrain->registerObject( terrainName ); + terrain->registerObject( terrainName.c_str() ); // Add to mission group! SimGroup *missionGroup; @@ -121,21 +115,11 @@ ConsoleStaticMethod( TerrainBlock, createNew, S32, 5, 5, return terrain->getId(); } -ConsoleStaticMethod( TerrainBlock, import, S32, 7, 8, - "( String terrainName, String heightMap, F32 metersPerPixel, F32 heightScale, String materials, String opacityLayers[, bool flipYAxis=true] )\n" +DefineEngineStaticMethod( TerrainBlock, import, S32, (String terrainName, String heightMapFile, F32 metersPerPixel, F32 heightScale, String opacityLayerFiles, String materialsStr, bool flipYAxis), (true), "" ) { - // Get the parameters. - const UTF8 *terrainName = argv[1]; - const UTF8 *hmap = argv[2]; - F32 metersPerPixel = dAtof(argv[3]); - F32 heightScale = dAtof(argv[4]); - const UTF8 *opacityFiles = argv[5]; - const UTF8 *materialsStr = argv[6]; - bool flipYAxis = argc == 8? dAtob(argv[7]) : true; - // First load the height map and validate it. - Resource heightmap = GBitmap::load( hmap ); + Resource heightmap = GBitmap::load(heightMapFile); if ( !heightmap ) { Con::errorf( "Heightmap failed to load!" ); @@ -155,7 +139,7 @@ ConsoleStaticMethod( TerrainBlock, import, S32, 7, 8, return 0; } - U32 fileCount = StringUnit::getUnitCount( opacityFiles, "\n" ); + U32 fileCount = StringUnit::getUnitCount(opacityLayerFiles, "\n" ); Vector layerMap; layerMap.setSize( terrSize * terrSize ); { @@ -163,7 +147,7 @@ ConsoleStaticMethod( TerrainBlock, import, S32, 7, 8, for ( U32 i = 0; i < fileCount; i++ ) { - String fileNameWithChannel = StringUnit::getUnit( opacityFiles, i, "\n" ); + String fileNameWithChannel = StringUnit::getUnit(opacityLayerFiles, i, "\n" ); String fileName = StringUnit::getUnit( fileNameWithChannel, 0, "\t" ); String channel = StringUnit::getUnit( fileNameWithChannel, 1, "\t" ); @@ -251,7 +235,7 @@ ConsoleStaticMethod( TerrainBlock, import, S32, 7, 8, } // Do we have an existing terrain with that name... then update it! - TerrainBlock *terrain = dynamic_cast( Sim::findObject( terrainName ) ); + TerrainBlock *terrain = dynamic_cast( Sim::findObject( terrainName.c_str() ) ); if ( terrain ) terrain->import( (*heightmap), heightScale, metersPerPixel, layerMap, materials, flipYAxis ); else From 7d91d0a5776763147043953acb5ca5ef2e36d4b0 Mon Sep 17 00:00:00 2001 From: Lukas Joergensen Date: Fri, 20 Apr 2018 22:09:58 +0200 Subject: [PATCH 11/34] Eliminate ConsoleFunction and ConsoleMethod, replace with DefineEngineStringlyVariadic --- Engine/source/T3D/aiConnection.cpp | 2 +- Engine/source/T3D/gameBase/gameConnection.cpp | 2 +- Engine/source/afx/afxCamera.cpp | 2 +- Engine/source/afx/afxMagicSpell.cpp | 44 +++++++------- Engine/source/afx/arcaneFX.cpp | 14 ++--- Engine/source/app/net/net.cpp | 6 +- Engine/source/cinterface/c_scripting.cpp | 2 +- Engine/source/console/console.h | 14 ----- Engine/source/console/consoleFunctions.cpp | 10 ++-- Engine/source/console/engineAPI.h | 58 +++++++++++++++++++ Engine/source/console/sim.cpp | 2 +- Engine/source/console/simObject.cpp | 4 +- Engine/source/console/simSet.cpp | 24 ++------ Engine/source/gui/editor/guiFilterCtrl.cpp | 2 +- Engine/source/gui/editor/guiGraphCtrl.cpp | 2 +- Engine/source/gui/worldEditor/worldEditor.cpp | 2 +- Engine/source/platformWin32/winMath.cpp | 2 +- Engine/source/sim/actionMap.cpp | 4 +- 18 files changed, 112 insertions(+), 84 deletions(-) diff --git a/Engine/source/T3D/aiConnection.cpp b/Engine/source/T3D/aiConnection.cpp index 21564d5eb..42ed1dff3 100644 --- a/Engine/source/T3D/aiConnection.cpp +++ b/Engine/source/T3D/aiConnection.cpp @@ -130,7 +130,7 @@ static inline F32 moveClamp(F32 v) //----------------------------------------------------------------------------- /// Construct and connect an AI connection object -ConsoleFunction(aiConnect, S32 , 2, 20, "(...)" +DefineEngineStringlyVariadicFunction(aiConnect, S32 , 2, 20, "(...)" "@brief Creates a new AIConnection, and passes arguments to its onConnect script callback.\n\n" "@returns The newly created AIConnection\n" "@see GameConnection for parameter information\n" diff --git a/Engine/source/T3D/gameBase/gameConnection.cpp b/Engine/source/T3D/gameBase/gameConnection.cpp index 2376e7180..dc5f69367 100644 --- a/Engine/source/T3D/gameBase/gameConnection.cpp +++ b/Engine/source/T3D/gameBase/gameConnection.cpp @@ -326,7 +326,7 @@ DefineEngineMethod( GameConnection, setJoinPassword, void, (const char* password object->setJoinPassword(password); } -ConsoleMethod(GameConnection, setConnectArgs, void, 3, 17, +DefineEngineStringlyVariadicMethod(GameConnection, setConnectArgs, void, 3, 17, "(const char* args) @brief On the client, pass along a variable set of parameters to the server.\n\n" "Once the connection is established with the server, the server calls its onConnect() method " diff --git a/Engine/source/afx/afxCamera.cpp b/Engine/source/afx/afxCamera.cpp index 1aad5f455..3c460dad8 100644 --- a/Engine/source/afx/afxCamera.cpp +++ b/Engine/source/afx/afxCamera.cpp @@ -452,7 +452,7 @@ const char* afxCamera::getMode() static char buffer[100]; -ConsoleMethod(afxCamera, setOrbitMode, void, 7, 8, +DefineEngineStringlyVariadicMethod(afxCamera, setOrbitMode, void, 7, 8, "(GameBase orbitObject, TransformF mat, float minDistance, float maxDistance, float curDistance, bool ownClientObject)" "Set the camera to orbit around some given object.\n\n" "@param orbitObject Object we want to orbit.\n" diff --git a/Engine/source/afx/afxMagicSpell.cpp b/Engine/source/afx/afxMagicSpell.cpp index 7aeb93da8..b7f2714ea 100644 --- a/Engine/source/afx/afxMagicSpell.cpp +++ b/Engine/source/afx/afxMagicSpell.cpp @@ -2633,29 +2633,29 @@ DefineEngineMethod(afxMagicSpell, getImpactedObject, S32, (),, return (imp_obj) ? imp_obj->getId() : -1; } -ConsoleMethod(afxMagicSpell, setTimeFactor, void, 3, 4, "(F32 factor) or (string phase, F32 factor)" - "Sets the time-factor for the spell, either overall or for a specific phrase.\n\n" - "@ingroup AFX") +DefineEngineStringlyVariadicMethod(afxMagicSpell, setTimeFactor, void, 3, 4, "(F32 factor) or (string phase, F32 factor)" + "Sets the time-factor for the spell, either overall or for a specific phrase.\n\n" + "@ingroup AFX") { - if (argc == 3) - object->setTimeFactor(dAtof(argv[2])); - else - { - if (dStricmp(argv[2], "overall") == 0) - object->setTimeFactor(dAtof(argv[3])); - else if (dStricmp(argv[2], "casting") == 0) - object->setTimeFactor(afxMagicSpell::CASTING_PHRASE, dAtof(argv[3])); - else if (dStricmp(argv[2], "launch") == 0) - object->setTimeFactor(afxMagicSpell::LAUNCH_PHRASE, dAtof(argv[3])); - else if (dStricmp(argv[2], "delivery") == 0) - object->setTimeFactor(afxMagicSpell::DELIVERY_PHRASE, dAtof(argv[3])); - else if (dStricmp(argv[2], "impact") == 0) - object->setTimeFactor(afxMagicSpell::IMPACT_PHRASE, dAtof(argv[3])); - else if (dStricmp(argv[2], "linger") == 0) - object->setTimeFactor(afxMagicSpell::LINGER_PHRASE, dAtof(argv[3])); - else - Con::errorf("afxMagicSpell::setTimeFactor() -- unknown spell phrase [%s].", argv[2].getStringValue()); - } + if (argc == 3) + object->setTimeFactor(dAtof(argv[2])); + else + { + if (dStricmp(argv[2], "overall") == 0) + object->setTimeFactor(dAtof(argv[3])); + else if (dStricmp(argv[2], "casting") == 0) + object->setTimeFactor(afxMagicSpell::CASTING_PHRASE, dAtof(argv[3])); + else if (dStricmp(argv[2], "launch") == 0) + object->setTimeFactor(afxMagicSpell::LAUNCH_PHRASE, dAtof(argv[3])); + else if (dStricmp(argv[2], "delivery") == 0) + object->setTimeFactor(afxMagicSpell::DELIVERY_PHRASE, dAtof(argv[3])); + else if (dStricmp(argv[2], "impact") == 0) + object->setTimeFactor(afxMagicSpell::IMPACT_PHRASE, dAtof(argv[3])); + else if (dStricmp(argv[2], "linger") == 0) + object->setTimeFactor(afxMagicSpell::LINGER_PHRASE, dAtof(argv[3])); + else + Con::errorf("afxMagicSpell::setTimeFactor() -- unknown spell phrase [%s].", argv[2].getStringValue()); + } } DefineEngineMethod(afxMagicSpell, interruptStage, void, (),, diff --git a/Engine/source/afx/arcaneFX.cpp b/Engine/source/afx/arcaneFX.cpp index 4252183c1..385c056f6 100644 --- a/Engine/source/afx/arcaneFX.cpp +++ b/Engine/source/afx/arcaneFX.cpp @@ -860,18 +860,18 @@ DefineEngineFunction(getMaxF, F32, (float a, float b),, return getMax(a, b); } -ConsoleFunction(echoThru, const char*, 2, 0, "(string passthru, string text...)" - "Like echo(), but first argument is returned.\n" - "@ingroup AFX") +DefineEngineStringlyVariadicFunction(echoThru, const char*, 2, 0, "(string passthru, string text...)" + "Like echo(), but first argument is returned.\n" + "@ingroup AFX") { U32 len = 0; S32 i; - for(i = 2; i < argc; i++) + for (i = 2; i < argc; i++) len += dStrlen(argv[i]); char *ret = Con::getReturnBuffer(len + 1); ret[0] = 0; - for(i = 2; i < argc; i++) + for (i = 2; i < argc; i++) dStrcat(ret, argv[i], len + 1); Con::printf("%s -- [%s]", ret, argv[1].getStringValue()); @@ -880,7 +880,7 @@ ConsoleFunction(echoThru, const char*, 2, 0, "(string passthru, string text...)" return argv[1]; } -ConsoleFunction(warnThru, const char*, 2, 0, "(string passthru, string text...)" +DefineEngineStringlyVariadicFunction(warnThru, const char*, 2, 0, "(string passthru, string text...)" "Like warn(), but first argument is returned.\n" "@ingroup AFX") { @@ -900,7 +900,7 @@ ConsoleFunction(warnThru, const char*, 2, 0, "(string passthru, string text...)" return argv[1]; } -ConsoleFunction(errorThru, const char*, 2, 0, "(string passthru, string text...)" +DefineEngineStringlyVariadicFunction(errorThru, const char*, 2, 0, "(string passthru, string text...)" "Like error(), but first argument is returned.\n" "@ingroup AFX") { diff --git a/Engine/source/app/net/net.cpp b/Engine/source/app/net/net.cpp index c5f1be189..abec3ccc1 100644 --- a/Engine/source/app/net/net.cpp +++ b/Engine/source/app/net/net.cpp @@ -212,7 +212,7 @@ ConsoleDocClass( RemoteCommandEvent, ConsoleFunctionGroupBegin( Net, "Functions for use with the network; tagged strings and remote commands."); -ConsoleFunction( commandToServer, void, 2, RemoteCommandEvent::MaxRemoteCommandArgs + 1, "(string func, ...)" +DefineEngineStringlyVariadicFunction( commandToServer, void, 2, RemoteCommandEvent::MaxRemoteCommandArgs + 1, "(string func, ...)" "@brief Send a command to the server.\n\n" "@param func Name of the server command being called\n" @@ -255,7 +255,7 @@ ConsoleFunction( commandToServer, void, 2, RemoteCommandEvent::MaxRemoteCommandA RemoteCommandEvent::sendRemoteCommand(conn, args.count(), args); } -ConsoleFunction( commandToClient, void, 3, RemoteCommandEvent::MaxRemoteCommandArgs + 2, "(NetConnection client, string func, ...)" +DefineEngineStringlyVariadicFunction( commandToClient, void, 3, RemoteCommandEvent::MaxRemoteCommandArgs + 2, "(NetConnection client, string func, ...)" "@brief Send a command from the server to the client\n\n" "@param client The numeric ID of a client GameConnection\n" @@ -349,7 +349,7 @@ DefineEngineFunction(getTaggedString, const char* , (const char *tag), (""), -ConsoleFunction( buildTaggedString, const char*, 2, 11, "(string format, ...)" +DefineEngineStringlyVariadicFunction( buildTaggedString, const char*, 2, 11, "(string format, ...)" "@brief Build a string using the specified tagged string format.\n\n" "This function takes an already tagged string (passed in as a tagged string ID) and one " diff --git a/Engine/source/cinterface/c_scripting.cpp b/Engine/source/cinterface/c_scripting.cpp index 1138cbc1c..f10effde2 100644 --- a/Engine/source/cinterface/c_scripting.cpp +++ b/Engine/source/cinterface/c_scripting.cpp @@ -420,7 +420,7 @@ extern "C" { } -ConsoleFunction(TestFunction2Args, const char *, 3, 3, "testFunction(arg1, arg2)") +DefineEngineStringlyVariadicFunction(TestFunction2Args, const char *, 3, 3, "testFunction(arg1, arg2)") { return "Return Value"; } diff --git a/Engine/source/console/console.h b/Engine/source/console/console.h index 358b738f9..dfa3cd5a8 100644 --- a/Engine/source/console/console.h +++ b/Engine/source/console/console.h @@ -1191,11 +1191,6 @@ public: # define ConsoleFunctionGroupBegin(groupName, usage) \ static ConsoleConstructor cfg_ConsoleFunctionGroup_##groupName##_GroupBegin(NULL,#groupName,usage) -# define ConsoleFunction(name,returnType,minArgs,maxArgs,usage1) \ - returnType cf_##name(SimObject *, S32, ConsoleValueRef *argv); \ - ConsoleConstructor cc_##name##_obj(NULL,#name,cf_##name,usage1,minArgs,maxArgs); \ - returnType cf_##name(SimObject *, S32 argc, ConsoleValueRef *argv) - # define ConsoleToolFunction(name,returnType,minArgs,maxArgs,usage1) \ returnType ctf_##name(SimObject *, S32, ConsoleValueRef *argv); \ ConsoleConstructor cc_##name##_obj(NULL,#name,ctf_##name,usage1,minArgs,maxArgs, true); \ @@ -1211,15 +1206,6 @@ public: # define ConsoleMethodGroupBegin(className, groupName, usage) \ static ConsoleConstructor cc_##className##_##groupName##_GroupBegin(#className,#groupName,usage) -# define ConsoleMethod(className,name,returnType,minArgs,maxArgs,usage1) \ - inline returnType cm_##className##_##name(className *, S32, ConsoleValueRef *argv); \ - returnType cm_##className##_##name##_caster(SimObject *object, S32 argc, ConsoleValueRef *argv) { \ - AssertFatal( dynamic_cast( object ), "Object passed to " #name " is not a " #className "!" ); \ - conmethod_return_##returnType ) cm_##className##_##name(static_cast(object),argc,argv); \ - }; \ - ConsoleConstructor cc_##className##_##name##_obj(#className,#name,cm_##className##_##name##_caster,usage1,minArgs,maxArgs); \ - inline returnType cm_##className##_##name(className *object, S32 argc, ConsoleValueRef *argv) - # define ConsoleMethodGroupEnd(className, groupName) \ static ConsoleConstructor cc_##className##_##groupName##_GroupEnd(#className,#groupName,NULL) diff --git a/Engine/source/console/consoleFunctions.cpp b/Engine/source/console/consoleFunctions.cpp index 565c79206..33c1c9a5f 100644 --- a/Engine/source/console/consoleFunctions.cpp +++ b/Engine/source/console/consoleFunctions.cpp @@ -1200,7 +1200,7 @@ DefineEngineFunction( isValidIP, bool, ( const char* str),, // Torque won't normally add another string if it already exists with another casing, // so this forces the addition. It should be called once near the start, such as in main.cs. -ConsoleFunction(addCaseSensitiveStrings,void,2,0,"[string1, string2, ...]" +DefineEngineStringlyVariadicFunction(addCaseSensitiveStrings,void,2,0,"[string1, string2, ...]" "Adds case sensitive strings to the StringTable.") { for(int i = 1; i < argc; i++) @@ -1879,7 +1879,7 @@ DefineEngineFunction( getTag, const char*, ( const char* textTagString ), , "( s //----------------------------------------------------------------------------- -ConsoleFunction( echo, void, 2, 0, "( string message... ) " +DefineEngineStringlyVariadicFunction( echo, void, 2, 0, "( string message... ) " "@brief Logs a message to the console.\n\n" "Concatenates all given arguments to a single string and prints the string to the console. " "A newline is added automatically after the text.\n\n" @@ -1902,7 +1902,7 @@ ConsoleFunction( echo, void, 2, 0, "( string message... ) " //----------------------------------------------------------------------------- -ConsoleFunction( warn, void, 2, 0, "( string message... ) " +DefineEngineStringlyVariadicFunction( warn, void, 2, 0, "( string message... ) " "@brief Logs a warning message to the console.\n\n" "Concatenates all given arguments to a single string and prints the string to the console as a warning " "message (in the in-game console, these will show up using a turquoise font by default). " @@ -1926,7 +1926,7 @@ ConsoleFunction( warn, void, 2, 0, "( string message... ) " //----------------------------------------------------------------------------- -ConsoleFunction( error, void, 2, 0, "( string message... ) " +DefineEngineStringlyVariadicFunction( error, void, 2, 0, "( string message... ) " "@brief Logs an error message to the console.\n\n" "Concatenates all given arguments to a single string and prints the string to the console as an error " "message (in the in-game console, these will show up using a red font by default). " @@ -2236,7 +2236,7 @@ DefineEngineFunction( generateUUID, Torque::UUID, (),, //----------------------------------------------------------------------------- -ConsoleFunction( call, const char *, 2, 0, "( string functionName, string args... ) " +DefineEngineStringlyVariadicFunction( call, const char *, 2, 0, "( string functionName, string args... ) " "Apply the given arguments to the specified global function and return the result of the call.\n\n" "@param functionName The name of the function to call. This function must be in the global namespace, i.e. " "you cannot call a function in a namespace through #call. Use eval() for that.\n" diff --git a/Engine/source/console/engineAPI.h b/Engine/source/console/engineAPI.h index 6d0484171..ab1717745 100644 --- a/Engine/source/console/engineAPI.h +++ b/Engine/source/console/engineAPI.h @@ -855,6 +855,64 @@ public: ); \ static inline returnType _fn ## className ## name ## impl args +# define DefineEngineStringlyVariadicFunction(name,returnType,minArgs,maxArgs,usage) \ + static inline returnType _fn ## name ## impl (SimObject *, S32 argc, ConsoleValueRef *argv); \ + TORQUE_API EngineTypeTraits< returnType >::ReturnValueType fn ## name \ + (S32 argc, const char** argv) \ + { \ + _CHECK_ENGINE_INITIALIZED( name, returnType ); \ + StringStackConsoleWrapper args(argc, argv); \ + return EngineTypeTraits< returnType >::ReturnValue( \ + _fn ## name ## impl(NULL, args.count(), args) \ + ); \ + } \ + static _EngineFunctionDefaultArguments< void (S32 argc, const char** argv) > _fn ## name ## DefaultArgs; \ + static EngineFunctionInfo _fn ## name ## FunctionInfo( \ + #name, \ + &_SCOPE<>()(), \ + usage, \ + #returnType " " #name "(S32 argc, const char** argv)", \ + "fn" #name, \ + TYPE< returnType (S32 argc, const char** argv) >(), \ + &_fn ## name ## DefaultArgs, \ + ( void* ) &fn ## name, \ + 0 \ + ); \ + ConsoleConstructor cc_##name##_obj(NULL,#name,_fn ## name ## impl,usage,minArgs,maxArgs); \ + returnType _fn ## name ## impl(SimObject *, S32 argc, ConsoleValueRef *argv) + +# define DefineEngineStringlyVariadicMethod(className, name,returnType,minArgs,maxArgs,usage) \ + static inline returnType _fn ## className ## _ ## name ## impl (className* object, S32 argc, ConsoleValueRef* argv); \ + TORQUE_API EngineTypeTraits< returnType >::ReturnValueType fn ## className ## _ ## name \ + (className* object, S32 argc, const char** argv) \ + { \ + _CHECK_ENGINE_INITIALIZED( name, returnType ); \ + StringStackConsoleWrapper args(argc, argv); \ + return EngineTypeTraits< returnType >::ReturnValue( \ + _fn ## className ## _ ## name ## impl(object, args.count(), args) \ + ); \ + } \ + static _EngineFunctionDefaultArguments< void (className* object, S32 argc, const char** argv) > _fn ## className ## _ ## name ## DefaultArgs; \ + static EngineFunctionInfo _fn ## className ## _ ## name ## FunctionInfo( \ + #name, \ + &_SCOPE<>()(), \ + usage, \ + #returnType " " #name "(SimObject* object, S32 argc, const char** argv)", \ + "fn" #className "_" #name, \ + TYPE< returnType (SimObject* object, S32 argc, const char** argv) >(), \ + &_fn ## className ## _ ## name ## DefaultArgs, \ + ( void* ) &fn ## className ## _ ## name, \ + 0 \ + ); \ + returnType cm_##className##_##name##_caster(SimObject* object, S32 argc, ConsoleValueRef* argv) { \ + AssertFatal( dynamic_cast( object ), "Object passed to " #name " is not a " #className "!" ); \ + conmethod_return_##returnType ) _fn ## className ## _ ## name ## impl(static_cast(object),argc,argv); \ + }; \ + ConsoleConstructor cc_##className##_##name##_obj(#className,#name,cm_##className##_##name##_caster,usage,minArgs,maxArgs); \ + static inline returnType _fn ## className ## _ ## name ## impl(className *object, S32 argc, ConsoleValueRef *argv) + + + // The following three macros are only temporary. They allow to define engineAPI functions using the framework // here in this file while being visible only in the new API. When the console interop is removed, these macros // can be removed and all their uses be replaced with their corresponding versions that now still include support diff --git a/Engine/source/console/sim.cpp b/Engine/source/console/sim.cpp index 6bb194db3..1fbcdd748 100644 --- a/Engine/source/console/sim.cpp +++ b/Engine/source/console/sim.cpp @@ -181,7 +181,7 @@ DefineEngineFunction( getTimeSinceStart, S32, (S32 scheduleId), ,"getTimeSinceSt return ret; } -ConsoleFunction(schedule, S32, 4, 0, "schedule(time, refobject|0, command, )") +DefineEngineStringlyVariadicFunction(schedule, S32, 4, 0, "schedule(time, refobject|0, command, )") { U32 timeDelta = U32(dAtof(argv[1])); SimObject *refObject = Sim::findObject(argv[2]); diff --git a/Engine/source/console/simObject.cpp b/Engine/source/console/simObject.cpp index 62ac25fd1..02d7eec40 100644 --- a/Engine/source/console/simObject.cpp +++ b/Engine/source/console/simObject.cpp @@ -2945,7 +2945,7 @@ DefineEngineMethod( SimObject, setFieldType, void, ( const char* fieldName, cons //----------------------------------------------------------------------------- -ConsoleMethod( SimObject, call, const char*, 3, 0, "( string method, string args... ) Dynamically call a method on an object.\n" +DefineEngineStringlyVariadicMethod( SimObject, call, const char*, 3, 0, "( string method, string args... ) Dynamically call a method on an object.\n" "@param method Name of method to call.\n" "@param args Zero or more arguments for the method.\n" "@return The result of the method call." ) @@ -3047,7 +3047,7 @@ DefineEngineMethod( SimObject, delete, void, (),, //----------------------------------------------------------------------------- -ConsoleMethod( SimObject,schedule, S32, 4, 0, "( float time, string method, string args... ) Delay an invocation of a method.\n" +DefineEngineStringlyVariadicMethod( SimObject,schedule, S32, 4, 0, "( float time, string method, string args... ) Delay an invocation of a method.\n" "@param time The number of milliseconds after which to invoke the method. This is a soft limit.\n" "@param method The method to call.\n" "@param args The arguments with which to call the method.\n" diff --git a/Engine/source/console/simSet.cpp b/Engine/source/console/simSet.cpp index 545c411b7..e04416d30 100644 --- a/Engine/source/console/simSet.cpp +++ b/Engine/source/console/simSet.cpp @@ -895,15 +895,7 @@ DefineEngineMethod( SimSet, listObjects, void, (),, //----------------------------------------------------------------------------- -DEFINE_CALLIN( fnSimSet_add, add, SimSet, void, ( SimSet* set, SimObject* object ),,, - "Add the given object to the set.\n" - "@param object An object." ) -{ - if( object ) - set->addObject( object ); -} - -ConsoleMethod( SimSet, add, void, 3, 0, +DefineEngineStringlyVariadicMethod( SimSet, add, void, 3, 0, "( SimObject objects... ) Add the given objects to the set.\n" "@param objects The objects to add to the set." ) { @@ -919,15 +911,7 @@ ConsoleMethod( SimSet, add, void, 3, 0, //----------------------------------------------------------------------------- -DEFINE_CALLIN( fnSimSet_remove, remove, SimSet, void, ( SimSet* set, SimObject* object ),,, - "Remove the given object from the set.\n" - "@param object An object." ) -{ - if( object ) - set->removeObject( object ); -} - -ConsoleMethod( SimSet, remove, void, 3, 0, +DefineEngineStringlyVariadicMethod( SimSet, remove, void, 3, 0, "( SimObject objects... ) Remove the given objects from the set.\n" "@param objects The objects to remove from the set." ) { @@ -970,7 +954,7 @@ DefineEngineMethod( SimSet, getRandom, SimObject*, (),, //----------------------------------------------------------------------------- -ConsoleMethod( SimSet, callOnChildren, void, 3, 0, +DefineEngineStringlyVariadicMethod( SimSet, callOnChildren, void, 3, 0, "( string method, string args... ) Call a method on all objects contained in the set.\n\n" "@param method The name of the method to call.\n" "@param args The arguments to the method.\n\n" @@ -982,7 +966,7 @@ ConsoleMethod( SimSet, callOnChildren, void, 3, 0, //----------------------------------------------------------------------------- -ConsoleMethod( SimSet, callOnChildrenNoRecurse, void, 3, 0, +DefineEngineStringlyVariadicMethod( SimSet, callOnChildrenNoRecurse, void, 3, 0, "( string method, string args... ) Call a method on all objects contained in the set.\n\n" "@param method The name of the method to call.\n" "@param args The arguments to the method.\n\n" diff --git a/Engine/source/gui/editor/guiFilterCtrl.cpp b/Engine/source/gui/editor/guiFilterCtrl.cpp index c0d9c2a72..7870abe24 100644 --- a/Engine/source/gui/editor/guiFilterCtrl.cpp +++ b/Engine/source/gui/editor/guiFilterCtrl.cpp @@ -77,7 +77,7 @@ DefineEngineMethod( GuiFilterCtrl, getValue, const char*, (), , "Return a tuple return buffer; } -ConsoleMethod( GuiFilterCtrl, setValue, void, 3, 20, "(f1, f2, ...)" +DefineEngineStringlyVariadicMethod( GuiFilterCtrl, setValue, void, 3, 20, "(f1, f2, ...)" "Reset the filter to use the specified points, spread equidistantly across the domain." "@internal") { diff --git a/Engine/source/gui/editor/guiGraphCtrl.cpp b/Engine/source/gui/editor/guiGraphCtrl.cpp index 8b1c14108..343f56e24 100644 --- a/Engine/source/gui/editor/guiGraphCtrl.cpp +++ b/Engine/source/gui/editor/guiGraphCtrl.cpp @@ -407,7 +407,7 @@ DefineEngineMethod( GuiGraphCtrl, setGraphType, void, ( S32 plotId, GuiGraphType //----------------------------------------------------------------------------- -ConsoleMethod( GuiGraphCtrl, matchScale, void, 3, GuiGraphCtrl::MaxPlots + 2, "( int plotID1, int plotID2, ... ) " +DefineEngineStringlyVariadicMethod( GuiGraphCtrl, matchScale, void, 3, GuiGraphCtrl::MaxPlots + 2, "( int plotID1, int plotID2, ... ) " "Set the scale of all specified plots to the maximum scale among them.\n\n" "@param plotID1 Index of plotting curve.\n" "@param plotID2 Index of plotting curve." ) diff --git a/Engine/source/gui/worldEditor/worldEditor.cpp b/Engine/source/gui/worldEditor/worldEditor.cpp index 24e710091..1f95b6376 100644 --- a/Engine/source/gui/worldEditor/worldEditor.cpp +++ b/Engine/source/gui/worldEditor/worldEditor.cpp @@ -3225,7 +3225,7 @@ void WorldEditor::setEditorTool(EditorTool* newTool) //------------------------------------------------------------------------------ -ConsoleMethod( WorldEditor, ignoreObjClass, void, 3, 0, "(string class_name, ...)") +DefineEngineStringlyVariadicMethod( WorldEditor, ignoreObjClass, void, 3, 0, "(string class_name, ...)") { object->ignoreObjClass(argc, argv); } diff --git a/Engine/source/platformWin32/winMath.cpp b/Engine/source/platformWin32/winMath.cpp index 50e5fdbc6..3b6e3ec15 100644 --- a/Engine/source/platformWin32/winMath.cpp +++ b/Engine/source/platformWin32/winMath.cpp @@ -33,7 +33,7 @@ extern void mInstall_AMD_Math(); extern void mInstall_Library_SSE(); //-------------------------------------- -ConsoleFunction( mathInit, void, 1, 10, "( ... )" +DefineEngineStringlyVariadicFunction( mathInit, void, 1, 10, "( ... )" "@brief Install the math library with specified extensions.\n\n" "Possible parameters are:\n\n" " - 'DETECT' Autodetect math lib settings.\n\n" diff --git a/Engine/source/sim/actionMap.cpp b/Engine/source/sim/actionMap.cpp index ca2932e84..a69ec4bea 100644 --- a/Engine/source/sim/actionMap.cpp +++ b/Engine/source/sim/actionMap.cpp @@ -2077,7 +2077,7 @@ static ConsoleDocFragment _ActionMapbind2( "ActionMap", "bool bind( string device, string action, string flag, string deadZone, string scale, string command );"); -ConsoleMethod( ActionMap, bind, bool, 5, 10, "actionMap.bind( device, action, [modifier, spec, mod...], command )" +DefineEngineStringlyVariadicMethod( ActionMap, bind, bool, 5, 10, "actionMap.bind( device, action, [modifier, spec, mod...], command )" "@hide") { StringStackWrapper args(argc - 2, argv + 2); @@ -2126,7 +2126,7 @@ static ConsoleDocFragment _ActionMapbindObj2( "ActionMap", "bool bindObj( string device, string action, string flag, string deadZone, string scale, string command, SimObjectID object );"); -ConsoleMethod( ActionMap, bindObj, bool, 6, 11, "(device, action, [modifier, spec, mod...], command, object)" +DefineEngineStringlyVariadicMethod( ActionMap, bindObj, bool, 6, 11, "(device, action, [modifier, spec, mod...], command, object)" "@hide") { SimObject* simObject = Sim::findObject(argv[argc - 1]); From b0be06c33de319d3a1fc3505b83ad7f2565a395b Mon Sep 17 00:00:00 2001 From: Lukas Joergensen Date: Sat, 21 Apr 2018 09:03:04 +0200 Subject: [PATCH 12/34] Add initPersistFields to mPropertyTable --- Engine/source/console/consoleObject.h | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/Engine/source/console/consoleObject.h b/Engine/source/console/consoleObject.h index 7eea3144e..08cb0dcec 100644 --- a/Engine/source/console/consoleObject.h +++ b/Engine/source/console/consoleObject.h @@ -662,6 +662,27 @@ public: // Finally, do any class specific initialization... T::initPersistFields(); T::consoleInit(); + + EnginePropertyTable::Property* props = new EnginePropertyTable::Property[sg_tempFieldList.size()]; + + for (int i = 0; i < sg_tempFieldList.size(); ++i) + { + EnginePropertyTable::Property prop; + prop.mDocString = sg_tempFieldList[i].pFieldDocs; + prop.mName = sg_tempFieldList[i].pFieldname; + prop.mNumElements = sg_tempFieldList[i].elementCount; + prop.mFlags = 0; + if (sg_tempFieldList[i].type == StartGroupFieldType) + prop.mFlags |= EnginePropertyGroupBegin; + if (sg_tempFieldList[i].type == EndGroupFieldType) + prop.mFlags |= EnginePropertyGroupEnd; + props[i] = prop; + } + + _smPropertyTable = EnginePropertyTable(sg_tempFieldList.size(), props); + smPropertyTable = _smPropertyTable; + + const_cast(mTypeInfo)->mPropertyTable = &_smPropertyTable; // Let the base finish up. AbstractClassRep::init(); From c1a234cae667655b3988add3fb1c66962f780f34 Mon Sep 17 00:00:00 2001 From: Lukas Joergensen Date: Sat, 21 Apr 2018 09:06:16 +0200 Subject: [PATCH 13/34] Fix EngineAPI xml generation, utilizing fixed_tuple for default args --- Engine/source/console/engineFunctions.h | 9 +- Engine/source/console/engineXMLExport.cpp | 2 +- Engine/source/console/fixedTuple.h | 153 ++++++++++++++++++++++ 3 files changed, 162 insertions(+), 2 deletions(-) create mode 100644 Engine/source/console/fixedTuple.h diff --git a/Engine/source/console/engineFunctions.h b/Engine/source/console/engineFunctions.h index 0f2a3f45d..eb935d995 100644 --- a/Engine/source/console/engineFunctions.h +++ b/Engine/source/console/engineFunctions.h @@ -25,6 +25,10 @@ #include +#ifndef _FIXEDTUPLE_H_ +#include "fixedTuple.h" +#endif + #ifndef _ENGINEEXPORTS_H_ #include "console/engineExports.h" #endif @@ -94,6 +98,7 @@ template struct _EngineFunctionDefaultArguments< void(ArgTs...) > : public EngineFunctionDefaultArguments { template using DefVST = typename EngineTypeTraits::DefaultArgumentValueStoreType; + fixed_tuple ...> mFixedArgs; std::tuple ...> mArgs; private: using SelfType = _EngineFunctionDefaultArguments< void(ArgTs...) >; @@ -130,7 +135,9 @@ private: public: template _EngineFunctionDefaultArguments(TailTs ...tail) : EngineFunctionDefaultArguments({sizeof...(TailTs)}), mArgs(SelfType::tailInit(tail...)) - {} + { + fixed_tuple_mutator...), void(DefVST...)>::copy(mArgs, mFixedArgs); + } }; #pragma pack( pop ) diff --git a/Engine/source/console/engineXMLExport.cpp b/Engine/source/console/engineXMLExport.cpp index ce12121e8..51951c52b 100644 --- a/Engine/source/console/engineXMLExport.cpp +++ b/Engine/source/console/engineXMLExport.cpp @@ -197,7 +197,7 @@ static String getDefaultArgumentValue( const EngineFunctionInfo* function, const //TODO: for now we store string literals in ASCII; needs to be sorted out if( TYPE< const char* >() == type ) { - const char* val = getArgValue< const char* >( defaultArgs, offset ); + const char* val = reinterpret_cast< const char* >(defaultArgs->getArgs() + offset); value = val; } diff --git a/Engine/source/console/fixedTuple.h b/Engine/source/console/fixedTuple.h new file mode 100644 index 000000000..871cd7011 --- /dev/null +++ b/Engine/source/console/fixedTuple.h @@ -0,0 +1,153 @@ +//----------------------------------------------------------------------------- +// 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 _FIXEDTUPLE_H_ +#define _FIXEDTUPLE_H_ +/// @name Fixed-layout tuple definition +/// These structs and templates serve as a way to pass arguments from external +/// applications and into the T3D console system. +/// They work as std::tuple, but they ensure a standardized fixed memory +/// layout. Allowing for unmanaged calls with these tuples as the parameter +/// lists. +/// +/// The implementation is from a SO solution: +/// https://codereview.stackexchange.com/a/52279 +/// As out use-case is pretty simple, this code could probably be simplified by +/// stripping out a lot of extra functionality. But eh. +/// +/// @{ + +template +struct fixed_tuple; + +template +struct fixed_tuple +{ + T first; + fixed_tuple rest; + + fixed_tuple() = default; + template ::type>::value>::type> + fixed_tuple(U&& u, Us&&...tail) : + first(::std::forward(u)), + rest(::std::forward(tail)...) {} +}; + +template +struct fixed_tuple +{ + T first; + + fixed_tuple() = default; + template ::type>::value>::type> + fixed_tuple(U&& u) : + first(::std::forward(u)) {} +}; + +template <> +struct fixed_tuple<> {}; + + +template < ::std::size_t i, class T> +struct fixed_tuple_element; + +template < ::std::size_t i, class T, class... Ts> +struct fixed_tuple_element > + : fixed_tuple_element > +{}; + +template +struct fixed_tuple_element<0, fixed_tuple > +{ + using type = T; +}; + +template < ::std::size_t i> +struct fixed_tuple_accessor +{ + template + static inline typename fixed_tuple_element >::type & get(fixed_tuple & t) + { + return fixed_tuple_accessor::get(t.rest); + } + + template + static inline const typename fixed_tuple_element >::type & get(const fixed_tuple & t) + { + return fixed_tuple_accessor::get(t.rest); + } +}; + +template <> +struct fixed_tuple_accessor<0> +{ + template + static inline typename fixed_tuple_element<0, fixed_tuple >::type & get(fixed_tuple & t) + { + return t.first; + } + + template + static inline const typename fixed_tuple_element<0, fixed_tuple >::type & get(const fixed_tuple & t) + { + return t.first; + } +}; + +template< typename T1, typename T2 > +struct fixed_tuple_mutator {}; + +template +struct fixed_tuple_mutator +{ + template + static inline typename std::enable_if::type + copy_r_t_l(fixed_tuple& src, fixed_tuple& dest) + { } + + template + static inline typename std::enable_if::type + copy_r_t_l(fixed_tuple& src, fixed_tuple& dest) + { + fixed_tuple_accessor::get(dest) = fixed_tuple_accessor::get(src); + copy_r_t_l(src, dest); + } + + template + static inline typename std::enable_if::type + copy(std::tuple& src, fixed_tuple& dest) + { } + + template + static inline typename std::enable_if::type + copy(std::tuple& src, fixed_tuple& dest) + { + fixed_tuple_accessor::get(dest) = std::get(src); + copy(src, dest); + } +}; + + +/// @} + + +#endif // !_FIXEDTUPLE_H_ \ No newline at end of file From fb412ff1081a198946d071f2f62d4466e2cc9d90 Mon Sep 17 00:00:00 2001 From: Lukas Joergensen Date: Sat, 21 Apr 2018 09:08:26 +0200 Subject: [PATCH 14/34] Add Type information for Properties in EngineXMLExport --- Engine/source/console/consoleObject.h | 2 + Engine/source/console/engineTypeInfo.h | 6 + Engine/source/console/engineXMLExport.cpp | 750 +++++++++++----------- 3 files changed, 395 insertions(+), 363 deletions(-) diff --git a/Engine/source/console/consoleObject.h b/Engine/source/console/consoleObject.h index 08cb0dcec..b15cd88ab 100644 --- a/Engine/source/console/consoleObject.h +++ b/Engine/source/console/consoleObject.h @@ -676,6 +676,8 @@ public: prop.mFlags |= EnginePropertyGroupBegin; if (sg_tempFieldList[i].type == EndGroupFieldType) prop.mFlags |= EnginePropertyGroupEnd; + prop.mType = sg_tempFieldList[i].type; + props[i] = prop; } diff --git a/Engine/source/console/engineTypeInfo.h b/Engine/source/console/engineTypeInfo.h index 7a9f7122c..9f9c0d12f 100644 --- a/Engine/source/console/engineTypeInfo.h +++ b/Engine/source/console/engineTypeInfo.h @@ -231,6 +231,9 @@ class EnginePropertyTable /// Combination of EnginePropertyFlags. U32 mFlags; + + /// Type-id of the property + U32 mType; /// Return the name of the property. const char* getName() const { return mName; } @@ -255,6 +258,9 @@ class EnginePropertyTable /// bool hideInInspectors() const { return ( mFlags & EnginePropertyHideInInspectors ); } + + /// Return the type-id of the property. + U32 getType() const { return mType; } }; protected: diff --git a/Engine/source/console/engineXMLExport.cpp b/Engine/source/console/engineXMLExport.cpp index 51951c52b..ae1b182bb 100644 --- a/Engine/source/console/engineXMLExport.cpp +++ b/Engine/source/console/engineXMLExport.cpp @@ -35,32 +35,32 @@ /// actually having to access them directly in the DLL as native entities. -static void exportScope( const EngineExportScope* scope, SimXMLDocument* xml, bool addNode = false ); +static void exportScope(const EngineExportScope* scope, SimXMLDocument* xml, bool addNode = false); -static String getTypeName( const EngineTypeInfo* type ) +static String getTypeName(const EngineTypeInfo* type) { - if( !type ) + if (!type) { - static String sVoid( "void" ); + static String sVoid("void"); return sVoid; } - + return type->getFullyQualifiedExportName(); } -static const char* getDocString( const EngineExport* exportInfo ) +static const char* getDocString(const EngineExport* exportInfo) { - if( !exportInfo->getDocString() ) + if (!exportInfo->getDocString()) return ""; - + return exportInfo->getDocString(); } template< typename T > -inline T getArgValue( const EngineFunctionDefaultArguments* defaultArgs, U32 offset ) +inline T getArgValue(const EngineFunctionDefaultArguments* defaultArgs, U32 offset) { - return *reinterpret_cast< const T* >( defaultArgs->getArgs() + offset ); + return *reinterpret_cast< const T* >(defaultArgs->getArgs() + offset); } @@ -71,14 +71,14 @@ static const char* sExportFilterList[] = "Console", // Console namespace }; -static bool isExportFiltered( const EngineExport* exportInfo ) +static bool isExportFiltered(const EngineExport* exportInfo) { String qualifiedName = exportInfo->getFullyQualifiedExportName(); - - for( U32 i = 0; i < ( sizeof( sExportFilterList ) / sizeof( sExportFilterList[ 0 ] ) ); ++ i ) - if( qualifiedName.compare( sExportFilterList[ i ] ) == 0 ) + + for (U32 i = 0; i < (sizeof(sExportFilterList) / sizeof(sExportFilterList[0])); ++i) + if (qualifiedName.compare(sExportFilterList[i]) == 0) return true; - + return false; } @@ -90,248 +90,248 @@ static bool isExportFiltered( const EngineExport* exportInfo ) //----------------------------------------------------------------------------- /// Helper to parse argument names out of a prototype string. -static Vector< String > parseFunctionArgumentNames( const EngineFunctionInfo* function ) +static Vector< String > parseFunctionArgumentNames(const EngineFunctionInfo* function) { Vector< String > argNames; - + const char* prototype = function->getPrototypeString(); - if( !prototype ) + if (!prototype) return argNames; - - const U32 prototypeLength = dStrlen( prototype ); - const char* prototypeEnd = &prototype[ prototypeLength ]; + + const U32 prototypeLength = dStrlen(prototype); + const char* prototypeEnd = &prototype[prototypeLength]; const char* ptr = prototypeEnd - 1; - + // Search for right parenthesis. - while( ptr >= prototype && *ptr != ')' ) - ptr --; - - if( ptr < prototype ) + while (ptr >= prototype && *ptr != ')') + ptr--; + + if (ptr < prototype) return argNames; - ptr --; - - while( ptr >= prototype && *ptr != '(' ) + ptr--; + + while (ptr >= prototype && *ptr != '(') { // Skip back over spaces. - - while( ptr >= prototype && dIsspace( *ptr ) ) - ptr --; - if( ptr < prototype ) + + while (ptr >= prototype && dIsspace(*ptr)) + ptr--; + if (ptr < prototype) return argNames; - + // Parse out name. - + const char* end = ptr + 1; - while( ptr > prototype && dIsalnum( *ptr ) ) - ptr --; + while (ptr > prototype && dIsalnum(*ptr)) + ptr--; const char* start = ptr + 1; - + // Skip back over spaces. - while( ptr >= prototype && dIsspace( *ptr ) ) - ptr --; - + while (ptr >= prototype && dIsspace(*ptr)) + ptr--; + // If we're sure we don't have just a type name without an // argument name, copy out the argument name name. - if( ptr >= prototype && *ptr != ',' && *ptr != '(' && end > start ) - argNames.push_front( String( start, end - start ) ); + if (ptr >= prototype && *ptr != ',' && *ptr != '(' && end > start) + argNames.push_front(String(start, end - start)); else - argNames.push_front( "" ); - + argNames.push_front(""); + // Skip back to comma or opening parenthesis. - + U32 parenNestingCount = 0; - while( ptr >= prototype ) + while (ptr >= prototype) { - if( *ptr == ')' ) - parenNestingCount ++; - else if( *ptr == '(' ) - parenNestingCount --; - else if( *ptr == ',' && parenNestingCount == 0 ) + if (*ptr == ')') + parenNestingCount++; + else if (*ptr == '(') + parenNestingCount--; + else if (*ptr == ',' && parenNestingCount == 0) { - ptr --; + ptr--; break; } - else if( *ptr == '(' && parenNestingCount == 0 ) + else if (*ptr == '(' && parenNestingCount == 0) break; - - ptr --; + + ptr--; } } - + // Add 'this' parameter if this is a method. - - if( dStrncmp( prototype, "virtual ", sizeof( "virtual " ) - 1 ) == 0 ) - argNames.push_front( "this" ); + + if (dStrncmp(prototype, "virtual ", sizeof("virtual ") - 1) == 0) + argNames.push_front("this"); return argNames; } //----------------------------------------------------------------------------- -static String getDefaultArgumentValue( const EngineFunctionInfo* function, const EngineTypeInfo* type, U32 offset ) +static String getDefaultArgumentValue(const EngineFunctionInfo* function, const EngineTypeInfo* type, U32 offset) { String value; const EngineFunctionDefaultArguments* defaultArgs = function->getDefaultArguments(); - - switch( type->getTypeKind() ) + + switch (type->getTypeKind()) { - case EngineTypeKindPrimitive: - { - #define PRIMTYPE( tp ) \ + case EngineTypeKindPrimitive: + { +#define PRIMTYPE( tp ) \ if( TYPE< tp >() == type ) \ { \ tp val = getArgValue< tp >( defaultArgs, offset ); \ value = String::ToString( val ); \ } - - PRIMTYPE( bool ); - PRIMTYPE( S8 ); - PRIMTYPE( U8 ); - PRIMTYPE( S32 ); - PRIMTYPE( U32 ); - PRIMTYPE( F32 ); - PRIMTYPE( F64 ); - - //TODO: for now we store string literals in ASCII; needs to be sorted out - if( TYPE< const char* >() == type ) - { - const char* val = reinterpret_cast< const char* >(defaultArgs->getArgs() + offset); - value = val; - } - - #undef PRIMTYPE - break; - } - - case EngineTypeKindEnum: + + PRIMTYPE(bool); + PRIMTYPE(S8); + PRIMTYPE(U8); + PRIMTYPE(S32); + PRIMTYPE(U32); + PRIMTYPE(F32); + PRIMTYPE(F64); + + //TODO: for now we store string literals in ASCII; needs to be sorted out + if (TYPE< const char* >() == type) { - S32 val = getArgValue< S32 >( defaultArgs, offset ); - AssertFatal( type->getEnumTable(), "engineXMLExport - Enum type without table!" ); - - const EngineEnumTable& table = *( type->getEnumTable() ); - const U32 numValues = table.getNumValues(); - - for( U32 i = 0; i < numValues; ++ i ) - if( table[ i ].getInt() == val ) - { - value = table[ i ].getName(); - break; - } - - break; + const char* val = reinterpret_cast(defaultArgs->getArgs() + offset); + value = val; } - case EngineTypeKindBitfield: - { - S32 val = getArgValue< S32 >( defaultArgs, offset ); - AssertFatal( type->getEnumTable(), "engineXMLExport - Bitfield type without table!" ); - - const EngineEnumTable& table = *( type->getEnumTable() ); - const U32 numValues = table.getNumValues(); - - bool isFirst = true; - for( U32 i = 0; i < numValues; ++ i ) - if( table[ i ].getInt() & val ) - { - if( !isFirst ) - value += '|'; - - value = table[ i ].getName(); - isFirst = false; - } - - break; - } - - case EngineTypeKindStruct: - { - //TODO: struct type default argument values - break; - } - - case EngineTypeKindClass: - case EngineTypeKindFunction: - { - // For these two kinds, we support "null" as the only valid - // default value. - - const void* ptr = getArgValue< const void* >( defaultArgs, offset ); - if( !ptr ) - value = "null"; - break; - } - - default: - break; +#undef PRIMTYPE + break; } - + + case EngineTypeKindEnum: + { + S32 val = getArgValue< S32 >(defaultArgs, offset); + AssertFatal(type->getEnumTable(), "engineXMLExport - Enum type without table!"); + + const EngineEnumTable& table = *(type->getEnumTable()); + const U32 numValues = table.getNumValues(); + + for (U32 i = 0; i < numValues; ++i) + if (table[i].getInt() == val) + { + value = table[i].getName(); + break; + } + + break; + } + + case EngineTypeKindBitfield: + { + S32 val = getArgValue< S32 >(defaultArgs, offset); + AssertFatal(type->getEnumTable(), "engineXMLExport - Bitfield type without table!"); + + const EngineEnumTable& table = *(type->getEnumTable()); + const U32 numValues = table.getNumValues(); + + bool isFirst = true; + for (U32 i = 0; i < numValues; ++i) + if (table[i].getInt() & val) + { + if (!isFirst) + value += '|'; + + value = table[i].getName(); + isFirst = false; + } + + break; + } + + case EngineTypeKindStruct: + { + //TODO: struct type default argument values + break; + } + + case EngineTypeKindClass: + case EngineTypeKindFunction: + { + // For these two kinds, we support "null" as the only valid + // default value. + + const void* ptr = getArgValue< const void* >(defaultArgs, offset); + if (!ptr) + value = "null"; + break; + } + + default: + break; + } + return value; } //----------------------------------------------------------------------------- -static void exportFunction( const EngineFunctionInfo* function, SimXMLDocument* xml ) +static void exportFunction(const EngineFunctionInfo* function, SimXMLDocument* xml) { - if( isExportFiltered( function ) ) + if (isExportFiltered(function)) return; - - xml->pushNewElement( "EngineFunction" ); - - xml->setAttribute( "name", function->getExportName() ); - xml->setAttribute( "returnType", getTypeName( function->getReturnType() ) ); - xml->setAttribute( "symbol", function->getBindingName() ); - xml->setAttribute( "isCallback", function->isCallout() ? "1" : "0" ); - xml->setAttribute( "isVariadic", function->getFunctionType()->isVariadic() ? "1" : "0" ); - xml->setAttribute( "docs", getDocString( function ) ); - - xml->pushNewElement( "arguments" ); - - const U32 numArguments = function->getNumArguments(); - const U32 numDefaultArguments = ( function->getDefaultArguments() ? function->getDefaultArguments()->mNumDefaultArgs : 0 ); - const U32 firstDefaultArg = numArguments - numDefaultArguments; - - Vector< String > argumentNames = parseFunctionArgumentNames( function ); - const U32 numArgumentNames = argumentNames.size(); - - // Accumulated offset in function argument frame vector. - U32 argFrameOffset = 0; - - for( U32 i = 0; i < numArguments; ++ i ) - { - xml->pushNewElement( "EngineFunctionArgument" ); - const EngineTypeInfo* type = function->getArgumentType( i ); - AssertFatal( type != NULL, "exportFunction - Argument cannot have type void!" ); - - String argName; - if( i < numArgumentNames ) - argName = argumentNames[ i ]; - - xml->setAttribute( "name", argName ); - xml->setAttribute( "type", getTypeName( type ) ); - - if( i >= firstDefaultArg ) - { - String defaultValue = getDefaultArgumentValue( function, type, argFrameOffset ); - xml->setAttribute( "defaultValue", defaultValue ); - } - xml->popElement(); - - if( type->getTypeKind() == EngineTypeKindStruct ) - argFrameOffset += type->getInstanceSize(); - else - argFrameOffset += type->getValueSize(); - - #ifdef _PACK_BUG_WORKAROUNDS - if( argFrameOffset % 4 > 0 ) - argFrameOffset += 4 - ( argFrameOffset % 4 ); - #endif - } - + xml->pushNewElement("EngineFunction"); + + xml->setAttribute("name", function->getExportName()); + xml->setAttribute("returnType", getTypeName(function->getReturnType())); + xml->setAttribute("symbol", function->getBindingName()); + xml->setAttribute("isCallback", function->isCallout() ? "1" : "0"); + xml->setAttribute("isVariadic", function->getFunctionType()->isVariadic() ? "1" : "0"); + xml->setAttribute("docs", getDocString(function)); + + xml->pushNewElement("arguments"); + + const U32 numArguments = function->getNumArguments(); + const U32 numDefaultArguments = (function->getDefaultArguments() ? function->getDefaultArguments()->mNumDefaultArgs : 0); + const U32 firstDefaultArg = numArguments - numDefaultArguments; + + Vector< String > argumentNames = parseFunctionArgumentNames(function); + const U32 numArgumentNames = argumentNames.size(); + + // Accumulated offset in function argument frame vector. + U32 argFrameOffset = 0; + + for (U32 i = 0; i < numArguments; ++i) + { + xml->pushNewElement("EngineFunctionArgument"); + const EngineTypeInfo* type = function->getArgumentType(i); + AssertFatal(type != NULL, "exportFunction - Argument cannot have type void!"); + + String argName; + if (i < numArgumentNames) + argName = argumentNames[i]; + + xml->setAttribute("name", argName); + xml->setAttribute("type", getTypeName(type)); + + if (i >= firstDefaultArg) + { + String defaultValue = getDefaultArgumentValue(function, type, argFrameOffset); + xml->setAttribute("defaultValue", defaultValue); + } + xml->popElement(); - + + if (type->getTypeKind() == EngineTypeKindStruct) + argFrameOffset += type->getInstanceSize(); + else + argFrameOffset += type->getValueSize(); + +#ifdef _PACK_BUG_WORKAROUNDS + if (argFrameOffset % 4 > 0) + argFrameOffset += 4 - (argFrameOffset % 4); +#endif + } + + xml->popElement(); + xml->popElement(); } @@ -343,148 +343,172 @@ static void exportFunction( const EngineFunctionInfo* function, SimXMLDocument* //----------------------------------------------------------------------------- -static void exportType( const EngineTypeInfo* type, SimXMLDocument* xml ) +static void exportType(const EngineTypeInfo* type, SimXMLDocument* xml) { // Don't export anonymous types. - if( !type->getTypeName()[ 0 ] ) + if (!type->getTypeName()[0]) return; - - if( isExportFiltered( type ) ) - return; - - const char* nodeName = NULL; - switch( type->getTypeKind() ) - { - case EngineTypeKindPrimitive: - nodeName = "EnginePrimitiveType"; - break; - - case EngineTypeKindEnum: - nodeName = "EngineEnumType"; - break; - - case EngineTypeKindBitfield: - nodeName = "EngineBitfieldType"; - break; - - case EngineTypeKindStruct: - nodeName = "EngineStructType"; - break; - - case EngineTypeKindClass: - nodeName = "EngineClassType"; - break; - - default: - return; - } - - xml->pushNewElement( nodeName ); - xml->setAttribute( "name", type->getTypeName() ); - xml->setAttribute( "size", String::ToString( type->getInstanceSize() ) ); - xml->setAttribute( "isAbstract", type->isAbstract() ? "1" : "0" ); - xml->setAttribute( "isInstantiable", type->isInstantiable() ? "1" : "0" ); - xml->setAttribute( "isDisposable", type->isDisposable() ? "1" : "0" ); - xml->setAttribute( "isSingleton", type->isSingleton() ? "1" : "0" ); - xml->setAttribute( "docs", getDocString( type ) ); - - if( type->getSuperType() ) - xml->setAttribute( "superType", getTypeName( type->getSuperType() ) ); - - if( type->getEnumTable() ) + if (isExportFiltered(type)) + return; + + const char* nodeName = NULL; + switch (type->getTypeKind()) + { + case EngineTypeKindPrimitive: + nodeName = "EnginePrimitiveType"; + break; + + case EngineTypeKindEnum: + nodeName = "EngineEnumType"; + break; + + case EngineTypeKindBitfield: + nodeName = "EngineBitfieldType"; + break; + + case EngineTypeKindStruct: + nodeName = "EngineStructType"; + break; + + case EngineTypeKindClass: + nodeName = "EngineClassType"; + break; + + default: + return; + } + + xml->pushNewElement(nodeName); + + xml->setAttribute("name", type->getTypeName()); + xml->setAttribute("size", String::ToString(type->getInstanceSize())); + xml->setAttribute("isAbstract", type->isAbstract() ? "1" : "0"); + xml->setAttribute("isInstantiable", type->isInstantiable() ? "1" : "0"); + xml->setAttribute("isDisposable", type->isDisposable() ? "1" : "0"); + xml->setAttribute("isSingleton", type->isSingleton() ? "1" : "0"); + xml->setAttribute("docs", getDocString(type)); + + if (type->getSuperType()) + xml->setAttribute("superType", getTypeName(type->getSuperType())); + + if (type->getEnumTable()) + { + xml->pushNewElement("enums"); + + const EngineEnumTable& table = *(type->getEnumTable()); + const U32 numValues = table.getNumValues(); + + for (U32 i = 0; i < numValues; ++i) { - xml->pushNewElement( "enums" ); - - const EngineEnumTable& table = *( type->getEnumTable() ); - const U32 numValues = table.getNumValues(); - - for( U32 i = 0; i < numValues; ++ i ) - { - xml->pushNewElement( "EngineEnum" ); - - xml->setAttribute( "name", table[ i ].getName() ); - xml->setAttribute( "value", String::ToString( table[ i ].getInt() ) ); - xml->setAttribute( "docs", table[ i ].getDocString() ? table[ i ].getDocString() : "" ); - - xml->popElement(); - } - + xml->pushNewElement("EngineEnum"); + + xml->setAttribute("name", table[i].getName()); + xml->setAttribute("value", String::ToString(table[i].getInt())); + xml->setAttribute("docs", table[i].getDocString() ? table[i].getDocString() : ""); + xml->popElement(); } - else if( type->getFieldTable() ) + + xml->popElement(); + } + else if (type->getFieldTable()) + { + xml->pushNewElement("fields"); + + const EngineFieldTable& table = *(type->getFieldTable()); + const U32 numFields = table.getNumFields(); + + for (U32 i = 0; i < numFields; ++i) { - xml->pushNewElement( "fields" ); - - const EngineFieldTable& table = *( type->getFieldTable() ); - const U32 numFields = table.getNumFields(); - - for( U32 i = 0; i < numFields; ++ i ) - { - const EngineFieldTable::Field& field = table[ i ]; - - xml->pushNewElement( "EngineField" ); - - xml->setAttribute( "name", field.getName() ); - xml->setAttribute( "type", getTypeName( field.getType() ) ); - xml->setAttribute( "offset", String::ToString( field.getOffset() ) ); - xml->setAttribute( "indexedSize", String::ToString( field.getNumElements() ) ); - xml->setAttribute( "docs", field.getDocString() ? field.getDocString() : "" ); - - xml->popElement(); - } - + const EngineFieldTable::Field& field = table[i]; + + xml->pushNewElement("EngineField"); + + xml->setAttribute("name", field.getName()); + xml->setAttribute("type", getTypeName(field.getType())); + xml->setAttribute("offset", String::ToString(field.getOffset())); + xml->setAttribute("indexedSize", String::ToString(field.getNumElements())); + xml->setAttribute("docs", field.getDocString() ? field.getDocString() : ""); + xml->popElement(); } - else if( type->getPropertyTable() ) + + xml->popElement(); + } + else if (type->getPropertyTable()) + { + xml->pushNewElement("properties"); + + const EnginePropertyTable& table = *(type->getPropertyTable()); + const U32 numProperties = table.getNumProperties(); + U32 groupNestingDepth = 0; + + for (U32 i = 0; i < numProperties; ++i) { - xml->pushNewElement( "properties" ); - - const EnginePropertyTable& table = *( type->getPropertyTable() ); - const U32 numProperties = table.getNumProperties(); - U32 groupNestingDepth = 0; - - for( U32 i = 0; i < numProperties; ++ i ) + const EnginePropertyTable::Property& property = table[i]; + + if (property.isGroupBegin()) + { + groupNestingDepth++; + xml->pushNewElement("EnginePropertyGroup"); + + xml->setAttribute("name", property.getName()); + xml->setAttribute("indexedSize", String::ToString(property.getNumElements())); + xml->setAttribute("docs", property.getDocString() ? property.getDocString() : ""); + + xml->pushNewElement("properties"); + } + else if (property.isGroupEnd()) + { + groupNestingDepth--; + xml->popElement(); + xml->popElement(); + } + else + { + if (property.getType() == AbstractClassRep::StartArrayFieldType + || property.getType() == AbstractClassRep::EndArrayFieldType) { + continue; + } + xml->pushNewElement("EngineProperty"); + + xml->setAttribute("name", property.getName()); + xml->setAttribute("indexedSize", String::ToString(property.getNumElements())); + xml->setAttribute("isConstant", property.isConstant() ? "1" : "0"); + xml->setAttribute("isTransient", property.isTransient() ? "1" : "0"); + xml->setAttribute("isVisible", property.hideInInspectors() ? "0" : "1"); + xml->setAttribute("docs", property.getDocString() ? property.getDocString() : ""); + + + const bool isDeprecated = (property.getType() == AbstractClassRep::DeprecatedFieldType); + + if (isDeprecated) { - const EnginePropertyTable::Property& property = table[ i ]; - - if( property.isGroupBegin() ) + xml->setAttribute("type", "deprecated"); + } + else + { + ConsoleBaseType *cbt = ConsoleBaseType::getType(property.getType()); + if (cbt != NULL) { - groupNestingDepth ++; - xml->pushNewElement( "EnginePropertyGroup" ); - - xml->setAttribute( "name", property.getName() ); - xml->setAttribute( "indexedSize", String::ToString( property.getNumElements() ) ); - xml->setAttribute( "docs", property.getDocString() ? property.getDocString() : "" ); - - xml->pushNewElement( "properties" ); - } - else if( property.isGroupEnd() ) - { - groupNestingDepth --; - xml->popElement(); - xml->popElement(); + xml->setAttribute("type", cbt->getTypeClassName()); } else { - xml->pushNewElement( "EngineProperty" ); - - xml->setAttribute( "name", property.getName() ); - xml->setAttribute( "indexedSize", String::ToString( property.getNumElements() ) ); - xml->setAttribute( "isConstant", property.isConstant() ? "1" : "0" ); - xml->setAttribute( "isTransient", property.isTransient() ? "1" : "0" ); - xml->setAttribute( "isVisible", property.hideInInspectors() ? "0" : "1" ); - xml->setAttribute( "docs", property.getDocString() ? property.getDocString() : "" ); - - xml->popElement(); + xml->setAttribute("type", "unknown"); } } - - AssertFatal( !groupNestingDepth, "exportType - Property group nesting mismatch!" ); - xml->popElement(); - } - exportScope( type, xml ); - + + xml->popElement(); + } + } + + AssertFatal(!groupNestingDepth, "exportType - Property group nesting mismatch!"); + xml->popElement(); + } + exportScope(type, xml); + xml->popElement(); } @@ -496,63 +520,63 @@ static void exportType( const EngineTypeInfo* type, SimXMLDocument* xml ) //----------------------------------------------------------------------------- -static void exportScope( const EngineExportScope* scope, SimXMLDocument* xml, bool addNode ) +static void exportScope(const EngineExportScope* scope, SimXMLDocument* xml, bool addNode) { - if( addNode ) + if (addNode) { - if( isExportFiltered( scope ) ) + if (isExportFiltered(scope)) return; - - xml->pushNewElement( "EngineExportScope" ); - - xml->setAttribute( "name", scope->getExportName() ); - xml->setAttribute( "docs", getDocString( scope ) ); + + xml->pushNewElement("EngineExportScope"); + + xml->setAttribute("name", scope->getExportName()); + xml->setAttribute("docs", getDocString(scope)); } // Dump all contained exports. - - xml->pushNewElement( "exports" ); - - for( const EngineExport* exportInfo = scope->getExports(); exportInfo != NULL; exportInfo = exportInfo->getNextExport() ) + + xml->pushNewElement("exports"); + + for (const EngineExport* exportInfo = scope->getExports(); exportInfo != NULL; exportInfo = exportInfo->getNextExport()) + { + switch (exportInfo->getExportKind()) { - switch( exportInfo->getExportKind() ) - { - case EngineExportKindScope: - exportScope( static_cast< const EngineExportScope* >( exportInfo ), xml, true ); - break; - - case EngineExportKindFunction: - exportFunction( static_cast< const EngineFunctionInfo* >( exportInfo ), xml ); - break; - - case EngineExportKindType: - exportType( static_cast< const EngineTypeInfo* >( exportInfo ), xml ); - break; - - default: - break; - } + case EngineExportKindScope: + exportScope(static_cast< const EngineExportScope* >(exportInfo), xml, true); + break; + + case EngineExportKindFunction: + exportFunction(static_cast< const EngineFunctionInfo* >(exportInfo), xml); + break; + + case EngineExportKindType: + exportType(static_cast< const EngineTypeInfo* >(exportInfo), xml); + break; + + default: + break; } - + } + xml->popElement(); - - if( addNode ) + + if (addNode) xml->popElement(); } //----------------------------------------------------------------------------- -DefineEngineFunction( exportEngineAPIToXML, SimXMLDocument*, (),, +DefineEngineFunction(exportEngineAPIToXML, SimXMLDocument*, (), , "Create a XML document containing a dump of the entire exported engine API.\n\n" "@return A SimXMLDocument containing a dump of the engine's export information or NULL if the operation failed.\n\n" - "@ingroup Console" ) + "@ingroup Console") { SimXMLDocument* xml = new SimXMLDocument; xml->registerObject(); - Sim::getRootGroup()->addObject( xml ); + Sim::getRootGroup()->addObject(xml); xml->addHeader(); - - exportScope( EngineExportScope::getGlobalScope(), xml, true ); - + + exportScope(EngineExportScope::getGlobalScope(), xml, true); + return xml; -} +} \ No newline at end of file From 33df2945314f42049e09b5c484cd3e117cd16863 Mon Sep 17 00:00:00 2001 From: Lukas Joergensen Date: Sat, 21 Apr 2018 09:21:21 +0200 Subject: [PATCH 15/34] Mark EngineAPI as initialized, otherwise it can't be used --- Engine/source/app/mainLoop.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Engine/source/app/mainLoop.cpp b/Engine/source/app/mainLoop.cpp index b08363f8a..36998169f 100644 --- a/Engine/source/app/mainLoop.cpp +++ b/Engine/source/app/mainLoop.cpp @@ -267,6 +267,9 @@ void StandardMainLoop::init() ThreadPool::GlobalThreadPool::createSingleton(); + // Set engineAPI initialized to true + engineAPI::gIsInitialized = true; + // Initialize modules. EngineModuleManager::initializeSystem(); From 780e1dc73fad59b6ebcd36b8074e066ce0f7118d Mon Sep 17 00:00:00 2001 From: Lukas Joergensen Date: Sat, 21 Apr 2018 09:22:12 +0200 Subject: [PATCH 16/34] Use FixedTuple in EngineTrampoline, to make memory-layout consistent --- Engine/source/console/engineAPI.h | 43 ++++++++++++++++++++++++++----- 1 file changed, 37 insertions(+), 6 deletions(-) diff --git a/Engine/source/console/engineAPI.h b/Engine/source/console/engineAPI.h index ab1717745..5fa20a82c 100644 --- a/Engine/source/console/engineAPI.h +++ b/Engine/source/console/engineAPI.h @@ -26,6 +26,10 @@ #include #include +#ifndef _FIXEDTUPLE_H_ +#include "fixedTuple.h" +#endif + #ifndef _CONSOLETYPES_H_ #include "console/consoleTypes.h" #endif @@ -347,6 +351,8 @@ struct _EngineTrampoline< R( ArgTs ... ) > { typedef std::tuple Args; std::tuple argT; + typedef fixed_tuple FixedArgs; + fixed_tuple fixedArgT; }; template< typename T > @@ -365,6 +371,7 @@ struct _EngineFunctionTrampoline< R(ArgTs...) > : public _EngineFunctionTrampoli private: using Super = _EngineFunctionTrampolineBase< R(ArgTs...) >; using ArgsType = typename Super::Args; + using FixedArgsType = typename Super::FixedArgs; template struct Seq {}; template struct Gens : Gens {}; @@ -374,6 +381,11 @@ private: static R dispatchHelper(typename Super::FunctionType fn, const ArgsType& args, Seq) { return R( fn(std::get(args) ...) ); } + + template + static R dispatchHelper(typename Super::FunctionType fn, const FixedArgsType& args, Seq) { + return R( fn(fixed_tuple_accessor::get(args) ...) ); + } using SeqType = typename Gens::type; public: @@ -381,6 +393,11 @@ public: { return dispatchHelper(fn, args, SeqType()); } + + static R jmp(typename Super::FunctionType fn, const FixedArgsType& args ) + { + return dispatchHelper(fn, args, SeqType()); + } }; // Trampolines for engine methods @@ -398,6 +415,7 @@ struct _EngineMethodTrampoline< Frame, R(ArgTs ...) > : public _EngineMethodTram private: using Super = _EngineMethodTrampolineBase< R(ArgTs ...) >; using ArgsType = typename _EngineFunctionTrampolineBase< R(ArgTs ...) >::Args; + using FixedArgsType = typename Super::FixedArgs; template struct Seq {}; template struct Gens : Gens {}; @@ -408,6 +426,11 @@ private: return R( f._exec(std::get(args) ...) ); } + template + static R dispatchHelper(Frame f, const FixedArgsType& args, Seq) { + return R( f._exec(fixed_tuple_accessor::get(args) ...) ); + } + using SeqType = typename Gens::type; public: static R jmp( typename Frame::ObjectType* object, const ArgsType& args ) @@ -417,6 +440,14 @@ public: f.object = object; return dispatchHelper(f, args, SeqType()); } + + static R jmp( typename Frame::ObjectType* object, const FixedArgsType& args ) + { + + Frame f; + f.object = object; + return dispatchHelper(f, args, SeqType()); + } }; /// @} @@ -683,7 +714,7 @@ public: #define DefineEngineFunction( name, returnType, args, defaultArgs, usage ) \ static inline returnType _fn ## name ## impl args; \ TORQUE_API EngineTypeTraits< returnType >::ReturnValueType fn ## name \ - ( _EngineFunctionTrampoline< returnType args >::Args a ) \ + ( _EngineFunctionTrampoline< returnType args >::FixedArgs a ) \ { \ _CHECK_ENGINE_INITIALIZED( name, returnType ); \ return EngineTypeTraits< returnType >::ReturnValue( \ @@ -702,7 +733,7 @@ public: ( void* ) &fn ## name, \ 0 \ ); \ - static _EngineConsoleThunkType< returnType >::ReturnType _ ## name ## caster( SimObject*, S32 argc, ConsoleValueRef *argv ) \ + static _EngineConsoleThunkType< returnType >::ReturnType _ ## name ## caster( SimObject*, S32 argc, ConsoleValueRef *argv ) \ { \ return _EngineConsoleThunkType< returnType >::ReturnType( _EngineConsoleThunk< 1, returnType args >::thunk( \ argc, argv, &_fn ## name ## impl, _fn ## name ## DefaultArgs \ @@ -737,7 +768,7 @@ public: #define _DefineMethodTrampoline( className, name, returnType, args ) \ TORQUE_API EngineTypeTraits< returnType >::ReturnValueType \ - fn ## className ## _ ## name ( className* object, _EngineMethodTrampoline< _ ## className ## name ## frame, returnType args >::Args a ) \ + fn ## className ## _ ## name ( className* object, _EngineMethodTrampoline< _ ## className ## name ## frame, returnType args >::FixedArgs a )\ { \ _CHECK_ENGINE_INITIALIZED( className::name, returnType ); \ return EngineTypeTraits< returnType >::ReturnValue( \ @@ -820,7 +851,7 @@ public: #define DefineEngineStaticMethod( className, name, returnType, args, defaultArgs, usage ) \ static inline returnType _fn ## className ## name ## impl args; \ TORQUE_API EngineTypeTraits< returnType >::ReturnValueType fn ## className ## _ ## name \ - ( _EngineFunctionTrampoline< returnType args >::Args a ) \ + ( _EngineFunctionTrampoline< returnType args >::FixedArgs a ) \ { \ _CHECK_ENGINE_INITIALIZED( className::name, returnType ); \ return EngineTypeTraits< returnType >::ReturnValue( \ @@ -920,7 +951,7 @@ public: #define DefineNewEngineFunction( name, returnType, args, defaultArgs, usage ) \ static inline returnType _fn ## name ## impl args; \ TORQUE_API EngineTypeTraits< returnType >::ReturnValueType fn ## name \ - ( _EngineFunctionTrampoline< returnType args >::Args a ) \ + ( _EngineFunctionTrampoline< returnType args >::FixedArgs a ) \ { \ _CHECK_ENGINE_INITIALIZED( name, returnType ); \ return EngineTypeTraits< returnType >::ReturnValue( \ @@ -967,7 +998,7 @@ public: #define DefineNewEngineStaticMethod( className, name, returnType, args, defaultArgs, usage ) \ static inline returnType _fn ## className ## name ## impl args; \ TORQUE_API EngineTypeTraits< returnType >::ReturnValueType fn ## className ## _ ## name \ - ( _EngineFunctionTrampoline< returnType args >::Args a ) \ + ( _EngineFunctionTrampoline< returnType args >::FixedArgs a ) \ { \ _CHECK_ENGINE_INITIALIZED( className::name, returnType ); \ return EngineTypeTraits< returnType >::ReturnValue( \ From 2fe623b7616e49ebda19be7607a8de6b91dd6675 Mon Sep 17 00:00:00 2001 From: Lukas Joergensen Date: Sat, 21 Apr 2018 09:23:38 +0200 Subject: [PATCH 17/34] Pass structs by value, not by reference, in EngineAPI. This simplifies call-layout through EngineAPI --- Engine/source/console/engineTypes.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Engine/source/console/engineTypes.h b/Engine/source/console/engineTypes.h index 2217ee770..51d2ef84d 100644 --- a/Engine/source/console/engineTypes.h +++ b/Engine/source/console/engineTypes.h @@ -236,16 +236,16 @@ template< typename T > struct _EngineStructTypeTraits { typedef T Type; - typedef const T& ValueType; + typedef const T ValueType; typedef void SuperType; // Structs get passed in as pointers and passed out as full copies. - typedef T* ArgumentValueType; + typedef T ArgumentValueType; typedef T ReturnValueType; typedef T DefaultArgumentValueStoreType; typedef ReturnValueType ReturnValue; - static ValueType ArgumentToValue( ArgumentValueType val ) { return *val; } + static ValueType ArgumentToValue( ArgumentValueType val ) { return val; } static const EngineTypeInfo* const TYPEINFO; }; From 13eb392c98706f65aa10c2a95c17c8a4f6fff465 Mon Sep 17 00:00:00 2001 From: Lukas Joergensen Date: Sat, 21 Apr 2018 09:29:57 +0200 Subject: [PATCH 18/34] Add a method to set the 'MainDotCsDir' when no main.cs is available --- Engine/source/platform/platformFileIO.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Engine/source/platform/platformFileIO.cpp b/Engine/source/platform/platformFileIO.cpp index 788ed4f62..58123dbb1 100644 --- a/Engine/source/platform/platformFileIO.cpp +++ b/Engine/source/platform/platformFileIO.cpp @@ -620,3 +620,8 @@ DefineEngineFunction( getUserHomeDirectory, const char *, (), , "getUserHomeDire { return Platform::getUserHomeDirectory(); } + +DefineEngineFunction(setMainDotCsDir, void, (const char* path), , "setMainDotCsDir()") +{ + Platform::setMainDotCsDir(StringTable->insert(path)); +} \ No newline at end of file From ae1f5a3c8956cfae3bfb76e37494470955faf12e Mon Sep 17 00:00:00 2001 From: Lukas Joergensen Date: Sat, 21 Apr 2018 10:11:01 +0200 Subject: [PATCH 19/34] Update the CInterface --- .../source/cinterface/c_consoleInterface.cpp | 143 +---- .../source/cinterface/c_controlInterface.cpp | 239 +++++++++ Engine/source/cinterface/c_controlInterface.h | 48 ++ Engine/source/cinterface/c_scripting.cpp | 426 --------------- Engine/source/cinterface/c_simInterface.cpp | 54 ++ .../cinterface/c_simdatablockInterface.cpp | 40 ++ .../cinterface/c_simobjectInterface.cpp | 71 +++ Engine/source/cinterface/cinterface.cpp | 499 +++--------------- Engine/source/cinterface/cinterface.h | 39 +- Engine/source/platformMac/macFileIO.mm | 2 +- 10 files changed, 576 insertions(+), 985 deletions(-) create mode 100644 Engine/source/cinterface/c_controlInterface.cpp create mode 100644 Engine/source/cinterface/c_controlInterface.h delete mode 100644 Engine/source/cinterface/c_scripting.cpp create mode 100644 Engine/source/cinterface/c_simInterface.cpp create mode 100644 Engine/source/cinterface/c_simdatablockInterface.cpp create mode 100644 Engine/source/cinterface/c_simobjectInterface.cpp diff --git a/Engine/source/cinterface/c_consoleInterface.cpp b/Engine/source/cinterface/c_consoleInterface.cpp index 21a2e48fd..09b406da3 100644 --- a/Engine/source/cinterface/c_consoleInterface.cpp +++ b/Engine/source/cinterface/c_consoleInterface.cpp @@ -20,154 +20,59 @@ // IN THE SOFTWARE. //----------------------------------------------------------------------------- -#include "platform/platform.h" -#include "console/compiler.h" #include "console/consoleInternal.h" #include "console/simSet.h" +#include "console/engineAPI.h" -extern "C" { - - // SimObject C interface - const char *SimObject_GetName(SimObject *so) +namespace Con +{ + DefineNewEngineFunction(AddConsumer, void, (ConsumerCallback cb), , "") { - return so->getName(); + addConsumer(cb); } - U32 SimObject_GetId(SimObject *so) + DefineNewEngineFunction(RemoveConsumer, void, (ConsumerCallback cb), , "") { - return so->getId(); + removeConsumer(cb); } - const char *SimObject_GetClassName(SimObject *so) + DefineNewEngineFunction(GetConsoleString, String, (String name),, "") { - return so->getClassName(); + return getVariable(StringTable->insert(name)); } - void *SimObject_GetFieldList(SimObject *so, S32 &outNumFields) + DefineNewEngineFunction(SetConsoleString, void, (String name, String value),, "") { - const AbstractClassRep::FieldList &fl = so->getFieldList(); - outNumFields = fl.size(); - return fl.address(); + setVariable(StringTable->insert(name), StringTable->insert(value)); } - bool SimObject_IsLocked(SimObject *so) + DefineNewEngineFunction(GetConsoleInt, S32, (String name),, "") { - return so->isLocked(); + return getIntVariable(StringTable->insert(name)); } - void SimObject_SetDataField(SimObject *so, const char *fieldName, const char *arr, const char *val) + DefineNewEngineFunction(SetConsoleInt, void, (String name, S32 value),, "") { - so->setDataField(StringTable->insert(fieldName), arr, val); + setIntVariable(StringTable->insert(name), value); } - const char *SimObject_GetDataField(SimObject *so, const char *fieldName, const char *arr) + DefineNewEngineFunction(GetConsoleFloat, F32, (String name),, "") { - return so->getDataField(StringTable->insert(fieldName), arr); + return getFloatVariable(StringTable->insert(name)); } - void SimObject_InspectPreApply(SimObject *so) + DefineNewEngineFunction(SetConsoleFloat, void, (String name, F32 value),, "") { - so->inspectPreApply(); + setFloatVariable(StringTable->insert(name), value); } - void SimObject_InspectPostApply(SimObject *so) + DefineNewEngineFunction(GetConsoleBool, bool, (String name),, "") { - so->inspectPostApply(); + return getBoolVariable(StringTable->insert(name)); } - // Con C interface - void Con_AddConsumer(ConsumerCallback cb) + DefineNewEngineFunction(SetConsoleBool, void, (String name, bool value),, "") { - Con::addConsumer(cb); + setBoolVariable(StringTable->insert(name), value); } - - void Con_RemoveConsumer(ConsumerCallback cb) - { - Con::removeConsumer(cb); - } - - void Con_AddCommand_String(StringCallback cb, const char *nameSpace, const char *funcName, const char* usage, S32 minArgs, S32 maxArgs) - { - if (!nameSpace || !dStrlen(nameSpace)) - Con::addCommand(funcName, cb, usage, minArgs + 1, maxArgs + 1); - else - Con::addCommand(nameSpace, funcName, cb, usage, minArgs + 1, maxArgs + 1); - } - - // ConsoleBaseType C interface - ConsoleBaseType *ConsoleBaseType_GetTypeById(const S32 typeId) - { - return ConsoleBaseType::getType(typeId); - } - - S32 ConsoleBaseType_GetTypeId(ConsoleBaseType *cbt) - { - return cbt->getTypeID(); - } - - S32 ConsoleBaseType_GetTypeSize(ConsoleBaseType *cbt) - { - return cbt->getTypeSize(); - } - - const char *ConsoleBaseType_GetTypeName(ConsoleBaseType *cbt) - { - return cbt->getTypeName(); - } - - const char *ConsoleBaseType_GetInspectorFieldType(ConsoleBaseType *cbt) - { - return cbt->getInspectorFieldType(); - } - - void ConsoleBaseType_SetData(ConsoleBaseType *cbt, void *dptr, S32 argc, const char **argv, const EnumTable *tbl, BitSet32 flag) - { - return cbt->setData(dptr, argc, argv, tbl, flag); - } - - const char *ConsoleBaseType_GetData(ConsoleBaseType *cbt, void *dptr, const EnumTable *tbl, BitSet32 flag) - { - return cbt->getData(dptr, tbl, flag); - } - - // Abstract Class Rep - AbstractClassRep *AbstractClassRep_GetCommonParent(AbstractClassRep *acr, AbstractClassRep *otheracr) - { - return acr->getCommonParent(otheracr); - } - - AbstractClassRep *AbstractClassRep_FindClassRep(const char* in_pClassName) - { - return AbstractClassRep::findClassRep(in_pClassName); - } - - U32 AbstractClassRep_GetFieldStructSize() - { - return sizeof(AbstractClassRep::Field); - } - - // Sim C interface - SimObject *Sim_FindObjectByString(const char *param) - { - return Sim::findObject(param); - } - - SimObject *Sim_FindObjectById(S32 param) - { - return Sim::findObject(param); - } - - // Sim Set - SimObject **SimSet_Begin(SimObject *simObject) - { - return dynamic_cast(simObject)->begin(); - } - - SimObject **SimSet_End(SimObject *simObject) - { - return dynamic_cast(simObject)->end(); - } - -}; - - +} \ No newline at end of file diff --git a/Engine/source/cinterface/c_controlInterface.cpp b/Engine/source/cinterface/c_controlInterface.cpp new file mode 100644 index 000000000..4a07d49db --- /dev/null +++ b/Engine/source/cinterface/c_controlInterface.cpp @@ -0,0 +1,239 @@ +//----------------------------------------------------------------------------- +// 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 "c_controlInterface.h" + +#include "console/consoleInternal.h" +#include "console/simSet.h" +#include "app/mainLoop.h" +#include "windowManager/platformWindow.h" +#include "windowManager/platformWindowMgr.h" + +#ifdef TORQUE_OS_WIN +#include "windowManager/win32/win32Window.h" +#include "windowManager/win32/winDispatch.h" +extern void createFontInit(void); +extern void createFontShutdown(void); +#endif + + +#if defined( TORQUE_MINIDUMP ) && defined( TORQUE_RELEASE ) +extern S32 CreateMiniDump(LPEXCEPTION_POINTERS ExceptionInfo); +#endif + +extern bool LinkConsoleFunctions; + +extern "C" { + + // reset the engine, unloading any current level and returning to the main menu + void torque_reset() + { + Con::evaluate("disconnect();"); + } + + // initialize Torque 3D including argument handling + bool torque_engineinit(S32 argc, const char **argv) + { + +#if defined( TORQUE_MINIDUMP ) && defined( TORQUE_RELEASE ) + __try { +#endif + + LinkConsoleFunctions = true; + +#if defined(_MSC_VER) + createFontInit(); +#endif + + // Initialize the subsystems. + StandardMainLoop::init(); + + // Handle any command line args. + if (!StandardMainLoop::handleCommandLine(argc, argv)) + { + Platform::AlertOK("Error", "Failed to initialize game, shutting down."); + return false; + } + +#if defined( TORQUE_MINIDUMP ) && defined( TORQUE_RELEASE ) + } + + __except (CreateMiniDump(GetExceptionInformation())) + { + _exit(0); + } +#endif + + return true; + + } + + // tick Torque 3D's main loop + S32 torque_enginetick() + { + +#if defined( TORQUE_MINIDUMP ) && defined( TORQUE_RELEASE ) + __try { +#endif + + bool ret = StandardMainLoop::doMainLoop(); + return ret; + +#if defined( TORQUE_MINIDUMP ) && defined( TORQUE_RELEASE ) + } + __except (CreateMiniDump(GetExceptionInformation())) + { + _exit(0); + } +#endif + + } + + S32 torque_getreturnstatus() + { + return StandardMainLoop::getReturnStatus(); + } + + // signal an engine shutdown (as with the quit(); console command) + void torque_enginesignalshutdown() + { + Con::evaluate("quit();"); + } + + // shutdown the engine + S32 torque_engineshutdown() + { + +#if defined( TORQUE_MINIDUMP ) && defined( TORQUE_RELEASE ) + __try { +#endif + + // Clean everything up. + StandardMainLoop::shutdown(); + +#if defined(_MSC_VER) + createFontShutdown(); +#endif + +#if defined( TORQUE_MINIDUMP ) && defined( TORQUE_RELEASE ) + } + + __except (CreateMiniDump(GetExceptionInformation())) + { + _exit(0); + } +#endif + + // Return. + return true; + + } + + bool torque_isdebugbuild() + { +#ifdef _DEBUG + return true; +#else + return false; +#endif + + } + + // set Torque 3D into web deployment mode (disable fullscreen exlusive mode, etc) + void torque_setwebdeployment() + { + Platform::setWebDeployment(true); + } + + // resize the Torque 3D child window to the specified width and height + void torque_resizewindow(S32 width, S32 height) + { + if (PlatformWindowManager::get() && PlatformWindowManager::get()->getFirstWindow()) + PlatformWindowManager::get()->getFirstWindow()->setSize(Point2I(width, height)); + } + +#if defined(TORQUE_OS_WIN) && !defined(TORQUE_SDL) + // retrieve the hwnd of our render window + void* torque_gethwnd() + { + if (PlatformWindowManager::get() && PlatformWindowManager::get()->getFirstWindow()) + { + Win32Window* w = (Win32Window*)PlatformWindowManager::get()->getFirstWindow(); + return (void *)w->getHWND(); + } + + return NULL; + } + + // directly add a message to the Torque 3D event queue, bypassing the Windows event queue + // this is useful in the case of the IE plugin, where we are hooking into an application + // level message, and posting to the windows queue would cause a hang + void torque_directmessage(U32 message, U32 wparam, U32 lparam) + { + if (PlatformWindowManager::get() && PlatformWindowManager::get()->getFirstWindow()) + { + Win32Window* w = (Win32Window*)PlatformWindowManager::get()->getFirstWindow(); + Dispatch(DelayedDispatch, w->getHWND(), message, wparam, lparam); + } + } + +#endif + +#ifdef TORQUE_OS_WIN + void torque_inputevent(S32 type, S32 value1, S32 value2) + { + if (PlatformWindowManager::get() && PlatformWindowManager::get()->getFirstWindow()) + { + Win32Window* w = (Win32Window*)PlatformWindowManager::get()->getFirstWindow(); + WindowId devId = w->getWindowId(); + + switch (type) + { + case 0: + w->mouseEvent.trigger(devId, 0, value1, value2, w->isMouseLocked()); + break; + case 1: + if (value2) + w->buttonEvent.trigger(devId, 0, IA_MAKE, value1); + else + w->buttonEvent.trigger(devId, 0, IA_BREAK, value1); + break; + + } + } + } +#endif + + static char* gExecutablePath = NULL; + + const char* torque_getexecutablepath() + { + return gExecutablePath; + } + + void torque_setexecutablepath(const char* directory) + { + dsize_t pathLen = dStrlen(directory) + 1; + gExecutablePath = new char[pathLen]; + dStrcpy(gExecutablePath, directory, pathLen); + } +} \ No newline at end of file diff --git a/Engine/source/cinterface/c_controlInterface.h b/Engine/source/cinterface/c_controlInterface.h new file mode 100644 index 000000000..229b07b88 --- /dev/null +++ b/Engine/source/cinterface/c_controlInterface.h @@ -0,0 +1,48 @@ +//----------------------------------------------------------------------------- +// 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 C_CONTROLINTERFACE_H +#define C_CONTROLINTERFACE_H +#include "platform/platformDlibrary.h" +#include "console/engineFunctions.h" + +TORQUE_API void torque_reset(); +TORQUE_API bool torque_engineinit(S32 argc, const char **argv); +TORQUE_API S32 torque_enginetick(); +TORQUE_API S32 torque_getreturnstatus(); +TORQUE_API void torque_enginesignalshutdown(); +TORQUE_API S32 torque_engineshutdown(); +TORQUE_API bool torque_isdebugbuild(); +TORQUE_API void torque_setwebdeployment(); +TORQUE_API void torque_resizewindow(S32 width, S32 height); + +#if defined(TORQUE_OS_WIN) && !defined(TORQUE_SDL) +TORQUE_API void* torque_gethwnd(); +TORQUE_API void torque_directmessage(U32 message, U32 wparam, U32 lparam); +#endif +#ifdef TORQUE_OS_WIN +TORQUE_API void torque_inputevent(S32 type, S32 value1, S32 value2); +#endif + +TORQUE_API const char* torque_getexecutablepath(); + +#endif // C_CONTROLINTERFACE_H diff --git a/Engine/source/cinterface/c_scripting.cpp b/Engine/source/cinterface/c_scripting.cpp deleted file mode 100644 index f10effde2..000000000 --- a/Engine/source/cinterface/c_scripting.cpp +++ /dev/null @@ -1,426 +0,0 @@ -//----------------------------------------------------------------------------- -// 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 "platform/platform.h" -#include "console/compiler.h" -#include "console/console.h" -#include "console/consoleInternal.h" -#include "core/util/tDictionary.h" -#include "app/mainLoop.h" - -// External scripting cinterface, suitable for import into any scripting system which support "C" interfaces (C#, Python, Lua, Java, etc) - -#ifdef TORQUE_OS_WIN -#include "windowManager/win32/win32Window.h" -#include "windowManager/win32/winDispatch.h" -#endif - -extern "C" { - - struct MarshalNativeEntry - { - const char* nameSpace; - const char* name; - Namespace::Entry* entry; - S32 minArgs; - S32 maxArgs; - S32 cbType; - }; - - - static Namespace::Entry* GetEntry(const char* nameSpace, const char* name) - { - Namespace* ns = NULL; - - if (!nameSpace || !dStrlen(nameSpace)) - ns = Namespace::mGlobalNamespace; - else - { - nameSpace = StringTable->insert(nameSpace); - ns = Namespace::find(nameSpace); //can specify a package here, maybe need, maybe not - } - - if (!ns) - return NULL; - - name = StringTable->insert(name); - - Namespace::Entry* entry = ns->lookupRecursive(name); - - return entry; - } - - const char * script_getconsolexml() - { - Namespace::Entry* entry = GetEntry("", "consoleExportXML"); - - if (!entry) - return ""; - - static const char* exportArgv[1] = { "consoleExportXML" }; - static StringStackConsoleWrapper exportCmd(1, exportArgv); - - return entry->cb.mStringCallbackFunc(NULL, exportCmd.argc, exportCmd.argv); - } - - MarshalNativeEntry* script_get_namespace_entry(const char* nameSpace, const char* name) - { - static MarshalNativeEntry mentry; - - Namespace::Entry* e = GetEntry(nameSpace, name); - - if (!e) - return NULL; - - mentry.nameSpace = e->mNamespace->mName; - mentry.name = e->mFunctionName; - mentry.minArgs = e->mMinArgs; - mentry.maxArgs = e->mMaxArgs; - mentry.cbType = e->mType; - mentry.entry = e; - - return &mentry; - } - - void* script_get_stringtable_entry(const char* string) - { - return (void*)StringTable->insert(string); - } - - // FIELD ACCESS - - // fieldNames must be from stringTable coming in! See Engine.stringTable - - const char* script_simobject_getfield_string(U32 id, const char* fieldName) - { - SimObject *object = Sim::findObject( id ); - if( object ) - { - return (const char *) object->getDataField(fieldName, ""); - } - return ""; - } - - void script_simobject_setfield_string(U32 objectId, const char* fieldName, const char* v) - { - SimObject *object = Sim::findObject( objectId ); - if( object ) - { - object->setDataField(fieldName, "", v); - } - } - - - bool script_simobject_getfield_bool(U32 objectId, const char* fieldName) - { - SimObject *object = Sim::findObject( objectId ); - if( object ) - { - const char *v = object->getDataField(fieldName, ""); - - return dAtob(v); - } - - return false; - } - - void script_simobject_setfield_bool(U32 objectId, const char* fieldName, bool v) - { - SimObject *object = Sim::findObject( objectId ); - if( object ) - { - object->setDataField(fieldName, "", v ? "1" : "0"); - } - } - - S32 script_simobject_getfield_int(U32 objectId, const char* fieldName) - { - SimObject *object = Sim::findObject( objectId ); - if( object ) - { - const char *v = object->getDataField(fieldName, ""); - - return dAtoi(v); - } - - return false; - } - - void script_simobject_setfield_int(U32 objectId, const char* fieldName, S32 v) - { - SimObject *object = Sim::findObject( objectId ); - if( object ) - { - // this seems pretty lame, though it is how it is handled in consoleType.cpp - char buf[256]; - dSprintf(buf, 256, "%d", v ); - object->setDataField(fieldName, "", buf); - } - } - - F32 script_simobject_getfield_float(U32 objectId, const char* fieldName) - { - SimObject *object = Sim::findObject( objectId ); - if( object ) - { - const char *v = object->getDataField(fieldName, ""); - - return dAtof(v); - } - - return false; - } - - void script_simobject_setfield_float(U32 objectId, const char* fieldName, F32 v) - { - SimObject *object = Sim::findObject( objectId ); - if( object ) - { - char buf[256]; - dSprintf(buf, 256, "%g", v ); - object->setDataField(fieldName, "", buf); - } - } - - const char* script_call_namespace_entry_string(Namespace::Entry* entry, S32 argc, const char** argv) - { - // maxArgs improper on a number of console function/methods - if (argc < entry->mMinArgs)// || argc > entry->mMaxArgs) - return ""; - - SimObject* o = NULL; - - if (entry->mNamespace && entry->mNamespace->isClass()) - { - o = Sim::findObject(dAtoi(argv[1])); - if (!o) - return ""; - } - - StringStackConsoleWrapper args(argc, argv); - return entry->cb.mStringCallbackFunc(o, args.count(), args); - } - - bool script_call_namespace_entry_bool(Namespace::Entry* entry, S32 argc, const char** argv) - { - // maxArgs improper on a number of console function/methods - if (argc < entry->mMinArgs)// || argc > entry->mMaxArgs) - return false; - - SimObject* o = NULL; - - if (entry->mNamespace && entry->mNamespace->isClass()) - { - o = Sim::findObject(dAtoi(argv[1])); - if (!o) - return false; - } - - StringStackConsoleWrapper args(argc, argv); - return entry->cb.mBoolCallbackFunc(o, args.count(), args); - } - - S32 script_call_namespace_entry_int(Namespace::Entry* entry, S32 argc, const char** argv) - { - // maxArgs improper on a number of console function/methods - if (argc < entry->mMinArgs)// || argc > entry->mMaxArgs) - return 0; - - SimObject* o = NULL; - - if (entry->mNamespace && entry->mNamespace->isClass()) - { - o = Sim::findObject(dAtoi(argv[1])); - if (!o) - return 0; - } - - StringStackConsoleWrapper args(argc, argv); - return entry->cb.mIntCallbackFunc(o, args.count(), args); - } - - F32 script_call_namespace_entry_float(Namespace::Entry* entry, S32 argc, const char** argv) - { - // maxArgs improper on a number of console function/methods - if (argc < entry->mMinArgs)// || argc > entry->mMaxArgs) - return 0.0f; - - SimObject* o = NULL; - - if (entry->mNamespace && entry->mNamespace->isClass()) - { - o = Sim::findObject(dAtoi(argv[1])); - if (!o) - return 0.0f; - } - - StringStackConsoleWrapper args(argc, argv); - return entry->cb.mFloatCallbackFunc(o, args.count(), args); - } - - - void script_call_namespace_entry_void(Namespace::Entry* entry, S32 argc, const char** argv) - { - // maxArgs improper on a number of console function/methods - if (argc < entry->mMinArgs)// || argc > entry->mMaxArgs) - return; - - SimObject* o = NULL; - - if (entry->mNamespace && entry->mNamespace->isClass()) - { - Sim::findObject(dAtoi(argv[1])); - if (!o) - return; - } - - StringStackConsoleWrapper args(argc, argv); - entry->cb.mVoidCallbackFunc(o, args.count(), args); - } - - S32 script_simobject_get_id(SimObject* so) - { - return so->getId(); - } - - S32 script_simobject_find(const char* classname, const char* name) - { - SimObject *object; - if( Sim::findObject( name, object ) ) - { - // if we specified a classname do type checking - if (classname && dStrlen(classname)) - { - AbstractClassRep* ocr = object->getClassRep(); - while (ocr) - { - if (!dStricmp(ocr->getClassName(), classname)) - return object->getId(); - ocr = ocr->getParentClass(); - } - - } - - // invalid type - return 0; - } - - // didn't find object - return 0; - } - - void script_export_callback_string(StringCallback cb, const char *nameSpace, const char *funcName, const char* usage, S32 minArgs, S32 maxArgs) - { - if (!nameSpace || !dStrlen(nameSpace)) - Con::addCommand(funcName, cb, usage, minArgs + 1, maxArgs + 1); - else - Con::addCommand(nameSpace, funcName, cb, usage, minArgs + 1, maxArgs + 1); - } - - void script_export_callback_void(VoidCallback cb, const char *nameSpace, const char *funcName, const char* usage, S32 minArgs, S32 maxArgs) - { - - if (!nameSpace || !dStrlen(nameSpace)) - Con::addCommand(funcName, cb, usage, minArgs + 1, maxArgs + 1); - else - Con::addCommand(nameSpace, funcName, cb, usage, minArgs + 1, maxArgs + 1); - - - - // example of package support - // note that Parent:: does not work with this, at least not yet anyway - - /* - Namespace* ns; - - StringTableEntry nspace = NULL; - - if (nameSpace && dStrlen(nameSpace)) - nspace = StringTable->insert(nameSpace); - - Namespace::unlinkPackages(); - ns = Namespace::find(nspace, StringTable->insert("fps")); - ns->addCommand(StringTable->insert(funcName), cb, StringTable->insert(usage), minArgs + 1, maxArgs + 1 ); - Namespace::relinkPackages(); - */ - } - - void script_export_callback_bool(BoolCallback cb, const char *nameSpace, const char *funcName, const char* usage, S32 minArgs, S32 maxArgs) - { - if (!nameSpace || !dStrlen(nameSpace)) - Con::addCommand(funcName, cb, usage, minArgs + 1, maxArgs + 1); - else - Con::addCommand(nameSpace, funcName, cb, usage, minArgs + 1, maxArgs + 1); - } - - void script_export_callback_int(IntCallback cb, const char *nameSpace, const char *funcName, const char* usage, S32 minArgs, S32 maxArgs) - { - if (!nameSpace || !dStrlen(nameSpace)) - Con::addCommand(funcName, cb, usage, minArgs + 1, maxArgs + 1); - else - Con::addCommand(nameSpace, funcName, cb, usage, minArgs + 1, maxArgs + 1); - } - - void script_export_callback_float(FloatCallback cb, const char *nameSpace, const char *funcName, const char* usage, S32 minArgs, S32 maxArgs) - { - if (!nameSpace || !dStrlen(nameSpace)) - Con::addCommand(funcName, cb, usage, minArgs + 1, maxArgs + 1); - else - Con::addCommand(nameSpace, funcName, cb, usage, minArgs + 1, maxArgs + 1); - } - - -#ifdef TORQUE_OS_WIN - - void script_input_event(S32 type, S32 value1, S32 value2) - { - if (PlatformWindowManager::get() && PlatformWindowManager::get()->getFirstWindow()) - { - Win32Window* w = (Win32Window*) PlatformWindowManager::get()->getFirstWindow(); - WindowId devId = w->getWindowId(); - - switch (type) - { - case 0: - w->mouseEvent.trigger(devId,0,value1,value2,w->isMouseLocked()); - break; - case 1: - if (value2) - w->buttonEvent.trigger(devId,0,IA_MAKE,value1); - else - w->buttonEvent.trigger(devId,0,IA_BREAK,value1); - break; - - } - - } - - } -#endif - -} - - -DefineEngineStringlyVariadicFunction(TestFunction2Args, const char *, 3, 3, "testFunction(arg1, arg2)") -{ - return "Return Value"; -} diff --git a/Engine/source/cinterface/c_simInterface.cpp b/Engine/source/cinterface/c_simInterface.cpp new file mode 100644 index 000000000..26130a685 --- /dev/null +++ b/Engine/source/cinterface/c_simInterface.cpp @@ -0,0 +1,54 @@ +//----------------------------------------------------------------------------- +// 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 "console/consoleInternal.h" +#include "console/simDatablock.h" +#include "console/simSet.h" +#include "console/engineAPI.h" + +namespace Sim +{ + DefineNewEngineFunction(FindObjectById, SimObject*, (U32 pId), , "") + { + return Sim::findObject(pId); + } + + DefineNewEngineFunction(FindObjectByName, SimObject*, (String pName), , "") + { + return Sim::findObject(StringTable->insert(pName)); + } + + DefineNewEngineFunction(FindDataBlockByName, SimObject*, (String pName), , "") + { + return Sim::getDataBlockGroup()->findObject(StringTable->insert(pName)); + } + + DefineNewEngineFunction(WrapObject, SimObjectPtr*, (SimObject* pObject), , "") + { + return new SimObjectPtr(pObject); + } + + DefineNewEngineFunction(DeleteObjectPtr, void, (SimObjectPtr* pObjectPtr), , "") + { + delete pObjectPtr; + } +} \ No newline at end of file diff --git a/Engine/source/cinterface/c_simdatablockInterface.cpp b/Engine/source/cinterface/c_simdatablockInterface.cpp new file mode 100644 index 000000000..2d7f862a3 --- /dev/null +++ b/Engine/source/cinterface/c_simdatablockInterface.cpp @@ -0,0 +1,40 @@ +//----------------------------------------------------------------------------- +// 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 "console/simDatablock.h" +#include "console/engineAPI.h" + +DefineNewEngineMethod(SimDataBlock, AssignId, void, (),, "") +{ + object->assignId(); +} + +DefineNewEngineMethod(SimDataBlock, Preload, void, (),, "") +{ + static String errorStr; + if (!object->preload(true, errorStr)) + { + Con::errorf(ConsoleLogEntry::General, "Preload failed for %s: %s.", + object->getName(), errorStr.c_str()); + object->deleteObject(); + } +} \ No newline at end of file diff --git a/Engine/source/cinterface/c_simobjectInterface.cpp b/Engine/source/cinterface/c_simobjectInterface.cpp new file mode 100644 index 000000000..757ba243b --- /dev/null +++ b/Engine/source/cinterface/c_simobjectInterface.cpp @@ -0,0 +1,71 @@ +//----------------------------------------------------------------------------- +// 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 "c_simobjectInterface.h" + +#include "console/engineAPI.h" +#include "console/simObject.h" + +DefineNewEngineMethod(SimObject, RegisterObject, bool, (),,"") +{ + return object->registerObject(); +} + +DefineNewEngineMethod(SimObject, GetField, String, (String fieldName, String arrayIndex),, "") +{ + return object->getDataField(StringTable->insert(fieldName), StringTable->insert(arrayIndex)); +} + +DefineNewEngineMethod(SimObject, SetField, void, (String fieldName, String arrayIndex, String value),, "") +{ + object->setDataField(StringTable->insert(fieldName), StringTable->insert(arrayIndex), StringTable->insert(value)); +} + +DefineNewEngineMethod(SimObject, CopyFrom, void, (SimObject* parent),, "") +{ + if (parent) + { + object->setCopySource(parent); + object->assignFieldsFrom(parent); + } +} + +DefineNewEngineMethod(SimObject, SetMods, void, (bool modStaticFields, bool modDynamicFields), , "") +{ + object->setModStaticFields(modStaticFields); + object->setModDynamicFields(modDynamicFields); +} + +DefineNewEngineMethod(SimObject, IsLocked, bool, (), , "") +{ + return object->isLocked(); +} + +DefineNewEngineMethod(SimObject, InspectPreApply, void, (), , "") +{ + object->inspectPreApply(); +} + +DefineNewEngineMethod(SimObject, InspectPostApply, void, (), , "") +{ + object->inspectPostApply(); +} \ No newline at end of file diff --git a/Engine/source/cinterface/cinterface.cpp b/Engine/source/cinterface/cinterface.cpp index 0820b3cf8..e62db2c91 100644 --- a/Engine/source/cinterface/cinterface.cpp +++ b/Engine/source/cinterface/cinterface.cpp @@ -19,449 +19,78 @@ // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS // IN THE SOFTWARE. //----------------------------------------------------------------------------- +#include "cinterface.h" -#include "platform/platform.h" #include "console/compiler.h" -#include "console/consoleInternal.h" -#include "console/engineAPI.h" -#include "core/util/tDictionary.h" -#include "core/strings/stringFunctions.h" -#include "app/mainLoop.h" #include "windowManager/platformWindow.h" -#include "windowManager/platformWindowMgr.h" -#ifdef TORQUE_OS_WIN -#include "windowManager/win32/win32Window.h" -#include "windowManager/win32/winDispatch.h" -extern void createFontInit(void); -extern void createFontShutdown(void); -#endif - -#if defined( TORQUE_MINIDUMP ) && defined( TORQUE_RELEASE ) - extern S32 CreateMiniDump(LPEXCEPTION_POINTERS ExceptionInfo); -#endif - -static HashTable gSecureScript; - -extern bool LinkConsoleFunctions; - -extern "C" { - - // reset the engine, unloading any current level and returning to the main menu - void torque_reset() - { - Con::evaluate("disconnect();"); - } - - // initialize Torque 3D including argument handling - S32 torque_engineinit(S32 argc, const char **argv) - { - -#if defined( TORQUE_MINIDUMP ) && defined( TORQUE_RELEASE ) - __try { -#endif - - LinkConsoleFunctions = true; - -#if defined(_MSC_VER) - createFontInit(); -#endif - - // Initialize the subsystems. - StandardMainLoop::init(); - - // Handle any command line args. - if(!StandardMainLoop::handleCommandLine(argc, argv)) - { - Platform::AlertOK("Error", "Failed to initialize game, shutting down."); - return false; - } - -#if defined( TORQUE_MINIDUMP ) && defined( TORQUE_RELEASE ) - } - - __except( CreateMiniDump(GetExceptionInformation()) ) - { - _exit(0); - } -#endif - - return true; - - } - - // tick Torque 3D's main loop - S32 torque_enginetick() - { - -#if defined( TORQUE_MINIDUMP ) && defined( TORQUE_RELEASE ) - __try { -#endif - - bool ret = StandardMainLoop::doMainLoop(); - return ret; - -#if defined( TORQUE_MINIDUMP ) && defined( TORQUE_RELEASE ) - } - __except( CreateMiniDump(GetExceptionInformation()) ) - { - _exit(0); - } -#endif - - - - } - - S32 torque_getreturnstatus() - { - return StandardMainLoop::getReturnStatus(); - } - - // signal an engine shutdown (as with the quit(); console command) - void torque_enginesignalshutdown() - { - Con::evaluate("quit();"); - } - - // shutdown the engine - S32 torque_engineshutdown() - { - -#if defined( TORQUE_MINIDUMP ) && defined( TORQUE_RELEASE ) - __try { -#endif - - // Clean everything up. - StandardMainLoop::shutdown(); - -#if defined(_MSC_VER) - createFontShutdown(); -#endif - -#if defined( TORQUE_MINIDUMP ) && defined( TORQUE_RELEASE ) - } - - __except( CreateMiniDump(GetExceptionInformation()) ) - { - _exit(0); - } -#endif - - // Return. - return true; - - } - - bool torque_isdebugbuild() - { -#ifdef _DEBUG - return true; -#else - return false; -#endif - - } - - S32 torque_getconsolebool(const char* name) - { - return Con::getBoolVariable(name); - } - - void torque_setconsolebool(const char* name, bool value) - { - Con::setBoolVariable(name, value); - } - - static char* gExecutablePath = NULL; - - const char* torque_getexecutablepath() - { - return gExecutablePath; - } - - void torque_setexecutablepath(const char* directory) - { - dsize_t pathLen = dStrlen(directory) + 1; - gExecutablePath = new char[pathLen]; - dStrcpy(gExecutablePath, directory, pathLen); - } - - // set Torque 3D into web deployment mode (disable fullscreen exlusive mode, etc) - void torque_setwebdeployment() - { - Platform::setWebDeployment(true); - } - - // Get a console variable - const char* torque_getvariable(const char* name) - { - return Con::getVariable(StringTable->insert(name)); - } - - // Set a console variable - void torque_setvariable(const char* name, const char* value) - { - Con::setVariable(StringTable->insert(name), StringTable->insert(value)); - } - - static Namespace::Entry* GetEntry(const char* nameSpace, const char* name) - { - Namespace* ns = NULL; - - if (!nameSpace || !dStrlen(nameSpace)) - ns = Namespace::mGlobalNamespace; - else - { - nameSpace = StringTable->insert(nameSpace); - ns = Namespace::find(nameSpace); //can specify a package here, maybe need, maybe not - } - - if (!ns) - return NULL; - - name = StringTable->insert(name); - - Namespace::Entry* entry = ns->lookupRecursive(name); - - return entry; - } - - // Export a function to the Torque 3D console system which matches the StringCallback function prototype - // specify the nameSpace, functionName, usage, min and max arguments - void torque_exportstringcallback(StringCallback cb, const char *nameSpace, const char *funcName, const char* usage, S32 minArgs, S32 maxArgs) - { - if (!nameSpace || !dStrlen(nameSpace)) - Con::addCommand(funcName, cb, usage, minArgs + 1, maxArgs + 1); - else - Con::addCommand(nameSpace, funcName, cb, usage, minArgs + 1, maxArgs + 1); - } - - void torque_callvoidfunction(const char* nameSpace, const char* name, S32 argc, const char ** argv) - { - - Namespace::Entry* entry = GetEntry(nameSpace, name); - - if (!entry) - return; - - StringStackConsoleWrapper args(argc, argv); - entry->cb.mVoidCallbackFunc(NULL, args.count(), args); - } - - F32 torque_callfloatfunction(const char* nameSpace, const char* name, S32 argc, const char ** argv) - { - - Namespace::Entry* entry = GetEntry(nameSpace, name); - - if (!entry) - return 0.0f; - - StringStackConsoleWrapper args(argc, argv); - return entry->cb.mFloatCallbackFunc(NULL, args.count(), args); - } - - S32 torque_callintfunction(const char* nameSpace, const char* name, S32 argc, const char ** argv) - { - - Namespace::Entry* entry = GetEntry(nameSpace, name); - - if (!entry) - return 0; - - StringStackConsoleWrapper args(argc, argv); - return entry->cb.mIntCallbackFunc(NULL, args.count(), args); - } - - - const char * torque_callstringfunction(const char* nameSpace, const char* name, S32 argc, const char ** argv) - { - Namespace::Entry* entry = GetEntry(nameSpace, name); - - if (!entry) - return ""; - - StringStackConsoleWrapper args(argc, argv); - return entry->cb.mStringCallbackFunc(NULL, args.count(), args); - } - - bool torque_callboolfunction(const char* nameSpace, const char* name, S32 argc, const char ** argv) - { - Namespace::Entry* entry = GetEntry(nameSpace, name); - - if (!entry) - return false; - - StringStackConsoleWrapper args(argc, argv); - return entry->cb.mBoolCallbackFunc(NULL, args.count(), args); - } - - - const char * torque_callscriptfunction(const char* nameSpace, const char* name, S32 argc, const char ** argv) - { - Namespace::Entry* entry = GetEntry(nameSpace, name); - - if (!entry) - return ""; - - if(!entry->mFunctionOffset) - return ""; - - StringStackConsoleWrapper args(argc, argv); - const char* ret = entry->mCode->exec(entry->mFunctionOffset, StringTable->insert(name), entry->mNamespace, args.count(), args, false, entry->mPackage); - - if (!ret || !dStrlen(ret)) - return ""; - - return ret; - - } - - - // Call a TorqueScript console function that has been marked as secure - const char* torque_callsecurefunction(const char* nameSpace, const char* name, S32 argc, const char ** argv) - { - static const char* invalidChars = "()=:{}"; - String s = nameSpace; - s += "::"; - s += name; - s = String::ToUpper(s); - - if (!gSecureScript.count(StringTable->insert(s.c_str()))) - { - Con::warnf("\nAttempt to call insecure script: %s\n", s.c_str()); - return ""; - } - - // scan through for invalid characters - for (S32 i = 0; i < argc ; i++) - for (S32 j = 0; j < dStrlen(invalidChars) ; j++) - for (S32 k = 0; k < dStrlen(argv[i]); k++) - if (invalidChars[j] == argv[i][k]) - { - Con::warnf("\nInvalid parameter passed to secure script: %s, %s\n", s.c_str(), argv[i]); - return ""; - } - - Namespace::Entry* entry = GetEntry(nameSpace, name); - - if (!entry) - return ""; - - static char returnBuffer[32]; - - switch(entry->mType) - { - case Namespace::Entry::ConsoleFunctionType: - return torque_callscriptfunction(nameSpace, name, argc, argv); - - case Namespace::Entry::StringCallbackType: - return torque_callstringfunction(nameSpace, name, argc, argv); - - case Namespace::Entry::IntCallbackType: - dSprintf(returnBuffer, sizeof(returnBuffer), "%d", torque_callintfunction(nameSpace, name, argc, argv)); - return returnBuffer; - - case Namespace::Entry::FloatCallbackType: - dSprintf(returnBuffer, sizeof(returnBuffer), "%g", torque_callfloatfunction(nameSpace, name, argc, argv)); - return returnBuffer; - - case Namespace::Entry::VoidCallbackType: - torque_callvoidfunction(nameSpace, name, argc, argv); - return ""; - - case Namespace::Entry::BoolCallbackType: - dSprintf(returnBuffer, sizeof(returnBuffer), "%d", (U32) torque_callboolfunction(nameSpace, name, argc, argv)); - return returnBuffer; - }; - - return ""; - - } - - // Set a TorqueScript console function as secure and available for JavaScript via the callScript plugin method - void torque_addsecurefunction(const char* nameSpace, const char* fname) - { - String s = nameSpace; - s += "::"; - s += fname; - s = String::ToUpper(s); - - gSecureScript.insertEqual(StringTable->insert(s.c_str()), StringTable->insert(s.c_str())); - } - - - // Evaluate arbitrary TorqueScript (ONLY CALL torque_evaluate FROM TRUSTED CODE!!!) - const char* torque_evaluate(const char* code) - { - return Con::evaluate(code); - } - - // resize the Torque 3D child window to the specified width and height - void torque_resizewindow(S32 width, S32 height) - { - if (PlatformWindowManager::get() && PlatformWindowManager::get()->getFirstWindow()) - PlatformWindowManager::get()->getFirstWindow()->setSize(Point2I(width,height)); - } - -#if defined(TORQUE_OS_WIN) && !defined(TORQUE_SDL) - // retrieve the hwnd of our render window - void* torque_gethwnd() - { - if (PlatformWindowManager::get() && PlatformWindowManager::get()->getFirstWindow()) - { - Win32Window* w = (Win32Window*) PlatformWindowManager::get()->getFirstWindow(); - return (void *) w->getHWND(); - } - - return NULL; - } - - // directly add a message to the Torque 3D event queue, bypassing the Windows event queue - // this is useful in the case of the IE plugin, where we are hooking into an application - // level message, and posting to the windows queue would cause a hang - void torque_directmessage(U32 message, U32 wparam, U32 lparam) - { - if (PlatformWindowManager::get() && PlatformWindowManager::get()->getFirstWindow()) - { - Win32Window* w = (Win32Window*) PlatformWindowManager::get()->getFirstWindow(); - Dispatch(DelayedDispatch,w->getHWND(),message,wparam,lparam); - } - } - -#endif -} - -// This function is solely to test the TorqueScript <-> Javascript binding -// By default, it is marked as secure by the web plugins and then can be called from -// Javascript on the web page to ensure that function calls across the language -// boundry are working with arguments and return values -DefineEngineFunction( testJavaScriptBridge, const char *, (const char* arg1, const char* arg2, const char* arg3), , "testBridge(arg1, arg2, arg3)") +CInterface& CInterface::GetCInterface() { - S32 failed = 0; - if (dStrcmp(arg1,"one")) - failed = 2; - if (dStrcmp(arg2,"two")) - failed = 2; - if (dStrcmp(arg3,"three")) - failed = 2; - - - //attempt to call from TorqueScript -> JavaScript - const char* jret = Con::evaluate("JS::bridgeCallback(\"one\",\"two\",\"three\");"); - - if (dStrcmp(jret,"42")) - failed = 3; - - static const U32 bufSize = 256; - char *ret = Con::getReturnBuffer(bufSize); - - dSprintf(ret, bufSize, "%i", failed); - - return ret; + static CInterface INSTANCE; + return INSTANCE; } +bool CInterface::isMethod(const char* className, const char* methodName) +{ + return GetCInterface()._isMethod(className, methodName); +} +const char* CInterface::CallFunction(const char* nameSpace, const char* name, const char **argv, int argc, bool *result) +{ + return GetCInterface()._CallFunction(nameSpace, name, argv, argc, result); +} +const char* CInterface::CallMethod(SimObject* obj, const char* name, const char **argv, int argc, bool *res) +{ + return GetCInterface()._CallMethod(obj->getClassName(), obj->getClassNamespace(), obj->getId(), name, argv, argc, res); +} +void CInterface::CallMain(bool *res) +{ + GetCInterface()._CallMain(res); +} +bool CInterface::_isMethod(const char* className, const char* methodName) const +{ + if (mIsMethodCallback) + return mIsMethodCallback(className, methodName); + + return NULL; +} + +const char* CInterface::_CallFunction(const char* nameSpace, const char* name, const char **argv, int argc, bool *result) const +{ + if (mFunctionCallback) + return mFunctionCallback(nameSpace, name, argv, argc, result); + + *result = false; + return NULL; +} + +const char* CInterface::_CallMethod(const char* className, const char* classNamespace, U32 object, const char* name, const char **argv, int argc, bool *res) const +{ + if (mMethodCallback) + return mMethodCallback(className, classNamespace, object, name, argv, argc, res); + + *res = false; + return NULL; +} + +void CInterface::_CallMain(bool *res) const +{ + if (mMainCallback) + { + *res = true; + mMainCallback(); + return; + } + + *res = false; +} + +TORQUE_API void SetCallbacks(void* ptr, void* methodPtr, void* isMethodPtr, void* mainPtr) { + CInterface::GetCInterface().SetCallFunctionCallback(ptr); + CInterface::GetCInterface().SetCallMethodCallback(methodPtr); + CInterface::GetCInterface().SetCallIsMethodCallback(isMethodPtr); + CInterface::GetCInterface().SetMainCallback(mainPtr); +} \ No newline at end of file diff --git a/Engine/source/cinterface/cinterface.h b/Engine/source/cinterface/cinterface.h index d7f839331..a1dcbcc9e 100644 --- a/Engine/source/cinterface/cinterface.h +++ b/Engine/source/cinterface/cinterface.h @@ -21,10 +21,41 @@ //----------------------------------------------------------------------------- #pragma once +#include "platform/platformDlibrary.h" +#include "console/engineAPI.h" +#include "console/simBase.h" -// cinterface can override this (useful for plugins, etc) -extern "C" { +#define CALL_CINTERFACE_FUNCTION(name, ...){const char *v[] = { __VA_ARGS__ }; CInterface::CallFunction(name, v, sizeof(v) / sizeof(*v));} -const char* torque_getexecutablepath(); +class CInterface { + typedef bool(*IsMethodCallback)(const char* className, const char* methodName); + typedef void(*CallMainCallback)(); + typedef const char* (*CallFunctionCallback)(const char* nameSpace, const char* name, const char **argv, int argc, bool *result); + typedef const char* (*CallMethodCallback)(const char* className, const char* classNamespace, U32 object, const char* name, const char **argv, int argc, bool *result); + IsMethodCallback mIsMethodCallback; + CallFunctionCallback mFunctionCallback; + CallMethodCallback mMethodCallback; + CallMainCallback mMainCallback; + const char* _CallFunction(const char* nameSpace, const char* name, const char **argv, int argc, bool *result) const; + const char* _CallMethod(const char* className, const char* classNamespace, U32 object, const char* name, const char **argv, int argc, bool *res) const; + void _CallMain(bool *res) const; + bool _isMethod(const char* className, const char* methodName) const; +public: + CInterface() + { + mFunctionCallback = NULL; + mMethodCallback = NULL; + mIsMethodCallback = NULL; + mMainCallback = NULL; + } -} + static const char* CallFunction(const char* nameSpace, const char* name, const char **argv, int argc, bool *result); + static const char* CallMethod(SimObject* obj, const char* name, const char **argv, int argc, bool *res); + static void CallMain(bool *res); + static bool isMethod(const char* className, const char* methodName); + static CInterface& GetCInterface(); + void SetCallFunctionCallback(void* ptr) { mFunctionCallback = (CallFunctionCallback)ptr; }; + void SetCallMethodCallback(void* ptr) { mMethodCallback = (CallMethodCallback)ptr; }; + void SetCallIsMethodCallback(void* ptr) { mIsMethodCallback = (IsMethodCallback)ptr; }; + void SetMainCallback(void* ptr) { mMainCallback = (CallMainCallback)ptr; }; +}; \ No newline at end of file diff --git a/Engine/source/platformMac/macFileIO.mm b/Engine/source/platformMac/macFileIO.mm index 767dbca8e..e4d182dc1 100644 --- a/Engine/source/platformMac/macFileIO.mm +++ b/Engine/source/platformMac/macFileIO.mm @@ -37,7 +37,7 @@ #import "core/strings/stringFunctions.h" #import "console/console.h" #import "platform/profiler.h" -#import "cinterface/cinterface.h" +#import "cinterface/c_controlInterface.h" #import "core/volume.h" //TODO: file io still needs some work... From 870ee9fb5be96b01929f2bb0ea69d259737bc729 Mon Sep 17 00:00:00 2001 From: Lukas Joergensen Date: Sat, 21 Apr 2018 10:24:41 +0200 Subject: [PATCH 20/34] Integrate new CInterface into the engine-console --- Engine/source/app/mainLoop.cpp | 6 +++++ Engine/source/cinterface/c_simInterface.cpp | 5 ++-- .../cinterface/c_simobjectInterface.cpp | 2 -- Engine/source/console/codeInterpreter.cpp | 27 ++++++++++++++++--- Engine/source/console/console.cpp | 26 ++++++++++++++++++ Engine/source/module/moduleManager.cpp | 9 +++++++ 6 files changed, 67 insertions(+), 8 deletions(-) diff --git a/Engine/source/app/mainLoop.cpp b/Engine/source/app/mainLoop.cpp index 36998169f..ea2322d81 100644 --- a/Engine/source/app/mainLoop.cpp +++ b/Engine/source/app/mainLoop.cpp @@ -61,6 +61,7 @@ // For the TickMs define... fix this for T2D... #include "T3D/gameBase/processList.h" +#include "cinterface/cinterface.h" #ifdef TORQUE_ENABLE_VFS #include "platform/platformVFS.h" @@ -443,6 +444,11 @@ bool StandardMainLoop::handleCommandLine( S32 argc, const char **argv ) // directly because the resource system restricts // access to the "root" directory. + bool foundExternalMain = false; + CInterface::CallMain(&foundExternalMain); + if (foundExternalMain) + return true; + #ifdef TORQUE_ENABLE_VFS Zip::ZipArchive *vfs = openEmbeddedVFSArchive(); bool useVFS = vfs != NULL; diff --git a/Engine/source/cinterface/c_simInterface.cpp b/Engine/source/cinterface/c_simInterface.cpp index 26130a685..d3b0ea58f 100644 --- a/Engine/source/cinterface/c_simInterface.cpp +++ b/Engine/source/cinterface/c_simInterface.cpp @@ -42,12 +42,13 @@ namespace Sim return Sim::getDataBlockGroup()->findObject(StringTable->insert(pName)); } - DefineNewEngineFunction(WrapObject, SimObjectPtr*, (SimObject* pObject), , "") + // EngineAPI doesn't work with SimObjectPtr + TORQUE_API SimObjectPtr* fnWrapObject (SimObject* pObject) { return new SimObjectPtr(pObject); } - DefineNewEngineFunction(DeleteObjectPtr, void, (SimObjectPtr* pObjectPtr), , "") + TORQUE_API void fnDeleteObjectPtr(SimObjectPtr* pObjectPtr) { delete pObjectPtr; } diff --git a/Engine/source/cinterface/c_simobjectInterface.cpp b/Engine/source/cinterface/c_simobjectInterface.cpp index 757ba243b..4c018c0ab 100644 --- a/Engine/source/cinterface/c_simobjectInterface.cpp +++ b/Engine/source/cinterface/c_simobjectInterface.cpp @@ -20,8 +20,6 @@ // IN THE SOFTWARE. //----------------------------------------------------------------------------- -#include "c_simobjectInterface.h" - #include "console/engineAPI.h" #include "console/simObject.h" diff --git a/Engine/source/console/codeInterpreter.cpp b/Engine/source/console/codeInterpreter.cpp index 46d58476e..294a14b2b 100644 --- a/Engine/source/console/codeInterpreter.cpp +++ b/Engine/source/console/codeInterpreter.cpp @@ -37,6 +37,7 @@ #include "core/strings/stringUnit.h" #include "console/console.h" #include "console/consoleInternal.h" +#include "cinterface/cinterface.h" //#define TORQUE_VALIDATE_STACK @@ -2023,7 +2024,7 @@ OPCodeReturn CodeInterpreter::op_callfunc_resolve(U32 &ip) // Try to look it up. mNSEntry = Namespace::find(fnNamespace)->lookup(fnName); - if (!mNSEntry) + if (!CInterface::GetCInterface().isMethod(fnNamespace, fnName) && !mNSEntry) { ip += 5; Con::warnf(ConsoleLogEntry::General, @@ -2051,6 +2052,7 @@ OPCodeReturn CodeInterpreter::op_callfunc(U32 &ip) U32 *code = mCodeBlock->code; + StringTableEntry fnNamespace = CodeToSTE(mCodeBlock->code, ip + 2); StringTableEntry fnName = CodeToSTE(code, ip); //if this is called from inside a function, append the ip and codeptr @@ -2068,10 +2070,16 @@ OPCodeReturn CodeInterpreter::op_callfunc(U32 &ip) const char *componentReturnValue = ""; Namespace *ns = NULL; + bool cFunctionRes = false; + const char* cRetRes = NULL; + if (callType == FuncCallExprNode::FunctionCall) { if (!mNSEntry) mNSEntry = Namespace::global()->lookup(fnName); + + StringStackWrapper args(mCallArgc, mCallArgv); + cRetRes = CInterface::GetCInterface().CallFunction(fnNamespace, fnName, args.argv, args.argc, &cFunctionRes); } else if (callType == FuncCallExprNode::MethodCall) { @@ -2102,6 +2110,9 @@ OPCodeReturn CodeInterpreter::op_callfunc(U32 &ip) mNSEntry = ns->lookup(fnName); else mNSEntry = NULL; + + StringStackWrapper args(mCallArgc, mCallArgv); + cRetRes = CInterface::GetCInterface().CallMethod(gEvalState.thisObject, fnName, args.argv, args.argc, &cFunctionRes); } else // it's a ParentCall { @@ -2128,7 +2139,7 @@ OPCodeReturn CodeInterpreter::op_callfunc(U32 &ip) nsUsage = mNSEntry->mUsage; routingId = 0; } - if (!mNSEntry || mExec.noCalls) + if (!cFunctionRes && (!mNSEntry || mExec.noCalls)) { if (!mExec.noCalls && !(routingId == MethodOnComponent)) { @@ -2152,11 +2163,19 @@ OPCodeReturn CodeInterpreter::op_callfunc(U32 &ip) // ConsoleFunctionType is for any function defined by script. // Any 'callback' type is an engine function that is exposed to script. - if (mNSEntry->mType == Namespace::Entry::ConsoleFunctionType) + if (mNSEntry->mType == Namespace::Entry::ConsoleFunctionType + || cFunctionRes) { ConsoleValueRef ret; - if (mNSEntry->mFunctionOffset) + if (cFunctionRes) + { + StringStackConsoleWrapper retVal(1, &cRetRes); + ret = retVal.argv[0]; + } + else if (mNSEntry->mFunctionOffset) + { ret = mNSEntry->mCode->exec(mNSEntry->mFunctionOffset, fnName, mNSEntry->mNamespace, mCallArgc, mCallArgv, false, mNSEntry->mPackage); + } STR.popFrame(); // Functions are assumed to return strings, so look ahead to see if we can skip the conversion diff --git a/Engine/source/console/console.cpp b/Engine/source/console/console.cpp index 55880f30f..eab14bbf8 100644 --- a/Engine/source/console/console.cpp +++ b/Engine/source/console/console.cpp @@ -40,6 +40,7 @@ #include #include "platform/threads/mutex.h" #include "core/util/journal/journal.h" +#include "cinterface/cinterface.h" extern StringStack STR; extern ConsoleValueStack CSTK; @@ -1488,6 +1489,18 @@ ConsoleValueRef evaluatef(const char* string, ...) // Internal execute for global function which does not save the stack ConsoleValueRef _internalExecute(S32 argc, ConsoleValueRef argv[]) { + const char** argv_str = static_cast(malloc((argc - 1) * sizeof(char *))); + for (int i = 0; i < argc - 1; i++) + { + argv_str[i] = argv[i + 1]; + } + bool result; + const char* methodRes = CInterface::CallFunction(NULL, argv[0], argv_str, argc - 1, &result); + if (result) + { + return ConsoleValueRef::fromValue(CSTK.pushString(methodRes)); + } + Namespace::Entry *ent; StringTableEntry funcName = StringTable->insert(argv[0]); ent = Namespace::global()->lookup(funcName); @@ -1559,6 +1572,18 @@ ConsoleValueRef _internalExecute(SimObject *object, S32 argc, ConsoleValueRef ar } } + const char** argv_str = static_cast(malloc((argc - 2) * sizeof(char *))); + for (int i = 0; i < argc - 2; i++) + { + argv_str[i] = argv[i + 2]; + } + bool result; + const char* methodRes = CInterface::CallMethod(object, argv[0], argv_str, argc - 2, &result); + if (result) + { + return ConsoleValueRef::fromValue(CSTK.pushString(methodRes)); + } + if(object->getNamespace()) { U32 ident = object->getId(); @@ -1655,6 +1680,7 @@ inline ConsoleValueRef _executef(S32 checkArgc, S32 argc, ConsoleValueRef *argv) //------------------------------------------------------------------------------ bool isFunction(const char *fn) { + if (CInterface::isMethod(NULL, fn)) return true; const char *string = StringTable->lookup(fn); if(!string) return false; diff --git a/Engine/source/module/moduleManager.cpp b/Engine/source/module/moduleManager.cpp index ec45ad918..c5d3b42f6 100644 --- a/Engine/source/module/moduleManager.cpp +++ b/Engine/source/module/moduleManager.cpp @@ -455,6 +455,15 @@ bool ModuleManager::loadModuleGroup( const char* pModuleGroup ) moduleGroup, pLoadReadyModuleDefinition->getModuleId(), pLoadReadyModuleDefinition->getVersionId(), pLoadReadyModuleDefinition->getModuleScriptFilePath() ); } } + else + { + // Is the create method available? + if (pScopeSet->isMethod(pLoadReadyModuleDefinition->getCreateFunction())) + { + // Yes, so call the create method. + Con::executef(pScopeSet, pLoadReadyModuleDefinition->getCreateFunction()); + } + } // Raise notifications. raiseModulePostLoadNotifications( pLoadReadyModuleDefinition ); From 6ebb05749eab000b284fcd36d87e86248912b3ba Mon Sep 17 00:00:00 2001 From: Lukas Joergensen Date: Sat, 21 Apr 2018 10:26:20 +0200 Subject: [PATCH 21/34] Don't automatically register objects, allow for modifications to the intial fields before register. This is necessary in order to set the fields before initialization such as TorqueScript does --- Engine/source/console/simObject.h | 1 - 1 file changed, 1 deletion(-) diff --git a/Engine/source/console/simObject.h b/Engine/source/console/simObject.h index 2119ea6a9..1fb30a0ef 100644 --- a/Engine/source/console/simObject.h +++ b/Engine/source/console/simObject.h @@ -455,7 +455,6 @@ class SimObject: public ConsoleObject, public TamlCallbacks { T* object = new T; object->incRefCount(); - object->registerObject(); return object; } From 19682cbe2228d83333aba20ff71fc0777fa4ff1e Mon Sep 17 00:00:00 2001 From: Ratfish Studios Date: Mon, 21 May 2018 01:32:01 -0500 Subject: [PATCH 22/34] Fixes the front/back ortho views in the editors to comply with art tool standards. --- Engine/source/gui/worldEditor/editTSCtrl.cpp | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/Engine/source/gui/worldEditor/editTSCtrl.cpp b/Engine/source/gui/worldEditor/editTSCtrl.cpp index 4518ef3ed..4b5104cc9 100644 --- a/Engine/source/gui/worldEditor/editTSCtrl.cpp +++ b/Engine/source/gui/worldEditor/editTSCtrl.cpp @@ -702,12 +702,12 @@ void EditTSCtrl::calcOrthoCamOffset(F32 mousex, F32 mousey, U8 modifier) break; case DisplayTypeFront: - mOrthoCamTrans.x += mousex * mOrthoFOV * camScale; + mOrthoCamTrans.x -= mousex * mOrthoFOV * camScale; mOrthoCamTrans.z += mousey * mOrthoFOV * camScale; break; case DisplayTypeBack: - mOrthoCamTrans.x -= mousex * mOrthoFOV * camScale; + mOrthoCamTrans.x += mousex * mOrthoFOV * camScale; mOrthoCamTrans.z += mousey * mOrthoFOV * camScale; break; @@ -1125,17 +1125,17 @@ bool EditTSCtrl::processCameraQuery(CameraQuery * query) break; case DisplayTypeFront: - camRot.setColumn(0, Point3F(-1.0, 0.0, 0.0)); - camRot.setColumn(1, Point3F( 0.0, -1.0, 0.0)); - camRot.setColumn(2, Point3F( 0.0, 0.0, 1.0)); - camPos.y = getMax(camPos.y + smMinSceneBounds.y, sceneBounds.maxExtents.y + camBuffer); + camRot.setColumn(0, Point3F(1.0, 0.0, 0.0)); + camRot.setColumn(1, Point3F(0.0, 1.0, 0.0)); + camRot.setColumn(2, Point3F(0.0, 0.0, 1.0)); + camPos.y = getMin(camPos.y - smMinSceneBounds.y, sceneBounds.minExtents.y - camBuffer); break; case DisplayTypeBack: - camRot.setColumn(0, Point3F(1.0, 0.0, 0.0)); - camRot.setColumn(1, Point3F(0.0, 1.0, 0.0)); - camRot.setColumn(2, Point3F(0.0, 0.0, 1.0)); - camPos.y = getMin(camPos.y - smMinSceneBounds.y, sceneBounds.minExtents.y - camBuffer); + camRot.setColumn(0, Point3F(-1.0, 0.0, 0.0)); + camRot.setColumn(1, Point3F(0.0, -1.0, 0.0)); + camRot.setColumn(2, Point3F(0.0, 0.0, 1.0)); + camPos.y = getMax(camPos.y + smMinSceneBounds.y, sceneBounds.maxExtents.y + camBuffer); break; case DisplayTypeLeft: From a95f678602dea6634f59e7a1bf2ea4b70228f765 Mon Sep 17 00:00:00 2001 From: rextimmy Date: Sat, 23 Jun 2018 12:20:07 +1000 Subject: [PATCH 23/34] physx support for vs 2017 round 2 --- Tools/CMake/modules/module_physx3.cmake | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/Tools/CMake/modules/module_physx3.cmake b/Tools/CMake/modules/module_physx3.cmake index e8065740f..a53075441 100644 --- a/Tools/CMake/modules/module_physx3.cmake +++ b/Tools/CMake/modules/module_physx3.cmake @@ -46,14 +46,11 @@ set(PHYSX3_PATH "${PHYSX3_BASE_PATH}/PhysX_3.4") # Windows/ Visual Studio if(MSVC) if(TORQUE_CPU_X32) - if(MSVC11) - set(PHYSX3_LIBPATH_PREFIX vc11win32) - elseif(MSVC12) + if(MSVC_VERSION EQUAL 1800 ) set(PHYSX3_LIBPATH_PREFIX vc12win32) - elseif(MSVC14) + elseif(MSVC_VERSION EQUAL 1900) set(PHYSX3_LIBPATH_PREFIX vc14win32) - #VS 2017 uses 14.x toolchain so can't use MSVC15 - elseif(MSVC_VERSION GREATER_OR_EQUAL_TO 1910) + elseif(MSVC_VERSION GREATER_EQUAL 1910) set(PHYSX3_LIBPATH_PREFIX vc15win32) else() message(FATAL_ERROR "This version of VS is not supported") @@ -62,14 +59,11 @@ if(TORQUE_CPU_X32) set(PHYSX3_LIBNAME_POSTFIX _x86) elseif(TORQUE_CPU_X64) - if(MSVC11) - set(PHYSX3_LIBPATH_PREFIX vc11win64) - elseif(MSVC12) + if(MSVC_VERSION EQUAL 1800 ) set(PHYSX3_LIBPATH_PREFIX vc12win64) - elseif(MSVC14) + elseif(MSVC_VERSION EQUAL 1900) set(PHYSX3_LIBPATH_PREFIX vc14win64) - #VS 2017 uses 14.x toolchain so can't use MSVC15 - elseif(MSVC_VERSION GREATER_OR_EQUAL_TO 1910) + elseif(MSVC_VERSION GREATER_EQUAL 1910) set(PHYSX3_LIBPATH_PREFIX vc15win64) else() message(FATAL_ERROR "This version of VS is not supported") From cf156f505689bd764688ee0e96a2051e8ac57b00 Mon Sep 17 00:00:00 2001 From: Calvin Balke Date: Sun, 15 Jul 2018 11:50:09 -0700 Subject: [PATCH 24/34] Network Code Fixes This should be backwards compatible with existing network code, however it fixes a bug. --- Engine/source/core/stream/bitStream.cpp | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/Engine/source/core/stream/bitStream.cpp b/Engine/source/core/stream/bitStream.cpp index 1a5ab3202..4a8553927 100644 --- a/Engine/source/core/stream/bitStream.cpp +++ b/Engine/source/core/stream/bitStream.cpp @@ -140,7 +140,7 @@ class HuffmanProcessor static HuffmanProcessor g_huffProcessor; - bool readHuffBuffer(BitStream* pStream, char* out_pBuffer); + bool readHuffBuffer(BitStream* pStream, char* out_pBuffer, S32 maxLen); bool writeHuffBuffer(BitStream* pStream, const char* out_pBuffer, S32 maxLen); }; @@ -667,12 +667,12 @@ void BitStream::readString(char buf[256]) if(readFlag()) { S32 offset = readInt(8); - HuffmanProcessor::g_huffProcessor.readHuffBuffer(this, stringBuffer + offset); + HuffmanProcessor::g_huffProcessor.readHuffBuffer(this, stringBuffer + offset, 256 - offset); dStrcpy(buf, stringBuffer, 256); return; } } - HuffmanProcessor::g_huffProcessor.readHuffBuffer(this, buf); + HuffmanProcessor::g_huffProcessor.readHuffBuffer(this, buf, 256); if(stringBuffer) dStrcpy(stringBuffer, buf, 256); } @@ -812,13 +812,16 @@ S16 HuffmanProcessor::determineIndex(HuffWrap& rWrap) } } -bool HuffmanProcessor::readHuffBuffer(BitStream* pStream, char* out_pBuffer) +bool HuffmanProcessor::readHuffBuffer(BitStream* pStream, char* out_pBuffer, S32 maxLen=256) { if (m_tablesBuilt == false) buildTables(); if (pStream->readFlag()) { S32 len = pStream->readInt(8); + if (len >= maxLen) { + len = maxLen; + } for (S32 i = 0; i < len; i++) { S32 index = 0; while (true) { @@ -839,6 +842,9 @@ bool HuffmanProcessor::readHuffBuffer(BitStream* pStream, char* out_pBuffer) } else { // Uncompressed string... U32 len = pStream->readInt(8); + if (len >= maxLen) { + len = maxLen; + } pStream->read(len, out_pBuffer); out_pBuffer[len] = '\0'; return true; From ee64270a2d498507a039b610b0ed85140b683240 Mon Sep 17 00:00:00 2001 From: Azaezel Date: Tue, 7 Aug 2018 13:14:25 -0500 Subject: [PATCH 25/34] micro patch to the nativefiledialogues library to mirror file type name folks with 'hide extensions for known file types' on windows weren't seeing any entries in thier drop-down lists for file types. --- Engine/lib/nativeFileDialogs/nfd_win.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Engine/lib/nativeFileDialogs/nfd_win.cpp b/Engine/lib/nativeFileDialogs/nfd_win.cpp index a73fd8a46..1187fc84b 100644 --- a/Engine/lib/nativeFileDialogs/nfd_win.cpp +++ b/Engine/lib/nativeFileDialogs/nfd_win.cpp @@ -183,7 +183,7 @@ static nfdresult_t AddFiltersToDialog( ::IFileDialog *fileOpenDialog, const char /* end of filter -- add it to specList */ // Empty filter name -- Windows describes them by extension. - specList[specIdx].pszName = EMPTY_WSTR; + CopyNFDCharToWChar(specbuf, (wchar_t**)&specList[specIdx].pszName); CopyNFDCharToWChar( specbuf, (wchar_t**)&specList[specIdx].pszSpec ); memset( specbuf, 0, sizeof(char)*NFD_MAX_STRLEN ); @@ -203,7 +203,7 @@ static nfdresult_t AddFiltersToDialog( ::IFileDialog *fileOpenDialog, const char /* Add wildcard */ specList[specIdx].pszSpec = WILDCARD; - specList[specIdx].pszName = EMPTY_WSTR; + specList[specIdx].pszName = WILDCARD; fileOpenDialog->SetFileTypes( filterCount+1, specList ); From 02972b5961da8be4b8fbb7a8b62f258bb9422145 Mon Sep 17 00:00:00 2001 From: Areloch Date: Sun, 2 Sep 2018 03:50:31 -0500 Subject: [PATCH 26/34] Clear out old core structure before adding the new module-ified structure. --- .../BaseGame/game/core/CoreComponents.cs | 10 - .../BaseGame/game/core/CoreComponents.module | 19 - Templates/BaseGame/game/core/audio.cs | 436 --- Templates/BaseGame/game/core/canvas.cs | 162 - .../components/RigidBodyComponent.asset.taml | 8 - .../components/animationComponent.asset.taml | 8 - .../cameraOrbiterComponent.asset.taml | 8 - .../components/collisionComponent.asset.taml | 8 - .../core/components/game/camera.asset.taml | 9 - .../game/core/components/game/camera.cs | 185 -- .../components/game/controlObject.asset.taml | 10 - .../core/components/game/controlObject.cs | 89 - .../components/game/itemRotate.asset.taml | 10 - .../game/core/components/game/itemRotate.cs | 49 - .../components/game/playerSpawner.asset.taml | 10 - .../core/components/game/playerSpawner.cs | 78 - .../components/input/fpsControls.asset.taml | 9 - .../game/core/components/input/fpsControls.cs | 247 -- .../core/components/input/inputManager.cs | 82 - .../core/components/meshComponent.asset.taml | 8 - .../playerControllerComponent.asset.taml | 8 - .../core/components/soundComponent.asset.taml | 8 - .../stateMachineComponent.asset.taml | 8 - .../BaseGame/game/core/console/console.gui | 191 -- Templates/BaseGame/game/core/console/main.cs | 140 - .../BaseGame/game/core/console/profiles.cs | 70 - Templates/BaseGame/game/core/cursor.cs | 102 - .../game/core/fonts/Arial 10 (ansi).uft | Bin 412 -> 0 bytes .../game/core/fonts/Arial 12 (ansi).uft | Bin 62 -> 0 bytes .../game/core/fonts/Arial 14 (ansi).uft | Bin 5160 -> 0 bytes .../game/core/fonts/Arial 16 (ansi).uft | Bin 13112 -> 0 bytes .../game/core/fonts/Arial 36 (ansi).uft | Bin 1046 -> 0 bytes .../game/core/fonts/Arial Bold 14 (ansi).uft | Bin 3227 -> 0 bytes .../game/core/fonts/Arial Bold 16 (ansi).uft | Bin 1254 -> 0 bytes .../game/core/fonts/Arial Bold 18 (ansi).uft | Bin 5276 -> 0 bytes .../game/core/fonts/ArialBold 14 (ansi).uft | Bin 2276 -> 0 bytes .../game/core/fonts/ArialItalic 14 (ansi).uft | Bin 2951 -> 0 bytes .../core/fonts/Lucida Console 12 (ansi).uft | Bin 5897 -> 0 bytes .../BaseGame/game/core/gfxData/clouds.cs | 55 - .../game/core/gfxData/commonMaterialData.cs | 79 - .../BaseGame/game/core/gfxData/scatterSky.cs | 48 - .../BaseGame/game/core/gfxData/shaders.cs | 152 - .../game/core/gfxData/terrainBlock.cs | 36 - Templates/BaseGame/game/core/gfxData/water.cs | 208 -- .../gfxprofile/D3D9.ATITechnologiesInc.cs | 36 - .../gfxprofile/D3D9.NVIDIA.GeForce8600.cs | 36 - .../gfxprofile/D3D9.NVIDIA.QuadroFXGo1000.cs | 39 - .../game/core/gfxprofile/D3D9.NVIDIA.cs | 36 - .../BaseGame/game/core/gfxprofile/D3D9.cs | 26 - Templates/BaseGame/game/core/globals.cs | 102 - .../BaseGame/game/core/helperFunctions.cs | 1158 ------- .../BaseGame/game/core/images/AreaMap33.dds | Bin 109028 -> 0 bytes .../BaseGame/game/core/images/button.png | Bin 1153 -> 0 bytes .../BaseGame/game/core/images/caustics_1.png | Bin 34398 -> 0 bytes .../BaseGame/game/core/images/caustics_2.png | Bin 33963 -> 0 bytes .../BaseGame/game/core/images/checkbox.png | Bin 3943 -> 0 bytes .../game/core/images/group-border.png | Bin 1273 -> 0 bytes .../game/core/images/inactive-overlay.png | Bin 131 -> 0 bytes .../BaseGame/game/core/images/loadingbar.png | Bin 635 -> 0 bytes .../BaseGame/game/core/images/materials.cs | 32 - .../game/core/images/missingTexture.png | Bin 10645 -> 0 bytes Templates/BaseGame/game/core/images/noise.png | Bin 14610 -> 0 bytes .../game/core/images/null_color_ramp.png | Bin 2843 -> 0 bytes .../BaseGame/game/core/images/scrollBar.png | Bin 3332 -> 0 bytes .../BaseGame/game/core/images/textEdit.png | Bin 250 -> 0 bytes .../game/core/images/thumbHighlightButton.png | Bin 778 -> 0 bytes .../BaseGame/game/core/images/unavailable.png | Bin 26528 -> 0 bytes .../BaseGame/game/core/images/warnMat.dds | Bin 699192 -> 0 bytes .../BaseGame/game/core/images/window.png | Bin 2559 -> 0 bytes Templates/BaseGame/game/core/lighting.cs | 74 - .../core/lighting/advanced/deferredShading.cs | 71 - .../game/core/lighting/advanced/init.cs | 68 - .../game/core/lighting/advanced/shaders.cs | 276 -- .../BaseGame/game/core/lighting/basic/init.cs | 92 - .../game/core/lighting/basic/shadowFilter.cs | 76 - .../game/core/lighting/shadowMaps/init.cs | 32 - Templates/BaseGame/game/core/main.cs | 99 - Templates/BaseGame/game/core/oculusVR.cs | 248 -- .../BaseGame/game/core/oculusVROverlay.gui | 19 - Templates/BaseGame/game/core/parseArgs.cs | 392 --- .../BaseGame/game/core/postFX/GammaPostFX.cs | 73 - Templates/BaseGame/game/core/postFX/MLAA.cs | 186 -- .../BaseGame/game/core/postFX/MotionBlurFx.cs | 53 - .../BaseGame/game/core/postFX/caustics.cs | 64 - .../game/core/postFX/chromaticLens.cs | 77 - .../game/core/postFX/default.postfxpreset.cs | 72 - Templates/BaseGame/game/core/postFX/dof.cs | 599 ---- Templates/BaseGame/game/core/postFX/edgeAA.cs | 113 - Templates/BaseGame/game/core/postFX/flash.cs | 63 - Templates/BaseGame/game/core/postFX/fog.cs | 135 - Templates/BaseGame/game/core/postFX/fxaa.cs | 64 - Templates/BaseGame/game/core/postFX/glow.cs | 184 -- Templates/BaseGame/game/core/postFX/hdr.cs | 529 ---- .../BaseGame/game/core/postFX/lightRay.cs | 110 - .../game/core/postFX/ovrBarrelDistortion.cs | 167 - .../game/core/postFX/postFxManager.gui | 2755 ----------------- .../game/core/postFX/postFxManager.gui.cs | 446 --- .../core/postFX/postFxManager.gui.settings.cs | 439 --- .../core/postFX/postFxManager.persistance.cs | 79 - Templates/BaseGame/game/core/postFX/ssao.cs | 302 -- .../BaseGame/game/core/postFX/turbulence.cs | 57 - .../BaseGame/game/core/postFX/vignette.cs | 55 - Templates/BaseGame/game/core/postFx.cs | 88 - Templates/BaseGame/game/core/profiles.cs | 226 -- Templates/BaseGame/game/core/renderManager.cs | 136 - .../BaseGame/game/core/sfx/audioAmbience.cs | 44 - Templates/BaseGame/game/core/sfx/audioData.cs | 42 - .../game/core/sfx/audioDescriptions.cs | 143 - .../game/core/sfx/audioEnvironments.cs | 916 ------ .../BaseGame/game/core/sfx/audioStates.cs | 158 - .../core/shaders/VolumetricFog/VFogP.hlsl | 87 - .../core/shaders/VolumetricFog/VFogPreP.hlsl | 40 - .../core/shaders/VolumetricFog/VFogPreV.hlsl | 44 - .../core/shaders/VolumetricFog/VFogRefl.hlsl | 38 - .../core/shaders/VolumetricFog/VFogV.hlsl | 46 - .../core/shaders/VolumetricFog/gl/VFogP.glsl | 87 - .../shaders/VolumetricFog/gl/VFogPreP.glsl | 37 - .../shaders/VolumetricFog/gl/VFogPreV.glsl | 42 - .../shaders/VolumetricFog/gl/VFogRefl.glsl | 33 - .../core/shaders/VolumetricFog/gl/VFogV.glsl | 38 - .../game/core/shaders/basicCloudsP.hlsl | 37 - .../game/core/shaders/basicCloudsV.hlsl | 58 - .../game/core/shaders/cloudLayerP.hlsl | 146 - .../game/core/shaders/cloudLayerV.hlsl | 106 - .../fixedFunction/addColorTextureP.hlsl | 37 - .../fixedFunction/addColorTextureV.hlsl | 48 - .../core/shaders/fixedFunction/colorP.hlsl | 34 - .../core/shaders/fixedFunction/colorV.hlsl | 45 - .../fixedFunction/gl/addColorTextureP.glsl | 32 - .../fixedFunction/gl/addColorTextureV.glsl | 38 - .../core/shaders/fixedFunction/gl/colorP.glsl | 30 - .../core/shaders/fixedFunction/gl/colorV.glsl | 35 - .../fixedFunction/gl/modColorTextureP.glsl | 32 - .../fixedFunction/gl/modColorTextureV.glsl | 38 - .../fixedFunction/gl/targetRestoreP.glsl | 31 - .../fixedFunction/gl/targetRestoreV.glsl | 22 - .../shaders/fixedFunction/gl/textureP.glsl | 31 - .../shaders/fixedFunction/gl/textureV.glsl | 35 - .../fixedFunction/modColorTextureP.hlsl | 37 - .../fixedFunction/modColorTextureV.hlsl | 48 - .../shaders/fixedFunction/targetRestoreP.hlsl | 31 - .../shaders/fixedFunction/targetRestoreV.hlsl | 26 - .../core/shaders/fixedFunction/textureP.hlsl | 36 - .../core/shaders/fixedFunction/textureV.hlsl | 46 - .../BaseGame/game/core/shaders/foliage.hlsl | 186 -- .../core/shaders/fxFoliageReplicatorP.hlsl | 60 - .../core/shaders/fxFoliageReplicatorV.hlsl | 129 - .../game/core/shaders/gl/basicCloudsP.glsl | 39 - .../game/core/shaders/gl/basicCloudsV.glsl | 53 - .../BaseGame/game/core/shaders/gl/blurP.glsl | 39 - .../BaseGame/game/core/shaders/gl/blurV.glsl | 48 - .../game/core/shaders/gl/cloudLayerP.glsl | 147 - .../game/core/shaders/gl/cloudLayerV.glsl | 106 - .../game/core/shaders/gl/foliage.glsl | 186 -- .../core/shaders/gl/fxFoliageReplicatorP.glsl | 42 - .../core/shaders/gl/fxFoliageReplicatorV.glsl | 99 - .../game/core/shaders/gl/guiMaterialV.glsl | 39 - .../game/core/shaders/gl/hlslCompat.glsl | 101 - .../game/core/shaders/gl/imposter.glsl | 161 - .../game/core/shaders/gl/lighting.glsl | 249 -- .../core/shaders/gl/particleCompositeP.glsl | 62 - .../core/shaders/gl/particleCompositeV.glsl | 48 - .../game/core/shaders/gl/particlesP.glsl | 113 - .../game/core/shaders/gl/particlesV.glsl | 54 - .../core/shaders/gl/planarReflectBumpP.glsl | 70 - .../core/shaders/gl/planarReflectBumpV.glsl | 51 - .../game/core/shaders/gl/planarReflectP.glsl | 43 - .../game/core/shaders/gl/planarReflectV.glsl | 51 - .../game/core/shaders/gl/precipP.glsl | 39 - .../game/core/shaders/gl/precipV.glsl | 54 - .../core/shaders/gl/projectedShadowP.glsl | 37 - .../core/shaders/gl/projectedShadowV.glsl | 49 - .../game/core/shaders/gl/scatterSkyP.glsl | 72 - .../game/core/shaders/gl/scatterSkyV.glsl | 154 - .../BaseGame/game/core/shaders/gl/torque.glsl | 339 -- .../BaseGame/game/core/shaders/gl/wavesP.glsl | 57 - .../BaseGame/game/core/shaders/gl/wind.glsl | 101 - .../game/core/shaders/guiMaterialV.hlsl | 45 - .../BaseGame/game/core/shaders/hlslStructs.h | 116 - .../game/core/shaders/hlslStructs.hlsl | 114 - .../BaseGame/game/core/shaders/imposter.hlsl | 149 - .../BaseGame/game/core/shaders/lighting.hlsl | 249 -- .../lighting/advanced/convexGeometryV.hlsl | 54 - .../advanced/deferredClearGBufferP.hlsl | 54 - .../advanced/deferredClearGBufferV.hlsl | 43 - .../advanced/deferredColorShaderP.hlsl | 46 - .../lighting/advanced/deferredShadingP.hlsl | 54 - .../lighting/advanced/farFrustumQuad.hlsl | 47 - .../lighting/advanced/farFrustumQuadV.hlsl | 43 - .../lighting/advanced/gl/convexGeometryV.glsl | 52 - .../advanced/gl/deferredClearGBufferP.glsl | 40 - .../advanced/gl/deferredColorShaderP.glsl | 37 - .../advanced/gl/deferredShadingP.glsl | 59 - .../lighting/advanced/gl/farFrustumQuad.glsl | 30 - .../lighting/advanced/gl/farFrustumQuadV.glsl | 51 - .../lighting/advanced/gl/lightingUtils.glsl | 79 - .../lighting/advanced/gl/pointLightP.glsl | 273 -- .../lighting/advanced/gl/softShadow.glsl | 159 - .../lighting/advanced/gl/spotLightP.glsl | 210 -- .../lighting/advanced/gl/vectorLightP.glsl | 327 -- .../lighting/advanced/lightingUtils.hlsl | 51 - .../advanced/particlePointLightP.hlsl | 76 - .../advanced/particlePointLightV.hlsl | 48 - .../lighting/advanced/pointLightP.hlsl | 277 -- .../shaders/lighting/advanced/softShadow.hlsl | 158 - .../shaders/lighting/advanced/spotLightP.hlsl | 209 -- .../lighting/advanced/vectorLightP.hlsl | 328 -- .../lighting/basic/gl/shadowFilterP.glsl | 46 - .../lighting/basic/gl/shadowFilterV.glsl | 37 - .../shaders/lighting/basic/shadowFilterP.hlsl | 50 - .../shaders/lighting/basic/shadowFilterV.hlsl | 42 - .../lighting/shadowMap/boxFilterP.hlsl | 82 - .../lighting/shadowMap/boxFilterV.hlsl | 57 - .../lighting/shadowMap/gl/boxFilterP.glsl | 49 - .../lighting/shadowMap/gl/boxFilterV.glsl | 34 - .../shaders/lighting/shadowMap/shadowMapIO.h | 50 - .../lighting/shadowMap/shadowMapIO_GLSL.h | 50 - .../lighting/shadowMap/shadowMapIO_HLSL.h | 50 - .../game/core/shaders/particleCompositeP.hlsl | 61 - .../game/core/shaders/particleCompositeV.hlsl | 53 - .../game/core/shaders/particlesP.hlsl | 109 - .../game/core/shaders/particlesV.hlsl | 55 - .../game/core/shaders/planarReflectBumpP.hlsl | 87 - .../game/core/shaders/planarReflectBumpV.hlsl | 67 - .../game/core/shaders/planarReflectP.hlsl | 58 - .../game/core/shaders/planarReflectV.hlsl | 57 - .../game/core/shaders/postFX/VolFogGlowP.hlsl | 74 - .../shaders/postFX/caustics/causticsP.hlsl | 77 - .../shaders/postFX/caustics/gl/causticsP.glsl | 87 - .../core/shaders/postFX/chromaticLens.hlsl | 60 - .../shaders/postFX/dof/DOF_CalcCoC_P.hlsl | 53 - .../shaders/postFX/dof/DOF_CalcCoC_V.hlsl | 70 - .../shaders/postFX/dof/DOF_DownSample_P.hlsl | 143 - .../shaders/postFX/dof/DOF_DownSample_V.hlsl | 61 - .../core/shaders/postFX/dof/DOF_Final_P.hlsl | 145 - .../core/shaders/postFX/dof/DOF_Final_V.hlsl | 72 - .../shaders/postFX/dof/DOF_Gausian_P.hlsl | 63 - .../shaders/postFX/dof/DOF_Gausian_V.hlsl | 80 - .../shaders/postFX/dof/DOF_Passthrough_V.hlsl | 70 - .../shaders/postFX/dof/DOF_SmallBlur_P.hlsl | 46 - .../shaders/postFX/dof/DOF_SmallBlur_V.hlsl | 56 - .../shaders/postFX/dof/gl/DOF_CalcCoC_P.glsl | 55 - .../shaders/postFX/dof/gl/DOF_CalcCoC_V.glsl | 69 - .../postFX/dof/gl/DOF_DownSample_P.glsl | 143 - .../postFX/dof/gl/DOF_DownSample_V.glsl | 67 - .../shaders/postFX/dof/gl/DOF_Final_P.glsl | 147 - .../shaders/postFX/dof/gl/DOF_Final_V.glsl | 71 - .../shaders/postFX/dof/gl/DOF_Gausian_P.glsl | 68 - .../shaders/postFX/dof/gl/DOF_Gausian_V.glsl | 91 - .../postFX/dof/gl/DOF_Passthrough_V.glsl | 69 - .../postFX/dof/gl/DOF_SmallBlur_P.glsl | 46 - .../postFX/dof/gl/DOF_SmallBlur_V.glsl | 54 - .../postFX/edgeaa/dbgEdgeDisplayP.hlsl | 30 - .../core/shaders/postFX/edgeaa/edgeAAP.hlsl | 66 - .../core/shaders/postFX/edgeaa/edgeAAV.hlsl | 45 - .../shaders/postFX/edgeaa/edgeDetectP.hlsl | 93 - .../postFX/edgeaa/gl/dbgEdgeDisplayP.glsl | 36 - .../shaders/postFX/edgeaa/gl/edgeAAP.glsl | 70 - .../shaders/postFX/edgeaa/gl/edgeAAV.glsl | 43 - .../shaders/postFX/edgeaa/gl/edgeDetectP.glsl | 96 - .../game/core/shaders/postFX/flashP.hlsl | 36 - .../game/core/shaders/postFX/fogP.hlsl | 47 - .../game/core/shaders/postFX/fxaa/Fxaa3_11.h | 2047 ------------ .../game/core/shaders/postFX/fxaa/fxaaP.hlsl | 143 - .../game/core/shaders/postFX/fxaa/fxaaV.hlsl | 42 - .../core/shaders/postFX/fxaa/gl/fxaaP.glsl | 125 - .../core/shaders/postFX/fxaa/gl/fxaaV.glsl | 40 - .../game/core/shaders/postFX/gammaP.hlsl | 50 - .../core/shaders/postFX/gl/VolFogGlowP.glsl | 67 - .../core/shaders/postFX/gl/chromaticLens.glsl | 62 - .../game/core/shaders/postFX/gl/flashP.glsl | 39 - .../game/core/shaders/postFX/gl/fogP.glsl | 52 - .../game/core/shaders/postFX/gl/gammaP.glsl | 54 - .../core/shaders/postFX/gl/glowBlurP.glsl | 59 - .../core/shaders/postFX/gl/glowBlurV.glsl | 59 - .../core/shaders/postFX/gl/motionBlurP.glsl | 78 - .../core/shaders/postFX/gl/passthruP.glsl | 33 - .../game/core/shaders/postFX/gl/postFX.glsl | 63 - .../game/core/shaders/postFX/gl/postFxV.glsl | 52 - .../core/shaders/postFX/gl/turbulenceP.glsl | 52 - .../shaders/postFX/gl/underwaterFogP.glsl | 140 - .../game/core/shaders/postFX/glowBlurP.hlsl | 63 - .../game/core/shaders/postFX/glowBlurV.hlsl | 63 - .../shaders/postFX/hdr/bloomGaussBlurHP.hlsl | 68 - .../shaders/postFX/hdr/bloomGaussBlurVP.hlsl | 67 - .../shaders/postFX/hdr/brightPassFilterP.hlsl | 62 - .../postFX/hdr/calculateAdaptedLumP.hlsl | 44 - .../shaders/postFX/hdr/downScale4x4P.hlsl | 53 - .../shaders/postFX/hdr/downScale4x4V.hlsl | 138 - .../shaders/postFX/hdr/finalPassCombineP.hlsl | 92 - .../postFX/hdr/gl/bloomGaussBlurHP.glsl | 72 - .../postFX/hdr/gl/bloomGaussBlurVP.glsl | 71 - .../postFX/hdr/gl/brightPassFilterP.glsl | 65 - .../postFX/hdr/gl/calculateAdaptedLumP.glsl | 48 - .../shaders/postFX/hdr/gl/downScale4x4P.glsl | 50 - .../shaders/postFX/hdr/gl/downScale4x4V.glsl | 141 - .../postFX/hdr/gl/finalPassCombineP.glsl | 97 - .../shaders/postFX/hdr/gl/luminanceVisP.glsl | 42 - .../postFX/hdr/gl/sampleLumInitialP.glsl | 62 - .../postFX/hdr/gl/sampleLumIterativeP.glsl | 52 - .../shaders/postFX/hdr/luminanceVisP.hlsl | 39 - .../shaders/postFX/hdr/sampleLumInitialP.hlsl | 59 - .../postFX/hdr/sampleLumIterativeP.hlsl | 50 - .../postFX/lightRay/gl/lightRayOccludeP.glsl | 55 - .../shaders/postFX/lightRay/gl/lightRayP.glsl | 94 - .../postFX/lightRay/lightRayOccludeP.hlsl | 53 - .../shaders/postFX/lightRay/lightRayP.hlsl | 89 - .../postFX/mlaa/blendWeightCalculationP.hlsl | 78 - .../shaders/postFX/mlaa/edgeDetectionP.hlsl | 72 - .../core/shaders/postFX/mlaa/functions.hlsl | 145 - .../mlaa/gl/blendWeightCalculationP.glsl | 83 - .../postFX/mlaa/gl/edgeDetectionP.glsl | 76 - .../shaders/postFX/mlaa/gl/functions.glsl | 145 - .../postFX/mlaa/gl/neighborhoodBlendingP.glsl | 88 - .../core/shaders/postFX/mlaa/gl/offsetV.glsl | 57 - .../shaders/postFX/mlaa/gl/passthruV.glsl | 52 - .../postFX/mlaa/neighborhoodBlendingP.hlsl | 84 - .../core/shaders/postFX/mlaa/offsetV.hlsl | 42 - .../core/shaders/postFX/mlaa/passthruV.hlsl | 37 - .../game/core/shaders/postFX/motionBlurP.hlsl | 70 - .../oculusvr/barrelDistortionChromaP.hlsl | 95 - .../postFX/oculusvr/barrelDistortionP.hlsl | 80 - .../oculusvr/gl/barrelDistortionChromaP.glsl | 95 - .../postFX/oculusvr/gl/barrelDistortionP.glsl | 81 - .../postFX/oculusvr/gl/monoToStereoP.glsl | 60 - .../postFX/oculusvr/monoToStereoP.hlsl | 59 - .../game/core/shaders/postFX/passthruP.hlsl | 30 - .../game/core/shaders/postFX/postFx.hlsl | 40 - .../game/core/shaders/postFX/postFxV.glsl | 51 - .../game/core/shaders/postFX/postFxV.hlsl | 45 - .../core/shaders/postFX/ssao/SSAO_Blur_P.hlsl | 106 - .../core/shaders/postFX/ssao/SSAO_Blur_V.hlsl | 86 - .../game/core/shaders/postFX/ssao/SSAO_P.hlsl | 272 -- .../postFX/ssao/SSAO_PowerTable_P.hlsl | 29 - .../postFX/ssao/SSAO_PowerTable_V.hlsl | 45 - .../shaders/postFX/ssao/gl/SSAO_Blur_P.glsl | 108 - .../shaders/postFX/ssao/gl/SSAO_Blur_V.glsl | 96 - .../core/shaders/postFX/ssao/gl/SSAO_P.glsl | 278 -- .../postFX/ssao/gl/SSAO_PowerTable_P.glsl | 34 - .../postFX/ssao/gl/SSAO_PowerTable_V.glsl | 38 - .../game/core/shaders/postFX/turbulenceP.hlsl | 44 - .../core/shaders/postFX/underwaterFogP.hlsl | 138 - .../shaders/postFX/vignette/VignetteP.hlsl | 35 - .../shaders/postFX/vignette/gl/VignetteP.glsl | 41 - .../BaseGame/game/core/shaders/precipP.hlsl | 53 - .../BaseGame/game/core/shaders/precipV.hlsl | 71 - .../game/core/shaders/projectedShadowP.hlsl | 40 - .../game/core/shaders/projectedShadowV.hlsl | 60 - .../shaders/ribbons/basicRibbonShaderP.hlsl | 19 - .../shaders/ribbons/basicRibbonShaderV.hlsl | 35 - .../ribbons/gl/basicRibbonShaderP.glsl | 20 - .../ribbons/gl/basicRibbonShaderV.glsl | 37 - .../shaders/ribbons/gl/texRibbonShaderP.glsl | 22 - .../shaders/ribbons/gl/texRibbonShaderV.glsl | 37 - .../shaders/ribbons/texRibbonShaderP.hlsl | 21 - .../shaders/ribbons/texRibbonShaderV.hlsl | 35 - .../game/core/shaders/scatterSkyP.hlsl | 69 - .../game/core/shaders/scatterSkyV.hlsl | 157 - .../game/core/shaders/shaderModel.hlsl | 97 - .../game/core/shaders/shaderModelAutoGen.hlsl | 35 - .../BaseGame/game/core/shaders/shdrConsts.h | 117 - .../game/core/shaders/terrain/blendP.hlsl | 48 - .../game/core/shaders/terrain/blendV.hlsl | 52 - .../game/core/shaders/terrain/gl/blendP.glsl | 48 - .../game/core/shaders/terrain/gl/blendV.glsl | 41 - .../game/core/shaders/terrain/terrain.glsl | 52 - .../game/core/shaders/terrain/terrain.hlsl | 55 - .../BaseGame/game/core/shaders/torque.hlsl | 342 -- .../core/shaders/water/gl/waterBasicP.glsl | 216 -- .../core/shaders/water/gl/waterBasicV.glsl | 243 -- .../game/core/shaders/water/gl/waterP.glsl | 396 --- .../game/core/shaders/water/gl/waterV.glsl | 241 -- .../game/core/shaders/water/waterBasicP.hlsl | 213 -- .../game/core/shaders/water/waterBasicV.hlsl | 237 -- .../game/core/shaders/water/waterP.hlsl | 383 --- .../game/core/shaders/water/waterV.hlsl | 216 -- .../BaseGame/game/core/shaders/wavesP.hlsl | 89 - .../BaseGame/game/core/shaders/wavesV.hlsl | 90 - .../BaseGame/game/core/shaders/wind.hlsl | 101 - .../game/data/clientServer/ClientServer.cs | 112 - .../data/clientServer/ClientServer.module | 9 - .../clientServer/scripts/client/client.cs | 29 - .../scripts/client/connectionToServer.cs | 130 - .../scripts/client/levelDownload.cs | 185 -- .../clientServer/scripts/client/levelLoad.cs | 92 - .../clientServer/scripts/client/message.cs | 94 - .../data/clientServer/scripts/server/audio.cs | 40 - .../clientServer/scripts/server/commands.cs | 35 - .../scripts/server/connectionToClient.cs | 178 -- .../clientServer/scripts/server/defaults.cs | 62 - .../clientServer/scripts/server/kickban.cs | 41 - .../scripts/server/levelDownload.cs | 187 -- .../clientServer/scripts/server/levelInfo.cs | 197 -- .../clientServer/scripts/server/levelLoad.cs | 181 -- .../clientServer/scripts/server/message.cs | 50 - .../clientServer/scripts/server/server.cs | 303 -- 396 files changed, 39611 deletions(-) delete mode 100644 Templates/BaseGame/game/core/CoreComponents.cs delete mode 100644 Templates/BaseGame/game/core/CoreComponents.module delete mode 100644 Templates/BaseGame/game/core/audio.cs delete mode 100644 Templates/BaseGame/game/core/canvas.cs delete mode 100644 Templates/BaseGame/game/core/components/RigidBodyComponent.asset.taml delete mode 100644 Templates/BaseGame/game/core/components/animationComponent.asset.taml delete mode 100644 Templates/BaseGame/game/core/components/cameraOrbiterComponent.asset.taml delete mode 100644 Templates/BaseGame/game/core/components/collisionComponent.asset.taml delete mode 100644 Templates/BaseGame/game/core/components/game/camera.asset.taml delete mode 100644 Templates/BaseGame/game/core/components/game/camera.cs delete mode 100644 Templates/BaseGame/game/core/components/game/controlObject.asset.taml delete mode 100644 Templates/BaseGame/game/core/components/game/controlObject.cs delete mode 100644 Templates/BaseGame/game/core/components/game/itemRotate.asset.taml delete mode 100644 Templates/BaseGame/game/core/components/game/itemRotate.cs delete mode 100644 Templates/BaseGame/game/core/components/game/playerSpawner.asset.taml delete mode 100644 Templates/BaseGame/game/core/components/game/playerSpawner.cs delete mode 100644 Templates/BaseGame/game/core/components/input/fpsControls.asset.taml delete mode 100644 Templates/BaseGame/game/core/components/input/fpsControls.cs delete mode 100644 Templates/BaseGame/game/core/components/input/inputManager.cs delete mode 100644 Templates/BaseGame/game/core/components/meshComponent.asset.taml delete mode 100644 Templates/BaseGame/game/core/components/playerControllerComponent.asset.taml delete mode 100644 Templates/BaseGame/game/core/components/soundComponent.asset.taml delete mode 100644 Templates/BaseGame/game/core/components/stateMachineComponent.asset.taml delete mode 100644 Templates/BaseGame/game/core/console/console.gui delete mode 100644 Templates/BaseGame/game/core/console/main.cs delete mode 100644 Templates/BaseGame/game/core/console/profiles.cs delete mode 100644 Templates/BaseGame/game/core/cursor.cs delete mode 100644 Templates/BaseGame/game/core/fonts/Arial 10 (ansi).uft delete mode 100644 Templates/BaseGame/game/core/fonts/Arial 12 (ansi).uft delete mode 100644 Templates/BaseGame/game/core/fonts/Arial 14 (ansi).uft delete mode 100644 Templates/BaseGame/game/core/fonts/Arial 16 (ansi).uft delete mode 100644 Templates/BaseGame/game/core/fonts/Arial 36 (ansi).uft delete mode 100644 Templates/BaseGame/game/core/fonts/Arial Bold 14 (ansi).uft delete mode 100644 Templates/BaseGame/game/core/fonts/Arial Bold 16 (ansi).uft delete mode 100644 Templates/BaseGame/game/core/fonts/Arial Bold 18 (ansi).uft delete mode 100644 Templates/BaseGame/game/core/fonts/ArialBold 14 (ansi).uft delete mode 100644 Templates/BaseGame/game/core/fonts/ArialItalic 14 (ansi).uft delete mode 100644 Templates/BaseGame/game/core/fonts/Lucida Console 12 (ansi).uft delete mode 100644 Templates/BaseGame/game/core/gfxData/clouds.cs delete mode 100644 Templates/BaseGame/game/core/gfxData/commonMaterialData.cs delete mode 100644 Templates/BaseGame/game/core/gfxData/scatterSky.cs delete mode 100644 Templates/BaseGame/game/core/gfxData/shaders.cs delete mode 100644 Templates/BaseGame/game/core/gfxData/terrainBlock.cs delete mode 100644 Templates/BaseGame/game/core/gfxData/water.cs delete mode 100644 Templates/BaseGame/game/core/gfxprofile/D3D9.ATITechnologiesInc.cs delete mode 100644 Templates/BaseGame/game/core/gfxprofile/D3D9.NVIDIA.GeForce8600.cs delete mode 100644 Templates/BaseGame/game/core/gfxprofile/D3D9.NVIDIA.QuadroFXGo1000.cs delete mode 100644 Templates/BaseGame/game/core/gfxprofile/D3D9.NVIDIA.cs delete mode 100644 Templates/BaseGame/game/core/gfxprofile/D3D9.cs delete mode 100644 Templates/BaseGame/game/core/globals.cs delete mode 100644 Templates/BaseGame/game/core/helperFunctions.cs delete mode 100644 Templates/BaseGame/game/core/images/AreaMap33.dds delete mode 100644 Templates/BaseGame/game/core/images/button.png delete mode 100644 Templates/BaseGame/game/core/images/caustics_1.png delete mode 100644 Templates/BaseGame/game/core/images/caustics_2.png delete mode 100644 Templates/BaseGame/game/core/images/checkbox.png delete mode 100644 Templates/BaseGame/game/core/images/group-border.png delete mode 100644 Templates/BaseGame/game/core/images/inactive-overlay.png delete mode 100644 Templates/BaseGame/game/core/images/loadingbar.png delete mode 100644 Templates/BaseGame/game/core/images/materials.cs delete mode 100644 Templates/BaseGame/game/core/images/missingTexture.png delete mode 100644 Templates/BaseGame/game/core/images/noise.png delete mode 100644 Templates/BaseGame/game/core/images/null_color_ramp.png delete mode 100644 Templates/BaseGame/game/core/images/scrollBar.png delete mode 100644 Templates/BaseGame/game/core/images/textEdit.png delete mode 100644 Templates/BaseGame/game/core/images/thumbHighlightButton.png delete mode 100644 Templates/BaseGame/game/core/images/unavailable.png delete mode 100644 Templates/BaseGame/game/core/images/warnMat.dds delete mode 100644 Templates/BaseGame/game/core/images/window.png delete mode 100644 Templates/BaseGame/game/core/lighting.cs delete mode 100644 Templates/BaseGame/game/core/lighting/advanced/deferredShading.cs delete mode 100644 Templates/BaseGame/game/core/lighting/advanced/init.cs delete mode 100644 Templates/BaseGame/game/core/lighting/advanced/shaders.cs delete mode 100644 Templates/BaseGame/game/core/lighting/basic/init.cs delete mode 100644 Templates/BaseGame/game/core/lighting/basic/shadowFilter.cs delete mode 100644 Templates/BaseGame/game/core/lighting/shadowMaps/init.cs delete mode 100644 Templates/BaseGame/game/core/main.cs delete mode 100644 Templates/BaseGame/game/core/oculusVR.cs delete mode 100644 Templates/BaseGame/game/core/oculusVROverlay.gui delete mode 100644 Templates/BaseGame/game/core/parseArgs.cs delete mode 100644 Templates/BaseGame/game/core/postFX/GammaPostFX.cs delete mode 100644 Templates/BaseGame/game/core/postFX/MLAA.cs delete mode 100644 Templates/BaseGame/game/core/postFX/MotionBlurFx.cs delete mode 100644 Templates/BaseGame/game/core/postFX/caustics.cs delete mode 100644 Templates/BaseGame/game/core/postFX/chromaticLens.cs delete mode 100644 Templates/BaseGame/game/core/postFX/default.postfxpreset.cs delete mode 100644 Templates/BaseGame/game/core/postFX/dof.cs delete mode 100644 Templates/BaseGame/game/core/postFX/edgeAA.cs delete mode 100644 Templates/BaseGame/game/core/postFX/flash.cs delete mode 100644 Templates/BaseGame/game/core/postFX/fog.cs delete mode 100644 Templates/BaseGame/game/core/postFX/fxaa.cs delete mode 100644 Templates/BaseGame/game/core/postFX/glow.cs delete mode 100644 Templates/BaseGame/game/core/postFX/hdr.cs delete mode 100644 Templates/BaseGame/game/core/postFX/lightRay.cs delete mode 100644 Templates/BaseGame/game/core/postFX/ovrBarrelDistortion.cs delete mode 100644 Templates/BaseGame/game/core/postFX/postFxManager.gui delete mode 100644 Templates/BaseGame/game/core/postFX/postFxManager.gui.cs delete mode 100644 Templates/BaseGame/game/core/postFX/postFxManager.gui.settings.cs delete mode 100644 Templates/BaseGame/game/core/postFX/postFxManager.persistance.cs delete mode 100644 Templates/BaseGame/game/core/postFX/ssao.cs delete mode 100644 Templates/BaseGame/game/core/postFX/turbulence.cs delete mode 100644 Templates/BaseGame/game/core/postFX/vignette.cs delete mode 100644 Templates/BaseGame/game/core/postFx.cs delete mode 100644 Templates/BaseGame/game/core/profiles.cs delete mode 100644 Templates/BaseGame/game/core/renderManager.cs delete mode 100644 Templates/BaseGame/game/core/sfx/audioAmbience.cs delete mode 100644 Templates/BaseGame/game/core/sfx/audioData.cs delete mode 100644 Templates/BaseGame/game/core/sfx/audioDescriptions.cs delete mode 100644 Templates/BaseGame/game/core/sfx/audioEnvironments.cs delete mode 100644 Templates/BaseGame/game/core/sfx/audioStates.cs delete mode 100644 Templates/BaseGame/game/core/shaders/VolumetricFog/VFogP.hlsl delete mode 100644 Templates/BaseGame/game/core/shaders/VolumetricFog/VFogPreP.hlsl delete mode 100644 Templates/BaseGame/game/core/shaders/VolumetricFog/VFogPreV.hlsl delete mode 100644 Templates/BaseGame/game/core/shaders/VolumetricFog/VFogRefl.hlsl delete mode 100644 Templates/BaseGame/game/core/shaders/VolumetricFog/VFogV.hlsl delete mode 100644 Templates/BaseGame/game/core/shaders/VolumetricFog/gl/VFogP.glsl delete mode 100644 Templates/BaseGame/game/core/shaders/VolumetricFog/gl/VFogPreP.glsl delete mode 100644 Templates/BaseGame/game/core/shaders/VolumetricFog/gl/VFogPreV.glsl delete mode 100644 Templates/BaseGame/game/core/shaders/VolumetricFog/gl/VFogRefl.glsl delete mode 100644 Templates/BaseGame/game/core/shaders/VolumetricFog/gl/VFogV.glsl delete mode 100644 Templates/BaseGame/game/core/shaders/basicCloudsP.hlsl delete mode 100644 Templates/BaseGame/game/core/shaders/basicCloudsV.hlsl delete mode 100644 Templates/BaseGame/game/core/shaders/cloudLayerP.hlsl delete mode 100644 Templates/BaseGame/game/core/shaders/cloudLayerV.hlsl delete mode 100644 Templates/BaseGame/game/core/shaders/fixedFunction/addColorTextureP.hlsl delete mode 100644 Templates/BaseGame/game/core/shaders/fixedFunction/addColorTextureV.hlsl delete mode 100644 Templates/BaseGame/game/core/shaders/fixedFunction/colorP.hlsl delete mode 100644 Templates/BaseGame/game/core/shaders/fixedFunction/colorV.hlsl delete mode 100644 Templates/BaseGame/game/core/shaders/fixedFunction/gl/addColorTextureP.glsl delete mode 100644 Templates/BaseGame/game/core/shaders/fixedFunction/gl/addColorTextureV.glsl delete mode 100644 Templates/BaseGame/game/core/shaders/fixedFunction/gl/colorP.glsl delete mode 100644 Templates/BaseGame/game/core/shaders/fixedFunction/gl/colorV.glsl delete mode 100644 Templates/BaseGame/game/core/shaders/fixedFunction/gl/modColorTextureP.glsl delete mode 100644 Templates/BaseGame/game/core/shaders/fixedFunction/gl/modColorTextureV.glsl delete mode 100644 Templates/BaseGame/game/core/shaders/fixedFunction/gl/targetRestoreP.glsl delete mode 100644 Templates/BaseGame/game/core/shaders/fixedFunction/gl/targetRestoreV.glsl delete mode 100644 Templates/BaseGame/game/core/shaders/fixedFunction/gl/textureP.glsl delete mode 100644 Templates/BaseGame/game/core/shaders/fixedFunction/gl/textureV.glsl delete mode 100644 Templates/BaseGame/game/core/shaders/fixedFunction/modColorTextureP.hlsl delete mode 100644 Templates/BaseGame/game/core/shaders/fixedFunction/modColorTextureV.hlsl delete mode 100644 Templates/BaseGame/game/core/shaders/fixedFunction/targetRestoreP.hlsl delete mode 100644 Templates/BaseGame/game/core/shaders/fixedFunction/targetRestoreV.hlsl delete mode 100644 Templates/BaseGame/game/core/shaders/fixedFunction/textureP.hlsl delete mode 100644 Templates/BaseGame/game/core/shaders/fixedFunction/textureV.hlsl delete mode 100644 Templates/BaseGame/game/core/shaders/foliage.hlsl delete mode 100644 Templates/BaseGame/game/core/shaders/fxFoliageReplicatorP.hlsl delete mode 100644 Templates/BaseGame/game/core/shaders/fxFoliageReplicatorV.hlsl delete mode 100644 Templates/BaseGame/game/core/shaders/gl/basicCloudsP.glsl delete mode 100644 Templates/BaseGame/game/core/shaders/gl/basicCloudsV.glsl delete mode 100644 Templates/BaseGame/game/core/shaders/gl/blurP.glsl delete mode 100644 Templates/BaseGame/game/core/shaders/gl/blurV.glsl delete mode 100644 Templates/BaseGame/game/core/shaders/gl/cloudLayerP.glsl delete mode 100644 Templates/BaseGame/game/core/shaders/gl/cloudLayerV.glsl delete mode 100644 Templates/BaseGame/game/core/shaders/gl/foliage.glsl delete mode 100644 Templates/BaseGame/game/core/shaders/gl/fxFoliageReplicatorP.glsl delete mode 100644 Templates/BaseGame/game/core/shaders/gl/fxFoliageReplicatorV.glsl delete mode 100644 Templates/BaseGame/game/core/shaders/gl/guiMaterialV.glsl delete mode 100644 Templates/BaseGame/game/core/shaders/gl/hlslCompat.glsl delete mode 100644 Templates/BaseGame/game/core/shaders/gl/imposter.glsl delete mode 100644 Templates/BaseGame/game/core/shaders/gl/lighting.glsl delete mode 100644 Templates/BaseGame/game/core/shaders/gl/particleCompositeP.glsl delete mode 100644 Templates/BaseGame/game/core/shaders/gl/particleCompositeV.glsl delete mode 100644 Templates/BaseGame/game/core/shaders/gl/particlesP.glsl delete mode 100644 Templates/BaseGame/game/core/shaders/gl/particlesV.glsl delete mode 100644 Templates/BaseGame/game/core/shaders/gl/planarReflectBumpP.glsl delete mode 100644 Templates/BaseGame/game/core/shaders/gl/planarReflectBumpV.glsl delete mode 100644 Templates/BaseGame/game/core/shaders/gl/planarReflectP.glsl delete mode 100644 Templates/BaseGame/game/core/shaders/gl/planarReflectV.glsl delete mode 100644 Templates/BaseGame/game/core/shaders/gl/precipP.glsl delete mode 100644 Templates/BaseGame/game/core/shaders/gl/precipV.glsl delete mode 100644 Templates/BaseGame/game/core/shaders/gl/projectedShadowP.glsl delete mode 100644 Templates/BaseGame/game/core/shaders/gl/projectedShadowV.glsl delete mode 100644 Templates/BaseGame/game/core/shaders/gl/scatterSkyP.glsl delete mode 100644 Templates/BaseGame/game/core/shaders/gl/scatterSkyV.glsl delete mode 100644 Templates/BaseGame/game/core/shaders/gl/torque.glsl delete mode 100644 Templates/BaseGame/game/core/shaders/gl/wavesP.glsl delete mode 100644 Templates/BaseGame/game/core/shaders/gl/wind.glsl delete mode 100644 Templates/BaseGame/game/core/shaders/guiMaterialV.hlsl delete mode 100644 Templates/BaseGame/game/core/shaders/hlslStructs.h delete mode 100644 Templates/BaseGame/game/core/shaders/hlslStructs.hlsl delete mode 100644 Templates/BaseGame/game/core/shaders/imposter.hlsl delete mode 100644 Templates/BaseGame/game/core/shaders/lighting.hlsl delete mode 100644 Templates/BaseGame/game/core/shaders/lighting/advanced/convexGeometryV.hlsl delete mode 100644 Templates/BaseGame/game/core/shaders/lighting/advanced/deferredClearGBufferP.hlsl delete mode 100644 Templates/BaseGame/game/core/shaders/lighting/advanced/deferredClearGBufferV.hlsl delete mode 100644 Templates/BaseGame/game/core/shaders/lighting/advanced/deferredColorShaderP.hlsl delete mode 100644 Templates/BaseGame/game/core/shaders/lighting/advanced/deferredShadingP.hlsl delete mode 100644 Templates/BaseGame/game/core/shaders/lighting/advanced/farFrustumQuad.hlsl delete mode 100644 Templates/BaseGame/game/core/shaders/lighting/advanced/farFrustumQuadV.hlsl delete mode 100644 Templates/BaseGame/game/core/shaders/lighting/advanced/gl/convexGeometryV.glsl delete mode 100644 Templates/BaseGame/game/core/shaders/lighting/advanced/gl/deferredClearGBufferP.glsl delete mode 100644 Templates/BaseGame/game/core/shaders/lighting/advanced/gl/deferredColorShaderP.glsl delete mode 100644 Templates/BaseGame/game/core/shaders/lighting/advanced/gl/deferredShadingP.glsl delete mode 100644 Templates/BaseGame/game/core/shaders/lighting/advanced/gl/farFrustumQuad.glsl delete mode 100644 Templates/BaseGame/game/core/shaders/lighting/advanced/gl/farFrustumQuadV.glsl delete mode 100644 Templates/BaseGame/game/core/shaders/lighting/advanced/gl/lightingUtils.glsl delete mode 100644 Templates/BaseGame/game/core/shaders/lighting/advanced/gl/pointLightP.glsl delete mode 100644 Templates/BaseGame/game/core/shaders/lighting/advanced/gl/softShadow.glsl delete mode 100644 Templates/BaseGame/game/core/shaders/lighting/advanced/gl/spotLightP.glsl delete mode 100644 Templates/BaseGame/game/core/shaders/lighting/advanced/gl/vectorLightP.glsl delete mode 100644 Templates/BaseGame/game/core/shaders/lighting/advanced/lightingUtils.hlsl delete mode 100644 Templates/BaseGame/game/core/shaders/lighting/advanced/particlePointLightP.hlsl delete mode 100644 Templates/BaseGame/game/core/shaders/lighting/advanced/particlePointLightV.hlsl delete mode 100644 Templates/BaseGame/game/core/shaders/lighting/advanced/pointLightP.hlsl delete mode 100644 Templates/BaseGame/game/core/shaders/lighting/advanced/softShadow.hlsl delete mode 100644 Templates/BaseGame/game/core/shaders/lighting/advanced/spotLightP.hlsl delete mode 100644 Templates/BaseGame/game/core/shaders/lighting/advanced/vectorLightP.hlsl delete mode 100644 Templates/BaseGame/game/core/shaders/lighting/basic/gl/shadowFilterP.glsl delete mode 100644 Templates/BaseGame/game/core/shaders/lighting/basic/gl/shadowFilterV.glsl delete mode 100644 Templates/BaseGame/game/core/shaders/lighting/basic/shadowFilterP.hlsl delete mode 100644 Templates/BaseGame/game/core/shaders/lighting/basic/shadowFilterV.hlsl delete mode 100644 Templates/BaseGame/game/core/shaders/lighting/shadowMap/boxFilterP.hlsl delete mode 100644 Templates/BaseGame/game/core/shaders/lighting/shadowMap/boxFilterV.hlsl delete mode 100644 Templates/BaseGame/game/core/shaders/lighting/shadowMap/gl/boxFilterP.glsl delete mode 100644 Templates/BaseGame/game/core/shaders/lighting/shadowMap/gl/boxFilterV.glsl delete mode 100644 Templates/BaseGame/game/core/shaders/lighting/shadowMap/shadowMapIO.h delete mode 100644 Templates/BaseGame/game/core/shaders/lighting/shadowMap/shadowMapIO_GLSL.h delete mode 100644 Templates/BaseGame/game/core/shaders/lighting/shadowMap/shadowMapIO_HLSL.h delete mode 100644 Templates/BaseGame/game/core/shaders/particleCompositeP.hlsl delete mode 100644 Templates/BaseGame/game/core/shaders/particleCompositeV.hlsl delete mode 100644 Templates/BaseGame/game/core/shaders/particlesP.hlsl delete mode 100644 Templates/BaseGame/game/core/shaders/particlesV.hlsl delete mode 100644 Templates/BaseGame/game/core/shaders/planarReflectBumpP.hlsl delete mode 100644 Templates/BaseGame/game/core/shaders/planarReflectBumpV.hlsl delete mode 100644 Templates/BaseGame/game/core/shaders/planarReflectP.hlsl delete mode 100644 Templates/BaseGame/game/core/shaders/planarReflectV.hlsl delete mode 100644 Templates/BaseGame/game/core/shaders/postFX/VolFogGlowP.hlsl delete mode 100644 Templates/BaseGame/game/core/shaders/postFX/caustics/causticsP.hlsl delete mode 100644 Templates/BaseGame/game/core/shaders/postFX/caustics/gl/causticsP.glsl delete mode 100644 Templates/BaseGame/game/core/shaders/postFX/chromaticLens.hlsl delete mode 100644 Templates/BaseGame/game/core/shaders/postFX/dof/DOF_CalcCoC_P.hlsl delete mode 100644 Templates/BaseGame/game/core/shaders/postFX/dof/DOF_CalcCoC_V.hlsl delete mode 100644 Templates/BaseGame/game/core/shaders/postFX/dof/DOF_DownSample_P.hlsl delete mode 100644 Templates/BaseGame/game/core/shaders/postFX/dof/DOF_DownSample_V.hlsl delete mode 100644 Templates/BaseGame/game/core/shaders/postFX/dof/DOF_Final_P.hlsl delete mode 100644 Templates/BaseGame/game/core/shaders/postFX/dof/DOF_Final_V.hlsl delete mode 100644 Templates/BaseGame/game/core/shaders/postFX/dof/DOF_Gausian_P.hlsl delete mode 100644 Templates/BaseGame/game/core/shaders/postFX/dof/DOF_Gausian_V.hlsl delete mode 100644 Templates/BaseGame/game/core/shaders/postFX/dof/DOF_Passthrough_V.hlsl delete mode 100644 Templates/BaseGame/game/core/shaders/postFX/dof/DOF_SmallBlur_P.hlsl delete mode 100644 Templates/BaseGame/game/core/shaders/postFX/dof/DOF_SmallBlur_V.hlsl delete mode 100644 Templates/BaseGame/game/core/shaders/postFX/dof/gl/DOF_CalcCoC_P.glsl delete mode 100644 Templates/BaseGame/game/core/shaders/postFX/dof/gl/DOF_CalcCoC_V.glsl delete mode 100644 Templates/BaseGame/game/core/shaders/postFX/dof/gl/DOF_DownSample_P.glsl delete mode 100644 Templates/BaseGame/game/core/shaders/postFX/dof/gl/DOF_DownSample_V.glsl delete mode 100644 Templates/BaseGame/game/core/shaders/postFX/dof/gl/DOF_Final_P.glsl delete mode 100644 Templates/BaseGame/game/core/shaders/postFX/dof/gl/DOF_Final_V.glsl delete mode 100644 Templates/BaseGame/game/core/shaders/postFX/dof/gl/DOF_Gausian_P.glsl delete mode 100644 Templates/BaseGame/game/core/shaders/postFX/dof/gl/DOF_Gausian_V.glsl delete mode 100644 Templates/BaseGame/game/core/shaders/postFX/dof/gl/DOF_Passthrough_V.glsl delete mode 100644 Templates/BaseGame/game/core/shaders/postFX/dof/gl/DOF_SmallBlur_P.glsl delete mode 100644 Templates/BaseGame/game/core/shaders/postFX/dof/gl/DOF_SmallBlur_V.glsl delete mode 100644 Templates/BaseGame/game/core/shaders/postFX/edgeaa/dbgEdgeDisplayP.hlsl delete mode 100644 Templates/BaseGame/game/core/shaders/postFX/edgeaa/edgeAAP.hlsl delete mode 100644 Templates/BaseGame/game/core/shaders/postFX/edgeaa/edgeAAV.hlsl delete mode 100644 Templates/BaseGame/game/core/shaders/postFX/edgeaa/edgeDetectP.hlsl delete mode 100644 Templates/BaseGame/game/core/shaders/postFX/edgeaa/gl/dbgEdgeDisplayP.glsl delete mode 100644 Templates/BaseGame/game/core/shaders/postFX/edgeaa/gl/edgeAAP.glsl delete mode 100644 Templates/BaseGame/game/core/shaders/postFX/edgeaa/gl/edgeAAV.glsl delete mode 100644 Templates/BaseGame/game/core/shaders/postFX/edgeaa/gl/edgeDetectP.glsl delete mode 100644 Templates/BaseGame/game/core/shaders/postFX/flashP.hlsl delete mode 100644 Templates/BaseGame/game/core/shaders/postFX/fogP.hlsl delete mode 100644 Templates/BaseGame/game/core/shaders/postFX/fxaa/Fxaa3_11.h delete mode 100644 Templates/BaseGame/game/core/shaders/postFX/fxaa/fxaaP.hlsl delete mode 100644 Templates/BaseGame/game/core/shaders/postFX/fxaa/fxaaV.hlsl delete mode 100644 Templates/BaseGame/game/core/shaders/postFX/fxaa/gl/fxaaP.glsl delete mode 100644 Templates/BaseGame/game/core/shaders/postFX/fxaa/gl/fxaaV.glsl delete mode 100644 Templates/BaseGame/game/core/shaders/postFX/gammaP.hlsl delete mode 100644 Templates/BaseGame/game/core/shaders/postFX/gl/VolFogGlowP.glsl delete mode 100644 Templates/BaseGame/game/core/shaders/postFX/gl/chromaticLens.glsl delete mode 100644 Templates/BaseGame/game/core/shaders/postFX/gl/flashP.glsl delete mode 100644 Templates/BaseGame/game/core/shaders/postFX/gl/fogP.glsl delete mode 100644 Templates/BaseGame/game/core/shaders/postFX/gl/gammaP.glsl delete mode 100644 Templates/BaseGame/game/core/shaders/postFX/gl/glowBlurP.glsl delete mode 100644 Templates/BaseGame/game/core/shaders/postFX/gl/glowBlurV.glsl delete mode 100644 Templates/BaseGame/game/core/shaders/postFX/gl/motionBlurP.glsl delete mode 100644 Templates/BaseGame/game/core/shaders/postFX/gl/passthruP.glsl delete mode 100644 Templates/BaseGame/game/core/shaders/postFX/gl/postFX.glsl delete mode 100644 Templates/BaseGame/game/core/shaders/postFX/gl/postFxV.glsl delete mode 100644 Templates/BaseGame/game/core/shaders/postFX/gl/turbulenceP.glsl delete mode 100644 Templates/BaseGame/game/core/shaders/postFX/gl/underwaterFogP.glsl delete mode 100644 Templates/BaseGame/game/core/shaders/postFX/glowBlurP.hlsl delete mode 100644 Templates/BaseGame/game/core/shaders/postFX/glowBlurV.hlsl delete mode 100644 Templates/BaseGame/game/core/shaders/postFX/hdr/bloomGaussBlurHP.hlsl delete mode 100644 Templates/BaseGame/game/core/shaders/postFX/hdr/bloomGaussBlurVP.hlsl delete mode 100644 Templates/BaseGame/game/core/shaders/postFX/hdr/brightPassFilterP.hlsl delete mode 100644 Templates/BaseGame/game/core/shaders/postFX/hdr/calculateAdaptedLumP.hlsl delete mode 100644 Templates/BaseGame/game/core/shaders/postFX/hdr/downScale4x4P.hlsl delete mode 100644 Templates/BaseGame/game/core/shaders/postFX/hdr/downScale4x4V.hlsl delete mode 100644 Templates/BaseGame/game/core/shaders/postFX/hdr/finalPassCombineP.hlsl delete mode 100644 Templates/BaseGame/game/core/shaders/postFX/hdr/gl/bloomGaussBlurHP.glsl delete mode 100644 Templates/BaseGame/game/core/shaders/postFX/hdr/gl/bloomGaussBlurVP.glsl delete mode 100644 Templates/BaseGame/game/core/shaders/postFX/hdr/gl/brightPassFilterP.glsl delete mode 100644 Templates/BaseGame/game/core/shaders/postFX/hdr/gl/calculateAdaptedLumP.glsl delete mode 100644 Templates/BaseGame/game/core/shaders/postFX/hdr/gl/downScale4x4P.glsl delete mode 100644 Templates/BaseGame/game/core/shaders/postFX/hdr/gl/downScale4x4V.glsl delete mode 100644 Templates/BaseGame/game/core/shaders/postFX/hdr/gl/finalPassCombineP.glsl delete mode 100644 Templates/BaseGame/game/core/shaders/postFX/hdr/gl/luminanceVisP.glsl delete mode 100644 Templates/BaseGame/game/core/shaders/postFX/hdr/gl/sampleLumInitialP.glsl delete mode 100644 Templates/BaseGame/game/core/shaders/postFX/hdr/gl/sampleLumIterativeP.glsl delete mode 100644 Templates/BaseGame/game/core/shaders/postFX/hdr/luminanceVisP.hlsl delete mode 100644 Templates/BaseGame/game/core/shaders/postFX/hdr/sampleLumInitialP.hlsl delete mode 100644 Templates/BaseGame/game/core/shaders/postFX/hdr/sampleLumIterativeP.hlsl delete mode 100644 Templates/BaseGame/game/core/shaders/postFX/lightRay/gl/lightRayOccludeP.glsl delete mode 100644 Templates/BaseGame/game/core/shaders/postFX/lightRay/gl/lightRayP.glsl delete mode 100644 Templates/BaseGame/game/core/shaders/postFX/lightRay/lightRayOccludeP.hlsl delete mode 100644 Templates/BaseGame/game/core/shaders/postFX/lightRay/lightRayP.hlsl delete mode 100644 Templates/BaseGame/game/core/shaders/postFX/mlaa/blendWeightCalculationP.hlsl delete mode 100644 Templates/BaseGame/game/core/shaders/postFX/mlaa/edgeDetectionP.hlsl delete mode 100644 Templates/BaseGame/game/core/shaders/postFX/mlaa/functions.hlsl delete mode 100644 Templates/BaseGame/game/core/shaders/postFX/mlaa/gl/blendWeightCalculationP.glsl delete mode 100644 Templates/BaseGame/game/core/shaders/postFX/mlaa/gl/edgeDetectionP.glsl delete mode 100644 Templates/BaseGame/game/core/shaders/postFX/mlaa/gl/functions.glsl delete mode 100644 Templates/BaseGame/game/core/shaders/postFX/mlaa/gl/neighborhoodBlendingP.glsl delete mode 100644 Templates/BaseGame/game/core/shaders/postFX/mlaa/gl/offsetV.glsl delete mode 100644 Templates/BaseGame/game/core/shaders/postFX/mlaa/gl/passthruV.glsl delete mode 100644 Templates/BaseGame/game/core/shaders/postFX/mlaa/neighborhoodBlendingP.hlsl delete mode 100644 Templates/BaseGame/game/core/shaders/postFX/mlaa/offsetV.hlsl delete mode 100644 Templates/BaseGame/game/core/shaders/postFX/mlaa/passthruV.hlsl delete mode 100644 Templates/BaseGame/game/core/shaders/postFX/motionBlurP.hlsl delete mode 100644 Templates/BaseGame/game/core/shaders/postFX/oculusvr/barrelDistortionChromaP.hlsl delete mode 100644 Templates/BaseGame/game/core/shaders/postFX/oculusvr/barrelDistortionP.hlsl delete mode 100644 Templates/BaseGame/game/core/shaders/postFX/oculusvr/gl/barrelDistortionChromaP.glsl delete mode 100644 Templates/BaseGame/game/core/shaders/postFX/oculusvr/gl/barrelDistortionP.glsl delete mode 100644 Templates/BaseGame/game/core/shaders/postFX/oculusvr/gl/monoToStereoP.glsl delete mode 100644 Templates/BaseGame/game/core/shaders/postFX/oculusvr/monoToStereoP.hlsl delete mode 100644 Templates/BaseGame/game/core/shaders/postFX/passthruP.hlsl delete mode 100644 Templates/BaseGame/game/core/shaders/postFX/postFx.hlsl delete mode 100644 Templates/BaseGame/game/core/shaders/postFX/postFxV.glsl delete mode 100644 Templates/BaseGame/game/core/shaders/postFX/postFxV.hlsl delete mode 100644 Templates/BaseGame/game/core/shaders/postFX/ssao/SSAO_Blur_P.hlsl delete mode 100644 Templates/BaseGame/game/core/shaders/postFX/ssao/SSAO_Blur_V.hlsl delete mode 100644 Templates/BaseGame/game/core/shaders/postFX/ssao/SSAO_P.hlsl delete mode 100644 Templates/BaseGame/game/core/shaders/postFX/ssao/SSAO_PowerTable_P.hlsl delete mode 100644 Templates/BaseGame/game/core/shaders/postFX/ssao/SSAO_PowerTable_V.hlsl delete mode 100644 Templates/BaseGame/game/core/shaders/postFX/ssao/gl/SSAO_Blur_P.glsl delete mode 100644 Templates/BaseGame/game/core/shaders/postFX/ssao/gl/SSAO_Blur_V.glsl delete mode 100644 Templates/BaseGame/game/core/shaders/postFX/ssao/gl/SSAO_P.glsl delete mode 100644 Templates/BaseGame/game/core/shaders/postFX/ssao/gl/SSAO_PowerTable_P.glsl delete mode 100644 Templates/BaseGame/game/core/shaders/postFX/ssao/gl/SSAO_PowerTable_V.glsl delete mode 100644 Templates/BaseGame/game/core/shaders/postFX/turbulenceP.hlsl delete mode 100644 Templates/BaseGame/game/core/shaders/postFX/underwaterFogP.hlsl delete mode 100644 Templates/BaseGame/game/core/shaders/postFX/vignette/VignetteP.hlsl delete mode 100644 Templates/BaseGame/game/core/shaders/postFX/vignette/gl/VignetteP.glsl delete mode 100644 Templates/BaseGame/game/core/shaders/precipP.hlsl delete mode 100644 Templates/BaseGame/game/core/shaders/precipV.hlsl delete mode 100644 Templates/BaseGame/game/core/shaders/projectedShadowP.hlsl delete mode 100644 Templates/BaseGame/game/core/shaders/projectedShadowV.hlsl delete mode 100644 Templates/BaseGame/game/core/shaders/ribbons/basicRibbonShaderP.hlsl delete mode 100644 Templates/BaseGame/game/core/shaders/ribbons/basicRibbonShaderV.hlsl delete mode 100644 Templates/BaseGame/game/core/shaders/ribbons/gl/basicRibbonShaderP.glsl delete mode 100644 Templates/BaseGame/game/core/shaders/ribbons/gl/basicRibbonShaderV.glsl delete mode 100644 Templates/BaseGame/game/core/shaders/ribbons/gl/texRibbonShaderP.glsl delete mode 100644 Templates/BaseGame/game/core/shaders/ribbons/gl/texRibbonShaderV.glsl delete mode 100644 Templates/BaseGame/game/core/shaders/ribbons/texRibbonShaderP.hlsl delete mode 100644 Templates/BaseGame/game/core/shaders/ribbons/texRibbonShaderV.hlsl delete mode 100644 Templates/BaseGame/game/core/shaders/scatterSkyP.hlsl delete mode 100644 Templates/BaseGame/game/core/shaders/scatterSkyV.hlsl delete mode 100644 Templates/BaseGame/game/core/shaders/shaderModel.hlsl delete mode 100644 Templates/BaseGame/game/core/shaders/shaderModelAutoGen.hlsl delete mode 100644 Templates/BaseGame/game/core/shaders/shdrConsts.h delete mode 100644 Templates/BaseGame/game/core/shaders/terrain/blendP.hlsl delete mode 100644 Templates/BaseGame/game/core/shaders/terrain/blendV.hlsl delete mode 100644 Templates/BaseGame/game/core/shaders/terrain/gl/blendP.glsl delete mode 100644 Templates/BaseGame/game/core/shaders/terrain/gl/blendV.glsl delete mode 100644 Templates/BaseGame/game/core/shaders/terrain/terrain.glsl delete mode 100644 Templates/BaseGame/game/core/shaders/terrain/terrain.hlsl delete mode 100644 Templates/BaseGame/game/core/shaders/torque.hlsl delete mode 100644 Templates/BaseGame/game/core/shaders/water/gl/waterBasicP.glsl delete mode 100644 Templates/BaseGame/game/core/shaders/water/gl/waterBasicV.glsl delete mode 100644 Templates/BaseGame/game/core/shaders/water/gl/waterP.glsl delete mode 100644 Templates/BaseGame/game/core/shaders/water/gl/waterV.glsl delete mode 100644 Templates/BaseGame/game/core/shaders/water/waterBasicP.hlsl delete mode 100644 Templates/BaseGame/game/core/shaders/water/waterBasicV.hlsl delete mode 100644 Templates/BaseGame/game/core/shaders/water/waterP.hlsl delete mode 100644 Templates/BaseGame/game/core/shaders/water/waterV.hlsl delete mode 100644 Templates/BaseGame/game/core/shaders/wavesP.hlsl delete mode 100644 Templates/BaseGame/game/core/shaders/wavesV.hlsl delete mode 100644 Templates/BaseGame/game/core/shaders/wind.hlsl delete mode 100644 Templates/BaseGame/game/data/clientServer/ClientServer.cs delete mode 100644 Templates/BaseGame/game/data/clientServer/ClientServer.module delete mode 100644 Templates/BaseGame/game/data/clientServer/scripts/client/client.cs delete mode 100644 Templates/BaseGame/game/data/clientServer/scripts/client/connectionToServer.cs delete mode 100644 Templates/BaseGame/game/data/clientServer/scripts/client/levelDownload.cs delete mode 100644 Templates/BaseGame/game/data/clientServer/scripts/client/levelLoad.cs delete mode 100644 Templates/BaseGame/game/data/clientServer/scripts/client/message.cs delete mode 100644 Templates/BaseGame/game/data/clientServer/scripts/server/audio.cs delete mode 100644 Templates/BaseGame/game/data/clientServer/scripts/server/commands.cs delete mode 100644 Templates/BaseGame/game/data/clientServer/scripts/server/connectionToClient.cs delete mode 100644 Templates/BaseGame/game/data/clientServer/scripts/server/defaults.cs delete mode 100644 Templates/BaseGame/game/data/clientServer/scripts/server/kickban.cs delete mode 100644 Templates/BaseGame/game/data/clientServer/scripts/server/levelDownload.cs delete mode 100644 Templates/BaseGame/game/data/clientServer/scripts/server/levelInfo.cs delete mode 100644 Templates/BaseGame/game/data/clientServer/scripts/server/levelLoad.cs delete mode 100644 Templates/BaseGame/game/data/clientServer/scripts/server/message.cs delete mode 100644 Templates/BaseGame/game/data/clientServer/scripts/server/server.cs diff --git a/Templates/BaseGame/game/core/CoreComponents.cs b/Templates/BaseGame/game/core/CoreComponents.cs deleted file mode 100644 index 5bdca8cd3..000000000 --- a/Templates/BaseGame/game/core/CoreComponents.cs +++ /dev/null @@ -1,10 +0,0 @@ - -function CoreComponentsModule::onCreate(%this) -{ - %classList = enumerateConsoleClasses( "Component" ); - - foreach$( %componentClass in %classList ) - { - echo("Native Component of type: " @ %componentClass); - } -} \ No newline at end of file diff --git a/Templates/BaseGame/game/core/CoreComponents.module b/Templates/BaseGame/game/core/CoreComponents.module deleted file mode 100644 index 0636e3bb5..000000000 --- a/Templates/BaseGame/game/core/CoreComponents.module +++ /dev/null @@ -1,19 +0,0 @@ - - - - \ No newline at end of file diff --git a/Templates/BaseGame/game/core/audio.cs b/Templates/BaseGame/game/core/audio.cs deleted file mode 100644 index a5932de8f..000000000 --- a/Templates/BaseGame/game/core/audio.cs +++ /dev/null @@ -1,436 +0,0 @@ -//----------------------------------------------------------------------------- -// 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. -//----------------------------------------------------------------------------- - -//----------------------------------------------------------------------------- -// Source groups. -//----------------------------------------------------------------------------- - -singleton SFXDescription( AudioMaster ); -singleton SFXSource( AudioChannelMaster ) -{ - description = AudioMaster; -}; - -singleton SFXDescription( AudioChannel ) -{ - sourceGroup = AudioChannelMaster; -}; - -singleton SFXSource( AudioChannelDefault ) -{ - description = AudioChannel; -}; -singleton SFXSource( AudioChannelGui ) -{ - description = AudioChannel; -}; -singleton SFXSource( AudioChannelEffects ) -{ - description = AudioChannel; -}; -singleton SFXSource( AudioChannelMessages ) -{ - description = AudioChannel; -}; -singleton SFXSource( AudioChannelMusic ) -{ - description = AudioChannel; -}; - -// Set default playback states of the channels. - -AudioChannelMaster.play(); -AudioChannelDefault.play(); - -AudioChannelGui.play(); -AudioChannelMusic.play(); -AudioChannelMessages.play(); - -// Stop in-game effects channels. -AudioChannelEffects.stop(); - -//----------------------------------------------------------------------------- -// Master SFXDescriptions. -//----------------------------------------------------------------------------- - -// Master description for interface audio. -singleton SFXDescription( AudioGui ) -{ - volume = 1.0; - sourceGroup = AudioChannelGui; -}; - -// Master description for game effects audio. -singleton SFXDescription( AudioEffect ) -{ - volume = 1.0; - sourceGroup = AudioChannelEffects; -}; - -// Master description for audio in notifications. -singleton SFXDescription( AudioMessage ) -{ - volume = 1.0; - sourceGroup = AudioChannelMessages; -}; - -// Master description for music. -singleton SFXDescription( AudioMusic ) -{ - volume = 1.0; - sourceGroup = AudioChannelMusic; -}; - -//----------------------------------------------------------------------------- -// SFX Functions. -//----------------------------------------------------------------------------- - -/// This initializes the sound system device from -/// the defaults in the $pref::SFX:: globals. -function sfxStartup() -{ - echo( "\nsfxStartup..." ); - - // If we have a provider set, try initialize a device now. - - if( $pref::SFX::provider !$= "" ) - { - if( sfxInit() ) - return; - else - { - // Force auto-detection. - $pref::SFX::autoDetect = true; - } - } - - // If enabled autodetect a safe device. - - if( ( !isDefined( "$pref::SFX::autoDetect" ) || $pref::SFX::autoDetect ) && - sfxAutodetect() ) - return; - - // Failure. - - error( " Failed to initialize device!\n\n" ); - - $pref::SFX::provider = ""; - $pref::SFX::device = ""; - - return; -} - - -/// This initializes the sound system device from -/// the defaults in the $pref::SFX:: globals. -function sfxInit() -{ - // If already initialized, shut down the current device first. - - if( sfxGetDeviceInfo() !$= "" ) - sfxShutdown(); - - // Start it up! - %maxBuffers = $pref::SFX::useHardware ? -1 : $pref::SFX::maxSoftwareBuffers; - if ( !sfxCreateDevice( $pref::SFX::provider, $pref::SFX::device, $pref::SFX::useHardware, %maxBuffers ) ) - return false; - - // This returns a tab seperated string with - // the initialized system info. - %info = sfxGetDeviceInfo(); - $pref::SFX::provider = getField( %info, 0 ); - $pref::SFX::device = getField( %info, 1 ); - $pref::SFX::useHardware = getField( %info, 2 ); - %useHardware = $pref::SFX::useHardware ? "Yes" : "No"; - %maxBuffers = getField( %info, 3 ); - - echo( " Provider: " @ $pref::SFX::provider ); - echo( " Device: " @ $pref::SFX::device ); - echo( " Hardware: " @ %useHardware ); - echo( " Max Buffers: " @ %maxBuffers ); - echo( " " ); - - if( isDefined( "$pref::SFX::distanceModel" ) ) - sfxSetDistanceModel( $pref::SFX::distanceModel ); - if( isDefined( "$pref::SFX::dopplerFactor" ) ) - sfxSetDopplerFactor( $pref::SFX::dopplerFactor ); - if( isDefined( "$pref::SFX::rolloffFactor" ) ) - sfxSetRolloffFactor( $pref::SFX::rolloffFactor ); - - // Restore master volume. - - sfxSetMasterVolume( $pref::SFX::masterVolume ); - - // Restore channel volumes. - - for( %channel = 0; %channel <= 8; %channel ++ ) - sfxSetChannelVolume( %channel, $pref::SFX::channelVolume[ %channel ] ); - - return true; -} - - -/// Destroys the current sound system device. -function sfxShutdown() -{ - // Store volume prefs. - - $pref::SFX::masterVolume = sfxGetMasterVolume(); - - for( %channel = 0; %channel <= 8; %channel ++ ) - $pref::SFX::channelVolume[ %channel ] = sfxGetChannelVolume( %channel ); - - // We're assuming here that a null info - // string means that no device is loaded. - if( sfxGetDeviceInfo() $= "" ) - return; - - sfxDeleteDevice(); -} - - -/// Determines which of the two SFX providers is preferable. -function sfxCompareProvider( %providerA, %providerB ) -{ - if( %providerA $= %providerB ) - return 0; - - switch$( %providerA ) - { - // Always prefer FMOD over anything else. - case "FMOD": - return 1; - - // Prefer OpenAL over anything but FMOD. - case "OpenAL": - if( %providerB $= "FMOD" ) - return -1; - else - return 1; - - // choose XAudio over DirectSound - case "XAudio": - if( %providerB $= "FMOD" || %providerB $= "OpenAL" ) - return -1; - else - return 0; - - case "DirectSound": - if( %providerB !$= "FMOD" && %providerB !$= "OpenAL" && %providerB !$= "XAudio" ) - return 1; - else - return -1; - - default: - return -1; - } -} - - -/// Try to detect and initalize the best SFX device available. -function sfxAutodetect() -{ - // Get all the available devices. - - %devices = sfxGetAvailableDevices(); - - // Collect and sort the devices by preferentiality. - - %deviceTrySequence = new ArrayObject(); - %bestMatch = -1; - %count = getRecordCount( %devices ); - for( %i = 0; %i < %count; %i ++ ) - { - %info = getRecord( %devices, %i ); - %provider = getField( %info, 0 ); - - %deviceTrySequence.push_back( %provider, %info ); - } - - %deviceTrySequence.sortfkd( "sfxCompareProvider" ); - - // Try the devices in order. - - %count = %deviceTrySequence.count(); - for( %i = 0; %i < %count; %i ++ ) - { - %provider = %deviceTrySequence.getKey( %i ); - %info = %deviceTrySequence.getValue( %i ); - - $pref::SFX::provider = %provider; - $pref::SFX::device = getField( %info, 1 ); - $pref::SFX::useHardware = getField( %info, 2 ); - - // By default we've decided to avoid hardware devices as - // they are buggy and prone to problems. - $pref::SFX::useHardware = false; - - if( sfxInit() ) - { - $pref::SFX::autoDetect = false; - %deviceTrySequence.delete(); - return true; - } - } - - // Found no suitable device. - - error( "sfxAutodetect - Could not initialize a valid SFX device." ); - - $pref::SFX::provider = ""; - $pref::SFX::device = ""; - $pref::SFX::useHardware = ""; - - %deviceTrySequence.delete(); - - return false; -} - - -//----------------------------------------------------------------------------- -// Backwards-compatibility with old channel system. -//----------------------------------------------------------------------------- - -// Volume channel IDs for backwards-compatibility. - -$GuiAudioType = 1; // Interface. -$SimAudioType = 2; // Game. -$MessageAudioType = 3; // Notifications. -$MusicAudioType = 4; // Music. - -$AudioChannels[ 0 ] = AudioChannelDefault; -$AudioChannels[ $GuiAudioType ] = AudioChannelGui; -$AudioChannels[ $SimAudioType ] = AudioChannelEffects; -$AudioChannels[ $MessageAudioType ] = AudioChannelMessages; -$AudioChannels[ $MusicAudioType ] = AudioChannelMusic; - -function sfxOldChannelToGroup( %channel ) -{ - return $AudioChannels[ %channel ]; -} - -function sfxGroupToOldChannel( %group ) -{ - %id = %group.getId(); - for( %i = 0;; %i ++ ) - if( !isObject( $AudioChannels[ %i ] ) ) - return -1; - else if( $AudioChannels[ %i ].getId() == %id ) - return %i; - - return -1; -} - -function sfxSetMasterVolume( %volume ) -{ - AudioChannelMaster.setVolume( %volume ); -} - -function sfxGetMasterVolume( %volume ) -{ - return AudioChannelMaster.getVolume(); -} - -function sfxStopAll( %channel ) -{ - // Don't stop channel itself since that isn't quite what the function - // here intends. - - %channel = sfxOldChannelToGroup( %channel ); - if (isObject(%channel)) - { - foreach( %source in %channel ) - %source.stop(); - } -} - -function sfxGetChannelVolume( %channel ) -{ - %obj = sfxOldChannelToGroup( %channel ); - if( isObject( %obj ) ) - return %obj.getVolume(); -} - -function sfxSetChannelVolume( %channel, %volume ) -{ - %obj = sfxOldChannelToGroup( %channel ); - if( isObject( %obj ) ) - %obj.setVolume( %volume ); -} - -/*singleton SimSet( SFXPausedSet ); - - -/// Pauses the playback of active sound sources. -/// -/// @param %channels An optional word list of channel indices or an empty -/// string to pause sources on all channels. -/// @param %pauseSet An optional SimSet which is filled with the paused -/// sources. If not specified the global SfxSourceGroup -/// is used. -/// -/// @deprecated -/// -function sfxPause( %channels, %pauseSet ) -{ - // Did we get a set to populate? - if ( !isObject( %pauseSet ) ) - %pauseSet = SFXPausedSet; - - %count = SFXSourceSet.getCount(); - for ( %i = 0; %i < %count; %i++ ) - { - %source = SFXSourceSet.getObject( %i ); - - %channel = sfxGroupToOldChannel( %source.getGroup() ); - if( %channels $= "" || findWord( %channels, %channel ) != -1 ) - { - %source.pause(); - %pauseSet.add( %source ); - } - } -} - - -/// Resumes the playback of paused sound sources. -/// -/// @param %pauseSet An optional SimSet which contains the paused sound -/// sources to be resumed. If not specified the global -/// SfxSourceGroup is used. -/// @deprecated -/// -function sfxResume( %pauseSet ) -{ - if ( !isObject( %pauseSet ) ) - %pauseSet = SFXPausedSet; - - %count = %pauseSet.getCount(); - for ( %i = 0; %i < %count; %i++ ) - { - %source = %pauseSet.getObject( %i ); - %source.play(); - } - - // Clear our pause set... the caller is left - // to clear his own if he passed one. - %pauseSet.clear(); -}*/ diff --git a/Templates/BaseGame/game/core/canvas.cs b/Templates/BaseGame/game/core/canvas.cs deleted file mode 100644 index b38cdccca..000000000 --- a/Templates/BaseGame/game/core/canvas.cs +++ /dev/null @@ -1,162 +0,0 @@ -//----------------------------------------------------------------------------- -// 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 createCanvas(%windowTitle) -{ - if ($isDedicated) - { - GFXInit::createNullDevice(); - return true; - } - - // Create the Canvas - $GameCanvas = new GuiCanvas(Canvas) - { - displayWindow = $platform !$= "windows"; - }; - - // Set the window title - if (isObject(Canvas)) - { - Canvas.setWindowTitle(%windowTitle @ " - " @ $pref::Video::displayDevice); - configureCanvas(); - } - else - { - error("Canvas creation failed. Shutting down."); - quit(); - } -} - -// Constants for referencing video resolution preferences -$WORD::RES_X = 0; -$WORD::RES_Y = 1; -$WORD::FULLSCREEN = 2; -$WORD::BITDEPTH = 3; -$WORD::REFRESH = 4; -$WORD::AA = 5; - -function configureCanvas() -{ - // Setup a good default if we don't have one already. - if ($pref::Video::Resolution $= "") - $pref::Video::Resolution = "800 600"; - if ($pref::Video::FullScreen $= "") - $pref::Video::FullScreen = false; - if ($pref::Video::BitDepth $= "") - $pref::Video::BitDepth = "32"; - if ($pref::Video::RefreshRate $= "") - $pref::Video::RefreshRate = "60"; - if ($pref::Video::AA $= "") - $pref::Video::AA = "4"; - - %resX = $pref::Video::Resolution.x; - %resY = $pref::Video::Resolution.y; - %fs = $pref::Video::FullScreen; - %bpp = $pref::Video::BitDepth; - %rate = $pref::Video::RefreshRate; - %aa = $pref::Video::AA; - - if($cliFullscreen !$= "") { - %fs = $cliFullscreen; - $cliFullscreen = ""; - } - - echo("--------------"); - echo("Attempting to set resolution to \"" @ %resX SPC %resY SPC %fs SPC %bpp SPC %rate SPC %aa @ "\""); - - %deskRes = getDesktopResolution(); - %deskResX = getWord(%deskRes, $WORD::RES_X); - %deskResY = getWord(%deskRes, $WORD::RES_Y); - %deskResBPP = getWord(%deskRes, 2); - - // We shouldn't be getting this any more but just in case... - if (%bpp $= "Default") - %bpp = %deskResBPP; - - // Make sure we are running at a valid resolution - if (%fs $= "0" || %fs $= "false") - { - // Windowed mode has to use the same bit depth as the desktop - %bpp = %deskResBPP; - - // Windowed mode also has to run at a smaller resolution than the desktop - if ((%resX >= %deskResX) || (%resY >= %deskResY)) - { - warn("Warning: The requested windowed resolution is equal to or larger than the current desktop resolution. Attempting to find a better resolution"); - - %resCount = Canvas.getModeCount(); - for (%i = (%resCount - 1); %i >= 0; %i--) - { - %testRes = Canvas.getMode(%i); - %testResX = getWord(%testRes, $WORD::RES_X); - %testResY = getWord(%testRes, $WORD::RES_Y); - %testBPP = getWord(%testRes, $WORD::BITDEPTH); - - if (%testBPP != %bpp) - continue; - - if ((%testResX < %deskResX) && (%testResY < %deskResY)) - { - // This will work as our new resolution - %resX = %testResX; - %resY = %testResY; - - warn("Warning: Switching to \"" @ %resX SPC %resY SPC %bpp @ "\""); - - break; - } - } - } - } - - $pref::Video::Resolution = %resX SPC %resY; - $pref::Video::FullScreen = %fs; - $pref::Video::BitDepth = %bpp; - $pref::Video::RefreshRate = %rate; - $pref::Video::AA = %aa; - - if (%fs == 1 || %fs $= "true") - %fsLabel = "Yes"; - else - %fsLabel = "No"; - - echo("Accepted Mode: " NL - "--Resolution : " @ %resX SPC %resY NL - "--Full Screen : " @ %fsLabel NL - "--Bits Per Pixel : " @ %bpp NL - "--Refresh Rate : " @ %rate NL - "--AA TypeXLevel : " @ %aa NL - "--------------"); - - // Actually set the new video mode - Canvas.setVideoMode(%resX, %resY, %fs, %bpp, %rate, %aa); - - commandToServer('setClientAspectRatio', %resX, %resY); - - // AA piggybacks on the AA setting in $pref::Video::mode. - // We need to parse the setting between AA modes, and then it's level - // It's formatted as AATypexAALevel - // So, FXAAx4 or MLAAx2 - if ( isObject( FXAA_PostEffect ) ) - FXAA_PostEffect.isEnabled = ( %aa > 0 ) ? true : false; -} diff --git a/Templates/BaseGame/game/core/components/RigidBodyComponent.asset.taml b/Templates/BaseGame/game/core/components/RigidBodyComponent.asset.taml deleted file mode 100644 index 8e60db364..000000000 --- a/Templates/BaseGame/game/core/components/RigidBodyComponent.asset.taml +++ /dev/null @@ -1,8 +0,0 @@ - diff --git a/Templates/BaseGame/game/core/components/animationComponent.asset.taml b/Templates/BaseGame/game/core/components/animationComponent.asset.taml deleted file mode 100644 index 771d38e02..000000000 --- a/Templates/BaseGame/game/core/components/animationComponent.asset.taml +++ /dev/null @@ -1,8 +0,0 @@ - diff --git a/Templates/BaseGame/game/core/components/cameraOrbiterComponent.asset.taml b/Templates/BaseGame/game/core/components/cameraOrbiterComponent.asset.taml deleted file mode 100644 index b615f2348..000000000 --- a/Templates/BaseGame/game/core/components/cameraOrbiterComponent.asset.taml +++ /dev/null @@ -1,8 +0,0 @@ - diff --git a/Templates/BaseGame/game/core/components/collisionComponent.asset.taml b/Templates/BaseGame/game/core/components/collisionComponent.asset.taml deleted file mode 100644 index 1a4f99a0d..000000000 --- a/Templates/BaseGame/game/core/components/collisionComponent.asset.taml +++ /dev/null @@ -1,8 +0,0 @@ - diff --git a/Templates/BaseGame/game/core/components/game/camera.asset.taml b/Templates/BaseGame/game/core/components/game/camera.asset.taml deleted file mode 100644 index f59e429e2..000000000 --- a/Templates/BaseGame/game/core/components/game/camera.asset.taml +++ /dev/null @@ -1,9 +0,0 @@ - diff --git a/Templates/BaseGame/game/core/components/game/camera.cs b/Templates/BaseGame/game/core/components/game/camera.cs deleted file mode 100644 index b6f510c9d..000000000 --- a/Templates/BaseGame/game/core/components/game/camera.cs +++ /dev/null @@ -1,185 +0,0 @@ -//----------------------------------------------------------------------------- -// 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 CameraComponent::onAdd(%this) -{ - %this.addComponentField(clientOwner, "The client that views this camera", "int", "1", ""); - - %test = %this.clientOwner; - - %barf = ClientGroup.getCount(); - - %clientID = %this.getClientID(); - if(%clientID && !isObject(%clientID.camera)) - { - %this.scopeToClient(%clientID); - %this.setDirty(); - - %clientID.setCameraObject(%this.owner); - %clientID.setControlCameraFov(%this.FOV); - - %clientID.camera = %this.owner; - } - - %res = $pref::Video::mode; - %derp = 0; -} - -function CameraComponent::onRemove(%this) -{ - %clientID = %this.getClientID(); - if(%clientID) - %clientID.clearCameraObject(); -} - -function CameraComponent::onInspectorUpdate(%this) -{ - //if(%this.clientOwner) - //%this.clientOwner.setCameraObject(%this.owner); -} - -function CameraComponent::getClientID(%this) -{ - return ClientGroup.getObject(%this.clientOwner-1); -} - -function CameraComponent::isClientCamera(%this, %client) -{ - %clientID = ClientGroup.getObject(%this.clientOwner-1); - - if(%client.getID() == %clientID) - return true; - else - return false; -} - -function CameraComponent::onClientConnect(%this, %client) -{ - //if(%this.isClientCamera(%client) && !isObject(%client.camera)) - //{ - %this.scopeToClient(%client); - %this.setDirty(); - - %client.setCameraObject(%this.owner); - %client.setControlCameraFov(%this.FOV); - - %client.camera = %this.owner; - //} - //else - //{ - // echo("CONNECTED CLIENT IS NOT CAMERA OWNER!"); - //} -} - -function CameraComponent::onClientDisconnect(%this, %client) -{ - Parent::onClientDisconnect(%this, %client); - - if(isClientCamera(%client)){ - %this.clearScopeToClient(%client); - %client.clearCameraObject(); - } -} - -/// -/// -/// - -function VRCameraComponent::onAdd(%this) -{ - %this.addComponentField(clientOwner, "The client that views this camera", "int", "1", ""); - - %test = %this.clientOwner; - - %barf = ClientGroup.getCount(); - - %clientID = %this.getClientID(); - if(%clientID && !isObject(%clientID.camera)) - { - %this.scopeToClient(%clientID); - %this.setDirty(); - - %clientID.setCameraObject(%this.owner); - %clientID.setControlCameraFov(%this.FOV); - - %clientID.camera = %this.owner; - } - - %res = $pref::Video::mode; - %derp = 0; -} - -function VRCameraComponent::onRemove(%this) -{ - %clientID = %this.getClientID(); - if(%clientID) - %clientID.clearCameraObject(); -} - -function CameraComponent::onInspectorUpdate(%this) -{ - //if(%this.clientOwner) - //%this.clientOwner.setCameraObject(%this.owner); -} - -function VRCameraComponent::getClientID(%this) -{ - return ClientGroup.getObject(%this.clientOwner-1); -} - -function VRCameraComponent::isClientCamera(%this, %client) -{ - %clientID = ClientGroup.getObject(%this.clientOwner-1); - - if(%client.getID() == %clientID) - return true; - else - return false; -} - -function VRCameraComponent::onClientConnect(%this, %client) -{ - //if(%this.isClientCamera(%client) && !isObject(%client.camera)) - //{ - %this.scopeToClient(%client); - %this.setDirty(); - - %client.setCameraObject(%this.owner); - %client.setControlCameraFov(%this.FOV); - - %client.camera = %this.owner; - //} - //else - //{ - // echo("CONNECTED CLIENT IS NOT CAMERA OWNER!"); - //} -} - -function VRCameraComponent::onClientDisconnect(%this, %client) -{ - Parent::onClientDisconnect(%this, %client); - - if(isClientCamera(%client)){ - %this.clearScopeToClient(%client); - %client.clearCameraObject(); - } -} \ No newline at end of file diff --git a/Templates/BaseGame/game/core/components/game/controlObject.asset.taml b/Templates/BaseGame/game/core/components/game/controlObject.asset.taml deleted file mode 100644 index 19515e833..000000000 --- a/Templates/BaseGame/game/core/components/game/controlObject.asset.taml +++ /dev/null @@ -1,10 +0,0 @@ - diff --git a/Templates/BaseGame/game/core/components/game/controlObject.cs b/Templates/BaseGame/game/core/components/game/controlObject.cs deleted file mode 100644 index 7f477ecca..000000000 --- a/Templates/BaseGame/game/core/components/game/controlObject.cs +++ /dev/null @@ -1,89 +0,0 @@ -//----------------------------------------------------------------------------- -// 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. -//----------------------------------------------------------------------------- - -//registerComponent("ControlObjectComponent", "Component", "Control Object", "Game", false, "Allows the behavior owner to operate as a camera."); - -function ControlObjectComponent::onAdd(%this) -{ - %this.addComponentField(clientOwner, "The shape to use for rendering", "int", "1", ""); - - %clientID = %this.getClientID(); - - if(%clientID && !isObject(%clientID.getControlObject())) - %clientID.setControlObject(%this.owner); -} - -function ControlObjectComponent::onRemove(%this) -{ - %clientID = %this.getClientID(); - - if(%clientID) - %clientID.setControlObject(0); -} - -function ControlObjectComponent::onClientConnect(%this, %client) -{ - if(%this.isControlClient(%client) && !isObject(%client.getControlObject())) - %client.setControlObject(%this.owner); -} - -function ControlObjectComponent::onClientDisconnect(%this, %client) -{ - if(%this.isControlClient(%client)) - %client.setControlObject(0); -} - -function ControlObjectComponent::getClientID(%this) -{ - return ClientGroup.getObject(%this.clientOwner-1); -} - -function ControlObjectComponent::isControlClient(%this, %client) -{ - %clientID = ClientGroup.getObject(%this.clientOwner-1); - - if(%client.getID() == %clientID) - return true; - else - return false; -} - -function ControlObjectComponent::onInspectorUpdate(%this, %field) -{ - %clientID = %this.getClientID(); - - if(%clientID && !isObject(%clientID.getControlObject())) - %clientID.setControlObject(%this.owner); -} - -function switchControlObject(%client, %newControlEntity) -{ - if(!isObject(%client) || !isObject(%newControlEntity)) - return error("SwitchControlObject: No client or target controller!"); - - %control = %newControlEntity.getComponent(ControlObjectComponent); - - if(!isObject(%control)) - return error("SwitchControlObject: Target controller has no conrol object behavior!"); - - %client.setControlObject(%newControlEntity); -} \ No newline at end of file diff --git a/Templates/BaseGame/game/core/components/game/itemRotate.asset.taml b/Templates/BaseGame/game/core/components/game/itemRotate.asset.taml deleted file mode 100644 index 4c0c1bec4..000000000 --- a/Templates/BaseGame/game/core/components/game/itemRotate.asset.taml +++ /dev/null @@ -1,10 +0,0 @@ - diff --git a/Templates/BaseGame/game/core/components/game/itemRotate.cs b/Templates/BaseGame/game/core/components/game/itemRotate.cs deleted file mode 100644 index 947d19214..000000000 --- a/Templates/BaseGame/game/core/components/game/itemRotate.cs +++ /dev/null @@ -1,49 +0,0 @@ -//----------------------------------------------------------------------------- -// 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. -//----------------------------------------------------------------------------- - -//registerComponent("ItemRotationComponent", "Component", "Item Rotation", "Game", false, "Rotates the entity around the z axis, like an item pickup."); - -function ItemRotationComponent::onAdd(%this) -{ - %this.addComponentField(rotationsPerMinute, "Number of rotations per minute", "float", "5", ""); - %this.addComponentField(forward, "Rotate forward or backwards", "bool", "1", ""); - %this.addComponentField(horizontal, "Rotate horizontal or verticle, true for horizontal", "bool", "1", ""); -} - -function ItemRotationComponent::Update(%this) -{ - %tickRate = 0.032; - - //Rotations per second is calculated based on a standard update tick being 32ms. So we scale by the tick speed, then add that to our rotation to - //get a nice rotation speed. - if(%this.horizontal) - { - if(%this.forward) - %this.owner.rotation.z += ( ( 360 * %this.rotationsPerMinute ) / 60 ) * %tickRate; - else - %this.owner.rotation.z -= ( ( 360 * %this.rotationsPerMinute ) / 60 ) * %tickRate; - } - else - { - %this.owner.rotation.x += ( ( 360 * %this.rotationsPerMinute ) / 60 ) * %tickRate; - } -} \ No newline at end of file diff --git a/Templates/BaseGame/game/core/components/game/playerSpawner.asset.taml b/Templates/BaseGame/game/core/components/game/playerSpawner.asset.taml deleted file mode 100644 index 8a597aca4..000000000 --- a/Templates/BaseGame/game/core/components/game/playerSpawner.asset.taml +++ /dev/null @@ -1,10 +0,0 @@ - diff --git a/Templates/BaseGame/game/core/components/game/playerSpawner.cs b/Templates/BaseGame/game/core/components/game/playerSpawner.cs deleted file mode 100644 index a7387eaf1..000000000 --- a/Templates/BaseGame/game/core/components/game/playerSpawner.cs +++ /dev/null @@ -1,78 +0,0 @@ -//----------------------------------------------------------------------------- -// 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. -//----------------------------------------------------------------------------- - -//registerComponent("PlayerSpawner", "Component", -// "Player Spawner", "Game", false, "When a client connects, it spawns a player object for them and attaches them to it"); - -function PlayerSpawner::onAdd(%this) -{ - %this.clientCount = 1; - %this.friendlyName = "Player Spawner"; - %this.componentType = "Spawner"; - - %this.addComponentField("GameObjectName", "The name of the game object we spawn for the players", "gameObject", "PlayerObject"); -} - -function PlayerSpawner::onClientConnect(%this, %client) -{ - %playerObj = spawnGameObject(%this.GameObjectName, false); - - if(!isObject(%playerObj)) - return; - - %playerObj.position = %this.owner.position; - - %playerObj.notify("onClientConnect", %client); - - switchControlObject(%client, %playerObj); - switchCamera(%client, %playerObj); - - %client.player = %playerObj; - %client.camera = %playerObj; - - %inventory = %playerObj.getComponent(InventoryController); - - if(isObject(%inventory)) - { - for(%i=0; %i<5; %i++) - { - %arrow = spawnGameObject(ArrowProjectile, false); - - %inventory.addItem(%arrow); - } - } - - %playerObj.position = %this.owner.position; - %playerObj.rotation = "0 0 0"; - - %this.clientCount++; -} - -function PlayerSpawner::onClientDisConnect(%this, %client) -{ - -} - -function PlayerSpawner::getClientID(%this) -{ - return ClientGroup.getObject(%this.clientOwner-1); -} \ No newline at end of file diff --git a/Templates/BaseGame/game/core/components/input/fpsControls.asset.taml b/Templates/BaseGame/game/core/components/input/fpsControls.asset.taml deleted file mode 100644 index cd0440055..000000000 --- a/Templates/BaseGame/game/core/components/input/fpsControls.asset.taml +++ /dev/null @@ -1,9 +0,0 @@ - diff --git a/Templates/BaseGame/game/core/components/input/fpsControls.cs b/Templates/BaseGame/game/core/components/input/fpsControls.cs deleted file mode 100644 index 8331e409d..000000000 --- a/Templates/BaseGame/game/core/components/input/fpsControls.cs +++ /dev/null @@ -1,247 +0,0 @@ -//----------------------------------------------------------------------------- -// 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. -//----------------------------------------------------------------------------- - -//registerComponent("FPSControls", "Component", "FPS Controls", "Input", false, "First Person Shooter-type controls"); - -function FPSControls::onAdd(%this) -{ - // - %this.beginGroup("Keys"); - %this.addComponentField(forwardKey, "Key to bind to vertical thrust", keybind, "keyboard w"); - %this.addComponentField(backKey, "Key to bind to vertical thrust", keybind, "keyboard s"); - %this.addComponentField(leftKey, "Key to bind to horizontal thrust", keybind, "keyboard a"); - %this.addComponentField(rightKey, "Key to bind to horizontal thrust", keybind, "keyboard d"); - - %this.addComponentField(jump, "Key to bind to horizontal thrust", keybind, "keyboard space"); - %this.endGroup(); - - %this.beginGroup("Mouse"); - %this.addComponentField(pitchAxis, "Key to bind to horizontal thrust", keybind, "mouse yaxis"); - %this.addComponentField(yawAxis, "Key to bind to horizontal thrust", keybind, "mouse xaxis"); - %this.endGroup(); - - %this.addComponentField(moveSpeed, "Horizontal thrust force", float, 300.0); - %this.addComponentField(jumpStrength, "Vertical thrust force", float, 3.0); - // - - %control = %this.owner.getComponent( ControlObjectComponent ); - if(!%control) - return echo("SPECTATOR CONTROLS: No Control Object behavior!"); - - //%this.Physics = %this.owner.getComponent( PlayerPhysicsComponent ); - - //%this.Animation = %this.owner.getComponent( AnimationComponent ); - - //%this.Camera = %this.owner.getComponent( MountedCameraComponent ); - - //%this.Animation.playThread(0, "look"); - - %this.setupControls(%control.getClientID()); -} - -function FPSControls::onRemove(%this) -{ - Parent::onBehaviorRemove(%this); - - commandToClient(%control.clientOwnerID, 'removeInput', %this.forwardKey); - commandToClient(%control.clientOwnerID, 'removeInput', %this.backKey); - commandToClient(%control.clientOwnerID, 'removeInput', %this.leftKey); - commandToClient(%control.clientOwnerID, 'removeInput', %this.rightKey); - - commandToClient(%control.clientOwnerID, 'removeInput', %this.pitchAxis); - commandToClient(%control.clientOwnerID, 'removeInput', %this.yawAxis); -} - -function FPSControls::onBehaviorFieldUpdate(%this, %field) -{ - %controller = %this.owner.getBehavior( ControlObjectBehavior ); - commandToClient(%controller.clientOwnerID, 'updateInput', %this.getFieldValue(%field), %field); -} - -function FPSControls::onClientConnect(%this, %client) -{ - %this.setupControls(%client); -} - - -function FPSControls::setupControls(%this, %client) -{ - %control = %this.owner.getComponent( ControlObjectComponent ); - if(!%control.isControlClient(%client)) - { - echo("FPS CONTROLS: Client Did Not Match"); - return; - } - - %inputCommand = "FPSControls"; - - %test = %this.forwardKey; - - /*SetInput(%client, %this.forwardKey.x, %this.forwardKey.y, %inputCommand@"_forwardKey"); - SetInput(%client, %this.backKey.x, %this.backKey.y, %inputCommand@"_backKey"); - SetInput(%client, %this.leftKey.x, %this.leftKey.y, %inputCommand@"_leftKey"); - SetInput(%client, %this.rightKey.x, %this.rightKey.y, %inputCommand@"_rightKey"); - - SetInput(%client, %this.jump.x, %this.jump.y, %inputCommand@"_jump"); - - SetInput(%client, %this.pitchAxis.x, %this.pitchAxis.y, %inputCommand@"_pitchAxis"); - SetInput(%client, %this.yawAxis.x, %this.yawAxis.y, %inputCommand@"_yawAxis");*/ - - SetInput(%client, "keyboard", "w", %inputCommand@"_forwardKey"); - SetInput(%client, "keyboard", "s", %inputCommand@"_backKey"); - SetInput(%client, "keyboard", "a", %inputCommand@"_leftKey"); - SetInput(%client, "keyboard", "d", %inputCommand@"_rightKey"); - - SetInput(%client, "keyboard", "space", %inputCommand@"_jump"); - - SetInput(%client, "mouse", "yaxis", %inputCommand@"_pitchAxis"); - SetInput(%client, "mouse", "xaxis", %inputCommand@"_yawAxis"); - - SetInput(%client, "keyboard", "f", %inputCommand@"_flashlight"); - -} - -function FPSControls::onMoveTrigger(%this, %triggerID) -{ - //check if our jump trigger was pressed! - if(%triggerID == 2) - { - %this.owner.applyImpulse("0 0 0", "0 0 " @ %this.jumpStrength); - } -} - -function FPSControls::Update(%this) -{ - return; - - %moveVector = %this.owner.getMoveVector(); - %moveRotation = %this.owner.getMoveRotation(); - - %this.Physics.moveVector = "0 0 0"; - - if(%moveVector.x != 0) - { - %fv = VectorNormalize(%this.owner.getRightVector()); - - %forMove = VectorScale(%fv, (%moveVector.x));// * (%this.moveSpeed * 0.032))); - - //%this.Physics.velocity = VectorAdd(%this.Physics.velocity, %forMove); - - %this.Physics.moveVector = VectorAdd(%this.Physics.moveVector, %forMove); - - //if(%forMove > 0) - // %this.Animation.playThread(1, "run"); - } - /*else - { - %fv = VectorNormalize(%this.owner.getRightVector()); - - %forMove = VectorScale(%fv, (%moveVector.x * (%this.moveSpeed * 0.032))); - - if(%forMove <= 0) - %this.Animation.stopThread(1); - - }*/ - - if(%moveVector.y != 0) - { - %fv = VectorNormalize(%this.owner.getForwardVector()); - - %forMove = VectorScale(%fv, (%moveVector.y));// * (%this.moveSpeed * 0.032))); - - //%this.Physics.velocity = VectorAdd(%this.Physics.velocity, %forMove); - - %this.Physics.moveVector = VectorAdd(%this.Physics.moveVector, %forMove); - - //if(VectorLen(%this.Physics.velocity) < 2) - // %this.Physics.velocity = VectorAdd(%this.Physics.velocity, %forMove); - } - - /*if(%moveVector.z) - { - %fv = VectorNormalize(%this.owner.getUpVector()); - - %forMove = VectorScale(%fv, (%moveVector.z * (%this.moveSpeed * 0.032))); - - %this.Physics.velocity = VectorAdd(%this.Physics.velocity, %forMove); - }*/ - - if(%moveRotation.x != 0) - { - %look = mRadToDeg(%moveRotation.x) / 180; - - //%this.Animation.setThreadPos(0, %look); - - %this.owner.getComponent( MountedCameraComponent ).rotationOffset.x += mRadToDeg(%moveRotation.x); - - //%this.Camera.rotationOffset.x += mRadToDeg(%moveRotation.x); - } - // %this.owner.rotation.x += mRadToDeg(%moveRotation.x); - - if(%moveRotation.z != 0) - { - %zrot = mRadToDeg(%moveRotation.z); - %this.owner.getComponent( MountedCameraComponent ).rotationOffset.z += %zrot; - //%this.owner.rotation.z += %zrot; - } -} - -// -function FPSControls_forwardKey(%val) -{ - $mvForwardAction = %val; -} - -function FPSControls_backKey(%val) -{ - $mvBackwardAction = %val; -} - -function FPSControls_leftKey(%val) -{ - $mvLeftAction = %val; -} - -function FPSControls_rightKey(%val) -{ - $mvRightAction = %val; -} - -function FPSControls_yawAxis(%val) -{ - $mvYaw += getMouseAdjustAmount(%val); -} - -function FPSControls_pitchAxis(%val) -{ - $mvPitch += getMouseAdjustAmount(%val); -} - -function FPSControls_jump(%val) -{ - $mvTriggerCount2++; -} - -function FPSControls_flashLight(%val) -{ - $mvTriggerCount3++; -} \ No newline at end of file diff --git a/Templates/BaseGame/game/core/components/input/inputManager.cs b/Templates/BaseGame/game/core/components/input/inputManager.cs deleted file mode 100644 index c8123d1e3..000000000 --- a/Templates/BaseGame/game/core/components/input/inputManager.cs +++ /dev/null @@ -1,82 +0,0 @@ -//----------------------------------------------------------------------------- -// 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 SetInput(%client, %device, %key, %command, %bindMap, %behav) -{ - commandToClient(%client, 'SetInput', %device, %key, %command, %bindMap, %behav); -} - -function RemoveInput(%client, %device, %key, %command, %bindMap) -{ - commandToClient(%client, 'removeInput', %device, %key, %command, %bindMap); -} - -function clientCmdSetInput(%device, %key, %command, %bindMap, %behav) -{ - //if we're requesting a custom bind map, set that up - if(%bindMap $= "") - %bindMap = moveMap; - - if (!isObject(%bindMap)){ - new ActionMap(moveMap); - moveMap.push(); - } - - //get our local - //%localID = ServerConnection.resolveGhostID(%behav); - - //%tmpl = %localID.getTemplate(); - //%tmpl.insantiateNamespace(%tmpl.getName()); - - //first, check if we have an existing command - %oldBind = %bindMap.getBinding(%command); - if(%oldBind !$= "") - %bindMap.unbind(getField(%oldBind, 0), getField(%oldBind, 1)); - - //now, set the requested bind - %bindMap.bind(%device, %key, %command); -} - -function clientCmdRemoveSpecCtrlInput(%device, %key, %bindMap) -{ - //if we're requesting a custom bind map, set that up - if(%bindMap $= "") - %bindMap = moveMap; - - if (!isObject(%bindMap)) - return; - - %bindMap.unbind(%device, %key); -} - -function clientCmdSetupClientBehavior(%bhvrGstID) -{ - %localID = ServerConnection.resolveGhostID(%bhvrGstID); - %tmpl = %localID.getTemplate(); - %tmpl.insantiateNamespace(%tmpl.getName()); -} - -function getMouseAdjustAmount(%val) -{ - // based on a default camera FOV of 90' - return(%val * ($cameraFov / 90) * 0.01) * $pref::Input::LinkMouseSensitivity; -} \ No newline at end of file diff --git a/Templates/BaseGame/game/core/components/meshComponent.asset.taml b/Templates/BaseGame/game/core/components/meshComponent.asset.taml deleted file mode 100644 index b41de171a..000000000 --- a/Templates/BaseGame/game/core/components/meshComponent.asset.taml +++ /dev/null @@ -1,8 +0,0 @@ - diff --git a/Templates/BaseGame/game/core/components/playerControllerComponent.asset.taml b/Templates/BaseGame/game/core/components/playerControllerComponent.asset.taml deleted file mode 100644 index 417f409e0..000000000 --- a/Templates/BaseGame/game/core/components/playerControllerComponent.asset.taml +++ /dev/null @@ -1,8 +0,0 @@ - diff --git a/Templates/BaseGame/game/core/components/soundComponent.asset.taml b/Templates/BaseGame/game/core/components/soundComponent.asset.taml deleted file mode 100644 index a29bcc9ff..000000000 --- a/Templates/BaseGame/game/core/components/soundComponent.asset.taml +++ /dev/null @@ -1,8 +0,0 @@ - diff --git a/Templates/BaseGame/game/core/components/stateMachineComponent.asset.taml b/Templates/BaseGame/game/core/components/stateMachineComponent.asset.taml deleted file mode 100644 index ff1d53cd8..000000000 --- a/Templates/BaseGame/game/core/components/stateMachineComponent.asset.taml +++ /dev/null @@ -1,8 +0,0 @@ - diff --git a/Templates/BaseGame/game/core/console/console.gui b/Templates/BaseGame/game/core/console/console.gui deleted file mode 100644 index c2f21eba9..000000000 --- a/Templates/BaseGame/game/core/console/console.gui +++ /dev/null @@ -1,191 +0,0 @@ -//--- OBJECT WRITE BEGIN --- -%guiContent = new GuiControl(ConsoleDlg) { - position = "0 0"; - extent = "1024 768"; - minExtent = "8 8"; - horizSizing = "right"; - vertSizing = "bottom"; - profile = "GuiDefaultProfile"; - visible = "1"; - active = "1"; - tooltipProfile = "GuiToolTipProfile"; - hovertime = "1000"; - isContainer = "1"; - canSave = "1"; - canSaveDynamicFields = "1"; - helpTag = "0"; - - new GuiConsoleEditCtrl(ConsoleEntry) { - useSiblingScroller = "1"; - historySize = "40"; - tabComplete = "0"; - sinkAllKeyEvents = "1"; - password = "0"; - passwordMask = "*"; - maxLength = "255"; - margin = "0 0 0 0"; - padding = "0 0 0 0"; - anchorTop = "1"; - anchorBottom = "0"; - anchorLeft = "1"; - anchorRight = "0"; - position = "0 750"; - extent = "1024 18"; - minExtent = "8 8"; - horizSizing = "width"; - vertSizing = "top"; - profile = "ConsoleTextEditProfile"; - visible = "1"; - active = "1"; - altCommand = "ConsoleEntry::eval();"; - tooltipProfile = "GuiToolTipProfile"; - hovertime = "1000"; - isContainer = "1"; - canSave = "1"; - canSaveDynamicFields = "0"; - }; - new GuiContainer() { - margin = "0 0 0 0"; - padding = "0 0 0 0"; - anchorTop = "1"; - anchorBottom = "0"; - anchorLeft = "1"; - anchorRight = "0"; - position = "1 728"; - extent = "1024 22"; - minExtent = "8 2"; - horizSizing = "width"; - vertSizing = "top"; - profile = "GuiDefaultProfile"; - visible = "1"; - active = "1"; - tooltipProfile = "GuiToolTipProfile"; - hovertime = "1000"; - isContainer = "1"; - canSave = "1"; - canSaveDynamicFields = "0"; - - new GuiBitmapCtrl() { - bitmap = "data/ui/art/hudfill.png"; - color = "255 255 255 255"; - wrap = "0"; - position = "0 0"; - extent = "1024 22"; - minExtent = "8 2"; - horizSizing = "width"; - vertSizing = "bottom"; - profile = "GuiDefaultProfile"; - visible = "1"; - active = "1"; - tooltipProfile = "GuiToolTipProfile"; - hovertime = "1000"; - isContainer = "0"; - canSave = "1"; - canSaveDynamicFields = "0"; - }; - new GuiCheckBoxCtrl(ConsoleDlgErrorFilterBtn) { - text = "Errors"; - groupNum = "-1"; - buttonType = "ToggleButton"; - useMouseEvents = "0"; - position = "2 2"; - extent = "113 20"; - minExtent = "8 2"; - horizSizing = "right"; - vertSizing = "bottom"; - profile = "GuiCheckBoxProfile"; - visible = "1"; - active = "1"; - tooltipProfile = "GuiToolTipProfile"; - hovertime = "1000"; - isContainer = "0"; - canSave = "1"; - canSaveDynamicFields = "0"; - }; - new GuiCheckBoxCtrl(ConsoleDlgWarnFilterBtn) { - text = "Warnings"; - groupNum = "-1"; - buttonType = "ToggleButton"; - useMouseEvents = "0"; - position = "119 2"; - extent = "113 20"; - minExtent = "8 2"; - horizSizing = "right"; - vertSizing = "bottom"; - profile = "GuiCheckBoxProfile"; - visible = "1"; - active = "1"; - tooltipProfile = "GuiToolTipProfile"; - hovertime = "1000"; - isContainer = "0"; - canSave = "1"; - canSaveDynamicFields = "0"; - }; - new GuiCheckBoxCtrl(ConsoleDlgNormalFilterBtn) { - text = "Normal Messages"; - groupNum = "-1"; - buttonType = "ToggleButton"; - useMouseEvents = "0"; - position = "236 2"; - extent = "113 20"; - minExtent = "8 2"; - horizSizing = "right"; - vertSizing = "bottom"; - profile = "GuiCheckBoxProfile"; - visible = "1"; - active = "1"; - tooltipProfile = "GuiToolTipProfile"; - hovertime = "1000"; - isContainer = "0"; - canSave = "1"; - canSaveDynamicFields = "0"; - }; - }; - new GuiScrollCtrl() { - willFirstRespond = "1"; - hScrollBar = "alwaysOn"; - vScrollBar = "alwaysOn"; - lockHorizScroll = "0"; - lockVertScroll = "0"; - constantThumbHeight = "0"; - childMargin = "0 0"; - mouseWheelScrollSpeed = "-1"; - margin = "0 0 0 0"; - padding = "0 0 0 0"; - anchorTop = "1"; - anchorBottom = "0"; - anchorLeft = "1"; - anchorRight = "0"; - position = "0 0"; - extent = "1024 730"; - minExtent = "8 8"; - horizSizing = "width"; - vertSizing = "height"; - profile = "ConsoleScrollProfile"; - visible = "1"; - active = "1"; - tooltipProfile = "GuiToolTipProfile"; - hovertime = "1000"; - isContainer = "1"; - internalName = "Scroll"; - canSave = "1"; - canSaveDynamicFields = "0"; - - new GuiConsole(ConsoleMessageLogView) { - position = "1 1"; - extent = "622 324"; - minExtent = "8 2"; - horizSizing = "right"; - vertSizing = "bottom"; - profile = "GuiConsoleProfile"; - visible = "1"; - active = "1"; - tooltipProfile = "GuiToolTipProfile"; - hovertime = "1000"; - isContainer = "1"; - canSave = "1"; - canSaveDynamicFields = "0"; - }; - }; -}; -//--- OBJECT WRITE END --- \ No newline at end of file diff --git a/Templates/BaseGame/game/core/console/main.cs b/Templates/BaseGame/game/core/console/main.cs deleted file mode 100644 index 3d89234b8..000000000 --- a/Templates/BaseGame/game/core/console/main.cs +++ /dev/null @@ -1,140 +0,0 @@ -//----------------------------------------------------------------------------- -// 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. -//----------------------------------------------------------------------------- - -exec("./profiles.cs"); -exec("./console.gui"); - -GlobalActionMap.bind("keyboard", "tilde", "toggleConsole"); - -function ConsoleEntry::eval() -{ - %text = trim(ConsoleEntry.getValue()); - if(%text $= "") - return; - - // If it's missing a trailing () and it's not a variable, - // append the parentheses. - if(strpos(%text, "(") == -1 && !isDefined(%text)) { - if(strpos(%text, "=") == -1 && strpos(%text, " ") == -1) { - if(strpos(%text, "{") == -1 && strpos(%text, "}") == -1) { - %text = %text @ "()"; - } - } - } - - // Append a semicolon if need be. - %pos = strlen(%text) - 1; - if(strpos(%text, ";", %pos) == -1 && strpos(%text, "}") == -1) { - %text = %text @ ";"; - } - - // Turn off warnings for assigning from void - // and evaluate the snippet. - if(!isDefined("$Con::warnVoidAssignment")) - %oldWarnVoidAssignment = true; - else - %oldWarnVoidAssignment = $Con::warnVoidAssignment; - $Con::warnVoidAssignment = false; - - echo("==>" @ %text); - if( !startsWith(%text, "function ") - && !startsWith(%text, "datablock ") - && !startsWith(%text, "foreach(") - && !startsWith(%text, "foreach$(") - && !startsWith(%text, "if(") - && !startsWith(%text, "while(") - && !startsWith(%text, "for(") - && !startsWith(%text, "switch(") - && !startsWith(%text, "switch$(")) - eval("%result = " @ %text); - else - eval(%text); - $Con::warnVoidAssignment = %oldWarnVoidAssignment; - - ConsoleEntry.setValue(""); - - // Echo result. - if(%result !$= "") - echo(%result); -} - -function ToggleConsole(%make) -{ - if (%make) { - if (ConsoleDlg.isAwake()) { - // Deactivate the console. - Canvas.popDialog(ConsoleDlg); - } else { - Canvas.pushDialog(ConsoleDlg, 99); - } - } -} - -function ConsoleDlg::hideWindow(%this) -{ - %this-->Scroll.setVisible(false); -} - -function ConsoleDlg::showWindow(%this) -{ - %this-->Scroll.setVisible(true); -} - -function ConsoleDlg::onWake(%this) -{ - ConsoleDlgErrorFilterBtn.setStateOn(ConsoleMessageLogView.getErrorFilter()); - ConsoleDlgWarnFilterBtn.setStateOn(ConsoleMessageLogView.getWarnFilter()); - ConsoleDlgNormalFilterBtn.setStateOn(ConsoleMessageLogView.getNormalFilter()); - - ConsoleMessageLogView.refresh(); -} - -function ConsoleDlg::setAlpha( %this, %alpha) -{ - if (%alpha $= "") - ConsoleScrollProfile.fillColor = $ConsoleDefaultFillColor; - else - ConsoleScrollProfile.fillColor = getWords($ConsoleDefaultFillColor, 0, 2) SPC %alpha * 255.0; -} - -function ConsoleDlgErrorFilterBtn::onClick(%this) -{ - ConsoleMessageLogView.toggleErrorFilter(); -} - -function ConsoleDlgWarnFilterBtn::onClick(%this) -{ - - ConsoleMessageLogView.toggleWarnFilter(); -} - -function ConsoleDlgNormalFilterBtn::onClick(%this) -{ - ConsoleMessageLogView.toggleNormalFilter(); -} - -function ConsoleMessageLogView::onNewMessage(%this, %errorCount, %warnCount, %normalCount) -{ - ConsoleDlgErrorFilterBtn.setText("(" @ %errorCount @ ") Errors"); - ConsoleDlgWarnFilterBtn.setText("(" @ %warnCount @ ") Warnings"); - ConsoleDlgNormalFilterBtn.setText("(" @ %normalCount @ ") Messages"); -} \ No newline at end of file diff --git a/Templates/BaseGame/game/core/console/profiles.cs b/Templates/BaseGame/game/core/console/profiles.cs deleted file mode 100644 index b83dd4fa7..000000000 --- a/Templates/BaseGame/game/core/console/profiles.cs +++ /dev/null @@ -1,70 +0,0 @@ -//----------------------------------------------------------------------------- -// 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. -//----------------------------------------------------------------------------- - -if(!isObject(GuiConsoleProfile)) -new GuiControlProfile(GuiConsoleProfile) -{ - fontType = ($platform $= "macos") ? "Monaco" : "Lucida Console"; - fontSize = ($platform $= "macos") ? 13 : 12; - fontColor = "255 255 255"; - fontColorHL = "0 255 255"; - fontColorNA = "255 0 0"; - fontColors[6] = "100 100 100"; - fontColors[7] = "100 100 0"; - fontColors[8] = "0 0 100"; - fontColors[9] = "0 100 0"; - category = "Core"; -}; - -if(!isObject(GuiConsoleTextProfile)) -new GuiControlProfile(GuiConsoleTextProfile) -{ - fontColor = "0 0 0"; - autoSizeWidth = true; - autoSizeHeight = true; - textOffset = "2 2"; - opaque = true; - fillColor = "255 255 255"; - border = true; - borderThickness = 1; - borderColor = "0 0 0"; - category = "Core"; -}; - -if(!isObject(ConsoleScrollProfile)) -new GuiControlProfile(ConsoleScrollProfile : GuiScrollProfile) -{ - opaque = true; - fillColor = "0 0 0 175"; - border = 1; - //borderThickness = 0; - borderColor = "0 0 0"; - category = "Core"; -}; - -if(!isObject(ConsoleTextEditProfile)) -new GuiControlProfile(ConsoleTextEditProfile : GuiTextEditProfile) -{ - fillColor = "242 241 240 255"; - fillColorHL = "255 255 255"; - category = "Core"; -}; diff --git a/Templates/BaseGame/game/core/cursor.cs b/Templates/BaseGame/game/core/cursor.cs deleted file mode 100644 index f71bc023a..000000000 --- a/Templates/BaseGame/game/core/cursor.cs +++ /dev/null @@ -1,102 +0,0 @@ -//----------------------------------------------------------------------------- -// 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. -//----------------------------------------------------------------------------- - -//--------------------------------------------------------------------------------------------- -// Cursor toggle functions. -//--------------------------------------------------------------------------------------------- -$cursorControlled = true; -function showCursor() -{ - if ($cursorControlled) - lockMouse(false); - Canvas.cursorOn(); -} - -function hideCursor() -{ - if ($cursorControlled) - lockMouse(true); - Canvas.cursorOff(); -} - -//--------------------------------------------------------------------------------------------- -// In the CanvasCursor package we add some additional functionality to the built-in GuiCanvas -// class, of which the global Canvas object is an instance. In this case, the behavior we want -// is for the cursor to automatically display, except when the only guis visible want no -// cursor - usually the in game interface. -//--------------------------------------------------------------------------------------------- -package CanvasCursorPackage -{ - -//--------------------------------------------------------------------------------------------- -// checkCursor -// The checkCursor method iterates through all the root controls on the canvas checking each -// ones noCursor property. If the noCursor property exists as anything other than false or an -// empty string on every control, the cursor will be hidden. -//--------------------------------------------------------------------------------------------- -function GuiCanvas::checkCursor(%this) -{ - %count = %this.getCount(); - for(%i = 0; %i < %count; %i++) - { - %control = %this.getObject(%i); - if ((%control.noCursor $= "") || !%control.noCursor) - { - showCursor(); - return; - } - } - // If we get here, every control requested a hidden cursor, so we oblige. - hideCursor(); -} - -//--------------------------------------------------------------------------------------------- -// The following functions override the GuiCanvas defaults that involve changing the content -// of the Canvas. Basically, all we are doing is adding a call to checkCursor to each one. -//--------------------------------------------------------------------------------------------- -function GuiCanvas::setContent(%this, %ctrl) -{ - Parent::setContent(%this, %ctrl); - %this.checkCursor(); -} - -function GuiCanvas::pushDialog(%this, %ctrl, %layer, %center) -{ - Parent::pushDialog(%this, %ctrl, %layer, %center); - %this.checkCursor(); -} - -function GuiCanvas::popDialog(%this, %ctrl) -{ - Parent::popDialog(%this, %ctrl); - %this.checkCursor(); -} - -function GuiCanvas::popLayer(%this, %layer) -{ - Parent::popLayer(%this, %layer); - %this.checkCursor(); -} - -}; - -activatePackage(CanvasCursorPackage); diff --git a/Templates/BaseGame/game/core/fonts/Arial 10 (ansi).uft b/Templates/BaseGame/game/core/fonts/Arial 10 (ansi).uft deleted file mode 100644 index 2b564950050cfca995e66f048e0523428ff493b0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 412 zcmZQ(U|?W%EXqvG;R3Qi07P>@F%ytx24VyN@mQf;5Dk%qsR4%?)Qy83;)lEIri7m zFZoExihWaFY>GaAyHfb_#$7>4rhD3-7VX{JcRHkY<;8EhWjEc^(!MS|x7jKnT~tu; z`y-fhfi55e9MJ#4lvSq~c?$DU2jYrb$q5Y1ZVG9@ Ja2IA^0RUczP(}a% diff --git a/Templates/BaseGame/game/core/fonts/Arial 12 (ansi).uft b/Templates/BaseGame/game/core/fonts/Arial 12 (ansi).uft deleted file mode 100644 index 67a177016766c6f06b5b601c3336b9fea2ac75ba..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 62 jcmZQ(U|?W%EXqvG;Q_Kh07P>_F*8U23jU*ldXO*xH#ZTF diff --git a/Templates/BaseGame/game/core/fonts/Arial 14 (ansi).uft b/Templates/BaseGame/game/core/fonts/Arial 14 (ansi).uft deleted file mode 100644 index 159010c6850f3424dbc7456533d0e2ae6f82e9bc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5160 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 A=Kufz diff --git a/Templates/BaseGame/game/core/fonts/Arial 16 (ansi).uft b/Templates/BaseGame/game/core/fonts/Arial 16 (ansi).uft deleted file mode 100644 index 058fbb305a81a9670c8a346f4384647711e5f8ae..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 13112 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 diff --git a/Templates/BaseGame/game/core/fonts/Arial 36 (ansi).uft b/Templates/BaseGame/game/core/fonts/Arial 36 (ansi).uft deleted file mode 100644 index 968441ce3b27703632299ab9837977bb7ee35234..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1046 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 Rs65Gnf66lkhDqo7I{?g*3BJNm1w(Cv{3L(q2 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 BNb3Lq diff --git a/Templates/BaseGame/game/core/gfxData/clouds.cs b/Templates/BaseGame/game/core/gfxData/clouds.cs deleted file mode 100644 index 00d56d6d3..000000000 --- a/Templates/BaseGame/game/core/gfxData/clouds.cs +++ /dev/null @@ -1,55 +0,0 @@ -//----------------------------------------------------------------------------- -// 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. -//----------------------------------------------------------------------------- - -//------------------------------------------------------------------------------ -// CloudLayer -//------------------------------------------------------------------------------ - -singleton ShaderData( CloudLayerShader ) -{ - DXVertexShaderFile = $Core::CommonShaderPath @ "/cloudLayerV.hlsl"; - DXPixelShaderFile = $Core::CommonShaderPath @ "/cloudLayerP.hlsl"; - - OGLVertexShaderFile = $Core::CommonShaderPath @ "/gl/cloudLayerV.glsl"; - OGLPixelShaderFile = $Core::CommonShaderPath @ "/gl/cloudLayerP.glsl"; - - samplerNames[0] = "$normalHeightMap"; - - pixVersion = 2.0; -}; - -//------------------------------------------------------------------------------ -// BasicClouds -//------------------------------------------------------------------------------ - -singleton ShaderData( BasicCloudsShader ) -{ - DXVertexShaderFile = $Core::CommonShaderPath @ "/basicCloudsV.hlsl"; - DXPixelShaderFile = $Core::CommonShaderPath @ "/basicCloudsP.hlsl"; - - OGLVertexShaderFile = $Core::CommonShaderPath @ "/gl/basicCloudsV.glsl"; - OGLPixelShaderFile = $Core::CommonShaderPath @ "/gl/basicCloudsP.glsl"; - - samplerNames[0] = "$diffuseMap"; - - pixVersion = 2.0; -}; diff --git a/Templates/BaseGame/game/core/gfxData/commonMaterialData.cs b/Templates/BaseGame/game/core/gfxData/commonMaterialData.cs deleted file mode 100644 index c5d8ef5bc..000000000 --- a/Templates/BaseGame/game/core/gfxData/commonMaterialData.cs +++ /dev/null @@ -1,79 +0,0 @@ -//----------------------------------------------------------------------------- -// 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. -//----------------------------------------------------------------------------- - -//----------------------------------------------------------------------------- -// Anim flag settings - must match material.h -// These cannot be enumed through script becuase it cannot -// handle the "|" operation for combining them together -// ie. Scroll | Wave does not work. -//----------------------------------------------------------------------------- -$scroll = 1; -$rotate = 2; -$wave = 4; -$scale = 8; -$sequence = 16; - - -// Common stateblock definitions -new GFXSamplerStateData(SamplerClampLinear) -{ - textureColorOp = GFXTOPModulate; - addressModeU = GFXAddressClamp; - addressModeV = GFXAddressClamp; - addressModeW = GFXAddressClamp; - magFilter = GFXTextureFilterLinear; - minFilter = GFXTextureFilterLinear; - mipFilter = GFXTextureFilterLinear; -}; - -new GFXSamplerStateData(SamplerClampPoint) -{ - textureColorOp = GFXTOPModulate; - addressModeU = GFXAddressClamp; - addressModeV = GFXAddressClamp; - addressModeW = GFXAddressClamp; - magFilter = GFXTextureFilterPoint; - minFilter = GFXTextureFilterPoint; - mipFilter = GFXTextureFilterPoint; -}; - -new GFXSamplerStateData(SamplerWrapLinear) -{ - textureColorOp = GFXTOPModulate; - addressModeU = GFXTextureAddressWrap; - addressModeV = GFXTextureAddressWrap; - addressModeW = GFXTextureAddressWrap; - magFilter = GFXTextureFilterLinear; - minFilter = GFXTextureFilterLinear; - mipFilter = GFXTextureFilterLinear; -}; - -new GFXSamplerStateData(SamplerWrapPoint) -{ - textureColorOp = GFXTOPModulate; - addressModeU = GFXTextureAddressWrap; - addressModeV = GFXTextureAddressWrap; - addressModeW = GFXTextureAddressWrap; - magFilter = GFXTextureFilterPoint; - minFilter = GFXTextureFilterPoint; - mipFilter = GFXTextureFilterPoint; -}; diff --git a/Templates/BaseGame/game/core/gfxData/scatterSky.cs b/Templates/BaseGame/game/core/gfxData/scatterSky.cs deleted file mode 100644 index 5add01d8b..000000000 --- a/Templates/BaseGame/game/core/gfxData/scatterSky.cs +++ /dev/null @@ -1,48 +0,0 @@ -//----------------------------------------------------------------------------- -// 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. -//----------------------------------------------------------------------------- - -new GFXStateBlockData( ScatterSkySBData ) -{ - cullMode = "GFXCullNone"; - - zDefined = true; - zEnable = true; - zWriteEnable = false; - - samplersDefined = true; - samplerStates[0] = SamplerClampLinear; - samplerStates[1] = SamplerClampLinear; - vertexColorEnable = true; -}; - -singleton ShaderData( ScatterSkyShaderData ) -{ - DXVertexShaderFile = $Core::CommonShaderPath @ "/scatterSkyV.hlsl"; - DXPixelShaderFile = $Core::CommonShaderPath @ "/scatterSkyP.hlsl"; - - OGLVertexShaderFile = $Core::CommonShaderPath @ "/gl/scatterSkyV.glsl"; - OGLPixelShaderFile = $Core::CommonShaderPath @ "/gl/scatterSkyP.glsl"; - - samplerNames[0] = "$nightSky"; - - pixVersion = 2.0; -}; diff --git a/Templates/BaseGame/game/core/gfxData/shaders.cs b/Templates/BaseGame/game/core/gfxData/shaders.cs deleted file mode 100644 index da3b7c864..000000000 --- a/Templates/BaseGame/game/core/gfxData/shaders.cs +++ /dev/null @@ -1,152 +0,0 @@ -//----------------------------------------------------------------------------- -// 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. -//----------------------------------------------------------------------------- - -//----------------------------------------------------------------------------- -// This file contains shader data necessary for various engine utility functions -//----------------------------------------------------------------------------- - - -singleton ShaderData( ParticlesShaderData ) -{ - DXVertexShaderFile = $Core::CommonShaderPath @ "/particlesV.hlsl"; - DXPixelShaderFile = $Core::CommonShaderPath @ "/particlesP.hlsl"; - - OGLVertexShaderFile = $Core::CommonShaderPath @ "/gl/particlesV.glsl"; - OGLPixelShaderFile = $Core::CommonShaderPath @ "/gl/particlesP.glsl"; - - samplerNames[0] = "$diffuseMap"; - samplerNames[1] = "$deferredTex"; - samplerNames[2] = "$paraboloidLightMap"; - - pixVersion = 2.0; -}; - -singleton ShaderData( OffscreenParticleCompositeShaderData ) -{ - DXVertexShaderFile = $Core::CommonShaderPath @ "/particleCompositeV.hlsl"; - DXPixelShaderFile = $Core::CommonShaderPath @ "/particleCompositeP.hlsl"; - - OGLVertexShaderFile = $Core::CommonShaderPath @ "/gl/particleCompositeV.glsl"; - OGLPixelShaderFile = $Core::CommonShaderPath @ "/gl/particleCompositeP.glsl"; - - samplerNames[0] = "$colorSource"; - samplerNames[1] = "$edgeSource"; - - pixVersion = 2.0; -}; - -//----------------------------------------------------------------------------- -// Planar Reflection -//----------------------------------------------------------------------------- -new ShaderData( ReflectBump ) -{ - DXVertexShaderFile = $Core::CommonShaderPath @ "/planarReflectBumpV.hlsl"; - DXPixelShaderFile = $Core::CommonShaderPath @ "/planarReflectBumpP.hlsl"; - - OGLVertexShaderFile = $Core::CommonShaderPath @ "/gl/planarReflectBumpV.glsl"; - OGLPixelShaderFile = $Core::CommonShaderPath @ "/gl/planarReflectBumpP.glsl"; - - samplerNames[0] = "$diffuseMap"; - samplerNames[1] = "$refractMap"; - samplerNames[2] = "$bumpMap"; - - pixVersion = 2.0; -}; - -new ShaderData( Reflect ) -{ - DXVertexShaderFile = $Core::CommonShaderPath @ "/planarReflectV.hlsl"; - DXPixelShaderFile = $Core::CommonShaderPath @ "/planarReflectP.hlsl"; - - OGLVertexShaderFile = $Core::CommonShaderPath @ "/gl/planarReflectV.glsl"; - OGLPixelShaderFile = $Core::CommonShaderPath @ "/gl/planarReflectP.glsl"; - - samplerNames[0] = "$diffuseMap"; - samplerNames[1] = "$refractMap"; - - pixVersion = 1.4; -}; - -//----------------------------------------------------------------------------- -// fxFoliageReplicator -//----------------------------------------------------------------------------- -new ShaderData( fxFoliageReplicatorShader ) -{ - DXVertexShaderFile = $Core::CommonShaderPath @ "/fxFoliageReplicatorV.hlsl"; - DXPixelShaderFile = $Core::CommonShaderPath @ "/fxFoliageReplicatorP.hlsl"; - - OGLVertexShaderFile = $Core::CommonShaderPath @ "/gl/fxFoliageReplicatorV.glsl"; - OGLPixelShaderFile = $Core::CommonShaderPath @ "/gl/fxFoliageReplicatorP.glsl"; - - samplerNames[0] = "$diffuseMap"; - samplerNames[1] = "$alphaMap"; - - pixVersion = 1.4; -}; - -singleton ShaderData( VolumetricFogDeferredShader ) -{ - DXVertexShaderFile = $Core::CommonShaderPath @ "/VolumetricFog/VFogPreV.hlsl"; - DXPixelShaderFile = $Core::CommonShaderPath @ "/VolumetricFog/VFogPreP.hlsl"; - - OGLVertexShaderFile = $Core::CommonShaderPath @ "/VolumetricFog/gl/VFogPreV.glsl"; - OGLPixelShaderFile = $Core::CommonShaderPath @ "/VolumetricFog/gl/VFogPreP.glsl"; - - pixVersion = 3.0; -}; -singleton ShaderData( VolumetricFogShader ) -{ - DXVertexShaderFile = $Core::CommonShaderPath @ "/VolumetricFog/VFogV.hlsl"; - DXPixelShaderFile = $Core::CommonShaderPath @ "/VolumetricFog/VFogP.hlsl"; - - OGLVertexShaderFile = $Core::CommonShaderPath @ "/VolumetricFog/gl/VFogV.glsl"; - OGLPixelShaderFile = $Core::CommonShaderPath @ "/VolumetricFog/gl/VFogP.glsl"; - - samplerNames[0] = "$deferredTex"; - samplerNames[1] = "$depthBuffer"; - samplerNames[2] = "$frontBuffer"; - samplerNames[3] = "$density"; - - pixVersion = 3.0; -}; -singleton ShaderData( VolumetricFogReflectionShader ) -{ - DXVertexShaderFile = $Core::CommonShaderPath @ "/VolumetricFog/VFogPreV.hlsl"; - DXPixelShaderFile = $Core::CommonShaderPath @ "/VolumetricFog/VFogRefl.hlsl"; - - OGLVertexShaderFile = $Core::CommonShaderPath @ "/VolumetricFog/gl/VFogPreV.glsl"; - OGLPixelShaderFile = $Core::CommonShaderPath @ "/VolumetricFog/gl/VFogRefl.glsl"; - - pixVersion = 3.0; -}; -singleton ShaderData( CubemapSaveShader ) -{ - DXVertexShaderFile = "shaders/common/cubemapSaveV.hlsl"; - DXPixelShaderFile = "shaders/common/cubemapSaveP.hlsl"; - - OGLVertexShaderFile = "shaders/common/gl/cubemapSaveV.glsl"; - OGLPixelShaderFile = "shaders/common/gl/cubemapSaveP.glsl"; - - samplerNames[0] = "$cubemapTex"; - - pixVersion = 3.0; -}; \ No newline at end of file diff --git a/Templates/BaseGame/game/core/gfxData/terrainBlock.cs b/Templates/BaseGame/game/core/gfxData/terrainBlock.cs deleted file mode 100644 index 69802b1da..000000000 --- a/Templates/BaseGame/game/core/gfxData/terrainBlock.cs +++ /dev/null @@ -1,36 +0,0 @@ -//----------------------------------------------------------------------------- -// 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. -//----------------------------------------------------------------------------- - -/// Used when generating the blended base texture. -singleton ShaderData( TerrainBlendShader ) -{ - DXVertexShaderFile = $Core::CommonShaderPath @ "/terrain/blendV.hlsl"; - DXPixelShaderFile = $Core::CommonShaderPath @ "/terrain/blendP.hlsl"; - - OGLVertexShaderFile = $Core::CommonShaderPath @ "/terrain/gl/blendV.glsl"; - OGLPixelShaderFile = $Core::CommonShaderPath @ "/terrain/gl/blendP.glsl"; - - samplerNames[0] = "layerTex"; - samplerNames[1] = "textureMap"; - - pixVersion = 2.0; -}; diff --git a/Templates/BaseGame/game/core/gfxData/water.cs b/Templates/BaseGame/game/core/gfxData/water.cs deleted file mode 100644 index ec5e4be71..000000000 --- a/Templates/BaseGame/game/core/gfxData/water.cs +++ /dev/null @@ -1,208 +0,0 @@ -//----------------------------------------------------------------------------- -// 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. -//----------------------------------------------------------------------------- - - - -//----------------------------------------------------------------------------- -// Water -//----------------------------------------------------------------------------- - -singleton ShaderData( WaterShader ) -{ - DXVertexShaderFile = $Core::CommonShaderPath @ "/water/waterV.hlsl"; - DXPixelShaderFile = $Core::CommonShaderPath @ "/water/waterP.hlsl"; - - OGLVertexShaderFile = $Core::CommonShaderPath @ "/water/gl/waterV.glsl"; - OGLPixelShaderFile = $Core::CommonShaderPath @ "/water/gl/waterP.glsl"; - - samplerNames[0] = "$bumpMap"; // noise - samplerNames[1] = "$deferredTex"; // #deferred - samplerNames[2] = "$reflectMap"; // $reflectbuff - samplerNames[3] = "$refractBuff"; // $backbuff - samplerNames[4] = "$skyMap"; // $cubemap - samplerNames[5] = "$foamMap"; // foam - samplerNames[6] = "$depthGradMap"; // depthMap ( color gradient ) - - pixVersion = 3.0; -}; - -new GFXSamplerStateData(WaterSampler) -{ - textureColorOp = GFXTOPModulate; - addressModeU = GFXAddressWrap; - addressModeV = GFXAddressWrap; - addressModeW = GFXAddressWrap; - magFilter = GFXTextureFilterLinear; - minFilter = GFXTextureFilterAnisotropic; - mipFilter = GFXTextureFilterLinear; - maxAnisotropy = 4; -}; - -singleton GFXStateBlockData( WaterStateBlock ) -{ - samplersDefined = true; - samplerStates[0] = WaterSampler; // noise - samplerStates[1] = SamplerClampPoint; // #deferred - samplerStates[2] = SamplerClampLinear; // $reflectbuff - samplerStates[3] = SamplerClampPoint; // $backbuff - samplerStates[4] = SamplerWrapLinear; // $cubemap - samplerStates[5] = SamplerWrapLinear; // foam - samplerStates[6] = SamplerClampLinear; // depthMap ( color gradient ) - cullDefined = true; - cullMode = "GFXCullCCW"; -}; - -singleton GFXStateBlockData( UnderWaterStateBlock : WaterStateBlock ) -{ - cullMode = "GFXCullCW"; -}; - -singleton CustomMaterial( WaterMat ) -{ - sampler["deferredTex"] = "#deferred"; - sampler["reflectMap"] = "$reflectbuff"; - sampler["refractBuff"] = "$backbuff"; - // These samplers are set in code not here. - // This is to allow different WaterObject instances - // to use this same material but override these textures - // per instance. - //sampler["bumpMap"] = ""; - //sampler["skyMap"] = ""; - //sampler["foamMap"] = ""; - //sampler["depthGradMap"] = ""; - - shader = WaterShader; - stateBlock = WaterStateBlock; - version = 3.0; - - useAnisotropic[0] = true; -}; - -//----------------------------------------------------------------------------- -// Underwater -//----------------------------------------------------------------------------- - -singleton ShaderData( UnderWaterShader : WaterShader ) -{ - defines = "UNDERWATER"; -}; - -singleton CustomMaterial( UnderwaterMat ) -{ - // These samplers are set in code not here. - // This is to allow different WaterObject instances - // to use this same material but override these textures - // per instance. - //sampler["bumpMap"] = "core/art/water/noise02"; - //sampler["foamMap"] = "core/art/water/foam"; - - sampler["deferredTex"] = "#deferred"; - sampler["refractBuff"] = "$backbuff"; - - shader = UnderWaterShader; - stateBlock = UnderWaterStateBlock; - specular = "0.75 0.75 0.75 1.0"; - specularPower = 48.0; - version = 3.0; -}; - -//----------------------------------------------------------------------------- -// Basic Water -//----------------------------------------------------------------------------- - -singleton ShaderData( WaterBasicShader ) -{ - DXVertexShaderFile = $Core::CommonShaderPath @ "/water/waterBasicV.hlsl"; - DXPixelShaderFile = $Core::CommonShaderPath @ "/water/waterBasicP.hlsl"; - - OGLVertexShaderFile = $Core::CommonShaderPath @ "/water/gl/waterBasicV.glsl"; - OGLPixelShaderFile = $Core::CommonShaderPath @ "/water/gl/waterBasicP.glsl"; - - samplerNames[0] = "$bumpMap"; - samplerNames[2] = "$reflectMap"; - samplerNames[3] = "$refractBuff"; - samplerNames[4] = "$skyMap"; - samplerNames[5] = "$depthGradMap"; - - pixVersion = 2.0; -}; - -singleton GFXStateBlockData( WaterBasicStateBlock ) -{ - samplersDefined = true; - samplerStates[0] = WaterSampler; // noise - samplerStates[2] = SamplerClampLinear; // $reflectbuff - samplerStates[3] = SamplerClampPoint; // $backbuff - samplerStates[4] = SamplerWrapLinear; // $cubemap - cullDefined = true; - cullMode = "GFXCullCCW"; -}; - -singleton GFXStateBlockData( UnderWaterBasicStateBlock : WaterBasicStateBlock ) -{ - cullMode = "GFXCullCW"; -}; - -singleton CustomMaterial( WaterBasicMat ) -{ - // These samplers are set in code not here. - // This is to allow different WaterObject instances - // to use this same material but override these textures - // per instance. - //sampler["bumpMap"] = "core/art/water/noise02"; - //sampler["skyMap"] = "$cubemap"; - - //sampler["deferredTex"] = "#deferred"; - sampler["reflectMap"] = "$reflectbuff"; - sampler["refractBuff"] = "$backbuff"; - - cubemap = NewLevelSkyCubemap; - shader = WaterBasicShader; - stateBlock = WaterBasicStateBlock; - version = 2.0; -}; - -//----------------------------------------------------------------------------- -// Basic UnderWater -//----------------------------------------------------------------------------- - -singleton ShaderData( UnderWaterBasicShader : WaterBasicShader) -{ - defines = "UNDERWATER"; -}; - -singleton CustomMaterial( UnderwaterBasicMat ) -{ - // These samplers are set in code not here. - // This is to allow different WaterObject instances - // to use this same material but override these textures - // per instance. - //sampler["bumpMap"] = "core/art/water/noise02"; - //samplers["skyMap"] = "$cubemap"; - - //sampler["deferredTex"] = "#deferred"; - sampler["refractBuff"] = "$backbuff"; - - shader = UnderWaterBasicShader; - stateBlock = UnderWaterBasicStateBlock; - version = 2.0; -}; \ No newline at end of file diff --git a/Templates/BaseGame/game/core/gfxprofile/D3D9.ATITechnologiesInc.cs b/Templates/BaseGame/game/core/gfxprofile/D3D9.ATITechnologiesInc.cs deleted file mode 100644 index 10c6bdf5b..000000000 --- a/Templates/BaseGame/game/core/gfxprofile/D3D9.ATITechnologiesInc.cs +++ /dev/null @@ -1,36 +0,0 @@ -//----------------------------------------------------------------------------- -// 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. -//----------------------------------------------------------------------------- - -// ATI Vendor Profile Script -// -// This script is responsible for setting global -// capability strings based on the nVidia vendor. - -if(GFXCardProfiler::getVersion() < 64.44) -{ - $GFX::OutdatedDrivers = true; - $GFX::OutdatedDriversLink = "You can get newer drivers here.."; -} -else -{ - $GFX::OutdatedDrivers = false; -} diff --git a/Templates/BaseGame/game/core/gfxprofile/D3D9.NVIDIA.GeForce8600.cs b/Templates/BaseGame/game/core/gfxprofile/D3D9.NVIDIA.GeForce8600.cs deleted file mode 100644 index 328788dac..000000000 --- a/Templates/BaseGame/game/core/gfxprofile/D3D9.NVIDIA.GeForce8600.cs +++ /dev/null @@ -1,36 +0,0 @@ -//----------------------------------------------------------------------------- -// 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. -//----------------------------------------------------------------------------- - -// nVidia Vendor Profile Script -// -// This script is responsible for setting global -// capability strings based on the nVidia vendor. - -if(GFXCardProfiler::getVersion() < 1.2) -{ - $GFX::OutdatedDrivers = true; - $GFX::OutdatedDriversLink = "You can get newer drivers here.."; -} -else -{ - $GFX::OutdatedDrivers = false; -} diff --git a/Templates/BaseGame/game/core/gfxprofile/D3D9.NVIDIA.QuadroFXGo1000.cs b/Templates/BaseGame/game/core/gfxprofile/D3D9.NVIDIA.QuadroFXGo1000.cs deleted file mode 100644 index 5681b2f6d..000000000 --- a/Templates/BaseGame/game/core/gfxprofile/D3D9.NVIDIA.QuadroFXGo1000.cs +++ /dev/null @@ -1,39 +0,0 @@ -//----------------------------------------------------------------------------- -// 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. -//----------------------------------------------------------------------------- - -// nVidia Vendor Profile Script -// -// This script is responsible for setting global -// capability strings based on the nVidia vendor. - -if(GFXCardProfiler::getVersion() < 53.82) -{ - $GFX::OutdatedDrivers = true; - $GFX::OutdatedDriversLink = "You can get newer drivers here.."; -} -else -{ - $GFX::OutdatedDrivers = false; -} - -// Silly card has trouble with this! -GFXCardProfiler::setCapability("autoMipmapLevel", false); diff --git a/Templates/BaseGame/game/core/gfxprofile/D3D9.NVIDIA.cs b/Templates/BaseGame/game/core/gfxprofile/D3D9.NVIDIA.cs deleted file mode 100644 index b33b8d5d3..000000000 --- a/Templates/BaseGame/game/core/gfxprofile/D3D9.NVIDIA.cs +++ /dev/null @@ -1,36 +0,0 @@ -//----------------------------------------------------------------------------- -// 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. -//----------------------------------------------------------------------------- - -// nVidia Vendor Profile Script -// -// This script is responsible for setting global -// capability strings based on the nVidia vendor. - -if(GFXCardProfiler::getVersion() < 56.72) -{ - $GFX::OutdatedDrivers = true; - $GFX::OutdatedDriversLink = "You can get newer drivers here.."; -} -else -{ - $GFX::OutdatedDrivers = false; -} diff --git a/Templates/BaseGame/game/core/gfxprofile/D3D9.cs b/Templates/BaseGame/game/core/gfxprofile/D3D9.cs deleted file mode 100644 index e1e299341..000000000 --- a/Templates/BaseGame/game/core/gfxprofile/D3D9.cs +++ /dev/null @@ -1,26 +0,0 @@ -//----------------------------------------------------------------------------- -// 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. -//----------------------------------------------------------------------------- - -// Direct3D 9 Renderer Profile Script -// -// This script is responsible for setting global -// capability strings based on the D3D9 renderer type. \ No newline at end of file diff --git a/Templates/BaseGame/game/core/globals.cs b/Templates/BaseGame/game/core/globals.cs deleted file mode 100644 index d4e4f1ca3..000000000 --- a/Templates/BaseGame/game/core/globals.cs +++ /dev/null @@ -1,102 +0,0 @@ -//----------------------------------------------------------------------------- -// 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. -//----------------------------------------------------------------------------- - -// ---------------------------------------------------------------------------- -// DInput keyboard, mouse, and joystick prefs -// ---------------------------------------------------------------------------- - -$pref::Input::MouseEnabled = 1; -$pref::Input::LinkMouseSensitivity = 1; -$pref::Input::KeyboardEnabled = 1; -$pref::Input::KeyboardTurnSpeed = 0.1; -$pref::Input::JoystickEnabled = 0; - -// ---------------------------------------------------------------------------- -// Video Preferences -// ---------------------------------------------------------------------------- - -// Set directory paths for various data or default images. -$pref::Video::ProfilePath = "core/gfxprofile"; -$pref::Video::missingTexturePath = "core/images/missingTexture.png"; -$pref::Video::unavailableTexturePath = "core/images/unavailable.png"; -$pref::Video::warningTexturePath = "core/images/warnMat.dds"; - -$pref::Video::disableVerticalSync = 1; -$pref::Video::mode = "800 600 false 32 60 4"; -$pref::Video::defaultFenceCount = 0; - -// This disables the hardware FSAA/MSAA so that we depend completely on the FXAA -// post effect which works on all cards and in deferred mode. Note that the new -// Intel Hybrid graphics on laptops will fail to initialize when hardware AA is -// enabled... so you've been warned. -$pref::Video::disableHardwareAA = true; - -$pref::Video::disableNormalmapping = false; -$pref::Video::disablePixSpecular = false; -$pref::Video::disableCubemapping = false; -$pref::Video::disableParallaxMapping = false; - -// The number of mipmap levels to drop on loaded textures to reduce video memory -// usage. It will skip any textures that have been defined as not allowing down -// scaling. -$pref::Video::textureReductionLevel = 0; - -$pref::Video::defaultAnisotropy = 1; -//$pref::Video::Gamma = 1.0; - -/// AutoDetect graphics quality levels the next startup. -$pref::Video::autoDetect = 1; - -// ---------------------------------------------------------------------------- -// Shader stuff -// ---------------------------------------------------------------------------- - -// This is the path used by ShaderGen to cache procedural shaders. If left -// blank ShaderGen will only cache shaders to memory and not to disk. -$shaderGen::cachePath = "data/shaderCache"; - -// Uncomment to disable ShaderGen, useful when debugging -//$ShaderGen::GenNewShaders = false; - -// Uncomment to dump disassembly for any shader that is compiled to disk. These -// will appear as shadername_dis.txt in the same path as the shader file. -//$gfx::disassembleAllShaders = true; - -// ---------------------------------------------------------------------------- -// Lighting and shadowing -// ---------------------------------------------------------------------------- - -// Uncomment to enable AdvancedLighting on the Mac (T3D 2009 Beta 3) -//$pref::machax::enableAdvancedLighting = true; - -$sceneLighting::cacheSize = 20000; -$sceneLighting::purgeMethod = "lastCreated"; -$sceneLighting::cacheLighting = 1; - -$pref::Shadows::textureScalar = 1.0; -$pref::Shadows::disable = false; - -// Sets the shadow filtering mode. -// None - Disables filtering. -// SoftShadow - Does a simple soft shadow -// SoftShadowHighQuality -$pref::Shadows::filterMode = "SoftShadow"; diff --git a/Templates/BaseGame/game/core/helperFunctions.cs b/Templates/BaseGame/game/core/helperFunctions.cs deleted file mode 100644 index 1b98f1ea5..000000000 --- a/Templates/BaseGame/game/core/helperFunctions.cs +++ /dev/null @@ -1,1158 +0,0 @@ -//----------------------------------------------------------------------------- -// 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. -//----------------------------------------------------------------------------- - - -//------------------------------------------------------------------------------ -// Check if a script file exists, compiled or not. -function isScriptFile(%path) -{ - if( isFile(%path @ ".dso") || isFile(%path) ) - return true; - - return false; -} - -function loadMaterials() -{ - // Load any materials files for which we only have DSOs. - - for( %file = findFirstFile( "*/materials.cs.dso" ); - %file !$= ""; - %file = findNextFile( "*/materials.cs.dso" )) - { - // Only execute, if we don't have the source file. - %csFileName = getSubStr( %file, 0, strlen( %file ) - 4 ); - if( !isFile( %csFileName ) ) - exec( %csFileName ); - } - - // Load all source material files. - - for( %file = findFirstFile( "*/materials.cs" ); - %file !$= ""; - %file = findNextFile( "*/materials.cs" )) - { - exec( %file ); - } - - // Load all materials created by the material editor if - // the folder exists - if( IsDirectory( "materialEditor" ) ) - { - for( %file = findFirstFile( "materialEditor/*.cs.dso" ); - %file !$= ""; - %file = findNextFile( "materialEditor/*.cs.dso" )) - { - // Only execute, if we don't have the source file. - %csFileName = getSubStr( %file, 0, strlen( %file ) - 4 ); - if( !isFile( %csFileName ) ) - exec( %csFileName ); - } - - for( %file = findFirstFile( "materialEditor/*.cs" ); - %file !$= ""; - %file = findNextFile( "materialEditor/*.cs" )) - { - exec( %file ); - } - } -} - -function reloadMaterials() -{ - reloadTextures(); - loadMaterials(); - reInitMaterials(); -} - -function loadDatablockFiles( %datablockFiles, %recurse ) -{ - if ( %recurse ) - { - recursiveLoadDatablockFiles( %datablockFiles, 9999 ); - return; - } - - %count = %datablockFiles.count(); - for ( %i=0; %i < %count; %i++ ) - { - %file = %datablockFiles.getKey( %i ); - if ( !isFile(%file @ ".dso") && !isFile(%file) ) - continue; - - exec( %file ); - } - - // Destroy the incoming list. - //%datablockFiles.delete(); -} - -function recursiveLoadDatablockFiles( %datablockFiles, %previousErrors ) -{ - %reloadDatablockFiles = new ArrayObject(); - - // Keep track of the number of datablocks that - // failed during this pass. - %failedDatablocks = 0; - - // Try re-executing the list of datablock files. - %count = %datablockFiles.count(); - for ( %i=0; %i < %count; %i++ ) - { - %file = %datablockFiles.getKey( %i ); - if ( !isFile(%file @ ".dso") && !isFile(%file) ) - continue; - - // Start counting copy constructor creation errors. - $Con::objectCopyFailures = 0; - - exec( %file ); - - // If errors occured then store this file for re-exec later. - if ( $Con::objectCopyFailures > 0 ) - { - %reloadDatablockFiles.add( %file ); - %failedDatablocks = %failedDatablocks + $Con::objectCopyFailures; - } - } - - // Clear the object copy failure counter so that - // we get console error messages again. - $Con::objectCopyFailures = -1; - - // Delete the old incoming list... we're done with it. - //%datablockFiles.delete(); - - // If we still have datablocks to retry. - %newCount = %reloadDatablockFiles.count(); - if ( %newCount > 0 ) - { - // If the datablock failures have not been reduced - // from the last pass then we must have a real syntax - // error and not just a bad dependancy. - if ( %previousErrors > %failedDatablocks ) - recursiveLoadDatablockFiles( %reloadDatablockFiles, %failedDatablocks ); - - else - { - // Since we must have real syntax errors do one - // last normal exec to output error messages. - loadDatablockFiles( %reloadDatablockFiles, false ); - } - - return; - } - - // Cleanup the empty reload list. - %reloadDatablockFiles.delete(); -} - -function getUserPath() -{ - %temp = getUserHomeDirectory(); - echo(%temp); - if(!isDirectory(%temp)) - { - %temp = getUserDataDirectory(); - echo(%temp); - if(!isDirectory(%temp)) - { - %userPath = "data"; - } - else - { - //put it in appdata/roaming - %userPath = %temp @ "/" @ $appName; - } - } - else - { - //put it in user/documents - %userPath = %temp @ "/" @ $appName; - } - return %userPath; -} - -function getPrefpath() -{ - $prefPath = getUserPath() @ "/preferences"; - return $prefPath; -} - -function updateTSShapeLoadProgress(%progress, %msg) -{ - // Check if the loading GUI is visible and use that instead of the - // separate import progress GUI if possible - /* if ( isObject(LoadingGui) && LoadingGui.isAwake() ) - { - // Save/Restore load progress at the start/end of the import process - if ( %progress == 0 ) - { - ColladaImportProgress.savedProgress = LoadingProgress.getValue(); - ColladaImportProgress.savedText = LoadingProgressTxt.getValue(); - - ColladaImportProgress.msgPrefix = "Importing " @ %msg; - %msg = "Reading file into memory..."; - } - else if ( %progress == 1.0 ) - { - LoadingProgress.setValue( ColladaImportProgress.savedProgress ); - LoadingProgressTxt.setValue( ColladaImportProgress.savedText ); - } - - %msg = ColladaImportProgress.msgPrefix @ ": " @ %msg; - - %progressCtrl = LoadingProgress; - %textCtrl = LoadingProgressTxt; - } - else - { - //it's probably the editors using it - if(isFunction("updateToolTSShapeLoadProgress")) - { - updateToolTSShapeLoadProgress(%progress, %msg); - } - } - - // Update progress indicators - if (%progress == 0) - { - %progressCtrl.setValue(0.001); - %textCtrl.setText(%msg); - } - else if (%progress != 1.0) - { - %progressCtrl.setValue(%progress); - %textCtrl.setText(%msg); - } - - Canvas.repaint(33);*/ -} - -/// A helper function which will return the ghosted client object -/// from a server object when connected to a local server. -function serverToClientObject( %serverObject ) -{ - assert( isObject( LocalClientConnection ), "serverToClientObject() - No local client connection found!" ); - assert( isObject( ServerConnection ), "serverToClientObject() - No server connection found!" ); - - %ghostId = LocalClientConnection.getGhostId( %serverObject ); - if ( %ghostId == -1 ) - return 0; - - return ServerConnection.resolveGhostID( %ghostId ); -} - -//---------------------------------------------------------------------------- -// Debug commands -//---------------------------------------------------------------------------- - -function netSimulateLag( %msDelay, %packetLossPercent ) -{ - if ( %packetLossPercent $= "" ) - %packetLossPercent = 0; - - commandToServer( 'NetSimulateLag', %msDelay, %packetLossPercent ); -} - -//Various client functions - -function validateDatablockName(%name) -{ - // remove whitespaces at beginning and end - %name = trim( %name ); - - // remove numbers at the beginning - %numbers = "0123456789"; - while( strlen(%name) > 0 ) - { - // the first character - %firstChar = getSubStr( %name, 0, 1 ); - // if the character is a number remove it - if( strpos( %numbers, %firstChar ) != -1 ) - { - %name = getSubStr( %name, 1, strlen(%name) -1 ); - %name = ltrim( %name ); - } - else - break; - } - - // replace whitespaces with underscores - %name = strreplace( %name, " ", "_" ); - - // remove any other invalid characters - %invalidCharacters = "-+*/%$&§=()[].?\"#,;!~<>|°^{}"; - %name = stripChars( %name, %invalidCharacters ); - - if( %name $= "" ) - %name = "Unnamed"; - - return %name; -} - -//-------------------------------------------------------------------------- -// Finds location of %word in %text, starting at %start. Works just like strPos -//-------------------------------------------------------------------------- - -function wordPos(%text, %word, %start) -{ - if (%start $= "") %start = 0; - - if (strpos(%text, %word, 0) == -1) return -1; - %count = getWordCount(%text); - if (%start >= %count) return -1; - for (%i = %start; %i < %count; %i++) - { - if (getWord( %text, %i) $= %word) return %i; - } - return -1; -} - -//-------------------------------------------------------------------------- -// Finds location of %field in %text, starting at %start. Works just like strPos -//-------------------------------------------------------------------------- - -function fieldPos(%text, %field, %start) -{ - if (%start $= "") %start = 0; - - if (strpos(%text, %field, 0) == -1) return -1; - %count = getFieldCount(%text); - if (%start >= %count) return -1; - for (%i = %start; %i < %count; %i++) - { - if (getField( %text, %i) $= %field) return %i; - } - return -1; -} - -//-------------------------------------------------------------------------- -// returns the text in a file with "\n" at the end of each line -//-------------------------------------------------------------------------- - -function loadFileText( %file) -{ - %fo = new FileObject(); - %fo.openForRead(%file); - %text = ""; - while(!%fo.isEOF()) - { - %text = %text @ %fo.readLine(); - if (!%fo.isEOF()) %text = %text @ "\n"; - } - - %fo.delete(); - return %text; -} - -function setValueSafe(%dest, %val) -{ - %cmd = %dest.command; - %alt = %dest.altCommand; - %dest.command = ""; - %dest.altCommand = ""; - - %dest.setValue(%val); - - %dest.command = %cmd; - %dest.altCommand = %alt; -} - -function shareValueSafe(%source, %dest) -{ - setValueSafe(%dest, %source.getValue()); -} - -function shareValueSafeDelay(%source, %dest, %delayMs) -{ - schedule(%delayMs, 0, shareValueSafe, %source, %dest); -} - - -//------------------------------------------------------------------------------ -// An Aggregate Control is a plain GuiControl that contains other controls, -// which all share a single job or represent a single value. -//------------------------------------------------------------------------------ - -// AggregateControl.setValue( ) propagates the value to any control that has an -// internal name. -function AggregateControl::setValue(%this, %val, %child) -{ - for(%i = 0; %i < %this.getCount(); %i++) - { - %obj = %this.getObject(%i); - if( %obj == %child ) - continue; - - if(%obj.internalName !$= "") - setValueSafe(%obj, %val); - } -} - -// AggregateControl.getValue() uses the value of the first control that has an -// internal name, if it has not cached a value via .setValue -function AggregateControl::getValue(%this) -{ - for(%i = 0; %i < %this.getCount(); %i++) - { - %obj = %this.getObject(%i); - if(%obj.internalName !$= "") - { - //error("obj = " @ %obj.getId() @ ", " @ %obj.getName() @ ", " @ %obj.internalName ); - //error(" value = " @ %obj.getValue()); - return %obj.getValue(); - } - } -} - -// AggregateControl.updateFromChild( ) is called by child controls to propagate -// a new value, and to trigger the onAction() callback. -function AggregateControl::updateFromChild(%this, %child) -{ - %val = %child.getValue(); - if(%val == mCeil(%val)){ - %val = mCeil(%val); - }else{ - if ( %val <= -100){ - %val = mCeil(%val); - }else if ( %val <= -10){ - %val = mFloatLength(%val, 1); - }else if ( %val < 0){ - %val = mFloatLength(%val, 2); - }else if ( %val >= 1000){ - %val = mCeil(%val); - }else if ( %val >= 100){ - %val = mFloatLength(%val, 1); - }else if ( %val >= 10){ - %val = mFloatLength(%val, 2); - }else if ( %val > 0){ - %val = mFloatLength(%val, 3); - } - } - %this.setValue(%val, %child); - %this.onAction(); -} - -// default onAction stub, here only to prevent console spam warnings. -function AggregateControl::onAction(%this) -{ -} - -// call a method on all children that have an internalName and that implement the method. -function AggregateControl::callMethod(%this, %method, %args) -{ - for(%i = 0; %i < %this.getCount(); %i++) - { - %obj = %this.getObject(%i); - if(%obj.internalName !$= "" && %obj.isMethod(%method)) - eval(%obj @ "." @ %method @ "( " @ %args @ " );"); - } - -} - -//------------------------------------------------------------------------------ -// Altered Version of TGB's QuickEditDropDownTextEditCtrl -//------------------------------------------------------------------------------ -function QuickEditDropDownTextEditCtrl::onRenameItem( %this ) -{ -} - -function QuickEditDropDownTextEditCtrl::updateFromChild( %this, %ctrl ) -{ - if( %ctrl.internalName $= "PopUpMenu" ) - { - %this->TextEdit.setText( %ctrl.getText() ); - } - else if ( %ctrl.internalName $= "TextEdit" ) - { - %popup = %this->PopupMenu; - %popup.changeTextById( %popup.getSelected(), %ctrl.getText() ); - %this.onRenameItem(); - } -} - -// Writes out all script functions to a file. -function writeOutFunctions() -{ - new ConsoleLogger(logger, "scriptFunctions.txt", false); - dumpConsoleFunctions(); - logger.delete(); -} - -// Writes out all script classes to a file. -function writeOutClasses() -{ - new ConsoleLogger(logger, "scriptClasses.txt", false); - dumpConsoleClasses(); - logger.delete(); -} - -// -function compileFiles(%pattern) -{ - %path = filePath(%pattern); - - %saveDSO = $Scripts::OverrideDSOPath; - %saveIgnore = $Scripts::ignoreDSOs; - - $Scripts::OverrideDSOPath = %path; - $Scripts::ignoreDSOs = false; - %mainCsFile = makeFullPath("main.cs"); - - for (%file = findFirstFileMultiExpr(%pattern); %file !$= ""; %file = findNextFileMultiExpr(%pattern)) - { - // we don't want to try and compile the primary main.cs - if(%mainCsFile !$= %file) - compile(%file, true); - } - - $Scripts::OverrideDSOPath = %saveDSO; - $Scripts::ignoreDSOs = %saveIgnore; - -} - -function displayHelp() -{ - // Notes on logmode: console logging is written to console.log. - // -log 0 disables console logging. - // -log 1 appends to existing logfile; it also closes the file - // (flushing the write buffer) after every write. - // -log 2 overwrites any existing logfile; it also only closes - // the logfile when the application shuts down. (default) - - error( - "Torque Demo command line options:\n"@ - " -log Logging behavior; see main.cs comments for details\n"@ - " -game Reset list of mods to only contain \n"@ - " Works like the -game argument\n"@ - " -dir Add to list of directories\n"@ - " -console Open a separate console\n"@ - " -jSave Record a journal\n"@ - " -jPlay Play back a journal\n"@ - " -help Display this help message\n" - ); -} - -// Execute startup scripts for each mod, starting at base and working up -function loadDir(%dir) -{ - pushback($userDirs, %dir, ";"); - - if (isScriptFile(%dir @ "/main.cs")) - exec(%dir @ "/main.cs"); -} - -function loadDirs(%dirPath) -{ - %dirPath = nextToken(%dirPath, token, ";"); - if (%dirPath !$= "") - loadDirs(%dirPath); - - if(exec(%token @ "/main.cs") != true) - { - error("Error: Unable to find specified directory: " @ %token ); - $dirCount--; - } -} - -//------------------------------------------------------------------------------ -// Utility remap functions: -//------------------------------------------------------------------------------ - -function ActionMap::copyBind( %this, %otherMap, %command ) -{ - if ( !isObject( %otherMap ) ) - { - error( "ActionMap::copyBind - \"" @ %otherMap @ "\" is not an object!" ); - return; - } - - %bind = %otherMap.getBinding( %command ); - if ( %bind !$= "" ) - { - %device = getField( %bind, 0 ); - %action = getField( %bind, 1 ); - %flags = %otherMap.isInverted( %device, %action ) ? "SDI" : "SD"; - %deadZone = %otherMap.getDeadZone( %device, %action ); - %scale = %otherMap.getScale( %device, %action ); - %this.bind( %device, %action, %flags, %deadZone, %scale, %command ); - } -} - -//------------------------------------------------------------------------------ -function ActionMap::blockBind( %this, %otherMap, %command ) -{ - if ( !isObject( %otherMap ) ) - { - error( "ActionMap::blockBind - \"" @ %otherMap @ "\" is not an object!" ); - return; - } - - %bind = %otherMap.getBinding( %command ); - if ( %bind !$= "" ) - %this.bind( getField( %bind, 0 ), getField( %bind, 1 ), "" ); -} - -//Dev helpers -/// Shortcut for typing dbgSetParameters with the default values torsion uses. -function dbgTorsion() -{ - dbgSetParameters( 6060, "password", false ); -} - -/// Reset the input state to a default of all-keys-up. -/// A helpful remedy for when Torque misses a button up event do to your breakpoints -/// and can't stop shooting / jumping / strafing. -function mvReset() -{ - for ( %i = 0; %i < 6; %i++ ) - setVariable( "mvTriggerCount" @ %i, 0 ); - - $mvUpAction = 0; - $mvDownAction = 0; - $mvLeftAction = 0; - $mvRightAction = 0; - - // There are others. -} - -//Persistance Manager tests - -new PersistenceManager(TestPManager); - -function runPManTest(%test) -{ - if (!isObject(TestPManager)) - return; - - if (%test $= "") - %test = 100; - - switch(%test) - { - case 0: - TestPManager.testFieldUpdates(); - case 1: - TestPManager.testObjectRename(); - case 2: - TestPManager.testNewObject(); - case 3: - TestPManager.testNewGroup(); - case 4: - TestPManager.testMoveObject(); - case 5: - TestPManager.testObjectRemove(); - case 100: - TestPManager.testFieldUpdates(); - TestPManager.testObjectRename(); - TestPManager.testNewObject(); - TestPManager.testNewGroup(); - TestPManager.testMoveObject(); - TestPManager.testObjectRemove(); - } -} - -function TestPManager::testFieldUpdates(%doNotSave) -{ - // Set some objects as dirty - TestPManager.setDirty(AudioGui); - TestPManager.setDirty(AudioSim); - TestPManager.setDirty(AudioMessage); - - // Alter some of the existing fields - AudioEffect.isLooping = true; - AudioMessage.isLooping = true; - AudioEffect.is3D = true; - - // Test removing a field - TestPManager.removeField(AudioGui, "isLooping"); - - // Alter some of the persistent fields - AudioGui.referenceDistance = 0.8; - AudioMessage.referenceDistance = 0.8; - - // Add some new dynamic fields - AudioGui.foo = "bar"; - AudioEffect.foo = "bar"; - - // Remove an object from the dirty list - // It shouldn't get updated in the file - TestPManager.removeDirty(AudioEffect); - - // Dirty an object in another file as well - TestPManager.setDirty(WarningMaterial); - - // Update a field that doesn't exist - WarningMaterial.glow[0] = true; - - // Drity another object to test for crashes - // when a dirty object is deleted - TestPManager.setDirty(SFXPausedSet); - - // Delete the object - SFXPausedSet.delete(); - - // Unless %doNotSave is set (by a batch/combo test) - // then go ahead and save now - if (!%doNotSave) - TestPManager.saveDirty(); -} - -function TestPManager::testObjectRename(%doNotSave) -{ - // Flag an object as dirty - if (isObject(AudioGui)) - TestPManager.setDirty(AudioGui); - else if (isObject(AudioGuiFoo)) - TestPManager.setDirty(AudioGuiFoo); - - // Rename it - if (isObject(AudioGui)) - AudioGui.setName(AudioGuiFoo); - else if (isObject(AudioGuiFoo)) - AudioGuiFoo.setName(AudioGui); - - // Unless %doNotSave is set (by a batch/combo test) - // then go ahead and save now - if (!%doNotSave) - TestPManager.saveDirty(); -} - -function TestPManager::testNewObject(%doNotSave) -{ - // Test adding a new named object - new SFXDescription(AudioNew) - { - volume = 0.5; - isLooping = true; - channel = $GuiAudioType; - foo = 2; - }; - - // Flag it as dirty - TestPManager.setDirty(AudioNew, "core/scripts/client/audio.cs"); - - // Test adding a new unnamed object - %obj = new SFXDescription() - { - volume = 0.75; - isLooping = true; - bar = 3; - }; - - // Flag it as dirty - TestPManager.setDirty(%obj, "core/scripts/client/audio.cs"); - - // Test adding an "empty" object - new SFXDescription(AudioEmpty); - - TestPManager.setDirty(AudioEmpty, "core/scripts/client/audio.cs"); - - // Unless %doNotSave is set (by a batch/combo test) - // then go ahead and save now - if (!%doNotSave) - TestPManager.saveDirty(); -} - -function TestPManager::testNewGroup(%doNotSave) -{ - // Test adding a new named SimGroup - new SimGroup(TestGroup) - { - foo = "bar"; - - new SFXDescription(TestObject) - { - volume = 0.5; - isLooping = true; - channel = $GuiAudioType; - foo = 1; - }; - new SimGroup(SubGroup) - { - foo = 2; - - new SFXDescription(SubObject) - { - volume = 0.5; - isLooping = true; - channel = $GuiAudioType; - foo = 3; - }; - }; - }; - - // Flag this as dirty - TestPManager.setDirty(TestGroup, "core/scripts/client/audio.cs"); - - // Test adding a new unnamed SimGroup - %group = new SimGroup() - { - foo = "bar"; - - new SFXDescription() - { - volume = 0.75; - channel = $GuiAudioType; - foo = 4; - }; - new SimGroup() - { - foo = 5; - - new SFXDescription() - { - volume = 0.75; - isLooping = true; - channel = $GuiAudioType; - foo = 6; - }; - }; - }; - - // Flag this as dirty - TestPManager.setDirty(%group, "core/scripts/client/audio.cs"); - - // Test adding a new unnamed SimSet - %set = new SimSet() - { - foo = "bar"; - - new SFXDescription() - { - volume = 0.75; - channel = $GuiAudioType; - foo = 7; - }; - new SimGroup() - { - foo = 8; - - new SFXDescription() - { - volume = 0.75; - isLooping = true; - channel = $GuiAudioType; - foo = 9; - }; - }; - }; - - // Flag this as dirty - TestPManager.setDirty(%set, "core/scripts/client/audio.cs"); - - // Unless %doNotSave is set (by a batch/combo test) - // then go ahead and save now - if (!%doNotSave) - TestPManager.saveDirty(); -} - -function TestPManager::testMoveObject(%doNotSave) -{ - // First add a couple of groups to the file - new SimGroup(MoveGroup1) - { - foo = "bar"; - - new SFXDescription(MoveObject1) - { - volume = 0.5; - isLooping = true; - channel = $GuiAudioType; - foo = 1; - }; - - new SimSet(SubGroup1) - { - new SFXDescription(SubObject1) - { - volume = 0.75; - isLooping = true; - channel = $GuiAudioType; - foo = 2; - }; - }; - }; - - // Flag this as dirty - TestPManager.setDirty(MoveGroup1, "core/scripts/client/audio.cs"); - - new SimGroup(MoveGroup2) - { - foo = "bar"; - - new SFXDescription(MoveObject2) - { - volume = 0.5; - isLooping = true; - channel = $GuiAudioType; - foo = 3; - }; - }; - - // Flag this as dirty - TestPManager.setDirty(MoveGroup2, "core/scripts/client/audio.cs"); - - // Unless %doNotSave is set (by a batch/combo test) - // then go ahead and save now - if (!%doNotSave) - TestPManager.saveDirty(); - - // Set them as dirty again - TestPManager.setDirty(MoveGroup1); - TestPManager.setDirty(MoveGroup2); - - // Give the subobject an new value - MoveObject1.foo = 4; - - // Move it into the other group - MoveGroup1.add(MoveObject2); - - // Switch the other subobject - MoveGroup2.add(MoveObject1); - - // Also add a new unnamed object to one of the groups - %obj = new SFXDescription() - { - volume = 0.75; - isLooping = true; - bar = 5; - }; - - MoveGroup1.add(%obj); - - // Unless %doNotSave is set (by a batch/combo test) - // then go ahead and save now - if (!%doNotSave) - TestPManager.saveDirty(); -} - -function TestPManager::testObjectRemove(%doNotSave) -{ - TestPManager.removeObjectFromFile(AudioSim); -} - -//Game Object management -function findGameObject(%name) -{ - //find all GameObjectAssets - %assetQuery = new AssetQuery(); - if(!AssetDatabase.findAssetType(%assetQuery, "GameObjectAsset")) - return 0; //if we didn't find ANY, just exit - - %count = %assetQuery.getCount(); - - for(%i=0; %i < %count; %i++) - { - %assetId = %assetQuery.getAsset(%i); - - %assetName = AssetDatabase.getAssetName(%assetId); - - if(%assetName $= %name) - { - %gameObjectAsset = AssetDatabase.acquireAsset(%assetId); - - %assetQuery.delete(); - return %gameObjectAsset; - } - } - - %assetQuery.delete(); - return 0; -} - -function spawnGameObject(%name, %addToMissionGroup) -{ - if(%addToMissionGroup $= "") - %addToMissionGroup = true; - - //First, check if this already exists in our GameObjectPool - if(isObject(GameObjectPool)) - { - %goCount = GameObjectPool.countKey(%name); - - //if we have some already in the pool, pull it out and use that - if(%goCount != 0) - { - %goIdx = GameObjectPool.getIndexFromKey(%name); - %go = GameObjectPool.getValue(%goIdx); - - %go.setHidden(false); - %go.setScopeAlways(); - - if(%addToMissionGroup == true) //save instance when saving level - MissionGroup.add(%go); - else // clear instance on level exit - MissionCleanup.add(%go); - - //remove from the object pool's list - GameObjectPool.erase(%goIdx); - - return %go; - } - } - - //We have no existing pool, or no existing game objects of this type, so spawn a new one - - %gameObjectAsset = findGameObject(%name); - - if(isObject(%gameObjectAsset)) - { - %newSGOObject = TamlRead(%gameObjectAsset.TAMLFilePath); - - if(%addToMissionGroup == true) //save instance when saving level - MissionGroup.add(%newSGOObject); - else // clear instance on level exit - MissionCleanup.add(%newSGOObject); - - return %newSGOObject; - } - - return 0; -} - -function saveGameObject(%name, %tamlPath, %scriptPath) -{ - %gameObjectAsset = findGameObject(%name); - - //find if it already exists. If it does, we'll update it, if it does not, we'll make a new asset - if(isObject(%gameObjectAsset)) - { - %assetID = %gameObjectAsset.getAssetId(); - - %gameObjectAsset.TAMLFilePath = %tamlPath; - %gameObjectAsset.scriptFilePath = %scriptPath; - - TAMLWrite(%gameObjectAsset, AssetDatabase.getAssetFilePath(%assetID)); - AssetDatabase.refreshAsset(%assetID); - } - else - { - //Doesn't exist, so make a new one - %gameObjectAsset = new GameObjectAsset() - { - assetName = %name @ "Asset"; - gameObjectName = %name; - TAMLFilePath = %tamlPath; - scriptFilePath = %scriptPath; - }; - - //Save it alongside the taml file - %path = filePath(%tamlPath); - - TAMLWrite(%gameObjectAsset, %path @ "/" @ %name @ ".asset.taml"); - AssetDatabase.refreshAllAssets(true); - } -} - -//Allocates a number of a game object into a pool to be pulled from as needed -function allocateGameObjects(%name, %amount) -{ - //First, we need to make sure our pool exists - if(!isObject(GameObjectPool)) - { - new ArrayObject(GameObjectPool); - } - - //Next, we loop and generate our game objects, and add them to the pool - for(%i=0; %i < %amount; %i++) - { - %go = spawnGameObject(%name, false); - - //When our object is in the pool, it's not "real", so we need to make sure - //that we don't ghost it to clients untill we actually spawn it. - %go.clearScopeAlways(); - - //We also hide it, so that we don't 'exist' in the scene until we spawn - %go.hidden = true; - - //Lastly, add us to the pool, with the key being our game object type - GameObjectPool.add(%name, %go); - } -} - -function Entity::delete(%this) -{ - //we want to intercept the delete call, and add it to our GameObjectPool - //if it's a game object - if(%this.gameObjectAsset !$= "") - { - %this.setHidden(true); - %this.clearScopeAlways(); - - if(!isObject(GameObjectPool)) - { - new ArrayObject(GameObjectPool); - } - - GameObjectPool.add(%this.gameObjectAsset, %this); - - %missionSet = %this.getGroup(); - %missionSet.remove(%this); - } - else - { - %this.superClass.delete(); - } -} - -function clearGameObjectPool() -{ - if(isObject(GameObjectPool)) - { - %count = GameObjectPool.count(); - - for(%i=0; %i < %count; %i++) - { - %go = GameObjectPool.getValue(%i); - - %go.superClass.delete(); - } - - GameObjectPool.empty(); - } -} - -// -function switchCamera(%client, %newCamEntity) -{ - if(!isObject(%client) || !isObject(%newCamEntity)) - return error("SwitchCamera: No client or target camera!"); - - %cam = %newCamEntity.getComponent(CameraComponent); - - if(!isObject(%cam)) - return error("SwitchCamera: Target camera doesn't have a camera behavior!"); - - //TODO: Cleanup clientOwner for previous camera! - if(%cam.clientOwner == 0 || %cam.clientOwner $= "") - %cam.clientOwner = 0; - - %cam.scopeToClient(%client); - %cam.setDirty(); - - %client.setCameraObject(%newCamEntity); - %client.setControlCameraFov(%cam.FOV); - - %client.camera = %newCamEntity; -} \ No newline at end of file diff --git a/Templates/BaseGame/game/core/images/AreaMap33.dds b/Templates/BaseGame/game/core/images/AreaMap33.dds deleted file mode 100644 index e01982a94528594a375ae6e61c44780a8e1c0b68..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 109028 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 RBF+E+002ovPDHLkV1nj@91s8i diff --git a/Templates/BaseGame/game/core/images/caustics_2.png b/Templates/BaseGame/game/core/images/caustics_2.png deleted file mode 100644 index 99097fa0ed112c28958363f2951478a0955218ec..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 33963 zcmXt91yGw^(+y53?yfEF?$Dy8g%+3M!L7Kv7cIrzrC6ZAi$fsA-5r9v75D$?H}i+d z1Tq8M+}(Tk>^Wz@e^F7u!XU>0fk0Rv6lK*wAOzrB1Q0qZ@S^WrW&ymQntoJ}1-<{B*J+^mJH=Z0)c2jA7tNYcrK2# zpW1?TQ{H+T>If3!6Vtt)H{*UsobAdZM{S;@binkkX7PQ?*DS}=_aD3F>&8Z8hY`-k&jPI zObj`_d$F{%guQ%LQ3-#^&B?(Y>lr)yw*7GD>wi|~ak@$+etLJ;oSmKBu)Dh(V!IJ= z=OQ5~`CngO-}U3;vctD;Oa7fS{@1s+^Vbi4KK}mHIUxb(k+Vv3;dAJ7qld2U?t;D? z#L@2V?z1YNKQApT=w_;v!fcP-TdyxKrv)>WmyX@-8Vmde-amVgH zj>@;*-rm0hV7bb3v&VP_wvC^cbEKrCXl6Yna~tyz0nM%&|jn;46ZC%aK@xu zB68PoPQPcytSOgHb}8Ih*$Ny|kH`56l2Jo@_vo^?Fx z?p!plRK~~0A75U&ay!^zx@}%#Hj7E$*B#ZJU0t-tV2=z8d{{cYF(^$W3#_ZF6U-fx zVc^ak1J>f_lz09(Vlg#3I*L6@Wb5JWy_l1eW4Ih(_|=VjLGQ4`G536>)ni{|L*ViH z_^apGt((dCCC`Ak-b{fB9&3V3eXS$I-AhxtFuD$@ovV0<-^2BWo_ni-n1~3OA<`Vq zSQOGT5JOHbuBFY*%^*5x_&98*?cINp6J2EBH%{3JBrZAH5T3=N+pjkrXOGDW^#gZ) zXJls?P4cAd9i=nqfj9l8wN?*L&rozI_h0Jx7?8r3lfXK<$e6(AxVdbsy67(pUCq0) zmWg9H^!;}6?cAVr1)m{>ox7O_hUGsI&{(sfUBMXg^e2C*Hfo>QeOGVCLLey@x3|rK zJvlx(ak$O)4p(}ED~B+#Zd~XN#2NQ_vyPoO`o9&2h%ti?Gt2U$*rc5_3VLn%%M!zq zB%M+UYUFq|PH~bEJ^?FSBqSs-iOpRg8E5ru8yg#8KEH!74yX$>c3VrNCRR1^jx2Q6#9eb?oiad8Q@>XFPxJ$*(sB;M)c&)zMw^Aa?qQ-uW0x zHCq*6?}WEzVqU{t>Qws+%2pTmFFO4m+;N{>ls4PiUuIg3Jr);#GUKV=lpj(TbrB7s@K=oO%!V#A&pDNKs=sJ3d?WU zAM`0v%z88hA5rsuWtcSLp72THC4i|(YLBFy1XJI$*m#tjZzqHJa*C-2hn&RVe z7o*{vK0H2(%f3ExoAx}jh@1=>#;rk^_@X0(6Y-l;z7?sDG}4=$(kd15*VgHTteCT{ z)_Wq9T+Fa;kb01sO#_Uq>`leDqj9 zf=>AHJF6(({9NlxTXj14djaiZ%$!~){Mg`LICm@pHa4*g+%gZB`%^zG8)p}R104}* z+_~0xl|`dWxK`u7TJ;q)zT^*nxISJw z^Wp+dgF|CouU=u`hpj6Hw$;~Hyh$P$PYG-Akabk+`S_k~$E*v>YiD0ae*GO=^=Ta! zwb1GVO#`!^>qrv(sSp}3$!~@lh&2w8T9o7ASi_KkO#Z(e5}*rG?wY?ojUO6{FuC@X z%E<38Y*k99+?|}99Dl%BNTPd;t&A}}kBteNhNFJ7m4;JdanJvHFcHjbpO>*|+r99z zLSNQhR|KKrVuv#5Xdv>hqzT7o&ouJMN+BhBo4mM+`mLwWGe}BF;RwkO2_*DIzP|)+ zkDZIV8U*3pow+L7ngqPaoIXf#ZzSXexQ@=m^}9TMeeI%qHsp$sKZkK$ec@c`hn5>! z^NG&uTa3_yZkibi36JylsB2V>VO`rAC^KhbM~x8?5$-N7d>X`GwAW5=(3bI(iJCIH zR0>Jnwpz)@F5TVT)u1ik0k^k(gC5qesE(Wx7NFX2y@N7W&f(zOFB|UnhS`Cf2)7j+ z4i!bQk*98Ed}D=3oh{g_9p3nT#$}mCYQp7KLUMf)-X6~o4$+x6%V4ZkfY;Mv+}zfg zuY05@$@$2})|PNqravRU@<%2tu z1y>nhJ3FOK7Y1$O4r8z#gt74h96RvrG>MLoxQm2lc$Rr*)A$OwEjR;!t&pj1T{;dw zBQ$(XgsF^ha&i(rmPN+eUTvev^zbReR2W8)>>zUB+~CSsZzT#>vY>q1rO3OkSix4e za3m*(oUm^vXbW6eNY98!wZI>Gsh}HYmR46h5;LSoCAMujnoXEPAATnruh$h=*dv*1 zW>=_`Lqpfl|3P0dgaUbN3=$&BHszF%%2L)N#E*!;7iuuTES%(f=EZk`aZ^YXI)502n{V9i;JFWRhaTbz9|qU`x{rVB2>d)d;QBE zb#x4Zq(^w3iz^~H-xqnb4+zFndI`nE@4Js5`>OSRoSW9a4?zo5lKt-C;Q>UwVZ}j6 z7GcGdwS@?Idj_g|<5$zmmTn{wax%3V**9( zq`K~je%T8%bK5JMCk#_KBQ)xuhbwg`1U7aGiJT!IGWezdT1Hr-*$(NrFI4^8b?DuA1Gns+|vrcle(U zHYVi9)KFcew9Dicb9tAYKXMs$VBXk>X8+e?>V#`e=RE!}+T0@g`j{oM0QBUGO}VSa zL-F^{cNIvW#hDpR04p7DY;3?+FPfKuL@vu4b_4Z%r}`S0#7oULX%Q2NR{bEE{Qhas?&zj^{& zqf=+Q;}2C?S22+r_gDq2A2g_4KsF6UM^@cr5r(nY{qKCKC{?qwvg%t~Td%i=Qjx$& z&{&!*J?o}1yj(DLxx(0Nrn<3(EN?MY0=)tqaMF)=c6I`jMJD7a#_0{xO8YreE1MoS z`X!W>Wc_>0CF?CM@}-Dt6q+WGN?upWgYsTU>67DcyEgp-Gk5ut&bT1mIHsW@>0@Hb z8~$0R!wcLc|GLOdgTdV;}Z{w0ZC_q1!jlb$|5 zH1Bp`U;sWtROt&8AZ|oX=S+~qG*&!QS8IjaAxxR8bF|wOYpl65^FpR1+orrgnveq7;I+d1K+^-~Pk4aI zbfKOwL<~FT!8e&XZ!UV04}^^a4`^=XFPE(0DN9nVE8)M)pL~E7mI)ALB6{d zI^KqF?~EoWm;9Z%c(S3=mBwcEbP{wj)8EFOv)P0&LkO*Mo8?GPZcE^`Fz|3Na?030 z`EDwDQs*2mGfh5omr?9wWDPpzdSFAv4e-bPxn;CoS zFfKE3o>`PqfB!ZNU7?@7wQg&{$6VZhB@GC(3`_K@_m7Yg@e@OfIg+r2g)2)?HIkFh zfm~ZS<*|l(U=)HQoeyD98KSBMCLvClEHaT+=@Qq!1bKS6L6Q$jI^XPz=K`(1T6`<= zN!A~aBe*Wcw?CV58mMPohwBpj%a*v@f8T(E1Xr1Ln6KdzB@=U&l=OcsRIQm>y6}F< zdtuv17aYnmm$CD~kz3-b@szN@5W-Y4L`y<`@2G;&GN*9JSFCrZ+|97lGtN{DE93%| zo|%)rBF1D_o(c;CBO@BhzYBJ=Dggeq6QrOg7Jkgk%rsI5RR^^$I&!(X(hysN*o!vM z(WT}ekU-N~TG&_>UheLZGqh)@2l=bmp~KE=)D^slvy>j4rdzl9pPC{)pi(Xy461V( zDWOz)$1#l`vnla79y-5rb;PT{_;`EU0DT_NYvrPlbZB2&K_Ws~PJ}CN z9}lluBmg*pOj{IQnSKkvU2bwFpjLrKcF)8vnkFJleq$*hQU0w+Rkz{LruWW#Gh}VB zN=}CC83Z(u3(CaF)O}@$a$fv)rmkGhw5L0QuG24f$mx29kr-ZyorsC#<(zQ4i~D%=SkyJwi{D2gLuaXL6D z845Xz+>H``E4_V*7j#55V@Zg_@eAA5dUsEy+DFwA2|jJJaFY?4wU7m=1q#6e>Xj0l zI9w&JI^t9d2BC%qJ`qcM>+#omD7czv>uSlYQu!IE!b-K1-Rt`e$LV4!OnULNxLima zok*2-(%{-h$zl3w6ChHTmqX*%8%}(BF zP&nhLDBFxc-7MbElY3ZQOKIYLR9Phv100n9>1TQHr1qLvfvW|TH6Hel{Mq?GI5;?h z1)f0cN=r-84%ebn^!v+2>{F&WeRm0#(TeykH*X?R!No}V zGd@@JzZsvG*H6D2G=+>U@Ael8%aNYI=FSZAE+ z&z48}bco&Rak`K{kqyNa21ec=(qk?6@hpPU=c@L|Yz~A45lN%ZHR_4kAO;^eRwUgM zNbbpMh*_=U>Lj|>T|#h|?b?{*H~WLOlapBb|KyboyVU9 zC+B((!&{?!W)Z~ABnA9laX|Zv4*qIcN ziOGUv{B*pSQ)O7LJe5-x`c9dKn?174lw?M*rMM9Pu-}c;4E*>kT9SE@(idu>TAfVy z+`dlMPVOau=;+nyzG;ru##D~CT|(Y#i(JCLzwau_JRz?!2XHOiBh0+Wq^5UYX`FX7 zV|uLO+W)ho?wy|o4-3f7V~Dw|1T1Fqkb;D`I1uwRWZz6CZvJp?T%vMCyw(%Xp6}E7 zxS}4iKj5bgd)d2dxpg=LGwSx(PwHm3sQq>xn-a91C5G>|c5%ejmhs*3U-ie_fAzi_ z#Ei!9=XcLF-^vFo4TI^)=Lq02ZSwa7bGy|b$M~>n~2zsGT2&6{Ow#9Kbh1|XU znNYpeJrOiOA8Ln-@v=IyFr_?zua=dmy_ns%inBtRVB`FzeuI&-_H1ipWMuq%S>cfG zFVfR}blE-)^<}y_Lbjn1wug;0=I$pyccXX?iECB`^81RN-q6<5d5|nL(IKw?w+zjX zi=nb#bd%Q#1ga$xQYBj{R9ift&!MU{S z5waH#g;DVGcjtrh6L?7Z=4wold*QG8KCMuT>FS*`G^XH5h{b{&Z?lD>LTMWIK@%Z* zzM(IBq%njx8l-%6HDK6F|J2Q3zyz)e=e{{OyYPDtHm=+#WwN2q9T-`y1>fLL%OAHI z%#_25Kx9p=U-0U7C7ChX_eLBLEk?>;bVmqb?d4->{Uv&ce#b4s#T&2G1ymWwxr2nf ziv={>CBHdp(M}@d*o`c+*EJ4Tl&j69TdrF}s(0!Bs@$g=G+_mfhIxKV5WB8<-SJW> z6>(^eLhpdI>*dunhiTd(@v|1hkj1D}5!Kv)=<62t=s&l zd+SpJ2`Iwwt4Ok`p2#C>YjHDUptQY`2~wU6&)riYizrdO+i>WT;eLFkC-08FxnaJH zJyp%UUf`4$i=c4=F~YM&-2x^p=ixA)BRXZEz(wlNcF^N>+S69cC%zC|&E(%EMeRw~ z9Is>{vF>qxSh2m~7I{{IbV7F;x?YQ~`dub9Z!kglqA3~^S}qjWRD50)mBg9be-kWS z0}I^GnnO-4T124gU1LhrFM1(xWQi;x_Yhg9Z(k;7Y_JtP#a+R*I`zlyOW9=b$(G?l zg~upN-)$L4{oX-RWlrL+BD=nnXK$4ufpj^T5|b`j$y|xQo zD^S`X*6?H$^OkGf!IhCh&o+x>T+R9)e%`q5v}Y#?N4=kPd2$mst1n6ew@$xrUjo;S76+t*T9aF6l z6A0j6cSkN3YF3ZblmmMr<8(CbYDTC2nwfpQkNTF5%xECX=!gxK-;BA`nRdfto(#2W z13f)G+!0h#GNRDUbgv`)F_HLQeFfj=9K1-(KtzAZI1iw;GSrIjViS zc0;yLzKlFpYi|sX#u%SxxcsQtP(AjmZ%v=D*%sNZlJvr{JC_9phy{|u=)3#3|>HIrJnoCKlT=C%Cfs`Ojk<9#WaIQ9wC;Kzy?n>2*)H(~tZ z+Q|Be7?8w^wn3A~vYGZXk?!_eKFgNmrvGZqO2A4}oa7_&k*$7(8?99hol3#xZaWw_ zi^+!tC=qzV0DUh0>Km;+`}*8Fy&p6E73EUNKPJM`;>g8wk*o-; zh&|qSrn7E)Kb#_7)15|`Ac;gyNn%#Q6+!Z=BkV`Y0-`%Vu1e5El>T$!O~4aobgL*S zI{Jc32OcxYb{jKSeJ)ZHb(yUybxzDL#H0my#{U3TA_9j7yVr1Sd709aUWXgC=$7&P zT~(ausT@c*TWaxB26@vOTiGnQq8Ym_sx(@>(EY8b3_B=7T0>tuREw$=xG8)R3ACYxrutWSf+F{9)8 zlT7*5d)%TZMeSb+6KKZ2@lruNRc1h!FHOr%!Ir`OJC4}G_lpXJ1~%(ZDj#GYJ3#RM zLl^(ejh^l9q%I^v^7UaIb0CqQPtIos>6j=FlNJZ(B(w&K9}EbdFSCn*uW8BmW-2Q3 zUA_gze*DgVy8Ez^l}~}E&9QccsgpETF`-qHj$qL4Fqg2fjc^Hyqn`Tofuv0PuLgld z-1h`%wYm$I50@xshooM!$x5f$ z%DER-kZ~D@7rKief{;^SSaOkwBKUA01M9HrG70lg9%XF-L{-%CR<3k>CkRa*$(`J2 zBo-)Ax5dL-J&Z}BsOEQm9e&1ZkMp{J5>Ze5%k$ccPv(fl@lYyPNQAJMm@V)FsZTMb z+X}a?9-Q3{71=_{BVQ8xhng-!4`s(M2e4?tr)26w@klY*lQS^}cuay1b_XSnG0^(~ z^ehk_L(KZUiLi=WX~Cj5rex(u=@fILy@3qNwQs7Fk`aw*C>*NA_ixH!cwR4EAdUMt zwzm7o2S`LzyAbY1=R<2}9poiK>Tw z8$C1vMV$89hm$K)H6hiOd(BrUI)T-Z1;r4xv{36c;H*?UnHu;r$yCZIwp*a+g1*y$ zmxq5j%+>km{H511B44Pbm1$#w4@Abi`(92G9oybR6(#=0z3s}1Sl>*8w;(2^U59>^ z4xT|`TSgs=4tqe{Qil}F(<%uR{xsQInWts3X6Man`PRU`SI#6p#4C0QCiVBdEewGy z6C~;K)N!-MU%09ChO;cJ#}m3Fy+f-Vxbu~y?Op%_WZaYgnpVXOZb^1-E{^pdhenFP zE-M#H%w8L68fBQ~h#S_!m9)HfL>y09y(UxbadoD3$70eJW|6nQ9K28|sN$Cxxo~R0 z0&dOjF8LD)NfKu2$1 zXEL}>ujxFxr{L+tqmzvT;In4FpfmwWha`MuWhFWjM$e>T-)K6l?@yXsu#C=(D#j3+ zih~t^$|%t+Xpb!dh;cZfdJN#7VWSR;j1*rKGGohH@qE7cV7a%h1WgMIBT}L?A(34D zGK=_Zx!D}2iE1g(=OGWTqOQKA^zs#!dZcFI2O~uOq?%bQmP-V?PWGV-)ZADyoZ-Bj z;T(T^-uWiaLHO(sNEQ9H1mcbbMMU@?ic2UFK26B#Fm_oH;w6_CyvuKQ(o>b)3{=E^ z(6kY^L9eh`5E(%|3IPOBfC--}nX+!}?3DUKAPNX;((h{C7gDC2B3$7A9?9`LzIh0$ zfDisB!R^UDGIz{#_1LoO=XDBO>Lz#PsK5nnHRA_=fBUsVp*fzW-t~*GW8Amr z=;N|f`^~aKVhTch4^lyF-Wq!>T179@wBlftWKAysRyc?(;kV404|`Vqz;SU2UQ96{gre;O4=B1g zpdc?TEv-{;UN~#heKSNeKFFK4QZ8_qQKiA`oRP zz|HN-^iqgm&+|zQGcWj7+xCU@?KXYj8jw$Dp)^1q#nor38?^?9`JmTYt*)Lb>;Rj_VPIPPhW6ow9SN%1p^C9A7*9J>LyNWi75Zy3jpS%Iv7FRTC+B%lj$(9m&EvXE+(te_unrq zHCb(YYWLD~&!kloriNj*#;^|{Ty ziJ#mBqKWyZ8KBtcV&y#;jhK*vCfc(pzdnq0Ytg0y9}HlFuL1Te=;ozV>S;f$Wz4u6ig__mx^7IjckM$+1twwnpFvkF|O|(-oh~Nj&TY zh9gxESQ4(+VG#&d3T|&(s{uTSG`sPp&_nAmrP?wF&qoI$^?V+Wmic_KI|c~1|GnHv zy;uSoojsuM0U!8!GhT{1Ml4(bi2&D}9-FT4*&d67k6)zqJ491KE!=qePvM#v06GOv zmCUh;MlI0WHk zz;9f13`AR#R5?)b2dQ7lKqA}CPD8;|dNcrVH&j)BR4oxVJE0)oB$%jM^n>66n_ zU~#rm&$nRU2y-#l4=1421bvC^c@H8lFA0p&W3I5P#M|3%yLvOJf!EZBF_lDH0TH|B zG}2B|YHL7t*J^hR59C2eRpSIK6fQ06e_`tiJ)u+; z1fIWEhrYiy@X7u-(?%nUlJxX12`%cZ0Y&Hd{=Vf2@^aM~UK7x6h;vYThWZIQj+;Re zn`|A}bTQUE`<0Amrv<>W{Wo-Lp8J_!_1^;wohVgZ{UHCjqXY8 zU^ov63*M}(7%ZmdFMgM>E7qPl82BFFyhg^UM#UZc5C_?IUXb*?b(GGxEcoJHRoUwG z1MzZvD#on)tyDIJhnt%~AhGe^r^k!2|1IoxGae8MO8lN5z511d4y44z>w(C-2L!wn z;Gw+GyAE9*Ps40KTAs?APe4hbeO1={n4NzkX#LcjTiV-SN5A{1hZ<3!$lm)z zjv6;5ALe^P=O@21MwX9F{1&*zXu1Nc{ot9;JU+I6*e}fu7soN79aO7+7(QQKDD0xO@*3DD7q%r8 z$UGa-fE>=E8btJ^gi^wL%x8u{P;}XKsn`B3zbC%>_$#XllLwh)P<)6V`-QKAVP{di zJO|gFa7?9!&PV&R!cE4w%~1o5Y$bDPNVOVK6ZZl&1esHLmJ9rDRy_U*l~`hcMDujm z`3%V4?!abw3qQ85oXGJhy$StgC#piw6jM~M-Dpxi$O-OlUxh|0QR#SLW`u~w`p5F> z^k(u9UYCdt>^J5ZK_1vLK6K6PO@d-ET;W!(kpiyQVkD)RYks4!0N2>G8m1GyX zFM$2S5a6?_a~IEF&sMW}hFOty5*O?QW%&muPQ!M~LkX)SCKFZzNi0gKkr1^}7c6cy zLOHCWy-*J>9#jf4e|m9R*q)al@_irjdwA*q>gjcA=c9Sq)#=THyN{1p=u5RfBqLbq z=a{@sw$v1_nv_ZG zZDbLQ{aQNEiKt@vk$&q-4W6gBcIUCu_*Xw^zmlF&qrJACW!PjD--`{Z|7T`UPi7__ z&A#mZiEb6#BU^=!mJ55C^`}BSAL8o7Ot}Eg(aPEy4M_9o&Ihw~kDJe2U97VpB!3_J zwO}pzixhzm{EP_7jFf~OG7($lcQ#yP#&viJVwF)}D|izr8E1!qqrg{f%X@I?I%%ca z0m<^A-Ca1FFzhLf2-!PqS{DNKlCiHHyQ7&)=hU797BB#>A4zM?S&M$3)?k3g;&f63 zq1e!Wj_+Dmh@g3`QvUZ-{Q8dbTXXyUi>xM#trhRhY}PwJt#a^}xVPDt&C*ZJx=gl` zrg&;v&F{3Sx@Aw=T<}-%tQINSXI&`C+vQfg<_UabW3+kCCQTtAzcCRe7@jt8SmFQ=F$_q0&mf$7*fkU&dPR&_X29eA^in~ zvx^|l?o7b1qPCJ3C%>wNlZxTl!ANv~7kt}NKO&R~8*i0Vt|hEAWG9xn)B7Mm{@mK} z#Qx&Js?^@#3?4Kl1e`KKFsPf!&JMsGp4})p$s_mRTM(?&aN6yN*tbQptDNmml>&eQ ztsAG?FO*aGu~HFVRjW|0QWhc3e=vIBebU58%qmlc(73w1a}F9yVjK=E$b1ZfzfvuZ z!O+)DUeyrtuJV?uj$uKVTW8OzsvY+~auhS?|@Yco%>N*KNp`Ny%< z{F)*#+w8?lBoLYDL}7$YrFq%SJ=~lck&;kfRVC=`7_g~3d0UsbpxVnerQ zSQUrv9QikSGS~7(EiqBYqs14bFGL+Xk^Lk5LgiVKmbf@M-*3cY7o-a#&s*ooA)?$$ z2wu2~+5>@&1mz+0tr+(G_{Pfs7fdWcSWu3-1)W&f5aKEmMxlmtrVd>LRu7UpDM6~g zf-9gl|2W;=e9@eECCnH;hGp(qcIfxHou5B_Aj}y3W}80dRfeMdD+zdD-puAac~G-I z>iFNBxV;|T&+o7D)x+v*KYlG-vFvGIvlB#9rSdNgrL8=am9aDs)@Irts>Fef7e(!0YBz-1wv#|R)du8)qvxzmkbcf ze9l+W^qI%*cDgJX_vE!BH6UF=Tmk8;a7W>q0k3DEeMB#Wf}lt)EJ*_*l=mWLIz5`M zn+}4RA#Evcx4J%%-7p5HAK<}|_KvF@V@txHmcbRQ6RRJo*v!vuq8*d&&m=dQrNx9A zHlWyo4mOG~rmt`wlU_&m29B%UuwVX3WX8gVwjio0b8cdITc;(3dplB8v0t>+3x5=k1n) z4+;)oXYxKQf%$3S$5C`yX|ODQ6sBA;VVazS?#b~z6Fp8fmc?TudX=h)@onOjhMW)guS|xOU}givs8i22EDV|VNh^LZ-1)df>FtTv zV~#^E>$Nb4$JSHD%t4-acf<>T&(Ypen=7%t>&@?NYi`Qwn*zMT-;84DLf|M73EpK{ zBwinh)@w07aMHV=zOnUiA6AxBEOWTpTVCj>4i1UqE~@|5hhxkInOg-r=K!9Q?--WM z;HXyw=np~c0WVKCNRgq@O|7jyUE=pr=aKzyMftc)qvSZc7OvQWn93gl?k}ws(V+8S z!<(zCtLT9?@`FRr=Uq9^ZXBNwzzYY!b!?@mHj96*=6o%7W6V~F+TmFDmf`%VT4tom z$)w)14>dbq?id;jBl~Gq?;pbjI5I)6jh(ROz>^c4Emk&FzN&ROZ1Y={^RH)) zuA^Wg?LM42TFFYE2xqHAEYB!Ij)UmGX`+x8uFPiIlWHO_yD;FM0X75J7BMK;ZUo`4 z+}q9=&g^3G!5Hwu9cAxQ*%GAHOj%Us9Fjfo~y0jg9-CY<$DdeFa5*2={ zwsBUUmmEyQeONEhGK}NBt7)p;nfQ@b1_{1mEbKIAG?=znBGCBmNw~1JulV!^GVIvVO_c57C} zA#1knhBSezzBCQlX|F_e&9sUUZ(_<=<*ij9HfjzQ2)TXVcj|7t*U<{FY*?%+@1={z z`4Bt9cE_M}#vt!AA603Mo6$jkJM{Y1xO+)V1Z1@aU5qt8=PDa6UDiKR5gOzHbfMdk z!L=xH$g7BOa&ViQJq&vvfAPHSei?EF$aSbo7Rf znU=cvO;0Gq&{ce5x%<^yD6YP~K4m@W!MaldsG>vkjTbvL?m(iY5V;+ToGRa`q&$V{ z;bFhJm*T6J*9Gy^{#Y+pe%Z5~A3X{p*-US;b8@IrQYf7<^S)xz`kOZV?~lY`nGAE055}%~}T=vyQ>oveA<)LsSqFI_#Q_ zpnhh@cTBm};bx(DLT;dNz;rfeC?(UmQd1cqQ4QSro2OW4R-PjzQ@7?E$W#yrSPFuA zh)r<7Y}}f?7WFAgE9MDbw9=ig96X<`%!E5j5BZF-K~szGF!ZXlkY1?KKAjVmsx5Dp zHaS~_W;$v7aAW_w`(5OW*i(G!WXs|&AQgDP=A}l zKWK$`h+B8i-Fta^?WK94`<~G`6&n&)jqlBF$UtH`b4V&E4R2ng`Er}TNBY)Pz5xF9s!@{KjYCq!_g`s5hACMQ)@-X zXGjrYm{PivV<_#27+p$LN1Q{F~OVqB>RRjBFNTD4Zi^}nX#4e2s1ktXP>zB|La!kRrR zn7M*=@FN2b#RoYPhWDeFh?BJ-a%vxps0^4<%VlfJcV^Wi)F zM~mI81+4ksu16rjueY|$ezeYVg)U9FX4&ZxoVw`0z5oRxFn@HG%*8RzBgfyxEq{!( zv2N7U8VOtns8u7Zz`xOMQ%(0Q-AX$4Z4#%wO;0m0gS)>!(_5NnSiXM_|cN z-{fQceHsIbsC-;tYuFsVsB`rZbSq;Tz0*5A#Y{>`YsR6D2mlD%Sastkb9(B8zA;9j zEB?18Z4(S2CR8=tYyQ$kY&2;?LBVM$)E5y8(t+2wKVbB2+|IO(k&(E#j3x}70Wbb( zcm4qZQkR%D$Ajz0(7PvxaL0<$Lo?hh=rYg__wZRL9v zB2Wx{ij@vafi8!tp`l^8DQlESdkF?ES#2Y!1>Xcx{_H2ASKS)e|D47?o}O0!L|qv3 zmsip%Jq9*e9?q9Qvran1>r&2!M=`wpIB{`%276$*?CaG3wkv4R_(5M*t*X$n{ErIG z7!~dDS5oz$J?pg#0b^3MkFFtB;jkBAaK-;_I~5q~0Gd0mS{0kL-k%OxA(8Z$k6D>p z!W@q3VRfu?wi+oFP)BnK#uHk{rm@1tyIsIG_0JLt@bX;`fZ-Pq2phX_q3FviEC0rk zxRVfnNfY;WTD-SsB-`1kkt-r3>6Nb(?NgDt-wKxyM*8vLn_N|u@2!EQu|`YOp!Ljh zGd;!u|D#(aWybLHQozHve{Nvux7Fud0e3^uwr=k;z!Ielx#oY}&>!wx01c)y&6H4} ziz-u1j@GOG89X}prez_WGmByl`42@UOOA4!lZkk>l29H7tp@*#cc3v2^7nC9N_@@7 z*u5e4&;#sF^1#R_%3mj1!g#{Ci>E_0xd+{nBdyL@c;XxeBygD~VJ^pf#a$WFBSl81?bHnX}KaKhmg+WC|ayzbVmQ zAv6MH7hsc2%P`?3h=j-)gUaN>{L)5rRaq0Ed^2-~Zv!KYTYB6I3mVcRzJ5wLby3W{ zx)h`SLkj21T#Rm8Q*PIc61*Vxj1jKD*Dl8b_vYKa8u0>z%ZJWy0EAulktfPRN9t#8 zAUh%WoisoG+7Zw*)D*-fY<%>j zYqarj+W8F_)*@y6w0?g2@_dSR7?Gf(iTuQI%aA}EqU3!cxxbGhI&AXkIVYK{&Y_PV zu`G#D|J8Syk!@!YfSV6wZ$*ZXVU=xp+kF1{pi}Mj2MLb#`iTDh!=3Tw1^r6^fV(~8 zeya2aN~Uk`HjEE6KZ;DJo%{B&&%k}+_Siqx@m3>`Kkl8qY)U;Bnx~i=88@+eFh3Kc zNp8kBSd#^#S@b*Yj{Z`s!wdS>UqI3n$EJ=KHXe`kE%_u2jEk743?t>1o( zZ%Amca`^$*9?`A^)y#=DxAMDAcAQEKMfnS?OMgc(4)WxrrX(Jkb21G!DVaL~bJ_ZQ zua~}fnk8Vc3eblBS9$K|UXItEs{n&%V{X86vwmz@=tv*6;PJw^>M}4Rzy;a{!yX$E z+l;~x%s65a`rx`QF$m0x-7fpwW1l#|Xs#S&iC$$_^cm7z;H3_kKlBAWDpc^C z0|P1JkLn*pev=1m2dSu#viH~q-of3ng9$1~%o7gM7%O7aljkXug!Oc z<}HZhwvJE$R1leZ)b7~-ge?oFy*ScmcEbmt=m27?2YBq~$6YBJOzxgdfIg4{jBdfYSUl?NJgA;pC4V~$c6hfoirprkt00Dznn|it>SEAjC-;VK`hZ(^>9u+ zmI*=*L*z|LILP*|0oROE`)VU@)Yto?b2R5oXAw z;S9(TSbp|@fJj*l%pP3tO1*d)KQ#9}Jv|}B>bbq9&+Z0aGWv+)wPFA8C0cU5jaQ$I z5@ldRyA?>T&N0bsD-qlm$3Z4am|Iz1#jxnd;*idv|*IQ8FrNM>k#_ym33IzVJp3e-F@UiB;`=B zgjzkzf*8~kK#mBvuwIiWW@pwUY^tf(`uCMa&@iKF`O%0FSb*Iiz=+j4c0P=_b}f&FINCp6NrLaN{)0E%q-x zpt6SP%qq}Na)btGoAo#wv~zCJJ3bfQttL0{FTKTCta97Vg%Q{Fcp|i=d)I8P*GV97Ofs*qD9iN1GY9F+;RNm`MV#GOh5#zfu4zdV^lp!n2PjAjJ2x9cev> zMBt;zi&Ot;%pcn@gFY)`vq`tN^y8$bYi!zOzP$0d8#h7FZeaQ2vd9J4g;VUpKf_ig zP~G5!d|S9!Rs(o=p{#TjLK7@4-v%UoIOzWDZ^sjjlu?#gZRW>BJ#-pEmP~6&v84WJF7d{4r18PDZDht+*wV znTvbMTv%ukI%j_?!v^lFHg0@Yq$=u#edvBSk8lqiYlpOxxi?cal}Oo+-$Yt9b@XXf zVc@E)UY|+dE?7d|_!Z}vyNI3Oy4D(rfOAnWI{`3f32>-iK8Is>23tol1x1Wc#SZTc zN?_*A;T>WJ5a!3d`^)AT?t+|5M!bR!Pa6=A85Ls-M~Z|E$;d&=o#jC$f`g7Nbl$XY zIy<9`&pIFVNhvJ+YSDU5$M0sATsbwKIam?W15qeID(%1f^Mv|mwr8;|14}KDMs4G5 zFfeg2K~oM_(y}rim))-4taz)c5O#z-SM{!HVt8xjDeeFEfcqqEu8uKP*Om$)gxjty z?ChMqqNaipa4~1FjPsx}KnEbIgwEGC)5QPk2K_S(*Yxr-|D zbo4Ki`CPtbq<^|y;I%#!0vDeSw#oQ64;5a}jF7-YQJrv)g`6Spw*_v)AUTo-(Wl;= zD79i!)vKdqR}Pyw4>Xn}wKs{Wyw-eJ zaQSlu5yI*p6+a^RK%loi*ni+v+?Dst&C0_3Lo&PJfeJe9p)&LyPgkQjzcecRwkNI) z5sMp2qg3NdPVVb!uGMQFjGsN9DRa5W0x!^QX)_GTzpLPD*E$%qix_;je{B2QuKu{5 zusU(U8{1u*T*QvyxEcTj@!FWVo0X6^6~h8pJX0k|KnO98qcYzN{wU z4ah?HGRT)RXHKAn;K|^RI1OM)aOV+r>q3;aePJ92;yd+>Vd9*D$DJM@)z)Nc@VN9t3kFVP>P|0vGzwVuP< zI2SKYu7iD6KB00O5na4`Y+UTd{9Duz-(zDbXGiD9YG^GXoMz}P^t5`4&r@QiycncG& z=Wi)a{WD#`d+8c~!rq!kXb33<^#HHCB!#5m6 zk!ahh2=CvnpI0eL=ea&5U3K6Q9*+cVfD*FwVVeoVNZ}p*mXeSp9CKCk=FU}YPcstK zp!nvUE7S3%_TDTN_Gmgj3uqoj*W7IoY(8RIHrqldg;p=~jj&T2o(~T3$Jok9;XJ&5 zySJ6|wy3rGSAQPXrqSE_*gMKXsS$I$&4^t41O_TKXlc2ZLN*9->6y*U(B5yzMDv`g z5Pvbf@G0P#{j0K9bLb@-7I<*C_jSUxV1LVJy)o5d)_E-@?EEG*XI63UlPQGrGx;aa zn5|A1uQCsp2DY}XRcmD0H(_M6ScaU&$26nc*QO4mj4{Rt^`CZ$rbI$H+G3eG8ZSqr zi_Mm45D9vNOQu!yVnrw^{w&{1OBRKBYr~IEQ{VvMpNPl+?j7!}chAH8cB9kJq`Z3Z0H(Nd)qVpx12$Kg&3zcP;`f*GcRM-@J05)cm-<`0dkM^5!Bu$GgbX zkWp+!f>-39H3X8W*4tVbO3H%gz#YTCI$-UYz9+FNWaZXxB(D|3`)8Mb*tP_PKHV(h zZzX;(Pd^VdDM6T*-9yKB#F-%$ORq$<^S%KOnbO5ac<#FuT}y6YhRfBnChvVz2X#~Q z(z@8>u0ldj8=o+n`7l$=qorUMs-w@OGhZNYnCUhp+bksmrnljk5)riYyiC)NLdmTv zj2je*sOl~HryyNVQUsiFti#8$sszq0O*{R$3Duz*OghaN9=x|GQMCM4YHo4e?V|Fzt}_u6WiD57y`zPUg*$b?%Vf9a#)pa{kuFSJdcsJUBR8(2rn4LT26=y16g9%Ir7G69`Wa_FOIfaC+>q zFTbd)1bH)~*w3->q}@SY0Gsf-6tXRFcDjZ|m9C{zWKPur{{kMJ9;)7DHMz z)YO2tMEKrtyOy7HwR10e!WyUwQ^7a7GbW!K_(@b!iQ~O zw5twGTc*{W4!W}ItAjH?zum`Kp_3*?{%Heg{f%pG#V{cM;3r^X z*(Vf^6q2NK;Qg9uxlHwZ#J=V1zV@(w<>VzHh%5_8D1W=Vr2y@Vqy|SfQhDsq36kn}H{{NG336p*-X3armj) z+V5z9@!rw#39_(?I>JpqJdj5Sgqd@Aq!It@FZD)O$C5UBVk4Q$n4*HhQe_f3Y!dxL=aWEY zfF}JHILJkz$3bBAqM=wKLFw2RQ=LV01F?Ds(Znk4SMSR$wECIws8fnlqW?p=Y-8YI z5bP``E^*oY^2_F0tWw_qxg2oJa)6^@5ct)Y(42i;5NF)vjtiOw*c!q?U}338zm_ty zVA9QU(Po1LYx+*@zlUCB3Btq{{3G(Yqk6VC#k(fE({N+CVx#|p!DoET=IqgA5*oeb zHTHUSfO-EC){`D0+Pk{~d7H4Ra(S8uA?8cQ!AlHC`3lK#(MVSTI6N;1igvfvM-Ebo zPT3m=pa<|$(g#jHK>Ej$+)^-y5AX3c%u#eu!U?CBddTE{eo05_zxv~LebL;{P3qKw z=t9jY5>MU6<1bc4u_PcB04SPc5Vfh-d9>^dvt7&8X)A0E-2!Pn-szG1V_7fzW6$O; z_M>}Oy8I!nb=YtTZt8U$5hcER18G|qlP4VbRX{E;Y!td{2qf{al$c_Uc=4k=uO?v2 zhhB9pDwJge+Z@ycLjK%S>hSa!Gii7T@hq=_r}NcQ3TlYuVP_bQ9dPQtzrTNhE&-=Y zAYu4&$OW|$8niX{3z`{BPMs&?^l}NXg9NR$&+U0ZEhWdk@?2TzBEC`eq3^?N4+5b#*RnQK!LeVhUy zLqJ5eln1f=n;MFlfy-$e2d6z;DL1`TfN%rhFl5@%G&rGBOU(5j`M^1rnG=wE_)F*Z%A>ZZf(kkQS zq{Jd1#{x`;|A1%;0Gl$f6rm%(efc|Ut;3d8LQsi?!j)s=% zHczMA)U7VmGdRB4Vxle`GOtDw8-pOLKeLt|0q;f5eL+N2iUN(=8&A?-_z`{45XeCP zR(j;khm)5qWA@Z4&hCN+wkJGbdk$-guEMkxu1Gl|ra?JWl9@Elg2ekI`#s)|y_J^J z6yW8AubNlCK(HiAdP1Qw(8S`CSA~DJj7Ax*SoMIQ-NQ6!_j~BD7PoxI_>P9eQ>AQW zy5>%je=Q|^Vkx8A`rc&c}zHnw%to-(PsR;oT&ASLlM9;TBp0#riW0%C5t+<5E z^^pl=^hMvWbw6h^!9R;$fSfe*M(kW&t$GY!KwGEA`|K?*b`0?>C-7OkWR?L-d;##v z<5>-ZZw;Q#z9R*IdD+2B_rH33ApATd=<-D zqlTzplM#vkx`aWtWMgUSRRs-b7l0it0Fl+w>5`WuGC&A>8uY(qL#t*6yWDhAJ&nB- zdCs;z1B>_wh!`M=1X)cCT}}1(G=Dp^`S^gbdqA7`>LW2O^;C6r7vYW)tFf~9IMd&Q zl!e052A6ZJ(rZDac&wE^P$ff+8Mh7&M)Wq2)dh6uJ)br2b|+16b!4b9;YH~aYm~bd z$@JG^6<49JXy#0<8-ME@B%YDsNQIXgD3V5?n|mM*T{Ad1X!P+PP)}N*dOAgGVg=kE z0HKrn5^U{Mx55;R!K}=4(F}KVNI;cjTo*^qJ`|kpa5$P}6jmX?EkNuIu9}{ro~Up! z62umXCK2Jf{;P@RAsH6^aRdpGtprI^Y%P===GSBLp{_Xqk*tLmh#A%MP47!itL6FWKIn{A2Fd@N z&z~y^489I*-yrBz0LT8hu^HTj5&5(%N9bqg4XuL^a9vfPRg;{nOb0jK3JhH!%<^=X zFZ6p96woY1(G_-ES9{RJY%gj{YpVmm1klsdqp;PmCHZArG`pG=!!+Z_Xhx0Rlst*0`hNHOCBo} zLqDNTfSM&CfCsPBhj(5~V#)4}ug3lNx-ltzaDZJEKe=Wi%WX>!$oT>P*l9<)bW&g6 z8Kfw$SNYxa!kVE5&fpvvp}D`*_vZTkG2X>ECV|!W>7fCTXlelflqW0NTMh(=8|4Iey6!7#$d19$mn%<4 zE7+dh*0rP^PXM1SKn~NS?H*|~>gvzuoVa(>kjam{()g&5i$bL7O@>tf)Y6T}i80E@ z-+|DxEo9Oo;PNyoP_J0F#i^{WzaNv-vF5QH6SFrtsrHg!2b@n-DBr`;(UJ0(mX;QK z0H4DsL(@1v9$K6al8+TEq><%gU-5BAT&OSTy8x;?ceDU;@BZQT9AO=f3caUs9kU_m zw(MGa@qYgTkgL!s%)CQUzlZ;MV=tk4fRl!{&l`<&ya9X~2sxkWRRkzMK`c&5g0hjm z7$LvUU~Wg`-0KQ3IDKLX`<0#MJj9i{zmMj$q$X^pas1FhjGcGB5A0>oKp8%c_N8X; zn^{rI04uN!)b+mevJJ`T9BDC9PEJKq4MHSnerG$KVgn2LWUA8D70Cujceg=rg1GfNx6vUQfjjvJW(SpzZHX)h~Y>6!j%jLWCu_Ya|L3FYC z3gp&i(V^`O`urLz-CVb z=e)gdra_WM_2uBn+|0B$G6=$q*Cp43AMHd)>NU@AePyQ|M-7qViG%>x2q^OaSqp4* zry=Yv0pq~TgQIX+S8%PL{6+7qyR-9|CM9%P$it4s_oxOj!} z=(AsmVVM+(>N1lY%Dsdbz51K2z1{#vk{HTmfb&6Ka$InScHo&g+Y9HlbMd@nf_F1D z@c?AbSU9+mZ(HEJ2Il3iNF9jP{!-7&LHhv?J`Pp4{4H!B7-%F|gh&?u>Mb5ywuhZ! z|1Hm&AFon7I4}#LNZmbU|Mdy{P>k3MGC0!sT$36mF3hL$DvM&AV@1hbs9aPk=GU2K zkK8l_`4g0iQPep1>!I(e-cH&VS8{4UkydjDbKf|Ud}p&}0(fXwTsN3s}~4i5Q@thonNS3&FccR-X-3i!Z+CewpX0sqSzFg2K8B)pF%BcAerW! zSO$yHQ-hB@X5-qgrW3UBRG8COv{F?w_SEX#oX^?8apU)|NCloLu>bJV2n6Mrxhe=$ z&*RQ3lM((rGD5;9-^Q#r%EmD!Rk`U;{%^m&R1&0}l2!o1zAzy-26nPaKSY2>^CRMY zczz}UzGKu$M?X4(CKk%O3QK%kGNtC&$|URWL>Yive)^ytlLm{@)6}=|pJq}2M+obW zT@D&_)=3yAsO5}c>OkxP{d@p8D1s?U*^BrJ^xW^ZxC1I_`1Tg0P%v5=bE?5cLl}WY zWADRCVXo9)*!kr1b8&FT9WDhF(N$rlo-PJ@dbI#0^rc6JaEP#Q*a)UeK&xvLDwy5c z5bnvc(eCMq+^ors6w~nWK;pS|;D$q_v*?&A(NyEMa|OOH`~e70hOLsBt|qUzVBlbI z=o=&D*dGb~Q!ZUccc|PQ6AZK^_2hYy+(wlsnmv;$Mv9>y=uG*E)M1$1Jq)JHrgeX@ zeC@FO0oQN^c)A1I@Sq$MdkI(NX)Y-}Z+?Qt92hg673Jy)-Kc?8S>)NNtz9NB!lYfT z!H;I8seo-vXeoaYz02B(jcJ{?93-tu$|@@TL%@{yyMZ}@_V~QbkzqF-uyU3RL5!q| z)jX);olE3Trabjwj#8J^(l9*PVrfRA3h0O9O&3{fXxvGp6rvvQ2kZvI(@OP6r$gMTzVVJ&%IX!r(%d1bSL~6mnf%In^<*NaT22lqG#=yQm2zre zws$2&rqc2|*lp<4y%wYJGIhQVp)|A{n_meQZVTKZD{nszX`6YltkJzL?y*KbLu6Qe z(;rYOK4;5|gaD*lDR%p~3`wTLmMkdqp3-6fDNAftlvE}&BxKq;lI#}@E8K~C55RcI zChx=Gu3U{i+G~b?P+l{y&_raarjF zC=0l~TTbsVa_)k6av=iW#^6(T%oc7FU$Sj)3Y$oNT2TGx%KM!)(PjU?MrlUh3Sgr! z*5>5pB_QR0{YwO&a?2&H7mZsMhq`hb@2srGOW*g@o!G*!}OtW+a9A>u?J zX;#F$UW};NTD>iwf3~47zZjs{xQ4Co04MQc-LDRBT;25EoAlwBs90cI^kAr8x!zQF z7Qa6J6E6TG^$pL*f0}C(z0K=hf8OITpwu-&I_&h9 z>s4tkKzQEp%Fx6X7SKu2Gbvymw}b%56g~+N#LOTZxG3i7z;1MTUqbLRw~J>f9GW_xS2<33<@E zv?7e5_jH9_BWi=0JKB-dgRjTne z6q}apNz4Zhf}GAxa)&ERloPXlIvLn^LOLfbYh2x{s~i21d5g1OA+Z6>&o=Lp!gc`P zYtZUf>mBHz?LGh+)4$f|`L+*xWUt^xL|?KE?2~;YYVZolR~t{g`9-BIxzjU$89kX2 ze$QhgTD&dbJ3fvZuOGXDG}Kc_O)7FZX4Z@cYW8IRxsmGPVPbl-jNw}nDHSX5P@+Gy z><4(+&j1_)Z8p*ChyLApvdc+N*)Rumo#an0Uo3OFm!mxC{QVLKKvQ@&7V_-E9u(uB zW!yo<(=aW|9r*W)vn;JY5{vn8xT~=ScpK1tWobu{v5(`xoVN)uT&=zMe4ndJD+dB zgNf_8Dl`Wc(}*}ypdZQ2&~Kpc_)-xtbyNSI(c@+wMEzjl82?Emb{!*d;7jlw?9Bd3 zf1GlVwydNVUPwupT0Jnzp7TZ9&m^;NuIf(m+;+NbvJ)QOAZJyYrr^qu7i2Krbn@>X zb4g9Sy>Y5}CL>O8vPH`|^4m;jH9$n%sJ%RuK_mqmbkvG=ZooB4-TnMT7M19amS6XC zSse^*T+QVOQ?saz3}gF9F&1}hAL=QgD0_IyC2`hswN+y>jT_f!zCX1rQyUGVOb<#m z_7riD)8KD^28)*`F?z4aND|DJAsrNVihI!jZxJZ;r7P#>=QoxcG1?g^JC2;s;w{ia zw(dYdxWMti8H2p|;p#~lK^4O>StDC|`24zRji}c%KMQYAXS`ZjYqo5*njMub9NREX z=9?5F-0rzNRyO?<)g_0v1voIWNt^#GTwCnXcGUbbQZt;3ljQa@hxl(ZTH|q21j@Vx z=&SA<$^VEus|38-uga$Y}T-Nzbg^KQR?=f z-?dTmKKIOq=t*-fVt%f1;3SXxKO6T!Pi7SZ0I_TL_vi|OCc*<+0Oc-Ikx84Cxp9mQ zeG4&NC`$|xKiwu|+?2%~f27!f4B@x+bPDnDpq4F`1m~6g%=w0D3jLchv&0Z$l20|U zdn4MXtRjdHCbrio-kw+SJSn8$U@chP2DTFjqb6{oF{7B*P==7)ONY>5U|o zNcT)^$*XXYpub<{$be^It1-wHRKYm+g&nnxEjKK|#nP^L3nw-VpX8`GyM9JpuR?!! zI7wcYYv(Q&4LYub=SWzK8`q6MPEA&TCL9wWkBbh!rGy!WIgtiN7X`u zpCSeAzG?u2F!|tTC(5tUG>#4a$;p@e-0TE+ICW|@p^<55(m9Q# z?_`WpNfR7aS|}{fN{@9%51Me9jAsP$f@o;U_6p_12^ZIDQN{RLDc|rtSA^ZYVCTd9 z8+3JoMyl}ul4NGqO3PQD09^~iq~oZf0Ys#Hyu!gm!m!9cemzv-sA1}ReT4EzKL)K> zr5B$lP2xjLy$g(%m4p^OI=n>wcQ=U95+lZqmkpZlLS(_?DTk4Yf2vco{>VOIj&|?( z0iZm9o1J1{Q`OA3A5I2b@i{Ouf-D=0w?`kM9s8e_s2M4Dae>@Y=rXwm6^z|jnb^~OYyoM2DnC5mdLrgF{Vi z;HI=?BbH{y`LRSRiN>Rt+V7tU!DJcf@;HHcILq|-sA2KMRpO33pM>L;Lxx#!vpV0> zzMrm_YF~XtT>b&PU*h>bEN))+!|!zf10eiDkHT+k|8aNC@>>U?+qEh>v|qb8`IWG3 zo70W<;bhEakA-qsC#;rR-rQLIT~&|_z+)$c3SZymKFl)`7Pt7Ri@4(jPHx8eX|_8O zjP3>OHV=@nS>a4DuyA&MZ}w>Jf9JMXoiW4(=8?ZpxsHr#TAERRWu+>3n+CCf58zg-2NZ+Ksh0pGpvh+FN7?v z6(BPKiD8GJQ^`wa6Qrwnjpd>Tf!lMN@B#gq$~qcDRL~kU4&SqxX~X0 z;?n?v1>lu9DuFGWgzIPIbCeOO6q5$R5SGnpx52)EB1B2L$m%#Yn4X{u(Aco(Co7U*gM|EKccm>65{RXXi(xA zqf%|gik}%<6C5b;yqT3E&KfNizbym?bQGlrK*9wC41`{)^q}V2H)OQ&Xf!+yu1gts z{Ie2I)tyv(ElmWdXg{8be!Mo$6{L#egI>M4P>*vn*^O})-RKq+@ z9nmca*9aET2s}7Ev@L3C!ZRItZPsQ0 zLCX}5`;1gok%2>}H0ETI&-Lp86Ui}5H21o3%wSMnsQvqMcXPL6oNU9)Rss3)x!~@z z5s71Kd%df{!v_>Dininc-$o1XFa!GAGZ%hZ$CJGZgkRp5ZBvIiQ?9Y>dD@x6NTBjj zAh4L;7WprqSoq=QBX@iPfgv(2;wx;CKV^eTbc2}`PbSjBGUFY9MD{XU;{MT(df2i4 zCrbm1ZYg)_g-)OzK2F_5$@pqTM&~`ihefzCiKB92$$ce&_wO}74)2a}CI9KErl#i0 zzzGmZYWBtB^-37(f9Z2cV9=9%qznH>Z)_}{hXRb)7u?X+d=W1syV)C(1aMhM`oJ=5)#nec*&H%pmse`8hIS)J#zuV zHGqp?-(`QAeZDg|s`vO0&mxNo#Hio#TJ=1Mut(jw{nt)KNjV|m2>{@@t$@P6UC}?|M8_235Lbwj=x;kt{B>8-| z${y>zu&J{pVs z=qR)8C>Q{%R7g$s54Ngjkp1fkPT2~IW#d5?KB3}CK9yGg&qw;o>E@*l*Xi%&H4n@* z0RZluE9|>>$#J`Gl_D=!sIUKG5dupul#K+*H(<2wfQYB?vXB=NHoWVCi^6|l(7qiW zd+1I6p8U98=v9Mp=CGFt4?i?nviYxqEuUFnIG} zwOv75BVNq}r!SO@Q8E=~F<*wZPtfa~&gbV|Bs^p$0{-0>3_PG} zY|=`ymyvd3Ldr=^3D)+9qA9CJrKw9prM|g0@_95Z!5N|3QaV^gu~aiL9jJkyXihb3 zbCxU%FxGzZMYSNJn^Tj=VS7xN3NL@mw_1&kAtUQ%s7+p71j#LD*Z%+@T@w5m2>z_m zZl?HzGG@|gT!wf0(U52bx6^r|sE}X!t7(8$y2s;%m{g9SS*)wcAXD2&3Aw%J=mFhC zzS&-E0iscjeDuDn6f|#1pM}iT6P-_Z)KzQsXZ!HB&K=gUn5YfkN|y+sV&gFvHBLgx zE-)p}_x|Yvf7wX=I~d9kIF1fIxbYR6V>WJk*J0=PRTAYmXUhUj7pPGMjb__;d3k}| z)j5CCb;zDJvhxq|INEA?jQTK1;JxZgh^#juNRfjf3{p2$`Os$&)2^&N6n50jcJ3{( z`0TgDg1Cte$cJN|1wW{1!g_Tkot(h|xB(8gh;tv9>U$w*Vv8bT^wm#@~p zXUd}QLq(kR_3;4!F!R}MU3L}1d6&Ra28d{#NvFW*8^ClScD3fk29#vBffW#fUN}WT zdqNfLc&Uu>ze$KGUCtXP;qnMULg5FXuO7w-6%oL|V?JM?h4(|rCZPJ|Lhk#=9C%_< z4=-it5YJEU6|~B1CAf}S@E8W)u^R!yfi(wlU#D3DJrnoL@z5=9$%CylB(ASMfcZZ9 zL$sAa2DpT=e^6LS59}IS6fo7X9m#g7SD(paDgso;{#QIfvm(se8Ts^EhVC$Y2U%k- zFQcVCT=2t#?l?a?NNbY;N7UU{#gzKV;j5`xGi9aZ!N^TnT1UP0E2=Afo7yU@JUO}G zGiGRd!Ix&)IGh0IE$t;>Xb-ijGayNSj7E;^#Eb0^eJSquP}2?rwI7PHNMKcALuCO3 zemQ@)ioMvog~{F6TaKFtY^se**K^9b_KvYiJjcDa6I2aMP05IcX1AO)5c@Es>RT{i@h2ny1bjH5^hStTG+`tFSouujj*u z{Perj+@P$GS#kwV6tBsP8LU&X19>X_0^QMeqwPiV2_`X3^g2fm#(cp3wn9Imr70(6mygz!W z@sc4NwFz&E{{2G;od~c!^<4DinE^4h7j>wGZ~m?7mmg^>MhM^j5Zetc(etz)bqpUW zPO+id_Q5(iQV$~U3$s}_;<6_tJjGH(;j|Bp%;s+=+Bu|$u>IIur1&894qt63NugJ9 z`4{P%N8ug|qkq8UriWbQ{Pf)3%w4>sDRybK?{vR}c@SA^J%^`KcN^!^8Go;0TDz|@ zZx-*i2+(a1xY7pb@FLs#R!5Rpp6LD_jQ9I*RAA8pcv&^SDG}6*Nn>96hEHE6kZeyz z@!NLMty{;X|9~ehdS;=CQh4{p0b5?#qoq_6gmA`7gA&Y*P^&cLqy{L0xh$5{i*MZqa{GH{us*}k{P^_o-~D&D?qp`6X{e1T7K zelfGEy}3k1MHMC#gEwBenX4bWuwi%}xc)L&s$x|O?p27P1-Zp+7VvET^kIB$_R{#< zCzPl)EFwlGtNKzL>HA)d@SAFDsxUI9#8+0PjPOnc+J2|6&y?o5sI7I^wPhut+4SML z<8xz}NwrrR+~d`{iy=3H7rEcRH}TGu^|pi|NIuS`@|nfqyoo=5GI7OV7U1(y`e{fm zWuNNm9v2l44zN`;OeU2MQe!%&tyZRDB=*rFwzp98p`*+G$}kT~vmCDK@Bc%DjXq_q zq^?sY$v)qf(XXX!C;vo2Q}N&<9M1yn=Zl?$vLNpEb3yhG=;`TSDsrl;eb3caQYs^t zI>!tt+R2s@SvUt+V@WD5fj=ghzK$-|A>2p(4|%JmIrSgM4(h15#%lu!xK4?+Av-8lW6U3d=W(ay zV1`2}m&@!pib$M?JxdlNgVRlWZuO@(DOuk*U^)8>|8y#L6*m8s_SDiV?dWTkA`1RU zIEjmuFC|3~dapP|XDwT7k2#y#C471O`EuiOOjAac$|jzvlO6!>@%vCS=fxtZ(y^5V z$*cdZkYOLNp18@15p#{XTewLNKibvrm139|CO=Q*W}B&@miy}3XRF>KOjNxqg{e)j z*C?X*t__?(IVRB0GMNJ2AJ2)*&(hw(Hc+hAd-ta_5W^&(ddBYv7s(@IkOS|OI3(C4 zf>~IpJ;yEyv0l)1%2IVp?t&6SvY|6OtQjqXqH{0Y*{Muh{d#u)V{L#93m;8l$S9_* zG)v^vuih61DZFY`F+O)TCrR7zr)jAi{4T`1>7b$K8e43LJ#sneudE5YR)Po2hg%~U z`DbU3GnKR8rm<50?!FJ5zx<|hj}lv69brs@031N6s*l2?CsHQ5VJQaxYP+*nX*OMU zsd*iQ7$m5~^_MRX6AIi|(BiV+aKWo%8=&QyX(Sk@P!K2nE*4XXO)8?WGF#wnn#ei8 z6#}X(+scqvd_rY`D1zQ5mA#}Fl|9*L!5V+8ub#kozwWdFE}yQ_Wh3*M3nVYM z=i@CwxhotNrT^9&c*4&TP$%X&U+!U&tjAMj8jPHenpX$q5Xo04w|}BsOA3jdCIAgn z3I3M%0aeY+n}B{+roaE(UUho~`_sB!oI8i< zk)pdLQtIDzB1W6$Ww|xTlUJCzYybOI(*e1V+4uIe>-|O*4Co>uUG3C)9z>n7bdeXM zAk75l>5EWROk&8eN=dskTW-3w-+o$nY{a*!F@O0fXL+9NkK%p`T)JC3tV=4iBp*7% z-%}!#8DT(+`FnL1Eu*cE3ZHOqYk_&;lO;Gu*z?@I8)lJq@i$X+|77WwHV}Ey8yG9+ zXyh{hYeLJy5mjO`8V?5`f#kcx8*MJN*|hrOK)?S_V5h$a|Jd6%%`(A~nw0^zYLX^Z z6o#H<;>DiLCF8fhVvMJu(W&T{U&xM!ysr44nh9tU3q0_UMyB$=(Mw~LA0tVciDV(> z83?+C)ou|sSn#T&RH$|l^f11ORCcFDg2Ly~d&f$q)6LR1Ns`UEBi?g?Vu5n|dZpH< z+L;xykZGT#G9jH$c|C_=m3BuaGvf&HvH9@#%1~GmcTY(x%%e|aaE=ClgihLpWDy~JpjtQ8F}>z{NinCE6f&NrFOm>7w=gQs36&MkZK>RtNs}K9F&V?D8yq&N>go=Y8akDb z)nLB#-<5%a2XbyExRF!v7(QAUyB4d<8dA$Ks8>`Ip*_vsQ<+B_FdUDzOm5t+L5y@_hSACy)4T*Zs z)*4*%tsuyu(o5dj<9M%A3_M@OB|9)Ytm31XwpuZb*#udTq2BuLee z0Kt?LdJJlepRr4dypH1y+rQp3TF0(o$S@UZdsRpNI$Ao%52w#<0sAhTz-RHXhx2hH?x}}*&`*zDy zw{oi!rU=<6U~q3k_2f6|((%{95}a{;KeR<(Yw9M^Wmm1*+jX5#k9JJzaH=R=8K-W3 z7ojo`L?kzkz9Ey3A5Vu`Rr=E9b!t&alSVj7t`?9Yh~!Vll%@nqTP?bwKS(v^};e99oX8 zyu8g*6>X$)%z^w}m7_7voT-+|%NX~rcp}{sV$=^GTRlZDBvpS=L4r)vf|IOC(hJU74jh$u-JLG%>xT#Z#`*3{=EQyC&` zEc*xe75&R~qC7}Y5|eccxgs-q%F_OH^{yEpNmF~&l5%KdyzK_X7Jp_sinqB+ZTZSw(-xCeg01KpmWcBNgto9r z`b5!<^w12=ZM8g&u@>&>q}A)ruGq6}(Hu{n{u-I`T09ToTk3?JgR3X( zG`AS!i6QLNoh1YE&y^t>h{pH%`m4rKsyieYo4|R^po=n!Ak?)P&;iHlyW_T;ttQ_S zD@d6wmaTV*6_LJ&RlqkO0mw@X7B!_JMElxSrTZO zmO(5hq|5=!0Le4zT9<_gElBvrA+tQM3Z41O_ zMVe)BbI&`W{VfJP6D{g-cjnG$2N9o|Qo>diu8ERrY47t+B=QCpE`nJ`$FG3bKYeyt z;PB*IlJDV6h}xdNmUV3|b<-xo+kW9|r3_sbSl{*w$$ zOZ^uCB!m7jAf9{sup48=BHZ>|2+f&i>>x@r}K9PcQxszqlEQjhQ(o#|wBhVW5jL zX7!tz<|RL-i%f}klx9+uuxy_RqF}cw-(W>I4#9GID*SdQs zE%H=$Br*p{+awGpIfnf}14@(y%=rcSlD!J{y`%_42oY@x-LtL)zV7ZHF{uatTf9C# z)vVcPp46yH`&}Jbu0KMS@>y0+SqDCgmH_fM03!|01`DYUN)U$T-ZyAySJj$1@(fUM zkusrc)!Ty_54X5FN9Gi{^Vl(}0g>s_)->!#gek1q6%({f$10%Tog#wTtLQ3W?A4ry z1fLb^@2D)nBjI{i;C%||u1za7i~6I*g1V~YVrNSr33}<|t0F$BBJ>o^cTJxOAbX_$ zshiJ>7wtge+#ny87?XvnA!O~{08>A?Z3SN0mwli3?W314av)>#jl!?DqKpa80*(H| zgNj3d$(JjBit$Sq~Yk($=q$0BE4bgZwXp;p}M zdg2cB{CQgjt|ro+aimM=Tn8%I^sqDi8KqyZ=b8}4b3A4Qd>r^_1tfIA4;wjD89V1| ztql!cYmZB7Cti<-rzUjN|MgFRTC8+nV}GdZ8k)aZ$4v}xQj!D!ug3};#61LA$s1u* zT_!TP1@at7Fw!}Hh2Pw;kaEJ(9ZLF{2fbYUGm83@N$CZ-re=NFo>-eLrj|4Xb}BTj zwE<^N!k6nL?waHS&2K*OpTzd(MiZO_9%SV}Y!(=pJQjQC?1x3AEne)ckh(Mbqxd?m z!&l^?{A&4NXt0fAq@dOJb^>S|;6#T!2^R`k#Zp3CITxin{m}B6p70>HRgr4kW88zc zUZNJcOxlbT2QNNw_<9@r(9U^Kb5Dba0UMcyMM||-F#gV`%!1M(jA-ny?tRQ^ZnU_Z zdDBccy(`ROA>RN~qc+R{3v{r?rICZmEtglacI+!c75&+PdXI#S*lyQSnyLcii^EhQ zjZQjYZn90gU^`=8ewWDlb_Cn6hBv`v;HtKe3L8E_oH7!x6|IXu~-{$}lqg+0LT(tPgRR;>f|#|DJj)?iRQE z&z_5Pk;UYifdPS+57-q$`vZ`FqnP=w!~Z=jrw?z3eET+d-;4cwjPqM;o-{$*$W>u_RsrK^CYrs@Oa#R|G9Sid-be~r^Ijf--d+W8(+;|EV~9YGq z8xoaAO%$N@mX{i%FNk{rgnEE=gpe|=<1_w2<#w|EnV4{CNAqU3e8;5&xTRs{Hl zoDgn+NVNr|h=HFCP|;=~dJ%BP5wA*Or=ti8KT?W8%%)(mt}Zs*PKWaKhw<0gEozSe zgj?Otwyl<2{6vOR>*NVZxq>xkf87w-u?fH5EQXGN=1gMRfG`m@JFdd3+}4dzVsNSa zwnBt#D#kaUjoIJODe7+RG-JD^8W{a+cP985HSY|Vjl9}NLgKEM0Ja*E+D%+G-z)A{ zp9tenk-l=-j=LUPXTWOnWCQuD%;881+sKUE(Jt27%)b5JKZSn5yQ%!%$g>*_=)k;Y5`ww7 zts?-K_T}^<-aCrWVtt!pp&l*pJ#o1mzT1D<);1)e(Z!o_cenuvjyiI#jbl z92iIOFWk{Jz#KP1wP4n4VJ7wKWDDx2?^sPZ-6myyKop2{GTdiwM2 z;?w4{Y7PxZKqe;U7#O*b!E0gv0*16MpmPjZW87>X7KiM~Opv`3rbv*o(VEWuRID1m z2gZO$k54gqh*-fD(dJ+EPF3+PnbkKydd@60LBB8Q~bX(p=F%NopY9sr%liu4(ERLTL zMqE9!F%%zzpvXKKq?fO<^nrg!?BPYG^TXg~iI)Z*WWRyX8<4Dz%4j9F!>n2*JeZSc z^2riHy3DOG02|6zMyFYjhxuVbHLxCg;=haOs$lzU{R7q^@vi^obkA-(#GFKOn%n|8 zcjW_ISNmG_WCR?5!OwT4(vIkD=*89%dFF2j0$5<#s4hwSo_MjYsC3_i-Za}@OV)#KWrD;Tu=#@92S-KPI`C_ynrOh?eFA}y(LYIwtAnz-G9aJo2?l*+ z^0NC=9z?5bO|*TRts3SRYqEAc&N2S^2?f99)G(}%$t<57Jm8}2OyN`u1!`D`(@2GH zEB1i_PO@B~Md|_%z>6;7BSePn&Ucz;3eS=yg4$Ibc>^z zoRB_o4FtLqrq%z6zvW0zNwbrmxv>V&~VEovntN zq+#Dc8{m=Hx@;FaEqAs=0bi(lUh9@;O>1#!)Bkk;>(k7!^|KOW%7)>j`?}7n3P}%v zvX>+j12{er{fgeCFBt`b*p?tm>?;*L#%mhG-9|{+^^i z*kZ!NfoFjweR|iAm`4CYuH2oX=uKn6!#$`Tlo2m+vdXn?zyT5*Wc4wWtNhZ&lwRTi zty0lQ*g0ypk7FMD+a(;N+D%`ALqRBVb=R|wFuwBfuKofSq|61>6|gCJlo5meX>mU)oM1L=X=D0pK~g%Rj*Ee8CdEMjQ*? zEb*y46&I=j%MTK}-Fugso}?zYZak*Fh&jFFg>q8;VCG)>@d};1@yMJ#Msun!mnt*H zT}_U`Jcu?`IY)=rYdQq?hB)c#$^4fcIX>A8JO`n9Unb!k-KfpL>t?_6vRD~ty zI`z^`%QC1ps2GHdxeR1u`OES?&b#->z-&qrb9|)p*W2^vQ3x&8)0}QDQ_2s6c`q%d z2?{OHd-8q3L_1nAcsKKVaD`@nLdoLUvJtrn$ni7}{15!@``@5(`}uS!^hUcA>8twJ zKyCH!rfv43R%KZkPmh>PYpHyl)5*a$t~upzVimJ|Y95SKIW`K_{pZf%{~3LLL%xlU&$iTp;`M%rCDs{K4s{ zreRM&rh^Sz1dfj{(X%-qoY6kadboymM_%SabQ#?(#)R)tHBrbU^nq}{>?}Srq;jcz z{Au-Z8@0JYkvcPblir5GY|9c) zT0hc)Q89O(Jz`07Vj(OrOx(a|8f~!;rq3jcFK|ns9|1Pbv%o0x`>vSasOW}5*ZNkx wPx6^^W}6!C?24m_)Od^3pro&j&sU!PHBsYjs7~_SLBQ81DMiWhkA{K&2MO=rQ2+n{ diff --git a/Templates/BaseGame/game/core/images/checkbox.png b/Templates/BaseGame/game/core/images/checkbox.png deleted file mode 100644 index 46e0ac959fc26d224015f316df050c2f137af4d0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3943 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 S3QYOT0XMIk>c74QkN6*F=2BAt diff --git a/Templates/BaseGame/game/core/images/group-border.png b/Templates/BaseGame/game/core/images/group-border.png deleted file mode 100644 index 61234ae1fb3dee29eda38a371165d36b060ee426..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1273 zcmVRq)0SqBM&U{ zK~RE8k;)fTv@rNVFsUphN-&N10jmTOk|LETicKV_m54TpVAK!`|L<7|`4E(7K4ARB zDus5>J(HaE?!4W7v&qH}czMI@+&44#&Ye5=o}G2_O1ZzkpGs6d@8oj17WcW!E!8%I zG7SwXm(AMBn08BdCX>0T948-RoKK$0X0t6*Q&aiH#l^fexw~LXm>2UyPMmS3yc8^% zPN&txvs=#V2iKgriKmXs^9tJFqjWWIBOj#Opr!-61IK}Xx1-s?{L4G0_&?_ilXv4x zqfZ_btu8MwSK|-wsQY~v)cnk(&+H?8J(|C{sz$fn!M^&){#~l$>@n5f-deC_;MX2J zsxZHFtA)8SUGF$_vOr$N_B~qGz~m2~oD@4WwsorNs!FYtyCThVSEZ(BX4T=g^Lm1w z!FRq%(Y|`AS3jc65Sso~f)<#1w-6X-QZF0;z1&IJw>OAO*=w$5nIM949%2g^Yzljy(oWy)Hf= zKP~7s_`nZIkS{YqF~l(je$;4#Z=xBAo(3O1_wqgCBii5tJte9r;~AA?zGq4`(Ts_n zWQL)#a^A!gm6r6qM+nP?0Sc)kNm@4Xtw-=SGYrxowl6GaQ(5@5B&1Y;X$f*x_i`5k zxlG?JMp&eYe3Cfrf#}H=#@X;~|BtO`5XzBM3_XQWv3X-F3LkUd8np$mW$;ZD@}tlb z@grOWzKMePX$!hz`6y0z95fS#p0K!L8Eqx>`_a=%75$H%65feFik{-gOB_87-@a&t zo=kbNraT|vFoAMIeOeI8_0#*bHBgfWlms3M{F=|;vk&HAk-V?7qf70j+dSQteXuCB zxme0WXRY7zZQiQU6W{Gki*a6ad*$6z80sP_3%q+`TtsI83dY1J6eRh$8vuYoz-JP{ zd_mbs-aVmUVdndNBq%XE#kqTuz$8gP5_U;MoS^NwxEOTzWZpMPmn%SJ z?(zSC4+0292nh@kvId`u$uPqZCPNED8bgi@LmbC`Ql1P|ln1?_pHA~@{Z%BXuPKfW j%4_?bDUt6}KLr>7B{DrC{G$C100000NkvXXu0mjfaJE^D diff --git a/Templates/BaseGame/game/core/images/inactive-overlay.png b/Templates/BaseGame/game/core/images/inactive-overlay.png deleted file mode 100644 index feab83209cc442c5ad8dc73c2b86e0a8115c4743..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 131 zcmeAS@N?(olHy`uVBq!ia0vp^A|TAc1|)ksWqE;=WQl7;NpOBzNqJ&XDuZK6ep0G} zXKrG8YEWuoN@d~6R2!foRZkbkkcwMLfBw9D?8~Obq{gPz9LVg>D`Q%4bP0l+XkKL$W0) diff --git a/Templates/BaseGame/game/core/images/loadingbar.png b/Templates/BaseGame/game/core/images/loadingbar.png deleted file mode 100644 index 34f5944030dce5a174233bcef11b7d7210bbeac8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 635 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 IM6N<$f@#CI-2eap diff --git a/Templates/BaseGame/game/core/images/null_color_ramp.png b/Templates/BaseGame/game/core/images/null_color_ramp.png deleted file mode 100644 index 5f5a52186eb93cb7ace739e645e5e8f8e6b8050d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2843 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

y=B0vFoY*eFT;806|)ERK!%dbrTa%1TK9Bjd-9 zr^}Zwi-N<44;PRUD|p8mJa{mjI(14AQ>RXy1kGcDhbtX7ZX8XXJXzkw;#?xT(6?{j z3J3uh>Ba9w{MtcKu%x6!T&t}`aS|7W2Z3^ccTP&GivWbIUcH(oO`0Ui9XxnYavbA4 z%5?&-1*M?e%a<=BO5(h$uP-kz7Yjmkmb6|ZFE2pFMP2CIHEU?vv}sa=9LG41awk#B zq7Ia{QxaviS3x(c2?E@105;E zR9{~&)}l)PttOOhZ4I|2jx8a+gcuZitEhD4$`!Ms zqC#Rpix)38j~_p7vL`X?Id;V^)8uz~lf9ey`0?YYbl|`NbLrBhsl}e~gpM6MmSaf# z4vshyr^beQs(JmIo;`aOl}3*qEj}EA0K<$KpHnmYb-2Cy`a0>A>greGimhql#EIf{ zQjw&e`c!V3Oxq|YTv72CD&=tqUmt1-QPA>^J$LS0?e%#WP%j>b2t4qxk)&k#^5x0s z71t(8Q9LZ8M*WU3_*)q908x1nc$Lp*%%DMo2E{4rrM;IrQC4khIDr8hqD>W0WMK?v!wXo*Sox6w^%mnQ(TC_-zKFZS8^{EVS zw8ffyettoOj)7h%>FMkg2ntlMeRelK&RT}s7JUfZ@!Pi-cVw4ae$%~oO))8A$|GfAL#3^{}?&;db3pOiK3Vbm7-lsLCqW$rzmzSf~tuG+U5+V zVXEU)6!6+MGU2Q63p@-Ii4Dgv|CzlIPvV?FXa!eP9ecf5D)rhdDqD7VZzm^s6_5ed zvATFL*uvwpQIcZas^e4?@Y+@sZRN44Hk?X#VqekwO{wZa04bQlkd&h8*z3(wspp$j z5&tR*cDQ0W=(-9_a6EL`lmL_h1w*(07|LK40No;%f}xJHp|J7v=~MI2p+k`!3$Zta zudn2Hr!Bl(quZU34PWn{l{=8Jow`mDubt{-#iH18 z8mX&%Art`E>G4is6t7)JdqnF zTQ{Ikk}k)E6-v_O$=*DXcE(HIdgj!iH}mZ9Z6_!B?Z}atAEOE->2fHjP?9cB#4^d& z^)Dz%_7`Wmoo_5^VDG1sH4sUD!e1e9l7Sz8obiXr@Qttc&B~q5qToJHnKFgOefF7b zTeB1JoR=+IM&-N`?Y735a_lLxXE`S3g#FBjOTps0m=oerh)ZQ9_7odyQpbo#sU70F zm=oerUUq}0W9o{4lDL?YWiHUgoDh%7mP8bdjX7E8EM3eA@u+M`1U>0uPFD038*@TD zDq9lJ#heh2Qlg7FAs&@23Fu-@h({^W#hmQEuahaoedFu>r|5?ob5cVopo=+Kw*={8 zPKZY#E|m?@q9+8;7A#mm13vml>+7N9`t|GSHykF3+Fsfd5jlj}TcX9f=zv}*>dx>;V=&NpN9e@jtbDyKdCUjy1xJXsWE znAx*ux2K+D`2Jx+ck@Rk#fmp?-lW5a54WpDwOtRsGCpq%!8$1@@9io6?0Rb#Tc7lk zCr=XojYoS*RM+E^-Kx7^y?RCS=g$}25H%UW|2(2S#h+c@o)&Yv_kRJO_n_Zf_&8bs O0000(_@_GbJ<_dZw^Q+&I7EPrEnI(eqE51YbYz7T13zwEE$$n>MSVv_3!WR xqwIV#4BRgm4JXvHMKX&S7St`!IKaTf!=UB9TBWi;$P?&J22WQ%mvv4FO#lthVzU4M diff --git a/Templates/BaseGame/game/core/images/thumbHighlightButton.png b/Templates/BaseGame/game/core/images/thumbHighlightButton.png deleted file mode 100644 index 9d83b75f31b965b79ff082e3a0f6e37e4c757c1b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 778 zcmV+l1NHogP)^%4Aj<$I1_}WqRRR$d z1~4y>8i*8ofd!i&&^88q;$hSbL@LC>f3!$o1Vs!3BNnyT#Q(FzWmcoc0=>O348mYE z7Di)XG#${gULYk9sZ%c;*}t7K1LT!85hAQlXK)Rq9_nInN)!ayOp3q3h5+?ZB@mfF0rU0$f5zPxzJM_-aIs(% zaacePd~O^y0Gb=Qf!I}_n|uR62^f})T}Q)U#D)ReA_iudz%LMg;eTdyg}>q%QN>TK zMd@&GqN(S^VIe239t#(mI2R5BxNsT3gC@>{!vG#!2JoSY^WiXn50?SFXyUv$4B(}@ z3n;D^SU}}Ft66XpQhe_P#$P)N-;>uu0ogpTEtG2ypD`}kb`^|A zTPQ=eg`y=V3C3g_aP84^23RtV84ZIG8wR5-l+hN-XbXi3Efk;Vaufm3qytH#c_6Z< zE(Ia9w3GDg3<4Lg-UZX@LvA#W$v3*3@#f9jjG!4Dq}d&UEfkp8X#0Q~5|tAdDOXK#LK`1pomC0NWAfc{C??-~a#s07*qo IM6N<$f>^aj6#xJL diff --git a/Templates/BaseGame/game/core/images/unavailable.png b/Templates/BaseGame/game/core/images/unavailable.png deleted file mode 100644 index 9d818a3765d48243dea04cf3d9a43e54b1b74bac..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 26528 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 diff --git a/Templates/BaseGame/game/core/images/warnMat.dds b/Templates/BaseGame/game/core/images/warnMat.dds deleted file mode 100644 index ea99dcbd74a8b2ae49c5cff5a69743498a66e937..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 699192 zcmeFaPi$M+p67Q(#Rw%q$lVCxuCM)|w4M~V{T2fJ7L9l5=?1EHs%~9T&ZsR?vxyfI zsJbygxsX^C8(DbKi&_Xl?Ia2f*klZ%fGCLvqZVm(77oyhDio(NUSwqH4PbCKf$})> zK(x$!f9LR!6h(@c5=l|gmq67qMe^Qr&pE%(@6Y+2bN=K{{@nQ=Ez9~Z?NQ76FYpif z&kD-_tTFX}|NnFFRr&d!EYAO`*{_1Od*;t>$tlSnS+X5C4k!oY069PokOSlZIY17O z1LOcXKn{=tbP?mEh4x0G{HM%>a}6jFwRD81ID`aV8azt6j+Y!2Ta>0>S?>#-q__zuK?WeVjr#I665w zc~jc8`_Ccz-TFrP=kceWh4zA)_i}DHIFIpvT8|g^R&40;d^w{^DEb86pH#|nIj!D{ z{+GX(_fn&(Or@-j%Fn4+>igz8<&wJIGA_I#_cx_i{%m~+2gfRQf;E=cc8V3)>3%zr zuifA)`-S6ZkjGJY9o)l9`78O82bwo~6|QOCm8-n#-us*zQ+|)~w*o`s*IiDa|1GHh zsL>y)9Z$+>;d-$L?I+i5)-U2WLj6h6oWt{TUZF(&Gsybq zx^w@!*Wc)W;mKYmJuSRRk6Ma%aBr;bP)x-)ds7xtZYdF(oDe@o@p|a`wr9*<#Y@`p zq`a5WdSf)8+bx~yP5Y(JT-P~H+*18t)%QUw{*9W4{|0`&vBz{gzNq~8s-EAI@g5Fl zQlnbG!+%%$7j~PJQ14ogr&0lVpT_t0LrIjDDp6QRq3w|9dsU{T+z%oAU-n<(_od43 z)%}uoDz2|zQuj&NrPM2BZ67%#jI?9%WG^En^ak_?xZc(FYkocFc-y{B{=dv4SypsO{NL4u z27QlsR>dAuahN?g@-oh$-Z8$#f8SGj9{#*~Z}dCdeXZAxJ};J2zjgLQc?4XfL~*A4 z(_dOv3a^Wnjn@_XLE9CuCtx5bdm>UUC_4l8f*MboVkgw>gEbfc>bYPS)W;3*^Udtr zn6d|)66}Fti4Sc40G?c9dz<>87y97(@|WY`BICj6fALSD{-OVq_SooXKzIZ7m2Tux zx8BS3m&>Js-0vVBw+`MXZG-{9rG#TyfosU6m@V;t(Kj=A35PS8bXs_gqG#>c*dK1` z$eG3K=F0KbBaHK?;e24c@D@c zfSr*0V#S_-{iO16MkFq9@E#bvhW2-JzFj|#@HsI4Zk-;!s&RVN`oG4j?NF(p=QUrH z3ZD=MumhM7xT<#P{Jv-Pe+Dn=|I6|W@#^Se#N_AeJk{cT(f23ijMDq*>41uZi(VIf z4>JJsE!&|{a75Z);sIuy^;!=P+V#zIOFKl?J{RikfognU`7@*~9F(vC>;QXYHV->s zOV%4Qe~@tj#szM$J#y9h-|$lS^a6PR!l#4HcwFKDvxrZEN3ze#HSkAbK^HIKXf6Iv z{olDArTkA<{QT_dQZ;{X1?`$I?y9^>OiL+0e=jqm{Cx5IW!%g_;mbIJ9gs14&x|jY zIzPd*i?ox84-_^{9!}wvnI~{dEB2(8Kjc>oU;FhrosYxI+O7OOxJ^HP!0pFD(f{>a zT3&wfLj1TACIpbrZVzEXVDRO)wf-;S)i3>XedGV}Ey0DX%a1NDRQ0~tQ$;xXQbO&k zJp6o7=T(ZIFL8Z@`PIBV*5#M`)y~)bKK1g3{M(eoOE%E~O74(1unqZ(EWh}4@b6ZF z2nWCpUw2@JGf!Z^c|Q1@q+J9t8yLH2Q1rjyso|3FC>yt|@N?t^dcvO-qy-KSa6B^H z(*LLaKX1HO^gi}2IHUK?I?8FS_u>8{zK`{HqXF&bBVo^s7c+iXUThtLX-6FwSoQ(E<+j9SU`CDGoc{!gp_51+L0+pYu=LJ@94nkmn<8s~QCG`*6^CsC*gR1`xXN5y+ znAa8m4{3pxQ%Hui|M3p_$%C{{0QJ8=xrl}0?%Yzn-iJT0=J#hRael4$lQ!Ic>itXZ zD`e#8vZad0sr=mS&_TRr2Uv#*`wj#Wc^h(m(g4QgsIUCVCEMvXw$q^Nf5R=|&vIp- zfWoIul^2NZ0yhT79;g04Uw&c^q64d&Kj{7UC7-`|qVxIFGkShs{CoQQ7n{E~a?Up-qW?`iQuIR{9U|QMyOP8qla4hI`vfTc zpOrXv%ouov(Try%yh)A;bOrS#^n`uSVk-}IBR15}=%+P^byeK7ff z*L5H7%klK`i^Sni+%g7Y&80v zj`yqlzP-JS>@Nd%e@6NZ>3yT3Kk}FeF#Xy}-}LM6PC@B=_^;5%lL6@W#LJ!$w=mkf7gK0xx3*1tnuARH#)4)!a%f_&tf{(tb`fjal^4PMHx&FAx`-n}jd zXa66Z$G5n&AoKj#w{KVUKf?Vg-mmrlc4!!WwCTrQw@bV0D?Ph09&k&KpLEBs?=~-w zoTaGv1risCEDlP$nRYexQS)<)-3D z{|$Fk{1FoZ!W+09aR(=#-no)Iq}WT>&8qo-+4o=SWAs1N|1Hx0IFC2(M%Slme!s-~ zr9FzU1JpeKSmk_47y_mr`(5T=}ft3 z^l!i0vGIOVpZfVZ?Au`@O*en_?RH)Im-VDxX8gaAE3Mue?j0cxV9pPM+ac?dLvTC# zn1_^oYv%v!^}qN-Sf?0hRsU}P{i^+ctn0Vn_s@&p4|T8C^^NNMe&qX2i+;$%5HS7L z?dNZIy~=#P=>4h55sB|#SKbc&BzAzx7nonoO1r`g$X`{vnszt$m-+b*8bI0rxfb)aEb+b>v&{zH0C!o3h7rR940aMRjmsh9%*Rda5 z)*Xs9@%v#1h~E#lzi;PCH@0(~zkkj3{u!PX#123_!0{GzJYer+aO?oHZ->a^o!N;E z>c2Dn$9;6w_+`7Cr>A=*H#bH98{UiGf$akI{^cqUDH-a|J^^R-|1Ms)NB?90{?)m~ zir@c6=KC?-ug>c+e!s;3O+WRktmMu8M*RKR@gdCb-&D?QZHXPA^97gYL=FbQ4p8#A z_Tt68C)<_$9ND*PnEM3X*l~DMm}S7#Y9Q$9cJ{>IdEzqwpHfuicLRyJ`C0_?5!F7iNDFObAH)QSTFQ z@FRw0&-{;8`rmNS)UQ`%|KtC6Ei0aNV?oUK@9e03eP$|o{uwy_(hpZL-|rkte&5C{ z&W-%~YS!;vEkB&&ZF_Omjf>t51V&XqWcGIZb`Evp_*QWMoa^nDwnLZ(U_K!If6jXh zfPHjR^}o@#!ky~*LC8ar^+?z*5PG3Ee7=49ALsY2&dtelpX~1KZHHo2{~u<+sI)(( z|NEBzVDygIL6hS{!@cU~YjE94UO+PBEzB=g@=(W&T$pz1S1I?E{G7u_`=JfBPWRpu zoafy$JNz2-5B1*w=)c=OPHw9HH(WEkGx5idx#~Uv$jk3Oe{P%pmvj7(?mu67Zne%2 z^B#!*%liI6-`Dr6eE9qX>^tkjZS?!k@+=uzjY=FKVUNzFGs+&jg8V=uhmsE?^K!C& zacE?m`vUaH4>>yydgJf#KG(ZlZ@T_Bc7SjX;m6uO0i`7NC!6Sc95VOCian2)@V0*b z-|)}Wr&ndagHs}@ECmV5qrOJGO zi36PUY8>I^Ycy&f5Z<$T43BkUf?VyByoQEa}0+|`;ECTV!_+t|A%eY zjYh@q-^0HCGVhG#=l{mntv5UK9 zXSchKx!>bw(Em#AoI*F`j{VMY-)!7-T%12H20{Oi<0bQflCLa&<6gP!Ntw#*mD};8 z)6WfmR2&i$0>Z-*_6d-@z;2u$boY5IxUjHr3*!G_dv$eH<^9#IcYGuB{(-BQ_eZ|} zHDy@(#4qcbyVUBH{&-JMS5=(67z`9ogrvRk?r3k-KZ4~N`8pZjbd zwvX6LSEc`r9u~bne&|{(Ico{&-_Spf4L9bB5UZ0>=PhyfaKI=&MT>J z&zn8}9}dnfE-vbM{~49{Cw72v9rONuUuP!qfN4+B|NU&wtI+>TOG|3qAC~!#NV24 ze>YkGyCt3Hn6P6(H_=X+g>-YVfmUi#GsF*}Nv^qc5?k^5>M01^Ru z-CySVHM?!!rvAS?$2tD}j(>hn)T$XTgP{K>@iO%}TfUn@TA(H8hhTbM?PtE*!~IJ{ zpDbfSK)8tQ0##n%I1VsBTd(HhDEqdS|6iy7`xamASNz}T|9U@i46lCsk@vpB{=yRz z6Mp-L-!u9@4E;X{aU1IYdLDCpHs>nar8n&|`1)Tzw{x5fAuZ6=^XZlOfK2!O72}sk zUKI8zONkxucY2?IkcA0>cH^*_{uj=g>l**3SLJQf|8lPK(_p_G+)jW#e^?JRts0|G&;3<2W_rlx08c!t0{{;cvclr9lo62Z+c%X0kq@ zcX^7!!xx`R1+h0i$%Fvr1N8YpTU)3_%lQDK|Lgr?>i<-#k^kL#ulnhQ&^{{~0@A4&e-Ejpi>daWON&A&dm-TiS@`rqj3i^i)lA7CRbFe?7J z6&N*nfnCo#Gj@Q)8xG=@6Vi zP5R?@%XcFO#crF!#toy!QcGOk*|J=8sz1`N>k9<$L?uH$8UG=|PI&_g1sMiPJ zU=x|IPxWvg6XD}BCIlo7fV9B4!~u{Ni1h)D<525=*$;o_!2|4vFYBxHe)#=ZUv*J? z>g;ngK3C)W81|E&o4acLFZLOx|10ar>i3aotS{edUP#<#enIJfj7vTLKcn^km8{#` zwywej;^o%H~p4W`vwcgMn|U=$1+$TVB!niDoq?f(O;+ZKh*!5Zpll#>lk@*OY7ea4F`HY&q+OJ#sN#(O|^K_RqKCn z+XlBgnE!7+er4Z2y>GD02LyVSZ?F7K>{}v!J;FexH>=kFBk*7EM`9Uy-`A1nUgJC&wO>Q-2go<`0MFO~cP$*(7+q24HNH{j zHSHlFCF2v_r{v`XgT?}%a{-ly(jwwxY$>HMC}ux_5U{hj`>uz|F8I2GJkNh;{V~7a-N*Tk+F}= zR7L-%nfG6vTU7fs;*8kQdoTFjI1c!po8$2J@q`{>n=cB@&5xiPyg%oKKOCP#&L4$yhE{X;zC9^7@yio4ky;{FjG_s>+;{qMe!{@M;@Z~#!h^}pn)@Vv%a9G2tNj8~TR`nlKR zVnFnN7vq3>-(cr(+wRA{!J>CwsPlu8_AAT>h~EF4O1+XYlS)mCeSqU|t(&U<-O>uy z0W4yFW;`zf|DsRQumk$7PgFmATPhvG4#R#x$OlY1n2zCkfKu3YSLc=_?q9^bjE>ig z2Bg2zGc(iDZu0kb{(84R7yXap8hKt5df(vK z^WN?oZ1kLPG_qXAe86^S6CEXfe`-3Q^nSj0Qa0b~Hb)z;*T4LK)6Oe4(g0o2Cy4tO z<++i5(X;%E#^*KfP5Vmw#}SZ0K1k>eHf-v({XDqW&wU|&zxAQ!_gCZoQ21)zAAx_< zZl)c3U2bjdV;^ss_s{(>1UVVp_A}#~WiRv&`+YFR)y>uax_$ep@nbGnTw)<%Jx_x;4+aU++=kxpd zrt5!MU*w7b`vLO-SRf$&VK4U$Zq!Hpe&2unZ^l<5v@pMf_LcqQbshl10bO5**{(f} zy(RvwI>!;~LiD--%m*~xugTQ^rj+4eJiEFW3&HP)K_+@1et%l;)1cR*%#4kye3aeY z{+;)0`VIRug~mr1_orUEDe`u`pJOoe|Hek|z_t^h=0Hfb@K7iz7B{5q`ev4WyYzFNzZs|E_s>pppZ|Vw zo%d{zzbFy}bReodkemthFVehuTZ9^wHxF4$@-Ra8@0Ulu-|(-8unva&J$P_Zu}@&R=m;40PwG`5SH4_K4)8*fU{Uk-Kw){De~m>z%~0R20*AtmP7t@~%kPq*b+?h{{>{d%oc z==*i;=gYi4^r?#PV>=0@_u=NNeSDzi)qcM4_f=j$;sICY@0)&*aR|4c`}=TzAMWo1 zaP*!V7vm81ziGGr>>F(O*sF4I^uKA>guRM{i@=v+UwO#4fPHmx_4ZZ09k5)P7x)CV zFY$o2QsI@H--L2g?19fP2x2Jzpj?WJULMPfT@bUav5I|Q&EUOcwOhMxDf$v+(Jf`) zqQu`#8T}6Lmn+|Uq3jCl6F!HYKZtnNVK{hz1~UGA41RtY8%T1jD{ zDKi>S^(^jXQc_=-0cM}6fzbQj#;mOGFEG!4aJfII`iS*1-0V*|Ao_n}0Q$Y)0?=}f zU_bT^zCHS1kK<DU!})f^RqOwIUtM+l zzp;JZJrsYn*ZT%H^0Qm-2haaE?OT}-D5!H8RtI$-ruw)*WbJc7>Uq#$58%(r@Aj6< zuoe*~D5sQNP)h0Z5TWkXxri_eRQv$jKx%#7Sf(rAOHHfq<7bxa(}V9%D}9dufY$dZ z#QBqUdQ|Is?+Wwz8pr98qxQM{4aQw)a(tM)WxStu$2GD$sQ-E8GnP z#%9Dn%w%>4J}+=^^}lIfm?`Z?K#rc#ZZA9(?_8+WYX~oNHMhf0Vef z&I`!wom|=a0KauV@_i5tYhL8Zr`=S?YppH_dD=RPSb{qB|3 z`UtTPrhyc~pZsZr-VV zgXLV=@=5V`!s|iaH~9MKf79Rlp+y7)^to`_4nSVOz{gqot#1eAelotijY+KMANq;; zebluD+7rkO+V~U zi5+15q~--wegNYES7#SEg`@Bea78Wb<7S0R&(y~%`^~&D-MHu?t^Cn~*YD)7oA42J8O@x!(@1#zhXq4p=&<*a4g$Xfr>c z&*kxEF|T58Xg{Cp_qxc_ZgH8{xh$9YdkpKgcEW(@|8L#W%6cFWxJLeeb$pq9gF}O` zZ}9EW|JC+ac7fyxEJRJdKxCD10UZ~}ZK*hkitBqDBjCZkCnG+%K>c%ie6c;)9)9%c zbsHyFt^bA7Yk1)t_LtWy{@*AMdf(vi^KBKER`UT@aL&zb)&DiQvp%>GRIvvlt5QmQ zI}*Ju_Q23jM>76I--o=7G3fi@UsK<=_k(KVr%|r?{wC@@_O~9_)c@U<@49`1NBh5T zF!g_{{@f2ejf)--d*B-@_k;3_7u(IJ4C?2PV@l6Y==Bjh$kWGj-IwRv`kw3asqd-Z zT5*7XKW)#&>_|l91^bhGQVJLAOW};X?^S8;C;q?O=eqaL)|QI~c1yBvaD6+P=j>HG zR(W)}e{-&mb13!kW^}zCNIj>t zo_`!0SL3YL?ZoS&nbGcS2et#p0p)-kxE&n$n2RdzA3a>w<&=j^17!y*yH4T=h06W} zpN-w1KZn7r?d2w=+Rva|`CUrBhwI3CJCu9s`c7Wu;U`|goyXrf-p~we2abb={9noi z<$_$Gejo?P0djyGAP2|+a)2Bl2gm_(fE*wP$N_SI93ThC0djyGAP2|+a)2Bl2gm_( zfE*wP$N_SI93ThC0djyGAP2|+a)2Bl2gm_(fE*wP$N_SI93ThC0djyGAP2|+a)2Bl z2gm_(fE*wP$N_SI93ThC0djyGAP2|+a)2Bl2gm_(fE*wP$N_SI93ThC0djyGAP2|+ za)2Bl2gm_(fE*wP$N_SI93ThC0djyGAP2|+a)2Bl2gm_(fE?&G2lVmhZYdmuym_6M zn?K-pLl^I-SO~wL>-@f|z8e?6Z@YH&)gF@i*-Gzi(r`l$`h-FC*Q*zk05v z_Wh&2=cB(HpO5cFP`cl5Y*)7HdE+YQ$}1eaEBfCuWh@vDdY)HqSGuKGXn1Jk!n|_| z;o#ij(!9B^DcjvQ`!*b$z^nW65)Q_*?y9LrV`=JT9fpIm6L}B!FQD1#^r>HY%f4;a z?&f~xKHV;HE3%VA{s=_mQ#JYMGcP1)}Htv)xum+^HU16k>doU_+$ z*WL&3r8=9h!Tkl#Tfu$vCwm!npK?0Y>VD?$+1!flN3V2VFKv%VeY|RWWSX}}Ar*H^ zD|TRb=mNag`oGfdJMvs7wRWF2&)MzLEq(l=nf|ZTqtgEV`@dcNK7Qe^pN#(3?NHYB z*h_V%9m**^p30?^*lptzVh^lOSysS@pWK;zU_5kN|BHR8{Qmich?bM$$!R%Brvj!Q z;#+9%ys~$mT4AI4zzdr+)jpbGbafe!L#rr@4M(yPV%Hns169 zd!m11!I{y3wI52@`En*LWf}ZzRl22QXksG|o_5;Ku~61^qlzcRU1fJ<($k~cxSvd!RYeNqfaULB-_xi{;Fzc33VKQqFPWg8r7) z|8gJb{XJ>-^jIJu_sPQ!Xw}}A`TH8$(=7$QY|#H-NF3s#{ok%WfiL~_Q_hVk|6l5X zVW8TU)?`F zQ<2kM)j#!e>bJkUR)RpiZ#{n2nZH%j z|7dr`(c;POuG}Y$`|A6gG->x%{n764XwQ=9|9fAx(*K!sx`Y02cR&64y|4WBQ|=3` z|79GYIUdM3^fL}jf3zy4pI)J#q+JW>FuCsMLTXdW$nsiA>B;f);#Yp<#Zzu*4uR=s$g^ZSkM!}bCGn#BE0yVUqLgO_ko^pWs1Un~~?^p}>E!mF|Tt+O90 z<0bN6DijKCX+H#a!*@QM^#Oi10-DO7sN8q=jof!Tlz}2L*KfS9dEagQulQD}59|=F zk6{Ri-T>|bQlAq%ueraepM1UraY4O z^X9&-%9XFx_a;8(REgg=miy|u75yKmap7at{`1rSm3j@Iy?*2U%zKQZeEyvAr^lhu z|1$nyeyMg3;APs`Ja^^(jUBw8xk)+_z_~# z#D4WBALjaygD&a++!vOWb%$b*6AXZg->u|xcUQ*eb|?UQ)ZEuRuRPz2Qb|4Er_If{ zTY5KzX#gMd9EJzYOQZiQ_8IOExxh>AUoRKb|IOR4CU5-we0{|B>2LeA<{Q+1RsScR z3t#gShBKyAym|5BTjzK`Gz*8L{WuTX782}~pIwRj!_QW6%nTIJFW@iYKC|Zft;+7{ z|CkNTMpb-uXXlTFv#5ru56qDnWsjuOsYcG4ddc%IFF$>O_(xa$ty(+oha@jf?vu)t zPg>O@@$%?`@sQT~zrO#?^SY&9G{g_OBd?A6U)zD1Oyl#m*RMxYi&@K(@#uLAi;cfG z?{&Yu&~^Y6rTEJTUv;Ga>)Xd%w|)KmwpZA85g=1?0);R0L&on;V|+^eB~E4f#gwKV z(tafv=CDgc7t7B%UC&nfU+N+Lg1JBS|LJzC$ua-lU%kfm_SfG2^uPF95^w+b9$bwq zRQ*xIn|n_X=Y^kw{OYeQ>%4h@n2kKLc^2Z!!;*pEWZ*syHkD))D+1xc~oOV||2w+TTjrpAIVi78XQw zPwuys{+IT#tkG$?-(LBoXxiP>C-Kr>oc(OQ{Pn-N-`V+t?#Nm9^uMXk(bTHzX2nm2 z9H@RwXZB7^dzt5{>B)U(WTaW%ey8oz9sghQ6qk?~E90^nkJ{035ljzN<06%D`A_D# zOey1J`NfMD)*;44UgR=&sdc*4|7KjV^ru(YPS>NI{PE4`e~I(YFD=dqU*M0b`RPL8 zKk9h^U1W9 zxVY%E8vji_Zo2+A?d;#b{)qV%J>Nf_mUa{SDNwNkGJB@ol>MgSSKIaoUT6EwpL}#) zzgFWxtv^+HvH7B2j{|pK$Hy{h#G}-_+%D|okeA<>ka4*Hfi%x!N>d+sZcGCpKPM^c zbX&^h+2=l8KkEO}?a{8i_&M9_X6b+U5gQwb?;lOgtwvqpP#J!OD$C`fl*`L&Yr>=E z>yKTmyN+89;Qkh>6|MH(bcJ=kwB9-eG^K$)6X0OWa%j^G`jeNhk71$v~ z_*J6+fmxMzF7ps_Kj3%Qf&T=|&bp=HU%{P>%imK71gJ7yE*s9ud-z+WgWPt--`aZJ zSw3JZd0A2Ve;fM$&F;>Q@H~L|5_4a}`(EpRc|J@lBVTSmG_2x03ENU-ET~KD|D)bF zDG@hn$HR91zjR;!%YGO# z9ubc+d9koZ6UfJ{#iOLYvy*qQ?)1o+gFwo2$hb7^WJ>vaWO@08%mZLs0LX8vad!US zssGP!pNqCDf5&#cT06m?e^b*hkDoyeT89s1e$|_=#8)lh%-UM{1g<;m1c^6VAMjjN zo`N4T&Aux7R{VV(XV-bmVh4y`ftp4B+`gU7x~}qDkawu{-L#H-pPW?Vx0lubl2;AP zMufAn{y_LD`d;o=pYP`!A32kEgtKOx>iG|O-jlqxe_)sF8s4gU$K#TBg*Zqz)?ewo zcxkT(c**sl29zILKkr)WA5%}irN91{=N0|0o)7+{v={81&(eM+B+^L<^;21AUn{X6 zjlcbWD*69%U5t-iiKoc(nRYd$U;XbKi+wkz^eD_Z6=#y`$#b-rw+{^s57*^In)dV8 zKAqODHlECVEVceL{(a3pMtDrsTjrlc&g%31MDLFb4Gp7wDDrqTwT*SU<bxx;@VJA3wiZJ;wIGSo{0q+gbgx9YPwwlIR2Y zqe?%Y0Ib3(s6XU;Z_B+~f2>NqQiv-HU-8`e zdftk^CG!CAxAK?g#9-+E+ViRP9_W{ZEqY(d2o~CleS&57mMY7&Qr6e`S*PjO{};a( z>+Aj&cEwAKcjz;)zX}q7*yBd#z{iF8bFzf7QW|VwMoGSNP$Nk;X&`(2X0COD~Z#8+Go{@36hd_s^ zmyt{P9?a5np0_zissEd|i)nwBY@dti->Ysne|$Tu|C6Cbr3VxCbSkCvW*QUJ!kuNj zz(J>ycdYg=vpztNVgIrUkEca%AirL(_k+F_ZbHq%4%k-uUp`O$UAZiJ7GYal|FqwB zas99N9aw>05Wh9N{c3*otXwDTC>$=SpZNXC{s{!C@p$>Y^0(lR z{bsFPMqaty*}e#k<6$uLznN!{=Ue++Du|tgb@VA^2gUXJdTbMEsrQw#fKvLioBChw ztK$#}8|iH?WIQ3y{gbTUh(unf()0BGc(R|O>fb%xzi_9u9z~qTJdfC$ljB28{C?99 z{^Y~x*^BCb*e{arcWyii{yoOiQ3zqOGxPW|zrQ#)7nO0T<#0PBrKy+n8_ZHQ51{w! zIvt-oJI>AX>yrBabbGXGFMiJUx*qm`KfayS|A}Co9^BJIkqJUP`_6{A%MkKKRi^$7XZbPtIGw{0HWhM|HkH=FM((9zg3Uz5Z(CLi;0| z`wo`=H+s{wlPN{NApDYlTo7Zaf{QB?I|L3>Q+5X`7 zfyruoitRI~i}}3p8{vU7^R}J)|6v=Lom&B4Wu9Mg7W3$G{Y+ZdTmEkJ zn~wW8GF88wy126Px8R>Thwy(l@`z8j+F!<8uT?o%`d{>qmmZdR zXU9|ieYNMX&lf7UlrlE_=Se!O3y4uB65F;H;cXS>C>lIkKu2MKc(!4bXvs^gs=K}YVlTc zojQN(g6AX-n*MLxKe#*N+pqo~{*}_>G1Wii&jl%)?@x`tV`F+{r#u)&UdhU{kqh}F z{^Y~-w}1aXz9s8n4&H~W>tPU%QsYVHpTusdUw>+@FXIVjbzH_}ZT_QFs2`W3)6+_B z5dJ@7H%oiHc=2s1hV?cRkV{!_bN+rEx__zvyED#P+iko)?TD+eBmD8L)xKV$|7AU( z($fH!@JaS<70zH90P%b5lONaf!v8w;%9791)1!gMPlVgz&#XK@?aw4aQM@Fs3-^5b z^7=pKNWNcvKA6k{%XKmDuk#OJhZw$^QtB<^QN9QDU(j*pxQR2rlJ_&yqw4e8b%B}{;bJ&Lf$w3eHI z8kZQ>Gx9sww2`8Kfbln|JYaTk*q(G z`PP}42YMcTY)o;dTs}Dw{w%{^meTlXc{tjbe|0t{n&n+%e?X=G!@+61F022ATUh45 zv;sbgUnTW~zJ4Irg&8oa_=vw7yb<q$JyJcqfyJP+b(YcdWC zsaJ6+*KiP*9+!Kn#4(j9lX8BSCEqWeoK*MCFxQj6OFm#FPY3qV`Rzgde}4P4Yd?O@ z_8Uxlz#rdQ>wn#^)*;q`E$DsfFzu+~jwje>#c->!lzC)qUsAU|(2S36>3@~q>`Gp> zS$BZ2zlyKI-BRZpBHypNkE-FKDNTJ9ZuNP_3Pfv_qCqW`V#XupAZKK1x7kq|K?9VOg}f)?`%J#We|^A zpTf9A{9W1)@u*SJ->^&5GQQxqSL0FUIZUaZ^K%K~5aTXViLa?~i1Aq&mq-s#;}UlE zo~f7ly(#7I2+t||_CW1hjeNjU>vd0$OTYSG>Lv3M@;uVs@_ZOBn__=IMZ6*$ysJh? zW9b~|MdqcQVRoL{k3s4w^_KG)V(ZwCK+St6 z9h{4IW*yzxe(@(CrhU%Vud#o_HuC){@u)W@9;L>)j89enx_A`EA)f2C&bK^wJT{I? zX^%qO$V+2s>MQn!J}2m%(|q4fUH=aCziDsSiP$IV=?iTq7GA|0$A@_@*Qfrc9zQF8 zjq=0y7t`~t+RY!|eCU77+q+qj_qz2*)phZPKkED-z22`y{&h|NL;au9|2ue9uai4} zU70>NeO~SVhGTuqKB~AL;-bj+Q=EleVXg;mhfeSF)2h9i|6TNtITr!P^i}nbx&A4C zYjYF(vHx}OJb$Yu2ZN>mrQML$spHQ$KUeIjHRX5K=0(i>h?IdZySx8SYyJApSzL8h zeFE6%SL%uF8LIIoUGFvJmzFT0<3Jn#J4n1Mj{D2_F#AL;SLZ48{8{}tk@FX^uaocfh-aVIJU2@;JL3Vq{j1wP zUi|T`qW|-)le}gTaP5KdZ_-~ z^okt;x9Uv3-_QqeR@o!g2Y>6q8tZG`?}tntB#!Az3s-SWU)2sUTvYxR)?dlKIOq9W zwRRp1{crlO_8e%pCi5cleB%F`vc27?+pk^zzqxN~{c8Fl>0mw}Ds~=@Niz0lH7`T8 ze@V}mV;iGa61N(MA%OLnqMw`C0siEpef`40T0E*@{V65@WV}e6%CxiCljqBcdERy< z&W}{g`|fg8w=ZE^lm zyXWKQ7`N2-)c2)}jRSvt6FHW7y_#NXC3gv1&Lb23KU3KcaHlT+SmOSe_HV*jbG?|o zir2;Ue^|~JuAG~`r{k-;I^Qpi0IT9G5&;dTWFMI3`}~;t_$}}1a}gdTVgJav2(k`h zbWHAtFhlizm3Azxe`oxy$IqJiTeWr`Ed6iV&6Gy(wJQ6s{{vsTiig|qpBI)y&!jLB zRbM|n@4X#5h-?28?r%ZXu?&wlJGarFe3c!eNGTItf-AYeZ5ZgzZoBsS9=C0u8$5A~J%SpM&``2)TlbxZ3HEi1n49EXFJ zRq~wUSjgJ+P~v^+Z0VN5w)%S^W?NQKf8Uz%+|p1C*V}PRRsrRR|9X($Xs-_X?b^3j zA?vzs^t*8I)xyHU&@+rP&-472)?v(ku;F36-F;?RfuUZFGw1l@qSVuGy;^+_^5u+; zj9j5SSRXLFqFTNWo?3^H-)}rm+8>3Nu){$wzc;PQa>`1|dz9OuSer5&EZ2QM843qy zm&>VaE*2ciSGX~@gMM0{LO*V-$oT9=uf~;gJoH5BDRS{YhD|Du1hkarXZPY-?!2M?ZV zIgjLbXXJTKGNWkc6+2(n?OsgF`=q@)ZCSr{l6E<$lO3m&=XiQD{3<#^+M5 z6;dgA-qI^e^6*i@xXTcc<_Cnx(zL5vFN$+)NpIsYy?)15|{4XYy{LA>s zq|<2`Ul?X;oSk33v&$H7cc1KsCNQqt(z_`uFf!hK{@;Bj@-KSuK3-D4;>pR0|9b9+ z*6<*1>1e7y^8axTcD(3$JNr$vj?Ci8Ad*(W`-!ggqKb^{zZ$U)(CaU9)!-YEYN{}aFUH1g1E`B(nBm0g8hAN*!P z>-pmDjIvYmJ2Rsq?o z_I*X}?~ewQ+(Yd9rr%9JT(qpW3%)ssTTUSn(j17r?5;g`W96wqZw>r&c2)k(xDz`- zI3RYw_~dLJc7V*^UBVxTe{bX;;y(!T{~Z3kEAwxQ3z3Sxf1vdJjFS6zb_VvnX^-nx z8jg!Spg17$UEPlo&%8uG4!k^EH~GD6eS0GR#;!b?+P42-?ek}ey9b6xCNJ&}#9q4D zY!>l9d-4ze@DHz8|Hqv|*p99)ElB)+_x{+J$jSY&(SXR!W#qonZhJ!?jvUX+-*=8t z=4asFq0ES%H~cFvRV(p%$ioP53iAEmTe;VG?|I*t_P;E5c^4s zOY|eyUqlKjgo&c}g>W zFRuS%jup>Fw;n<7NAgPV!|WfG>s}np6xRv{%I~-8) zU1iU0ZC%WsYpCD#*Q3{!3w@FQdJZhZkd(L}@&xj(?|hSkA4UIfO={yCZ&9~L{mzjEM!1Bpj{So}xRE~bC{ zmeT$(17HX2JHsQr$oJ}RyY#ys2Izi$mw&O7W&FI*c>)+ee&R{i2hsmmB>&3phuIIi zA923>_u=oqlRT-8<=-jnhh`_oJFt7YEeF=23wOXlo>pXGX;H~P0x5pw-h5AfC-$81 zzkiu@1%`bgqTe`dxD{_Dm;=%4@9{$Gn-iD9JT zbLWjG^E;8_N}hm&aMDI)oHkjPrsO~SaV}wFnPT7M-#N~~?ZCVP=J_7nfAFAF?il$W z!hBwSV`3K1R~YWBe|qFsu7B?$9xxQ!4tbGQL#OK5sT`X7bRPd(ccOSz z)*a2rbvnsAG;-o#{(g3La-inT*EOY!v0n>R+T{g%?MYcTYj<9lBT|F8Oac>j+5 zpHq7E5_0vheqF81^DoUsvofwy>2$`(U#oFtK9}!*3x`0hA38n1e2nma_U<$7|Lb~Y zGOe!H_;+*t&h>xHUd5{t_fzYR&+}^A}Tziu$(ANgxJ7v`nJyFC+UF1L>}OI%&%m15tS^+U3sfXWkq{Ku`k(Ek$u z6Zy~J)#*6xT>jTXs|b``R{n8c#K{NC{ulG#DXb{{FV6?@zl8ihenR=b)$-qTUk&H@ z@X@Lpx58h81D@BJKLCe7tsl~P0*4r`!{PP5%fI;l?q%g49CR>EHZfrKY5d?l<~1tw znir9O9q--4{*NoqhlYlS2kiMeiGvS{KJIrtx@G^j+*d0O!NtBn4#I*_ zPOqvZn_J0)NX^JJKJn3sGxHBaU{ z?qK9Z$2DZ#jQ9a6U*?L|(aS#LaTn__?Io4Zv|_)x|G>;^`p*9`&n5kiY0b9%PQPGa z?Taqy|08D{FF*Y(@+5hq2n$A)T>4nYYvfnT2mo>AL!3Yu> z{q(zT$F4pP?TyRZ8(otB{g7Yz*W=*c6Y&ScuJ@vL0<;#$i71dw!sme6{-f z<>lXu$E4UTt16CpLHU>b0r|c7Gn+poZN2^hd5?kdor)gqhCUVl!d3ebXTMo+p3DB@ z66ceB3-mt37umPq@0}yHFTBV3<_n)?pR{wbQ)e zR&w6z@79?Elq_cwayFM2V-pB0f`CS=VCyDa_aSos0`?lZ@<3SXAc< zC2Slsq|O<6bBXf?R-PS6{>Fsp{c&tq(nOD3wI1XB#o+7Q9_fz!7xwLo>Hh|~f*rAh z34+VYm60z~8aeBh{JYq<#MO3-Q(f=mBfrtqr?E8klXAJ@A1s&jIbO@={H}5;F6)r= zd4T%7Kl5Jl6THg#VfoCoB^*h^FPH0G=G*}j=aY8ZnAG+@=lL!qXM@V8fs%jZ$GkUk z)k)rPqdYafH}cgz`8V8p{I$d}u?`;VXqT|=QN=Mko*!&gUsG=>tLOd!5Hb%b=l!X_ z=k&xB-%`mN#(sg9 z@w3f%H}cSZ`8OQ6_arJDkbO40$N^LTew9Yw%YNco?uY(w%KeSzURUH_&)X^&Rz z%)eupuzff_I1ffSAP2|+a)2Bl2gm_(fE*wP$N_SI93ThC0djyGAP2|+a^OaC;NZPH zmRoYyQDR-`nerw6eokIr^t(2{m+Si27tA`u_p&YSf6jTiuGDX_$?sY{PyOHVTy3Af z{`;nV@@`43x5v5|RhoK7+SCKTll}Ls`;~dACi{G}tj}}&Zr1;Nmg>i)hWd2+`-O(z z*F87q&(I$?KrcqWNB)l+lYJr<{?i}Hx^d6jo7QCt`8F|oa&}^))wsj{GIBl^PUV!} z>2>F|-xuPt&!oR~!Ld+08;!1Gf0_j^f1#;{r>dxoPBP}|ILv9xRU>EJ7yPm?%$Vn<0t7rK*}=mO2S`bpE|W~{nqz5 zho^3w>i!o#EG{iA$oli*?wc9&J5$Pjw|?YbuCuzhG%x#6V}B~OFXc%pV9EL5`u@2V z<91!izuYg64eiW*+m+5S&Kbl@tuFxo^z%Q!J~^kKzwtVOFHs*Q|5y);mvBJ%nR~Pn zod5af-^urj>CtNYHU3`SFQ?*aeZIF=*mO$C(8#HCkDK?0b+~Q&lmD0lj;@N_|L@q~ zQ`ILkrt4FPBj51d)bLRI{m0|q%ef%)^OfI^o_%i0|4ovAk>4G>Bu~7E4ep13C3&QO z@wL3iw)HrNXWuzJZsJ>VeuVQpW@9^k@3&J)yLhr|&d2*)mv7%j{&5Zk^i}kGTt}Tl zk+ARoQtz*8*0C?EbATG}Z^qxcv-tmt9k%ay$ct0?^=nbRuW-41V(NiBSjQ{M{=_IN z`E!#G|26u0n=Dl zgS=bO*OlMP{g)4{_3!Za$~j2b?yGzk=V#!!Q?UnLYQAduZ|o0QSL{drokCb~RQ-PU zjp~mgI#lmJo=VAe?wsO{X~)xLT%EHpug+P=K7r|ba?bZD?w$UA&HmuuuNN22jyE~q zB8UC${-K;FiX?vo1fB2Apb)HZ3 za4OVc0WDsS#RX=cwEIj)y~;Th$>-8i_epEnqnV-~7!>k^g_YAm{VQzL+N`t>s_G&19d-MI1yS zcIM9H{rf{dVZSPzCnNH@xVVb_bmTh4{JogblYuYK8@JB!O3=u^IjTX`{pOy z(&J}1KM!1MUY~aIFL9C@M;|RTyCY@OD=X`NTem6EYit#V!$&8QVJ`bbVa9_#E=-3~baVvH{ zjsa{rZYAE>?7VLCJTYUgQ;ozIhgBh_K z;HUnvgY|AB>KxgF_c(5&y#9Ss_@nj%#`TI)uUQq3Y(8$gCI46_54~KRbY=Z49RF$w zKIIVrsL4xn`LFO}P1@rr03!Qz{v-Gy?~89{0xtXj=>7ZfGp5E>9KnpU=KaxH{@14z zN70V|X=nG1Twl)fk@y4LF~mEhoh;8OBy6##bbR8?8)@(V1%VZut2))}JVMI9>5rRU zHXm=0v&y{PyN9b##Clwf-Iww6Kj1uGdB2yMMm!nvsLp>2KZp3c@^=$QY%c$jFA#U* zuW=5II)4uFKAb}Zd9l;!|5!MBxNTb)ms?XSK`Rm|3umSfUodes8Mpslk6WkNxb2$! zU(){T}O!f6k$w_Cq_9qIYw$??#jJGn)5DEBQBmnD7PR6Mdc!;(cQ8 zkK@Mg9wzKfIB?RQ2l=A1XW({>>UdxwCGk>BufqR0Jvo4NZr;od1|2v3hOdybM5TtDAQQI%#sWqfj@GLGuvna%s7c0DsLCGQCw z{r(I`Lv`~eO5RJabUU7)J*9nd{73ctk9EXtEAtP?FOuic*KaQW(hkYS_E7DDbHHLq zW2pY#T!*FUuR$%FkGGoq>w2T#L-pt1%DL~_zf8PD*b4GjC;#w2Wt=yW|F{GHyc+L= zql);K4YB`?>`&vpmiQO;yTCZDD}N>LKjv^hI0A+f>o3i?4S#()9@riE7da8m2!A3^ zORr>pVj1@Pp}T_opFco-Pv`&STE_pt&p0e_#8a^^FwPGKKM@x_1Suz=pXFT9)8~LT z?~g|LHyoAum)(keBpekUdpmL-@0oT~?FxUx@&3CxvrqY+)JNtYgr`UgsK!+q<==2u z+T)wwAH=0S);^~!x&Ip4#W@~&qUSFLb)2(a7=?9u(zJ&jZ(=9r^Z8(9|EPfM6E}WG z{73UWoPWEz8WsB-a;^5?LYQ8S7YQ$+|6`*6j~>Q?_ep%> zvib9y-!+zxF%N<8KjdHK|G@51`ak<|5$A(1Ec{dD``Z7;gnhOBj+4$R0vfS(aKMY0 z?^&C#k=K*=U`M@s1dbukxp{q*KVQ3ETuKuSP#&It-^P0IJ(^pMAC_!~s+~}^w&W%% zuZ#B&X8m68?DwSJmg|sXnIi-ZXh*#rv z%zL-AADYFh^LAgKvaEwerw|JsJoUW&P&oLHd!wqp#Zk-pt&_CNsZ{E>&VI-%m&>&> zX@6FKPuk0cRO-k{*cf-FnV0eK5aVII^ZH!(aiaS__h{Sx9bSL>OUpttrA#U9 zhh{8qz1|N^2F*g^)uJ?Tbk#R@lwL`9{ji+npMx2oU#HVlkK1Hy7#-O|M~rI+S9a`Q`mRLCnxe~ zpX2lOLAUxp7P7L@#k(=p?|JF3H)$>3GA>R1E?dg;t>Jo`Z_PMQhOEHwE#QH_{x|KL zbbcG!Lpy;34+BHv=g3LYxt#nDJ+rL1d+_fP_R@mqnSM9*Fy-GnM~Y8Q;V9&JJLAsr z(Uf;z?5$sfPsBhd{o>1IRUSFsw{Z)f<9m^B%y>4}F{Sytb-3?fn1gq@j_jW6$BoYV zzpi~kvm4SrvFFg6XY4}jFd3S|OTK?G{>MVmRk0sd?D4VTfVr>fCsT?Z@ir!*k8)c> zs-F$lT9uEVMe#k@GmaNoT5WY*`TH7x06WDQ9yxEEx4O@D`Fm&mZ`xh84>%z0i00X- zjQgq`?G%#E#rr>=RdPSS5Rv(f)9bw?j*di-rSd z?9`R7@q8QkyjvRj3HHDl&Rz7rgY&!d``@&`=+(dc7k@o`?}^BZSCyCA=g^n48=hOT zega;HoZ}U16)(}-o%R36xvcBD!u^qvkulTXjU~pXR66KJpzAz zv$qF5u=V}$@K6`-H)tI2*Z*#5<@pd^4)o!|(kj~Poej6CD%a9}1^hweN%ST9KX}pp zNB5)u6Vm@9js0F5Z^OSvb$s}t=eM`SDWZ5Cg|87zf0**%z4o7+g7p7i{#EDlfA?$G&BiPJe@6bzeT4rbBjb1c zKWFpya*jp*=Mbl8&Z%F7_e1&o#suukABKj9tM<)h?>jiZ_uK!EW4ixMJMKG+(QN$i zVWU2Hr#NsIdNcN~wBH7-R^v%VzFO=5gCAvl#kbV>s_Gf@J5x&h5c&ps*(qQ&4tL(3 z2S4I>u639QEzK{$zf^uo)vhu3`S|`Qgzle}>jy4mXPWjJ)Y5PN-+OYp|D6)LN%>Kc zrKbHqpY9cPs5LD)!(MyOxd>o zkKav20fN9+r}<)jZ|*Y$dsO)!$4SQ;ne{Lqgm{G2*k9=HyI{pyc?-^XwN4~Lugzo{?u!D=+C`{ks{0n?t1 zWxM{D_LgCVcynlBakX;Y@)`fkj05S%r!YXB^<-!k4$8rgiBLe7b{wVi9C1XHBJaC1 z0jpKNi@gu`_BW{C)a>NQ1@ww(kLyzU?tihj&#`~4L$}gjFbj=8-EtiG>3>`fa`!PO z*OmV878c=m==rF|@nqhc&!vo@Bc;^yfbZ-*$hrC4eBYF&-^H%X&yGvK7yQK&uS-9- zs;BS%|JC{ZZ?6B&fmvv+e<$2N8&@;!?Z5xcb@e!q{)sF_uyXA3+D^NYP^~I-t*&(=OS<68Z0vGTpT&$BsvKU(+u%6(4V z@8#Lg)%8#xm1neHsTba#`rS_DbHsfbpF`ENF%AIUtKTo6l;>#tJYM-cQn}xy2#x`FkWWE#a{PDfc>sWWPZgdsVT-)>Bj3JNKZj!ebm;Ag% z1X7VtX(KF~M}J`4NM6X+l+3T_-)F{jnX*jjmXcF1@v7W^)cidVUI}h&{04rwbr{BL z>)}f9=lS3L8}s?$)QUapl~ah{+JW)e4fNNk=RjV7nm?+w|6Sx0WnK5>iaj4eJm5GP z8ox6+Tl?HOmOR*@C-{7R{%6czPu;<*?(-XJFPL^qgvRk&c_w!9@}Egw2d2A6Fpp;= z4QDB_E`R@vuOuFGy8n?ki~0IPHxc~#KNoi&$CRBtFL^ToOax-yJQjtZImdx7J&ZGn zyI|VzjdT2qFFh4cxcB5`JRZkL`z6s-O>)n1XXRd>J%8<+-n*NjViDA6>i*O={e5C&>CwYEqoNv9>Esj|*uy-p9B5&R2i_XLD!!KW3v@m*jVPo&@o_r6uJ3 z?>qQ833^9Yl6f8*c*6RIBWLGt?~KP}JVzEVPLHNAOhwKs z@_)Pg-zgkEiiLCQS;)t1-b249ZQZX)mCs%4{{!fUxSBtc@qxcPvy%uEU_Nbi)$?K? z`UHOOmL7wxt{A)gWUnkbL(eD!*BB!$> z^1aj7smcGk13X1VZ~Wo?kue#UBO{0p=P<4j5SDsZ^1Gz}-wi#v<^6v=99{>PH-FIb zf%d}u*CaUp|F?HFp;28?_+|#7Ng3)U?JOTtf+vqP($mF%)5J^G2i7I#FCm zDa49Y3(}bc7g)PCQ&xlVp2 z)~KUY@7o;Sd-w00d(XM|p7+jobv#F-|Mj}ycYH@Vdv@bS={N5#)?w7gyK1w{Bimp{ z%fUAJfAYclpa0#WdpuP|yiUcdu>W1m|3?2=|GvxZ?fE?GVfiKepV;%kH zUt5*wD^b%vw#)NAFYx;k$0_EgUjE-@`hV_fIT$eQ0ENBDE19p1J$qIt<;L$Ur7)z9 zdHPj+=OZnJ`_j~_dN=_6!g>k+bCWV|gEZ$P^?lf@Fr8B~{_-pgF8;?3r}{KydaMKb zbvs4`J!FY&V_Z{z<#%&^J~6QZa~)qH>kA#UORO8Q@Xv+O21n^FibgapV4)_<;(W3 z9p6^JtsSs-z}f+82do{icEH*JYX__yuy(-O0c!`W9k6!5+5u|^tR1j+z}f+82do{i zcEH*JYX__yuy(-Ofv0K*5T`2jKc^II3;&i{IZzMmII!cujsvR))(%)Zu$mok<^?7s z>CE$72ZjH+*D`&lvlw2-wxs(KE!|UL8b2Ce{fQsi%~>< z`Wy+=b7u8&TC2bOUt8ntPU8FqjuZU1FY!&elW3pdwrDv_N<1Fpu$Yecx1G3FwwrRv zW*E;mo8AW8oZag$`ZV7Dl5-V;lfi8_fxCnHUX*hb7-#2`xGP;>Yxy?qZt$=1VGPa- z<2?XV9yRIQTfmjVMf^(Qk`^!2m+>!gr-*9-el_?uI6;eWLJ&7_UjBpkyw8A>!8ii% z9u6YoNf3^RaUpTDi{#!~IV|Vj;9oG#Nyp)oiD!?vn^Kr@Sd-}>6+3qe}jMqp3N6++&s+J;~<6HKw*8kLF;`SRp7$?*90Q@WPpH8Rm;WaXD1l2dO zzs=?MsB&1&Kll!kf8f(403)Xu&*OQiH1R5rLSZ%kckeDA|Fjp$!Hnn!`=7WnT7ODB zAEt?2<9RfNOy*=c$hcyImreT{2xz>Vr!oH7kD7lY?>h0>vJ2zjj_Kd!{1ZQq@=`V8 zMHqe8?B!GIW3dy!Pr*1+FJT^N zb-$bPYwmV!r+RkN4$aqk_Q-v$C!wE*5#9;=r{<_q!s_4|E zbJf7%56~YGRo-)exIt>q$QQF$albbaS5=%({m#2vh-0Rro)Mb5+BCt z+S}pl&A@R+oTy*^KF$4MAn92=uWW+_Whs_Gc^>ga54_&J+q6(sq0( zVY^r6&!XSz&aprT^al1kMtv%;zYgGk=Gz6wGwjM%^POQ?{^JD~UovJw108=HRI0jp z;G1jzz+Q&>-@Gx7`_R_VS2vJ9z8~KyJ66{JNb-NE{}<7I$#?(pI(G@(;;L#rqAq+3 z`xfeVQdh2^9|rK5pE!#}H(MyEs=xP3H9bu}Q_gvmJ9nu~a2Sn!27e2BVQ7ck6R+_! raGdj4Z)`w+6{m>%2LJK#4dUl7PN}gm$ggc?divbC*=z9`o}2kEfiE*! diff --git a/Templates/BaseGame/game/core/images/window.png b/Templates/BaseGame/game/core/images/window.png deleted file mode 100644 index d9e8006e473974be6c97716e9ab9abc2e0e373e3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2559 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

y=B0vFoY*eFT;806|)ERK!%dbrTa%1TK9Bjd-9 zr^}Zwi-N<44;PRUD|p8mJa{mjI(14AQ>RXy1kGcDhbtX7ZX8XXJXzkw;#?xT(6?{j z3J3uh>Ba9w{MtcKu%x6!T&t}`aS|7W2Z3^ccTP&GivWbIUcH(oO`0Ui9XxnYavbA4 z%5?&-1*M?e%a<=BO5(h$uP-kz7Yjmkmb6|ZFE2pFMP2CIHEU?vv}sa=9LG41awk#B zq7Ia{QxaviS3x(c2?E@105;E zR9{~&)}l)PttOOhZ4I|2jx8a+gcuZitEhD4$`!Ms zqC#Rpix)38j~_p7vL`X?Id;V^)8uz~lf9ey`0?YYbl|`NbLrBhsl}e~gpM6MmSaf# z4vshyr^beQs(JmIo;`aOl}3*qEj}EA0K<$KpHnmYb-2Cy`a0>A>greGimhql#EIf{ zQjw&e`c!V3Oxq|YTv72CD&=tqUmt1-QPA>^J$LS0?e%#WP%j>b2t4qxk)&k#^5x0s z71t(8Q9LZ8M*WU3_*)q908x1nc$Lp*%%DMo2E{4rrM;IrQC4khIDr8hqD>W0WMK?v!wXo*Sox6w^%mnQ(TC_-zKFZS8^{EVS zw8ffyettoOj)7h%>FMkg2ntlMeRelK&RT}s7JUfZ@!Pi-cVw4ae$%~oO))8A$|GfAL#3^{}?&;db3pOiK3Vbm7-lsLCqW$rzmzSf~tuG+U5+V zVXEU)6!6+MGU2Q63p@-Ii4Dgv|CzlIPvV?FXa!eP9ecf5D)rhdDqD7VZzm^s6_5ed zvATFL*uvwpQIcZas^e4?@Y+@sZRN44Hk?X#VqekwO{wZa04bQlkd&h8*z3(wspp$j z5&tR*cDQ0W=(-9_a6EL`lmL_h1w*(07|LK40No;%f}xJHp|J7v=~MI2p+k`!3$Zta zudn2Hr!Bl(quZU34PWn{l{=8Jow`mDubt{-#iH18 z8mX&%Art`E>G4is6t7)JdqnF zTQ{Ikk}k)E6-v_O$=*DXcE(HIdgj!iH}mZ9Z6_!B?Z}atAEOE->2fHjP?9cB#4^d& z^)Dz%_7`Wmoo_5^VDG1sH4sUD!e1e9l7Sz8obiXr@Qttc&B~q5qToJHnKFgOefF7b zTeB1JoR=+IM&-N`?Y735a_lLxXE`S3g#FBjOTps0m=oerh)ZQ9_7odyQpbo#sU70F zm=oerUUq}0W9o{4lDL?YWiHUgoDh%7mP8bdjX7E8EM3eA@u+M`1U>0uPFD038*@TD zDq9lJ#heh2Qlg7FAs&@23Fu-@h({^W#hmQEuahaoedFu>r|5?ob5cVopo=+Kw*={8 zPKZY#E|m?@q9+8;7A#mm13vml>+7N9`t|GSHykF3+Fsfd5jlj}TcX9f=zv}*>dx>;V=&NpN9e@jtbDyKdCUjy1xJXsWE znAx*ux2K+D`2Jx+ck@Rk#fmp?-lW5a54WpDwOtRsGCpq%!8$1@@9io6?0Rb#Tc7lk zCr=XojYoS*RM+E^-Kx7^y?RCS=g$}25H%UW|2(2S#h+c@o)&Yv_kRJO_n_Zf_&8bs O0000(_@_GbJ<_dZw^Q+&I7EPrEnI(eqE51YbYz7T13zwEE$$n>MSVv_3!WR xqwIV#4BRgm4JXvHMKX&S7St`!IKaTf!=UB9TBWi;$P?&J22WQ%mvv4FO#lthVzU4M literal 0 HcmV?d00001 diff --git a/Templates/BaseGame/game/core/gui/images/thumbHighlightButton.png b/Templates/BaseGame/game/core/gui/images/thumbHighlightButton.png new file mode 100644 index 0000000000000000000000000000000000000000..9d83b75f31b965b79ff082e3a0f6e37e4c757c1b GIT binary patch literal 778 zcmV+l1NHogP)^%4Aj<$I1_}WqRRR$d z1~4y>8i*8ofd!i&&^88q;$hSbL@LC>f3!$o1Vs!3BNnyT#Q(FzWmcoc0=>O348mYE z7Di)XG#${gULYk9sZ%c;*}t7K1LT!85hAQlXK)Rq9_nInN)!ayOp3q3h5+?ZB@mfF0rU0$f5zPxzJM_-aIs(% zaacePd~O^y0Gb=Qf!I}_n|uR62^f})T}Q)U#D)ReA_iudz%LMg;eTdyg}>q%QN>TK zMd@&GqN(S^VIe239t#(mI2R5BxNsT3gC@>{!vG#!2JoSY^WiXn50?SFXyUv$4B(}@ z3n;D^SU}}Ft66XpQhe_P#$P)N-;>uu0ogpTEtG2ypD`}kb`^|A zTPQ=eg`y=V3C3g_aP84^23RtV84ZIG8wR5-l+hN-XbXi3Efk;Vaufm3qytH#c_6Z< zE(Ia9w3GDg3<4Lg-UZX@LvA#W$v3*3@#f9jjG!4Dq}d&UEfkp8X#0Q~5|tAdDOXK#LK`1pomC0NWAfc{C??-~a#s07*qo IM6N<$f>^aj6#xJL literal 0 HcmV?d00001 diff --git a/Templates/BaseGame/game/core/gui/images/window.png b/Templates/BaseGame/game/core/gui/images/window.png new file mode 100644 index 0000000000000000000000000000000000000000..d9e8006e473974be6c97716e9ab9abc2e0e373e3 GIT binary patch literal 2559 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 %deskResX) || (%resY >= %deskResY)) + { + warn("Warning: The requested windowed resolution is equal to or larger than the current desktop resolution. Attempting to find a better resolution"); + + %resCount = Canvas.getModeCount(); + for (%i = (%resCount - 1); %i >= 0; %i--) + { + %testRes = Canvas.getMode(%i); + %testResX = getWord(%testRes, $WORD::RES_X); + %testResY = getWord(%testRes, $WORD::RES_Y); + %testBPP = getWord(%testRes, $WORD::BITDEPTH); + + if (%testBPP != %bpp) + continue; + + if ((%testResX < %deskResX) && (%testResY < %deskResY)) + { + // This will work as our new resolution + %resX = %testResX; + %resY = %testResY; + + warn("Warning: Switching to \"" @ %resX SPC %resY SPC %bpp @ "\""); + + break; + } + } + } + } + + $pref::Video::Resolution = %resX SPC %resY; + $pref::Video::FullScreen = %fs; + $pref::Video::BitDepth = %bpp; + $pref::Video::RefreshRate = %rate; + $pref::Video::AA = %aa; + + if (%fs == 1 || %fs $= "true") + %fsLabel = "Yes"; + else + %fsLabel = "No"; + + echo("Accepted Mode: " NL + "--Resolution : " @ %resX SPC %resY NL + "--Full Screen : " @ %fsLabel NL + "--Bits Per Pixel : " @ %bpp NL + "--Refresh Rate : " @ %rate NL + "--AA TypeXLevel : " @ %aa NL + "--------------"); + + // Actually set the new video mode + Canvas.setVideoMode(%resX, %resY, %fs, %bpp, %rate, %aa); + + commandToServer('setClientAspectRatio', %resX, %resY); + + // AA piggybacks on the AA setting in $pref::Video::mode. + // We need to parse the setting between AA modes, and then it's level + // It's formatted as AATypexAALevel + // So, FXAAx4 or MLAAx2 + if ( isObject( FXAA_PostEffect ) ) + FXAA_PostEffect.isEnabled = ( %aa > 0 ) ? true : false; +} diff --git a/Templates/BaseGame/game/core/gui/scripts/cursor.cs b/Templates/BaseGame/game/core/gui/scripts/cursor.cs new file mode 100644 index 000000000..f71bc023a --- /dev/null +++ b/Templates/BaseGame/game/core/gui/scripts/cursor.cs @@ -0,0 +1,102 @@ +//----------------------------------------------------------------------------- +// 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. +//----------------------------------------------------------------------------- + +//--------------------------------------------------------------------------------------------- +// Cursor toggle functions. +//--------------------------------------------------------------------------------------------- +$cursorControlled = true; +function showCursor() +{ + if ($cursorControlled) + lockMouse(false); + Canvas.cursorOn(); +} + +function hideCursor() +{ + if ($cursorControlled) + lockMouse(true); + Canvas.cursorOff(); +} + +//--------------------------------------------------------------------------------------------- +// In the CanvasCursor package we add some additional functionality to the built-in GuiCanvas +// class, of which the global Canvas object is an instance. In this case, the behavior we want +// is for the cursor to automatically display, except when the only guis visible want no +// cursor - usually the in game interface. +//--------------------------------------------------------------------------------------------- +package CanvasCursorPackage +{ + +//--------------------------------------------------------------------------------------------- +// checkCursor +// The checkCursor method iterates through all the root controls on the canvas checking each +// ones noCursor property. If the noCursor property exists as anything other than false or an +// empty string on every control, the cursor will be hidden. +//--------------------------------------------------------------------------------------------- +function GuiCanvas::checkCursor(%this) +{ + %count = %this.getCount(); + for(%i = 0; %i < %count; %i++) + { + %control = %this.getObject(%i); + if ((%control.noCursor $= "") || !%control.noCursor) + { + showCursor(); + return; + } + } + // If we get here, every control requested a hidden cursor, so we oblige. + hideCursor(); +} + +//--------------------------------------------------------------------------------------------- +// The following functions override the GuiCanvas defaults that involve changing the content +// of the Canvas. Basically, all we are doing is adding a call to checkCursor to each one. +//--------------------------------------------------------------------------------------------- +function GuiCanvas::setContent(%this, %ctrl) +{ + Parent::setContent(%this, %ctrl); + %this.checkCursor(); +} + +function GuiCanvas::pushDialog(%this, %ctrl, %layer, %center) +{ + Parent::pushDialog(%this, %ctrl, %layer, %center); + %this.checkCursor(); +} + +function GuiCanvas::popDialog(%this, %ctrl) +{ + Parent::popDialog(%this, %ctrl); + %this.checkCursor(); +} + +function GuiCanvas::popLayer(%this, %layer) +{ + Parent::popLayer(%this, %layer); + %this.checkCursor(); +} + +}; + +activatePackage(CanvasCursorPackage); diff --git a/Templates/BaseGame/game/core/gui/scripts/fonts/Arial 10 (ansi).uft b/Templates/BaseGame/game/core/gui/scripts/fonts/Arial 10 (ansi).uft new file mode 100644 index 0000000000000000000000000000000000000000..2b564950050cfca995e66f048e0523428ff493b0 GIT binary patch literal 412 zcmZQ(U|?W%EXqvG;R3Qi07P>@F%ytx24VyN@mQf;5Dk%qsR4%?)Qy83;)lEIri7m zFZoExihWaFY>GaAyHfb_#$7>4rhD3-7VX{JcRHkY<;8EhWjEc^(!MS|x7jKnT~tu; z`y-fhfi55e9MJ#4lvSq~c?$DU2jYrb$q5Y1ZVG9@ Ja2IA^0RUczP(}a% literal 0 HcmV?d00001 diff --git a/Templates/BaseGame/game/core/gui/scripts/fonts/Arial 12 (ansi).uft b/Templates/BaseGame/game/core/gui/scripts/fonts/Arial 12 (ansi).uft new file mode 100644 index 0000000000000000000000000000000000000000..67a177016766c6f06b5b601c3336b9fea2ac75ba GIT binary patch literal 62 jcmZQ(U|?W%EXqvG;Q_Kh07P>_F*8U23jU*ldXO*xH#ZTF literal 0 HcmV?d00001 diff --git a/Templates/BaseGame/game/core/gui/scripts/fonts/Arial 14 (ansi).uft b/Templates/BaseGame/game/core/gui/scripts/fonts/Arial 14 (ansi).uft new file mode 100644 index 0000000000000000000000000000000000000000..f4f19745fb7ea405e3c544ab4380b665efbfde9c GIT binary patch literal 4631 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 b6sM#M<#jvpb9awrZFUL$u!K`tU*`B9%GMUT literal 0 HcmV?d00001 diff --git a/Templates/BaseGame/game/core/gui/scripts/fonts/Arial 16 (ansi).uft b/Templates/BaseGame/game/core/gui/scripts/fonts/Arial 16 (ansi).uft new file mode 100644 index 0000000000000000000000000000000000000000..ec996019dfe8c0fdc39ecd2cb8f3a59021328064 GIT binary patch literal 13031 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 U#C$+paVt3?At42ntauri09vTq4gdfE literal 0 HcmV?d00001 diff --git a/Templates/BaseGame/game/core/gui/scripts/fonts/Arial Bold 14 (ansi).uft b/Templates/BaseGame/game/core/gui/scripts/fonts/Arial Bold 14 (ansi).uft new file mode 100644 index 0000000000000000000000000000000000000000..4dbbddede62addac380eca861535ac39d2f3819b GIT binary patch literal 2669 zcmc(gdpMM76u`eR7mNrosa-n?>zZ;YOU01exP>&9T87ny+|sOTB}BQ@Xb^?RrC6a@ zk;|6sPMeg5by+*2MLRCz5(+7?^ZLGdnrB!3-Sa%}oO9maIp=-P`+nayXb6JvCc!?Q zehQ|6e%=y17YNW|$UyV7CU1ORK*T2j9v*Q;cp9@}^J8#456l7qT6o10UHOF|K*0b4 zG)&j8_z)z-(}KBhO(}$8d0H?Rwh00h1ZfjDi02QnZ=N?^?`XLnLfx*9DIG2Xd)$cb1p&(XpUD!T@ zP{Gpx1g;#rCQU#n|E&1Cf-5uD%*{mT>buHaGq(_-t3MkhYvxw0nOlv}fA0!Djr*UW zaKB81f?EIs2+;8J{M(8TLHs@Q&kBA+pCVN77Jv<}+lEjO3ub`;4QfG9=gKeqgbGsd zWrLuX2<3MK)&)^;BnP3ugS&t=yzZDlE{G7!Me+Ou2YX9#{ATcKh?A|%oFE9yqTov5 zo963zA0T_OnTc~)_Cyzvrg#WynkHg!LUE=Fk|G#uu)6gn-_pZAG9CzQ8VUALv$UZ|egBK6=a zDO#3NXrKz$l54r+W^0f^(j#1m;6%dq_Si@xbs`gK$L3yQUb zj-$F67$>@_TwCmm0^yPPa`Wlr>ZL);HV!t;QR|l@8KT*_rZo}|44YLZe`uYZlc3u! zgy==}b&w5G(}cWJhC(3|Ysr)$I(s1GLx7CpU=LHes)*^PRw&&VQ8ryKLbcyjXVBLw z)%j#{vNE1ZuE`uVI;Uc>s9Lg7&-oatBNnnxNGc%d_AES^cy-mPlV0ji4 z&yMuqxU_RmLK^BGR>F3L7{)zRaae*0iIJh9Dcdd6tt44ihY`=zaj;f{OF!UmIPx_P@zT;YGCD zu#%bT@b;B|X|lP!*&S1A%na|N!xsgf5zZT-yb;!OiN%(P*&%a&AQ3MVb8!$?+n?C5 z{3dJQh3*4oOVTCdwg5uWH1NiayW=7ziIAv--bWF zx$%f{1}lucoHHMaj!H^D#gW;s^zPRa6RfFdI@X>0*Po5%iRtf&T--+E`VapAtP-Jh literal 0 HcmV?d00001 diff --git a/Templates/BaseGame/game/core/gui/scripts/fonts/Arial Bold 16 (ansi).uft b/Templates/BaseGame/game/core/gui/scripts/fonts/Arial Bold 16 (ansi).uft new file mode 100644 index 0000000000000000000000000000000000000000..fb096776f37c76773bef44144599604436e1c8bb GIT binary patch literal 1198 zcmZQ(U|`^KEXqvGQE$SaLNPOx52T=g4M=kVF(Z`b0E>e}K>$Rv12ISz zL_=hGfGiNeE-M6)1j}NYECH2e0@BE`EMRddB)ypSDj>$^|@K978JRyuG5B zFYPJ8_JCgk2t*{r*hE-FWH>Y|Bm@!y1R$W`fkR?rJZ0y`T zKp-X&QN^DVv->Z5-#qulv6*Eiv) z*N4?xwX5UJ&N`=0+#dScWNy`L*H5L>=D#|zMg8BD*|TeA@xG3o_BLnIpVDbhlh?^j z%5o3&E&6M?csb8&laraepQps^xjD6N4WrJb_vwM@kALp#TM~a#Ywy2@=VO;%Kl{k; z@vhTW<))`_ElB4ebe{K=1iZfwl|jHxTI6{v%tK(Pv4E+ z=TH86e%X32wVkuxFiC`bnsNL4%l9g(Ar{7*sI`_#Qy-9cW<$SJUn(^e< z=Y8{@?JJ*F|GMb&-{}nZR9{|KIQjCl*>ULu@6+XN*029oEdDuX|J*Iw{ExGYR7`6g@ft;7yps<;JgQ$Wwo=o=d4Dp<5KmV>mvv4FO@T-zDgfCfKx_xZ6}OTT5)%IV zvjNEm|NWI2OlI@<%P@03D-d4U$Ju$7=SWO|nY2JLlOgvc8~rJ1tVwPvg>o8a85wpk H3YP!?K^+@u literal 0 HcmV?d00001 diff --git a/Templates/BaseGame/game/core/gui/scripts/fonts/Arial Bold 18 (ansi).uft b/Templates/BaseGame/game/core/gui/scripts/fonts/Arial Bold 18 (ansi).uft new file mode 100644 index 0000000000000000000000000000000000000000..1f8fdedd3337dae3859867addedafffcd75bd980 GIT binary patch literal 3066 zcmchYdpwle8poG0VJ0I}Y>jdYT~tz&OJW;xnMrO#ZhIF>ndm|;C4^yj)KoNEDM#|b zPTO_Mt&mHhWI}2bN}?o}+(L-XyS(Gmd(PJW^E{u=TF-jdcm1CAtY^LNj4%LzXn6dP z+hIkcV~5?BB9G9Zmk=~O;@2VVyNMyg#Yhtpc;Xy_v(Ruz!&0b6Hks=I5Jfy(3ANA@ zkOlyGu1D#-_B&lJpbJNq#c2N?SqVe`9(gT>VzqD#z$OfZT4<2KGXS79*8{K!@mQ_M z-28R{h3A{!7kV^~v4BGDd}W}A&p$S_k_^ED7#YnITS=yX!W`#wh8|t%grV4+(OYm8 zP?!nS%-^s0+`OlN!t-IZXk>2zo!@s}i$*?yp;#?SPyb`&NQ@Sn6{_V3C<*b9LW3SY z18{Y&|L^w-QdE0GKw(C3c0OnHM$!ay;cDaxD2#;F!Z85FbN!FLg;D{9`=ZrDJvy$! zP;6v0E1rPqR;sQNo3Uc>2Ty^S9bpPD-w5p_cJr&;&l^7 zT7OUOij(Aq=MS&Ee}}{wRBd$CDnDBnLUm@=>oGY_PM(Ik%RjhJw56+sWyRF^$Z9!l z){n+V^dIq!DIcV<=$`nP=eXvdq|?$arFL~XcmN^#sfz71nXuQL)9s5Z>|Tg(b;S=Q z{Q~Zn(atqBS}Uj8w3G>haerGo@04{Fb)G;!Z18LM_sUN20jN`nvW%;6 zfe&z(R9I{DinhPCz#UnTH6Sst&Kck}g zD0#4fniz*;1>-dqB|7uAx<#L5I?wQJW+ojE1eI3~*@A*)H*uFk8{KXxU0;=Brtf{{ zR;sDGiHEP)ivqPULfljSJ|dmn*TZ(V>;tLmnd&qc_|-V&R>c&> zUzP3?UwOp;yihe^ow~K2l>c~pc*0FxTH2QbvmZ07D5K5=XAI2bapEAZ7jroY%&GJ8!iSF5Ik?YyT+^#wQSrnAqAgn+H;s|RCz z`rPE@Wr`{4{h)cTTFs57#NvPM_+y-|40ad09bcBY>7lP$53k)m@T=n%2$b!;6= zGwkPeA>oB}_=(40oRJ!9xYGaH?k-B8$KG967h_JMTh zSOPUvw{Z~HctF#%E@a1T+Qm{dG)X`QZlhAzu3jkSx)Vbo5c3c2@URuW$T=v)lfX z-rMC#w96rQHIg_d23mbz&eRQj-A|JV{$>W=N*N{oMq+roWPJ|SPnw!8Ezn)mo5pi3 zqrPKQe||Z0JC1!kYv`GY2ChdfUTS@mRo-x%1Z_#Ch@?WCxltRhm)%V%3C+C_YM1N0 z-357P_Xf-Rs5VYDookS>{XF{F798`ix$BGr? z^6vr|CYHw8My~7)$Qb@9LQ_OqAktV!JK1`#zE*+_#7&-VsZH7vfqR@e^35PhJ9n{t zm9&Lr{J5%x$-CR~)~jy!y9@6X)9AcNx!g@MD!r8aF!H2t%4HXQo4)L?quLHZ7gwyj gzEMiUZ??izbQ#$)evm%<0A^7=iU0rr literal 0 HcmV?d00001 diff --git a/Templates/BaseGame/game/core/gui/scripts/fonts/ArialItalic 14 (ansi).uft b/Templates/BaseGame/game/core/gui/scripts/fonts/ArialItalic 14 (ansi).uft new file mode 100644 index 0000000000000000000000000000000000000000..5bac0316eb5a91b60214d283e613e06abf22c7a6 GIT binary patch literal 777 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 + \ No newline at end of file diff --git a/Templates/BaseGame/game/core/lighting/scripts/advancedLighting_Init.cs b/Templates/BaseGame/game/core/lighting/scripts/advancedLighting_Init.cs new file mode 100644 index 000000000..c7d357bb8 --- /dev/null +++ b/Templates/BaseGame/game/core/lighting/scripts/advancedLighting_Init.cs @@ -0,0 +1,68 @@ +//----------------------------------------------------------------------------- +// 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. +//----------------------------------------------------------------------------- + +/////////////////////////////////////////////////////////////////////////////// +// Default Prefs + +/* +$pref::LightManager::sgAtlasMaxDynamicLights = "16"; +$pref::LightManager::sgDynamicShadowDetailSize = "0"; +$pref::LightManager::sgDynamicShadowQuality = "0"; +$pref::LightManager::sgLightingProfileAllowShadows = "1"; +$pref::LightManager::sgLightingProfileQuality = "0"; +$pref::LightManager::sgMaxBestLights = "10"; +$pref::LightManager::sgMultipleDynamicShadows = "1"; +$pref::LightManager::sgShowCacheStats = "0"; +$pref::LightManager::sgUseBloom = ""; +$pref::LightManager::sgUseDRLHighDynamicRange = "0"; +$pref::LightManager::sgUseDynamicRangeLighting = "0"; +$pref::LightManager::sgUseDynamicShadows = "1"; +$pref::LightManager::sgUseToneMapping = ""; +*/ + +//exec( "./shaders.cs" ); +//exec( "./deferredShading.cs" ); + +function onActivateAdvancedLM() +{ + // Enable the offscreen target so that AL will work + // with MSAA back buffers and for HDR rendering. + AL_FormatToken.enable(); + + // Activate Deferred Shading + AL_DeferredShading.enable(); +} + +function onDeactivateAdvancedLM() +{ + // Disable the offscreen render target. + AL_FormatToken.disable(); + + // Deactivate Deferred Shading + AL_DeferredShading.disable(); +} + +function setAdvancedLighting() +{ + setLightManager( "Advanced Lighting" ); +} + diff --git a/Templates/BaseGame/game/core/lighting/scripts/advancedLighting_Shaders.cs b/Templates/BaseGame/game/core/lighting/scripts/advancedLighting_Shaders.cs new file mode 100644 index 000000000..a73598d9b --- /dev/null +++ b/Templates/BaseGame/game/core/lighting/scripts/advancedLighting_Shaders.cs @@ -0,0 +1,276 @@ +//----------------------------------------------------------------------------- +// 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. +//----------------------------------------------------------------------------- + + +// Vector Light State +new GFXStateBlockData( AL_VectorLightState ) +{ + blendDefined = true; + blendEnable = true; + blendSrc = GFXBlendOne; + blendDest = GFXBlendOne; + blendOp = GFXBlendOpAdd; + + zDefined = true; + zEnable = false; + zWriteEnable = false; + + samplersDefined = true; + samplerStates[0] = SamplerClampPoint; // G-buffer + mSamplerNames[0] = "deferredBuffer"; + samplerStates[1] = SamplerClampPoint; // Shadow Map (Do not change this to linear, as all cards can not filter equally.) + mSamplerNames[1] = "shadowMap"; + samplerStates[2] = SamplerClampPoint; // Shadow Map (Do not change this to linear, as all cards can not filter equally.) + mSamplerNames[2] = "dynamicShadowMap"; + samplerStates[3] = SamplerClampLinear; // SSAO Mask + mSamplerNames[3] = "ssaoMask"; + samplerStates[4] = SamplerWrapPoint; // Random Direction Map + + cullDefined = true; + cullMode = GFXCullNone; + + stencilDefined = true; + stencilEnable = true; + stencilFailOp = GFXStencilOpKeep; + stencilZFailOp = GFXStencilOpKeep; + stencilPassOp = GFXStencilOpKeep; + stencilFunc = GFXCmpLess; + stencilRef = 0; +}; + +// Vector Light Material +new ShaderData( AL_VectorLightShader ) +{ + DXVertexShaderFile = $Core::CommonShaderPath @ "/lighting/advanced/farFrustumQuadV.hlsl"; + DXPixelShaderFile = $Core::CommonShaderPath @ "/lighting/advanced/vectorLightP.hlsl"; + + OGLVertexShaderFile = $Core::CommonShaderPath @ "/lighting/advanced/gl/farFrustumQuadV.glsl"; + OGLPixelShaderFile = $Core::CommonShaderPath @ "/lighting/advanced/gl/vectorLightP.glsl"; + + samplerNames[0] = "$deferredBuffer"; + samplerNames[1] = "$shadowMap"; + samplerNames[2] = "$dynamicShadowMap"; + samplerNames[3] = "$ssaoMask"; + samplerNames[4] = "$gTapRotationTex"; + samplerNames[5] = "$lightBuffer"; + samplerNames[6] = "$colorBuffer"; + samplerNames[7] = "$matInfoBuffer"; + + pixVersion = 3.0; +}; + +new CustomMaterial( AL_VectorLightMaterial ) +{ + shader = AL_VectorLightShader; + stateBlock = AL_VectorLightState; + + sampler["deferredBuffer"] = "#deferred"; + sampler["shadowMap"] = "$dynamiclight"; + sampler["dynamicShadowMap"] = "$dynamicShadowMap"; + sampler["ssaoMask"] = "#ssaoMask"; + sampler["lightBuffer"] = "#lightinfo"; + sampler["colorBuffer"] = "#color"; + sampler["matInfoBuffer"] = "#matinfo"; + + target = "lightinfo"; + + pixVersion = 3.0; +}; + +//------------------------------------------------------------------------------ + +// Convex-geometry light states +new GFXStateBlockData( AL_ConvexLightState ) +{ + blendDefined = true; + blendEnable = true; + blendSrc = GFXBlendOne; + blendDest = GFXBlendOne; + blendOp = GFXBlendOpAdd; + + zDefined = true; + zEnable = true; + zWriteEnable = false; + zFunc = GFXCmpGreaterEqual; + + samplersDefined = true; + samplerStates[0] = SamplerClampPoint; // G-buffer + mSamplerNames[0] = "deferredBuffer"; + samplerStates[1] = SamplerClampPoint; // Shadow Map (Do not use linear, these are perspective projections) + mSamplerNames[1] = "shadowMap"; + samplerStates[2] = SamplerClampPoint; // Shadow Map (Do not use linear, these are perspective projections) + mSamplerNames[2] = "dynamicShadowMap"; + samplerStates[3] = SamplerClampLinear; // Cookie Map + samplerStates[4] = SamplerWrapPoint; // Random Direction Map + + cullDefined = true; + cullMode = GFXCullCW; + + stencilDefined = true; + stencilEnable = true; + stencilFailOp = GFXStencilOpKeep; + stencilZFailOp = GFXStencilOpKeep; + stencilPassOp = GFXStencilOpKeep; + stencilFunc = GFXCmpLess; + stencilRef = 0; +}; + +// Point Light Material +new ShaderData( AL_PointLightShader ) +{ + DXVertexShaderFile = $Core::CommonShaderPath @ "/lighting/advanced/convexGeometryV.hlsl"; + DXPixelShaderFile = $Core::CommonShaderPath @ "/lighting/advanced/pointLightP.hlsl"; + + OGLVertexShaderFile = $Core::CommonShaderPath @ "/lighting/advanced/gl/convexGeometryV.glsl"; + OGLPixelShaderFile = $Core::CommonShaderPath @ "/lighting/advanced/gl/pointLightP.glsl"; + + samplerNames[0] = "$deferredBuffer"; + samplerNames[1] = "$shadowMap"; + samplerNames[2] = "$dynamicShadowMap"; + samplerNames[3] = "$cookieMap"; + samplerNames[4] = "$gTapRotationTex"; + samplerNames[5] = "$lightBuffer"; + samplerNames[6] = "$colorBuffer"; + samplerNames[7] = "$matInfoBuffer"; + + pixVersion = 3.0; +}; + +new CustomMaterial( AL_PointLightMaterial ) +{ + shader = AL_PointLightShader; + stateBlock = AL_ConvexLightState; + + sampler["deferredBuffer"] = "#deferred"; + sampler["shadowMap"] = "$dynamiclight"; + sampler["dynamicShadowMap"] = "$dynamicShadowMap"; + sampler["cookieMap"] = "$dynamiclightmask"; + sampler["lightBuffer"] = "#lightinfo"; + sampler["colorBuffer"] = "#color"; + sampler["matInfoBuffer"] = "#matinfo"; + + target = "lightinfo"; + + pixVersion = 3.0; +}; + +// Spot Light Material +new ShaderData( AL_SpotLightShader ) +{ + DXVertexShaderFile = $Core::CommonShaderPath @ "/lighting/advanced/convexGeometryV.hlsl"; + DXPixelShaderFile = $Core::CommonShaderPath @ "/lighting/advanced/spotLightP.hlsl"; + + OGLVertexShaderFile = $Core::CommonShaderPath @ "/lighting/advanced/gl/convexGeometryV.glsl"; + OGLPixelShaderFile = $Core::CommonShaderPath @ "/lighting/advanced/gl/spotLightP.glsl"; + + samplerNames[0] = "$deferredBuffer"; + samplerNames[1] = "$shadowMap"; + samplerNames[2] = "$dynamicShadowMap"; + samplerNames[3] = "$cookieMap"; + samplerNames[4] = "$gTapRotationTex"; + samplerNames[5] = "$lightBuffer"; + samplerNames[6] = "$colorBuffer"; + samplerNames[7] = "$matInfoBuffer"; + + pixVersion = 3.0; +}; + +new CustomMaterial( AL_SpotLightMaterial ) +{ + shader = AL_SpotLightShader; + stateBlock = AL_ConvexLightState; + + sampler["deferredBuffer"] = "#deferred"; + sampler["shadowMap"] = "$dynamiclight"; + sampler["dynamicShadowMap"] = "$dynamicShadowMap"; + sampler["cookieMap"] = "$dynamiclightmask"; + sampler["lightBuffer"] = "#lightinfo"; + sampler["colorBuffer"] = "#color"; + sampler["matInfoBuffer"] = "#matinfo"; + + target = "lightinfo"; + + pixVersion = 3.0; +}; + +/// This material is used for generating deferred +/// materials for objects that do not have materials. +new Material( AL_DefaultDeferredMaterial ) +{ + // We need something in the first pass else it + // won't create a proper material instance. + // + // We use color here because some objects may not + // have texture coords in their vertex format... + // for example like terrain. + // + diffuseColor[0] = "1 1 1 1"; +}; + +/// This material is used for generating shadow +/// materials for objects that do not have materials. +new Material( AL_DefaultShadowMaterial ) +{ + // We need something in the first pass else it + // won't create a proper material instance. + // + // We use color here because some objects may not + // have texture coords in their vertex format... + // for example like terrain. + // + diffuseColor[0] = "1 1 1 1"; + + // This is here mostly for terrain which uses + // this material to create its shadow material. + // + // At sunset/sunrise the sun is looking thru + // backsides of the terrain which often are not + // closed. By changing the material to be double + // sided we avoid holes in the shadowed geometry. + // + doubleSided = true; +}; + +// Particle System Point Light Material +new ShaderData( AL_ParticlePointLightShader ) +{ + DXVertexShaderFile = $Core::CommonShaderPath @ "/lighting/advanced/particlePointLightV.hlsl"; + DXPixelShaderFile = $Core::CommonShaderPath @ "/lighting/advanced/particlePointLightP.hlsl"; + + OGLVertexShaderFile = $Core::CommonShaderPath @ "/lighting/advanced/gl/convexGeometryV.glsl"; + OGLPixelShaderFile = $Core::CommonShaderPath @ "/lighting/advanced/gl/pointLightP.glsl"; + + samplerNames[0] = "$deferredBuffer"; + + pixVersion = 3.0; +}; + +new CustomMaterial( AL_ParticlePointLightMaterial ) +{ + shader = AL_ParticlePointLightShader; + stateBlock = AL_ConvexLightState; + + sampler["deferredBuffer"] = "#deferred"; + target = "lightinfo"; + + pixVersion = 3.0; +}; diff --git a/Templates/BaseGame/game/core/lighting/scripts/basicLighting_Init.cs b/Templates/BaseGame/game/core/lighting/scripts/basicLighting_Init.cs new file mode 100644 index 000000000..99be20c5c --- /dev/null +++ b/Templates/BaseGame/game/core/lighting/scripts/basicLighting_Init.cs @@ -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. +//----------------------------------------------------------------------------- + +//exec( "./shadowFilter.cs" ); + +singleton GFXStateBlockData( BL_ProjectedShadowSBData ) +{ + blendDefined = true; + blendEnable = true; + blendSrc = GFXBlendDestColor; + blendDest = GFXBlendZero; + + zDefined = true; + zEnable = true; + zWriteEnable = false; + + samplersDefined = true; + samplerStates[0] = SamplerClampLinear; + vertexColorEnable = true; +}; + +singleton ShaderData( BL_ProjectedShadowShaderData ) +{ + DXVertexShaderFile = $Core::CommonShaderPath @ "/projectedShadowV.hlsl"; + DXPixelShaderFile = $Core::CommonShaderPath @ "/projectedShadowP.hlsl"; + + OGLVertexShaderFile = $Core::CommonShaderPath @ "/gl/projectedShadowV.glsl"; + OGLPixelShaderFile = $Core::CommonShaderPath @ "/gl/projectedShadowP.glsl"; + + samplerNames[0] = "inputTex"; + + pixVersion = 2.0; +}; + +singleton CustomMaterial( BL_ProjectedShadowMaterial ) +{ + sampler["inputTex"] = "$miscbuff"; + + shader = BL_ProjectedShadowShaderData; + stateBlock = BL_ProjectedShadowSBData; + version = 2.0; + forwardLit = true; +}; + +function onActivateBasicLM() +{ + // If HDR is enabled... enable the special format token. + if ( $platform !$= "macos" && HDRPostFx.isEnabled ) + AL_FormatToken.enable(); + + // Create render pass for projected shadow. + new RenderPassManager( BL_ProjectedShadowRPM ); + + // Create the mesh bin and add it to the manager. + %meshBin = new RenderMeshMgr(); + BL_ProjectedShadowRPM.addManager( %meshBin ); + + // Add both to the root group so that it doesn't + // end up in the MissionCleanup instant group. + RootGroup.add( BL_ProjectedShadowRPM ); + RootGroup.add( %meshBin ); +} + +function onDeactivateBasicLM() +{ + // Delete the pass manager which also deletes the bin. + BL_ProjectedShadowRPM.delete(); +} + +function setBasicLighting() +{ + setLightManager( "Basic Lighting" ); +} diff --git a/Templates/BaseGame/game/core/lighting/scripts/basicLighting_shadowFilter.cs b/Templates/BaseGame/game/core/lighting/scripts/basicLighting_shadowFilter.cs new file mode 100644 index 000000000..5aea7b607 --- /dev/null +++ b/Templates/BaseGame/game/core/lighting/scripts/basicLighting_shadowFilter.cs @@ -0,0 +1,76 @@ +//----------------------------------------------------------------------------- +// 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. +//----------------------------------------------------------------------------- + + +singleton ShaderData( BL_ShadowFilterShaderV ) +{ + DXVertexShaderFile = $Core::CommonShaderPath @ "/lighting/basic/shadowFilterV.hlsl"; + DXPixelShaderFile = $Core::CommonShaderPath @ "/lighting/basic/shadowFilterP.hlsl"; + + OGLVertexShaderFile = $Core::CommonShaderPath @ "/lighting/basic/gl/shadowFilterV.glsl"; + OGLPixelShaderFile = $Core::CommonShaderPath @ "/lighting/basic/gl/shadowFilterP.glsl"; + + samplerNames[0] = "$diffuseMap"; + + defines = "BLUR_DIR=float2(1.0,0.0)"; + + pixVersion = 2.0; +}; + +singleton ShaderData( BL_ShadowFilterShaderH : BL_ShadowFilterShaderV ) +{ + defines = "BLUR_DIR=float2(0.0,1.0)"; +}; + + +singleton GFXStateBlockData( BL_ShadowFilterSB : PFX_DefaultStateBlock ) +{ + colorWriteDefined=true; + colorWriteRed=false; + colorWriteGreen=false; + colorWriteBlue=false; + blendDefined = true; + blendEnable = true; +}; + +// NOTE: This is ONLY used in Basic Lighting, and +// only directly by the ProjectedShadow. It is not +// meant to be manually enabled like other PostEffects. +singleton PostEffect( BL_ShadowFilterPostFx ) +{ + // Blur vertically + shader = BL_ShadowFilterShaderV; + stateBlock = PFX_DefaultStateBlock; + targetClear = "PFXTargetClear_OnDraw"; + targetClearColor = "0 0 0 0"; + texture[0] = "$inTex"; + target = "$outTex"; + + // Blur horizontal + new PostEffect() + { + shader = BL_ShadowFilterShaderH; + stateBlock = PFX_DefaultStateBlock; + texture[0] = "$inTex"; + target = "$outTex"; + }; +}; diff --git a/Templates/BaseGame/game/core/lighting/scripts/deferredShading.cs b/Templates/BaseGame/game/core/lighting/scripts/deferredShading.cs new file mode 100644 index 000000000..5dbacd2e3 --- /dev/null +++ b/Templates/BaseGame/game/core/lighting/scripts/deferredShading.cs @@ -0,0 +1,71 @@ +singleton ShaderData( ClearGBufferShader ) +{ + DXVertexShaderFile = $Core::CommonShaderPath @ "/lighting/advanced/deferredClearGBufferV.hlsl"; + DXPixelShaderFile = $Core::CommonShaderPath @ "/lighting/advanced/deferredClearGBufferP.hlsl"; + + OGLVertexShaderFile = $Core::CommonShaderPath @ "/postFX/gl/postFxV.glsl"; + OGLPixelShaderFile = $Core::CommonShaderPath @ "/lighting/advanced/gl/deferredClearGBufferP.glsl"; + + pixVersion = 2.0; +}; + +singleton ShaderData( DeferredColorShader ) +{ + DXVertexShaderFile = $Core::CommonShaderPath @ "/postFx/postFxV.hlsl"; + DXPixelShaderFile = $Core::CommonShaderPath @ "/lighting/advanced/deferredColorShaderP.hlsl"; + + OGLVertexShaderFile = $Core::CommonShaderPath @ "/postFX/gl/postFxV.glsl"; + OGLPixelShaderFile = $Core::CommonShaderPath @ "/lighting/advanced/gl/deferredColorShaderP.glsl"; + + pixVersion = 2.0; +}; + +// Primary Deferred Shader +new GFXStateBlockData( AL_DeferredShadingState : PFX_DefaultStateBlock ) +{ + cullMode = GFXCullNone; + + blendDefined = true; + blendEnable = true; + blendSrc = GFXBlendSrcAlpha; + blendDest = GFXBlendInvSrcAlpha; + + samplersDefined = true; + samplerStates[0] = SamplerWrapLinear; + samplerStates[1] = SamplerWrapLinear; + samplerStates[2] = SamplerWrapLinear; + samplerStates[3] = SamplerWrapLinear; + samplerStates[4] = SamplerWrapLinear; +}; + +new ShaderData( AL_DeferredShader ) +{ + DXVertexShaderFile = $Core::CommonShaderPath @ "/postFX/postFxV.hlsl"; + DXPixelShaderFile = $Core::CommonShaderPath @ "/lighting/advanced/deferredShadingP.hlsl"; + + OGLVertexShaderFile = $Core::CommonShaderPath @ "/postFX/gl/postFxV.glsl"; + OGLPixelShaderFile = $Core::CommonShaderPath @ "/lighting/advanced/gl/deferredShadingP.glsl"; + + samplerNames[0] = "colorBufferTex"; + samplerNames[1] = "lightDeferredTex"; + samplerNames[2] = "matInfoTex"; + samplerNames[3] = "deferredTex"; + + pixVersion = 2.0; +}; + +singleton PostEffect( AL_DeferredShading ) +{ + renderTime = "PFXAfterBin"; + renderBin = "SkyBin"; + shader = AL_DeferredShader; + stateBlock = AL_DeferredShadingState; + texture[0] = "#color"; + texture[1] = "#lightinfo"; + texture[2] = "#matinfo"; + texture[3] = "#deferred"; + + target = "$backBuffer"; + renderPriority = 10000; + allowReflectPass = true; +}; \ No newline at end of file diff --git a/Templates/BaseGame/game/core/lighting/scripts/lighting.cs b/Templates/BaseGame/game/core/lighting/scripts/lighting.cs new file mode 100644 index 000000000..b7d4034ff --- /dev/null +++ b/Templates/BaseGame/game/core/lighting/scripts/lighting.cs @@ -0,0 +1,74 @@ +//----------------------------------------------------------------------------- +// 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 initLightingSystems(%manager) +{ + echo( "\nInitializing Lighting Systems" ); + + // First exec the scripts for the different light managers + // in the lighting folder. + /*%pattern = "./lighting/*//*init.cs"; + %file = findFirstFile( %pattern ); + if ( %file $= "" ) + { + // Try for DSOs next. + %pattern = "./lighting/*//*init.cs.dso"; + %file = findFirstFile( %pattern ); + } + + while( %file !$= "" ) + { + exec( %file ); + %file = findNextFile( %pattern ); + }*/ + + // Try the perfered one first. + %success = setLightManager(%manager); + + // Did we completely fail to initialize a light manager? + if (!%success) + { + // If we completely failed to initialize a light + // manager then the 3d scene cannot be rendered. + quitWithErrorMessage( "Failed to set a light manager!" ); + } +} + +//--------------------------------------------------------------------------------------------- + +function onLightManagerActivate( %lmName ) +{ + // Call activation callbacks. + %activateNewFn = "onActivate" @ getWord( %lmName, 0 ) @ "LM"; + if( isFunction( %activateNewFn ) ) + eval( %activateNewFn @ "();" ); +} + +//--------------------------------------------------------------------------------------------- + +function onLightManagerDeactivate( %lmName ) +{ + // Call deactivation callback. + %deactivateOldFn = "onDeactivate" @ getWord( %lmName, 0 ) @ "LM"; + if( isFunction( %deactivateOldFn ) ) + eval( %deactivateOldFn @ "();" ); +} diff --git a/Templates/BaseGame/game/core/lighting/scripts/shadowMaps_Init.cs b/Templates/BaseGame/game/core/lighting/scripts/shadowMaps_Init.cs new file mode 100644 index 000000000..f4875bf08 --- /dev/null +++ b/Templates/BaseGame/game/core/lighting/scripts/shadowMaps_Init.cs @@ -0,0 +1,32 @@ +//----------------------------------------------------------------------------- +// 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. +//----------------------------------------------------------------------------- + + +new ShaderData(BlurDepthShader) +{ + DXVertexShaderFile = $Core::CommonShaderPath @ "/lighting/shadowMap/boxFilterV.hlsl"; + DXPixelShaderFile = $Core::CommonShaderPath @ "/lighting/shadowMap/boxFilterP.hlsl"; + + OGLVertexShaderFile = $Core::CommonShaderPath @ "/lighting/shadowMap/gl/boxFilterV.glsl"; + OGLPixelShaderFile = $Core::CommonShaderPath @ "/lighting/shadowMap/gl/boxFilterP.glsl"; + pixVersion = 2.0; +}; diff --git a/Templates/BaseGame/game/core/postFX/Core_PostFX.cs b/Templates/BaseGame/game/core/postFX/Core_PostFX.cs new file mode 100644 index 000000000..d36d912ab --- /dev/null +++ b/Templates/BaseGame/game/core/postFX/Core_PostFX.cs @@ -0,0 +1,33 @@ + +function Core_PostFX::onCreate(%this) +{ + // + exec("./scripts/postFx.cs"); + /*exec("./scripts/postFxManager.gui.cs"); + exec("./scripts/postFxManager.gui.settings.cs"); + exec("./scripts/postFxManager.persistance.cs"); + + exec("./scripts/default.postfxpreset.cs"); + + exec("./scripts/caustics.cs"); + exec("./scripts/chromaticLens.cs"); + exec("./scripts/dof.cs"); + exec("./scripts/edgeAA.cs"); + exec("./scripts/flash.cs"); + exec("./scripts/fog.cs"); + exec("./scripts/fxaa.cs"); + exec("./scripts/GammaPostFX.cs"); + exec("./scripts/glow.cs"); + exec("./scripts/hdr.cs"); + exec("./scripts/lightRay.cs"); + exec("./scripts/MLAA.cs"); + exec("./scripts/MotionBlurFx.cs"); + exec("./scripts/ovrBarrelDistortion.cs"); + exec("./scripts/ssao.cs"); + exec("./scripts/turbulence.cs"); + exec("./scripts/vignette.cs");*/ +} + +function Core_PostFX::onDestroy(%this) +{ +} \ No newline at end of file diff --git a/Templates/BaseGame/game/core/postFX/Core_PostFX.module b/Templates/BaseGame/game/core/postFX/Core_PostFX.module new file mode 100644 index 000000000..627a32d94 --- /dev/null +++ b/Templates/BaseGame/game/core/postFX/Core_PostFX.module @@ -0,0 +1,10 @@ + + \ No newline at end of file diff --git a/Templates/BaseGame/game/core/postFX/guis/postFxManager.gui b/Templates/BaseGame/game/core/postFX/guis/postFxManager.gui new file mode 100644 index 000000000..6a704eb65 --- /dev/null +++ b/Templates/BaseGame/game/core/postFX/guis/postFxManager.gui @@ -0,0 +1,2755 @@ +//--- OBJECT WRITE BEGIN --- +%guiContent = new GuiControl(PostFXManager) { + position = "0 0"; + extent = "1024 768"; + minExtent = "8 8"; + horizSizing = "width"; + vertSizing = "height"; + profile = "GuiModelessDialogProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "1"; + canSave = "1"; + canSaveDynamicFields = "1"; + + new DbgFileView() { + position = "0 0"; + extent = "8 2"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiDefaultProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "1"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiWindowCtrl(ppOptionsWindow) { + text = "PostFX Manager"; + resizeWidth = "0"; + resizeHeight = "0"; + canMove = "1"; + canClose = "1"; + canMinimize = "0"; + canMaximize = "0"; + canCollapse = "0"; + closeCommand = "Canvas.popDialog(PostFXManager);"; + edgeSnap = "0"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "0"; + anchorLeft = "1"; + anchorRight = "0"; + position = "306 216"; + extent = "411 336"; + minExtent = "8 8"; + horizSizing = "center"; + vertSizing = "center"; + profile = "GuiWindowProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "1"; + canSave = "1"; + canSaveDynamicFields = "0"; + + new GuiBitmapBorderCtrl() { + position = "11 77"; + extent = "390 216"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiTabBorderProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiTabBookCtrl(ppOptionsTabBook) { + tabPosition = "Top"; + tabMargin = "7"; + minTabWidth = "32"; + tabHeight = "20"; + allowReorder = "0"; + defaultPage = "-1"; + selectedPage = "1"; + frontTabPadding = "0"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "0"; + anchorLeft = "1"; + anchorRight = "0"; + position = "11 58"; + extent = "394 233"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiTabBookProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "1"; + canSave = "1"; + canSaveDynamicFields = "0"; + + new GuiTabPageCtrl(ppOptionsSSAOTab) { + fitBook = "0"; + text = "SSAO"; + maxLength = "1024"; + docking = "Client"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "1"; + anchorLeft = "1"; + anchorRight = "1"; + position = "0 20"; + extent = "394 213"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiTabPageProfile"; + visible = "0"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + tooltip = "Options for the Screen Space Ambient Occlusion postFX"; + hovertime = "1000"; + isContainer = "1"; + canSave = "1"; + canSaveDynamicFields = "0"; + + new GuiBitmapBorderCtrl() { + position = "12 30"; + extent = "365 170"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiTabBorderProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "1"; + }; + new GuiTabBookCtrl(ppOptionsSSAOOptions) { + tabPosition = "Top"; + tabMargin = "7"; + minTabWidth = "64"; + tabHeight = "20"; + allowReorder = "0"; + defaultPage = "-1"; + selectedPage = "2"; + frontTabPadding = "0"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "0"; + anchorLeft = "1"; + anchorRight = "0"; + position = "12 11"; + extent = "362 185"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiTabBookProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "1"; + canSave = "1"; + canSaveDynamicFields = "0"; + + new GuiTabPageCtrl(ppOptionsSSAOGeneralTab) { + fitBook = "0"; + text = "General"; + maxLength = "1024"; + docking = "Client"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "1"; + anchorLeft = "1"; + anchorRight = "1"; + position = "0 20"; + extent = "362 165"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiTabPageProfile"; + visible = "0"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + tooltip = "Contains general overall settings for the SSAO postFX"; + hovertime = "1000"; + isContainer = "1"; + canSave = "1"; + canSaveDynamicFields = "0"; + + new GuiTextCtrl(ppOptionsSSAOOverallStrengthLabel) { + text = "Overall Strength"; + maxLength = "1024"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "0"; + anchorLeft = "1"; + anchorRight = "0"; + position = "31 57"; + extent = "77 18"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiTextProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + tooltip = "Controls the overall strength of the Ambient Occlusion effect."; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiTextCtrl(ppOptionsSSAOBlurDepthLabel) { + text = "Blur (Softness)"; + maxLength = "1024"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "0"; + anchorLeft = "1"; + anchorRight = "0"; + position = "38 85"; + extent = "73 18"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiTextProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + tooltip = "Controls the amount of softness in the SSAO, overall."; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiTextCtrl(ppOptionsSSAOBlurNormalLabel) { + text = "Blur (Normal Maps)"; + maxLength = "1024"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "0"; + anchorLeft = "1"; + anchorRight = "0"; + position = "19 112"; + extent = "92 18"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiTextProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + tooltip = "Controls the amount of softness in the SSAO, in the normal maps."; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiPopUpMenuCtrl(ppOptionsSSAOQuality) { + maxPopupHeight = "200"; + sbUsesNAColor = "0"; + reverseTextList = "0"; + bitmapBounds = "16 16"; + text = "Low"; + maxLength = "1024"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "0"; + anchorLeft = "1"; + anchorRight = "0"; + position = "120 28"; + extent = "211 20"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiPopUpMenuProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiTextCtrl(ppOptionsSSAOQualityLabel) { + text = "Quality"; + maxLength = "1024"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "0"; + anchorLeft = "1"; + anchorRight = "0"; + position = "76 29"; + extent = "32 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 GuiSliderCtrl(ppOptionsSSAOOverallStrength) { + range = "0 50"; + ticks = "1000"; + snap = "0"; + value = "2"; + position = "120 56"; + extent = "211 17"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiSliderBoxProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiSliderCtrl(ppOptionsSSAOBlurDepth) { + range = "0 0.3"; + ticks = "1000"; + snap = "0"; + value = "0.001"; + position = "120 86"; + extent = "211 17"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiSliderBoxProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiSliderCtrl(ppOptionsSSAOBlurNormal) { + range = "0 1"; + ticks = "1000"; + snap = "0"; + value = "0.95"; + position = "119 113"; + extent = "212 17"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiSliderBoxProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + }; + new GuiTabPageCtrl(ppOptionsSSAONearTab) { + fitBook = "0"; + text = "Near"; + maxLength = "1024"; + docking = "Client"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "1"; + anchorLeft = "1"; + anchorRight = "1"; + position = "0 20"; + extent = "362 165"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiTabPageProfile"; + visible = "0"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + tooltip = "Contains settings for the near range ambient occlusion aspect of the SSAO postFX"; + hovertime = "1000"; + isContainer = "1"; + canSave = "1"; + canSaveDynamicFields = "0"; + + new GuiSliderCtrl(ppOptionsSSAONearRadius) { + range = "0.001 5"; + ticks = "1000"; + snap = "0"; + value = "0.1"; + position = "122 17"; + extent = "221 17"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiSliderBoxProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiSliderCtrl(ppOptionsSSAONearDepthMin) { + range = "0 5"; + ticks = "1000"; + snap = "0"; + value = "0.1"; + position = "122 62"; + extent = "221 17"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiSliderBoxProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiSliderCtrl(ppOptionsSSAONearStrength) { + range = "0 20"; + ticks = "1000"; + snap = "0"; + value = "6"; + position = "122 39"; + extent = "221 17"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiSliderBoxProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiTextCtrl(ppOptionsSSAONearRadiusLabel) { + text = "Radius"; + maxLength = "1024"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "0"; + anchorLeft = "1"; + anchorRight = "0"; + position = "80 16"; + extent = "34 18"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiTextProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + tooltip = "Controls the near/small radius SSAO reach."; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiTextCtrl(ppOptionsSSAONearStrengthLabel) { + text = "Strength"; + maxLength = "1024"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "0"; + anchorLeft = "1"; + anchorRight = "0"; + position = "73 38"; + extent = "41 18"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiTextProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + tooltip = "Controls the near/small radius SSAO strength."; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiTextCtrl(ppOptionsSSAONearDepthMinLabel) { + text = "Depth Min"; + maxLength = "1024"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "0"; + anchorLeft = "1"; + anchorRight = "0"; + position = "66 61"; + extent = "48 18"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiTextProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + tooltip = "Controls the near/small radius SSAO minimum depth value."; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiTextCtrl(ppOptionsSSAONearDepthMaxLabel) { + text = "Depth Max"; + maxLength = "1024"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "0"; + anchorLeft = "1"; + anchorRight = "0"; + position = "62 85"; + extent = "52 18"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiTextProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + tooltip = "Controls the near/small radius SSAO maximum depth value."; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiSliderCtrl(ppOptionsSSAONearDepthMax) { + range = "0 50"; + ticks = "1000"; + snap = "0"; + value = "1"; + position = "122 86"; + extent = "221 17"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiSliderBoxProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiSliderCtrl(ppOptionsSSAONearToleranceNormal) { + range = "0 2"; + ticks = "1000"; + snap = "0"; + value = "0"; + position = "122 133"; + extent = "103 17"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiSliderBoxProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiSliderCtrl(ppOptionsSSAONearTolerancePower) { + range = "0 2"; + ticks = "1000"; + snap = "0"; + value = "1"; + position = "246 133"; + extent = "97 17"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiSliderBoxProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiTextCtrl(ppOptionsSSAONearToleranceLabel2) { + text = "Tolerance / Power"; + maxLength = "1024"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "0"; + anchorLeft = "1"; + anchorRight = "0"; + position = "24 132"; + extent = "92 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 GuiTextCtrl(ppOptionsSSAONearToleranceLabel1) { + text = "Normal Maps : "; + maxLength = "1024"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "0"; + anchorLeft = "1"; + anchorRight = "0"; + position = "19 113"; + extent = "71 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 GuiTabPageCtrl(ppOptionsSSAOFarTab) { + fitBook = "0"; + text = "Far"; + maxLength = "1024"; + docking = "Client"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "1"; + anchorLeft = "1"; + anchorRight = "1"; + position = "0 20"; + extent = "362 165"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiTabPageProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + tooltip = "Contains settings for the far range ambient occlusion aspect of the SSAO postFX"; + hovertime = "1000"; + isContainer = "1"; + canSave = "1"; + canSaveDynamicFields = "0"; + + new GuiTextCtrl(ppOptionsSSAOFarRadiusLabel) { + text = "Radius"; + maxLength = "1024"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "0"; + anchorLeft = "1"; + anchorRight = "0"; + position = "80 16"; + extent = "34 18"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiTextProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + tooltip = "Controls the far/large radius SSAO reach."; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiSliderCtrl(ppOptionsSSAOFarRadius) { + range = "0.001 5"; + ticks = "1000"; + snap = "0"; + value = "1"; + position = "122 17"; + extent = "221 17"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiSliderBoxProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiTextCtrl(ppOptionsSSAOFarStrengthLabel) { + text = "Strength"; + maxLength = "1024"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "0"; + anchorLeft = "1"; + anchorRight = "0"; + position = "73 38"; + extent = "41 18"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiTextProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + tooltip = "Controls the far/large radius SSAO strength."; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiSliderCtrl(ppOptionsSSAOFarStrength) { + range = "0 20"; + ticks = "1000"; + snap = "0"; + value = "10"; + position = "122 39"; + extent = "221 17"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiSliderBoxProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiTextCtrl(ppOptionsSSAOFarDepthMinLabel) { + text = "Depth Min"; + maxLength = "1024"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "0"; + anchorLeft = "1"; + anchorRight = "0"; + position = "66 61"; + extent = "48 18"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiTextProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + tooltip = "Controls the far/large radius SSAO minimum depth."; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiSliderCtrl(ppOptionsSSAOFarDepthMin) { + range = "0 5"; + ticks = "1000"; + snap = "0"; + value = "0.2"; + position = "122 62"; + extent = "221 17"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiSliderBoxProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiTextCtrl(ppOptionsSSAOFarDepthMaxLabel) { + text = "Depth Max"; + maxLength = "1024"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "0"; + anchorLeft = "1"; + anchorRight = "0"; + position = "62 85"; + extent = "52 18"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiTextProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + tooltip = "Controls the far/large radius SSAO maximum."; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiSliderCtrl(ppOptionsSSAOFarDepthMax) { + range = "0 5"; + ticks = "1000"; + snap = "0"; + value = "2"; + position = "122 86"; + extent = "221 17"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiSliderBoxProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiTextCtrl(ppOptionsSSAOFarToleranceLabel1) { + text = "Normal Maps :"; + maxLength = "1024"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "0"; + anchorLeft = "1"; + anchorRight = "0"; + position = "6 113"; + extent = "72 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 GuiTextCtrl() { + text = "Tolerance / Power"; + maxLength = "1024"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "0"; + anchorLeft = "1"; + anchorRight = "0"; + position = "24 132"; + extent = "90 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 GuiSliderCtrl(ppOptionsSSAOFarToleranceNormal) { + range = "0 2"; + ticks = "1000"; + snap = "0"; + value = "0"; + position = "122 133"; + extent = "100 17"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiSliderBoxProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiSliderCtrl(ppOptionsSSAOFarTolerancePower) { + range = "0 2"; + ticks = "1000"; + snap = "0"; + value = "2"; + position = "239 133"; + extent = "104 17"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiSliderBoxProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + }; + }; + new GuiCheckBoxCtrl(ppOptionsEnableSSAO) { + useInactiveState = "0"; + text = "Enable"; + groupNum = "-1"; + buttonType = "ToggleButton"; + useMouseEvents = "0"; + position = "329 7"; + extent = "53 20"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiCheckBoxProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + tooltip = "Enable/Disable the SSAO postFX"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + }; + new GuiTabPageCtrl(ppOptionsHDRTab) { + fitBook = "0"; + text = "HDR"; + maxLength = "1024"; + docking = "Client"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "1"; + anchorLeft = "1"; + anchorRight = "1"; + position = "0 20"; + extent = "394 213"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiTabPageProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + tooltip = "Options for the High Definition Range Lighting postFX"; + hovertime = "1000"; + isContainer = "1"; + canSave = "1"; + canSaveDynamicFields = "0"; + + new GuiBitmapBorderCtrl() { + position = "12 30"; + extent = "363 172"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiTabBorderProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "1"; + }; + new GuiTabBookCtrl(ppOptionsHDROptions) { + tabPosition = "Top"; + tabMargin = "7"; + minTabWidth = "64"; + tabHeight = "20"; + allowReorder = "0"; + defaultPage = "-1"; + selectedPage = "0"; + frontTabPadding = "0"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "0"; + anchorLeft = "1"; + anchorRight = "0"; + position = "12 11"; + extent = "365 195"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiTabBookProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "1"; + canSave = "1"; + canSaveDynamicFields = "0"; + + new GuiTabPageCtrl(ppOptionsHDRBrightnessTab) { + fitBook = "0"; + text = "Brightness"; + maxLength = "1024"; + docking = "Client"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "1"; + anchorLeft = "1"; + anchorRight = "1"; + position = "0 20"; + extent = "365 175"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiTabPageProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + tooltip = "Contains settings related to the brightness of the HDR postFX"; + hovertime = "1000"; + isContainer = "1"; + canSave = "1"; + canSaveDynamicFields = "0"; + + new GuiSliderCtrl(ppOptionsHDRMinLuminance) { + range = "0 1"; + ticks = "1000"; + snap = "0"; + value = "0"; + position = "132 77"; + extent = "206 17"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiSliderBoxProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + tooltip = "Value : 0"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiSliderCtrl(ppOptionsHDRKeyValue) { + range = "0 1"; + ticks = "1000"; + snap = "0"; + value = "0.0459184"; + position = "132 50"; + extent = "206 17"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiSliderBoxProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + tooltip = "Value : 0.0459184"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiTextCtrl(ppOptionsHDRKeyValueLabel) { + text = "Key Value"; + maxLength = "1024"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "0"; + anchorLeft = "1"; + anchorRight = "0"; + position = "69 50"; + extent = "52 16"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiTextProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + tooltip = "The tone mapping middle grey or exposure value used to adjust the overall \"balance\" of the image."; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiTextCtrl(ppOptionsHDRMinLuminanceLabel) { + text = "Minimum Luminance"; + maxLength = "1024"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "0"; + anchorLeft = "1"; + anchorRight = "0"; + position = "25 77"; + extent = "96 16"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiTextProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + tooltip = "The minimum luminance value to allow when tone mapping the scene. This is particularly useful if your scene is very dark or has a black ambient color in places."; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiTextCtrl(ppOptionsHDRWhiteCutoffLabel) { + text = "White Cutoff"; + maxLength = "1024"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "0"; + anchorLeft = "1"; + anchorRight = "0"; + position = "56 104"; + extent = "65 16"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiTextProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + tooltip = "The cutoff level for the white levels in the brightness."; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiSliderCtrl(ppOptionsHDRWhiteCutoff) { + range = "0 1"; + ticks = "1000"; + snap = "0"; + value = "0.52551"; + position = "132 104"; + extent = "206 17"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiSliderBoxProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + tooltip = "Value : 0.52551"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiSliderCtrl(ppOptionsHDRBrightnessAdaptRate) { + range = "0.1 10"; + ticks = "1000"; + snap = "0"; + value = "2"; + position = "132 132"; + extent = "205 17"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiSliderBoxProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiTextCtrl(ppOptionsHDRBrightnessAdaptRateLabel) { + text = "Brightness Adapt Rate"; + maxLength = "1024"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "0"; + anchorLeft = "1"; + anchorRight = "0"; + position = "12 132"; + extent = "109 16"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiTextProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + tooltip = "The speed at which the view adjusts to the new lighting in the environment."; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiTextCtrl(ppOptionsHDRKeyValueLabel1) { + text = "Tone Mapping Contrast"; + maxLength = "1024"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "0"; + anchorLeft = "1"; + anchorRight = "0"; + position = "10 24"; + extent = "111 16"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiTextProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + tooltip = "Tone mapping contrast is the amount of scene to blend, with the tone mapped HDR scene. Lower values are recommended but higher values give a strong contrasted darker shadowed look."; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiSliderCtrl(ppOptionsHDRToneMappingAmount) { + range = "0 1"; + ticks = "1000"; + snap = "0"; + value = "0.265306"; + position = "132 24"; + extent = "206 17"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiSliderBoxProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + tooltip = "value : 0.265306"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + }; + new GuiTabPageCtrl(ppOptionsHDRBloomTab) { + fitBook = "0"; + text = "Bloom"; + maxLength = "1024"; + docking = "Client"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "1"; + anchorLeft = "1"; + anchorRight = "1"; + position = "0 20"; + extent = "365 175"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiTabPageProfile"; + visible = "0"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + tooltip = "Contains settings related to the blooming aspect of the HDR postFX"; + hovertime = "1000"; + isContainer = "1"; + canSave = "1"; + canSaveDynamicFields = "0"; + + new GuiSliderCtrl(ppOptionsHDRBloomBlurMultiplier) { + range = "0 5"; + ticks = "1000"; + snap = "0"; + value = "0.502645"; + position = "132 70"; + extent = "199 17"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiSliderBoxProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + tooltip = "Value : 0.502645"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiSliderCtrl(ppOptionsHDRBloomBlurMean) { + range = "0 1"; + ticks = "1000"; + snap = "0"; + value = "0.510526"; + position = "132 97"; + extent = "200 17"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiSliderBoxProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + tooltip = "Value : 0.510526"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiSliderCtrl(ppOptionsHDRBloomBlurStdDev) { + range = "0 3"; + ticks = "1000"; + snap = "0"; + value = "1.4127"; + position = "132 123"; + extent = "199 17"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiSliderBoxProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + tooltip = "Value : 1.4127"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiTextCtrl(ppOptionsHDRBlurMultiplierLabel) { + text = "Blur Multiplier"; + maxLength = "1024"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "0"; + anchorLeft = "1"; + anchorRight = "0"; + position = "59 70"; + extent = "63 16"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiTextProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + tooltip = "The amount of blur to apply to the bloomed areas in the HDR."; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiTextCtrl(ppOptionsHDRBlurMeanLabel) { + text = "Blur \"mean\" value"; + maxLength = "1024"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "0"; + anchorLeft = "1"; + anchorRight = "0"; + position = "38 97"; + extent = "84 16"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiTextProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiTextCtrl(ppOptionsHDRBlurStandardDevianceLabel) { + text = "Blur \"Std Dev\" value"; + maxLength = "1024"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "0"; + anchorLeft = "1"; + anchorRight = "0"; + position = "23 123"; + extent = "99 16"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiTextProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiTextCtrl(ppOptionsHDRBloomBrightPassThresholdLabel) { + text = "Bright pass threshold"; + maxLength = "1024"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "0"; + anchorLeft = "1"; + anchorRight = "0"; + position = "19 43"; + extent = "103 16"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiTextProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + tooltip = "The bright pass threshold controls how bright the brightest areas of the scene are in the HDR."; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiSliderCtrl(ppOptionsHDRBloomBlurBrightPassThreshold) { + range = "0 5"; + ticks = "1000"; + snap = "0"; + value = "1.60526"; + position = "132 43"; + extent = "200 17"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiSliderBoxProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + tooltip = "Value : 1.60526"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiCheckBoxCtrl(ppOptionsHDRBloom) { + useInactiveState = "0"; + text = " Enable Bloom"; + groupNum = "-1"; + buttonType = "ToggleButton"; + useMouseEvents = "0"; + position = "250 9"; + extent = "85 24"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiCheckBoxProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + tooltip = "Enables or disables the bloom (glowing effect) of the HDR PostFX."; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + }; + new GuiTabPageCtrl(ppOptionsHDRBloomEffectsTab) { + fitBook = "0"; + text = "Effects"; + maxLength = "1024"; + docking = "Client"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "1"; + anchorLeft = "1"; + anchorRight = "1"; + position = "0 20"; + extent = "365 175"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiTabPageProfile"; + visible = "0"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + tooltip = "Contains settings related to the effects the HDR postFX can offer"; + hovertime = "1000"; + isContainer = "1"; + canSave = "1"; + canSaveDynamicFields = "0"; + + new GuiCheckBoxCtrl(ppOptionsHDREffectsBlueShift) { + useInactiveState = "0"; + text = " Enable Color Shift"; + groupNum = "-1"; + buttonType = "ToggleButton"; + useMouseEvents = "0"; + position = "11 4"; + extent = "117 24"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiCheckBoxProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + tooltip = "Enables a scene tinting/Blue shift based on the color selected below."; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiColorPickerCtrl(ppOptionsHDREffectsBlueShiftColorBlend) { + baseColor = "1 0 0.0235294 1"; + pickColor = "0 0 0 1"; + selectorGap = "1"; + displayMode = "BlendColor"; + actionOnMove = "1"; + showReticle = "1"; + position = "10 29"; + extent = "344 110"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiDefaultProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + tooltip = "Select a color"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiColorPickerCtrl(ppOptionsHDREffectsBlueShiftColorBaseColor) { + baseColor = "1 0 0.0235294 1"; + pickColor = "0 0 0 1"; + selectorGap = "1"; + displayMode = "HorizColor"; + actionOnMove = "1"; + showReticle = "1"; + position = "10 142"; + extent = "343 21"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiDefaultProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + tooltip = "Select a color"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + }; + }; + new GuiCheckBoxCtrl(ppOptionsHDRToneMapping) { + useInactiveState = "0"; + text = " Enable Tone Mapping"; + groupNum = "-1"; + buttonType = "ToggleButton"; + useMouseEvents = "0"; + position = "18 8"; + extent = "120 24"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiCheckBoxProfile"; + visible = "0"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + tooltip = "Enables or disabled tone mapping on the HDR. The tone mapping balanced the brightness levels during the HDR process. Recommended"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiCheckBoxCtrl(ppOptionsEnableHDR) { + useInactiveState = "0"; + text = "Enable"; + groupNum = "-1"; + buttonType = "ToggleButton"; + useMouseEvents = "0"; + position = "329 7"; + extent = "53 20"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiCheckBoxProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + tooltip = "Enable/Disable the HDR postFX (takes some time to initialise, be patient)"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiCheckBoxCtrl(ppOptionsEnableHDRDebug) { + useInactiveState = "0"; + text = "Debug"; + groupNum = "-1"; + buttonType = "ToggleButton"; + useMouseEvents = "0"; + position = "262 7"; + extent = "53 20"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiCheckBoxProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + }; + new GuiTabPageCtrl(ppOptionsLightRaysTab) { + fitBook = "0"; + text = "Light Rays"; + maxLength = "1024"; + docking = "Client"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "1"; + anchorLeft = "1"; + anchorRight = "1"; + position = "0 20"; + extent = "394 213"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiTabPageProfile"; + visible = "0"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + tooltip = "Options for the Light Rays postFX"; + hovertime = "1000"; + isContainer = "1"; + canSave = "1"; + canSaveDynamicFields = "0"; + + new GuiSliderCtrl(ppOptionsLightRaysBrightScalar) { + range = "0 5"; + ticks = "1000"; + snap = "0"; + value = "0.75"; + position = "96 46"; + extent = "264 17"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiSliderBoxProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiTextCtrl(ppOptionsLightRaysBrightnessScalarLabel) { + text = "Brightness"; + maxLength = "1024"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "0"; + anchorLeft = "1"; + anchorRight = "0"; + position = "26 48"; + extent = "87 15"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiTextProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + tooltip = "Controls how bright the rays and the object casting them are in the scene."; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + + new GuiSliderCtrl(ppOptionsLightRaysSampleScalar) { + range = "20 512"; + ticks = "512"; + snap = "0"; + value = "40"; + position = "96 75"; + extent = "264 17"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiSliderBoxProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + + new GuiTextCtrl(ppOptionsLightRaysSampleScalarLabel) { + text = "Samples"; + maxLength = "512"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "0"; + anchorLeft = "1"; + anchorRight = "0"; + position = "26 76"; + extent = "87 15"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiTextProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + tooltip = "Controls the number of samples for the shader."; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + + new GuiSliderCtrl(ppOptionsLightRaysDensityScalar) { + range = "0.01 1"; + ticks = "1000"; + snap = "0"; + value = "0.94"; + position = "96 105"; + extent = "264 17"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiSliderBoxProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + + new GuiTextCtrl(ppOptionsLightRaysDensityScalarLabel) { + text = "Density"; + maxLength = "1000"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "0"; + anchorLeft = "1"; + anchorRight = "0"; + position = "26 106"; + extent = "87 15"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiTextProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + tooltip = "Controls the density of the rays."; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + + new GuiSliderCtrl(ppOptionsLightRaysWeightScalar) { + range = "0.1 10"; + ticks = "1000"; + snap = "0"; + value = "5.65"; + position = "96 135"; + extent = "264 17"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiSliderBoxProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + + new GuiTextCtrl(ppOptionsLightRaysWeightScalarLabel) { + text = "Weight"; + maxLength = "1000"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "0"; + anchorLeft = "1"; + anchorRight = "0"; + position = "26 136"; + extent = "87 15"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiTextProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + tooltip = "Controls the weight of the rays."; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + + + new GuiSliderCtrl(ppOptionsLightRaysDecayScalar) { + range = "0.01 1"; + ticks = "1000"; + snap = "0"; + value = "1.0"; + position = "96 165"; + extent = "264 17"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiSliderBoxProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + + new GuiTextCtrl(ppOptionsLightRaysDecayScalarLabel) { + text = "Decay"; + maxLength = "1000"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "0"; + anchorLeft = "1"; + anchorRight = "0"; + position = "26 166"; + extent = "87 15"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiTextProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + tooltip = "Controls the decay of the rays."; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiCheckBoxCtrl(ppOptionsEnableLightRays) { + useInactiveState = "0"; + text = "Enable"; + groupNum = "-1"; + buttonType = "ToggleButton"; + useMouseEvents = "0"; + position = "329 7"; + extent = "53 20"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiCheckBoxProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + tooltip = "Enable/Disable the light rays postFX"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + }; + new GuiTabPageCtrl(ppOptionsDOFTab) { + fitBook = "0"; + text = "DOF"; + maxLength = "1024"; + docking = "Client"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "1"; + anchorLeft = "1"; + anchorRight = "1"; + position = "0 20"; + extent = "394 213"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiTabPageProfile"; + visible = "0"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + tooltip = "Options for the Depth Of Field postFX"; + hovertime = "1000"; + isContainer = "1"; + canSave = "1"; + canSaveDynamicFields = "0"; + + new GuiBitmapBorderCtrl() { + position = "14 28"; + extent = "362 170"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiTabBorderProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "1"; + }; + new GuiTabBookCtrl() { + tabPosition = "Top"; + tabMargin = "7"; + minTabWidth = "64"; + tabHeight = "20"; + allowReorder = "0"; + defaultPage = "-1"; + selectedPage = "1"; + frontTabPadding = "0"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "0"; + anchorLeft = "1"; + anchorRight = "0"; + position = "14 9"; + extent = "360 189"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiTabBookProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "1"; + canSave = "1"; + canSaveDynamicFields = "0"; + + new GuiTabPageCtrl(ppOptionsDOFGeneralTab) { + fitBook = "0"; + text = "General"; + maxLength = "1024"; + docking = "Client"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "1"; + anchorLeft = "1"; + anchorRight = "1"; + position = "0 20"; + extent = "360 169"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiTabPageProfile"; + visible = "0"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + tooltip = "Contains general settings related to the DOF system"; + hovertime = "1000"; + isContainer = "1"; + canSave = "1"; + canSaveDynamicFields = "0"; + + //new GuiCheckBoxCtrl(ppOptionsDOFEnableDOF) { + //useInactiveState = "0"; + //text = "Enable DOF"; + //groupNum = "-1"; + //buttonType = "ToggleButton"; + //useMouseEvents = "0"; + //position = "31 43"; + //extent = "140 30"; + //minExtent = "8 2"; + //horizSizing = "right"; + //vertSizing = "bottom"; + //profile = "GuiCheckBoxProfile"; + //visible = "1"; + //active = "1"; + //tooltipProfile = "GuiToolTipProfile"; + //hovertime = "1000"; + //isContainer = "0"; + //canSave = "1"; + //canSaveDynamicFields = "0"; + //}; + new GuiCheckBoxCtrl(ppOptionsDOFEnableAutoFocus) { + useInactiveState = "0"; + text = "Enable Auto Focus"; + groupNum = "-1"; + buttonType = "ToggleButton"; + useMouseEvents = "0"; + position = "31 8"; + extent = "140 30"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiCheckBoxProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + }; + new GuiTabPageCtrl(ppOptionsDOFAutoFocusTab) { + fitBook = "0"; + text = "Auto Focus"; + maxLength = "1024"; + docking = "Client"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "1"; + anchorLeft = "1"; + anchorRight = "1"; + position = "0 20"; + extent = "360 169"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiTabPageProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + tooltip = "Contains settings related to the fine control of the auto focus system"; + hovertime = "1000"; + isContainer = "1"; + canSave = "1"; + canSaveDynamicFields = "0"; + + new GuiTextCtrl(ppOptionsDOFNearBlurMaxLabel) { + text = "Near Blur Max"; + maxLength = "1024"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "0"; + anchorLeft = "1"; + anchorRight = "0"; + position = "36 8"; + extent = "67 16"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiTextProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + tooltip = "The max allowed value of near blur"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiSliderCtrl(ppOptionsDOFFarBlurMinSlider) { + range = "0 1"; + ticks = "1000"; + snap = "0"; + value = "0"; + position = "120 8"; + extent = "224 17"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiSliderBoxProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiTextCtrl(ppOptionsDOFFarBlurMaxLabel) { + text = "Far Blur Max"; + maxLength = "1024"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "0"; + anchorLeft = "1"; + anchorRight = "0"; + position = "43 34"; + extent = "60 16"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiTextProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + tooltip = "The max allowed value of far blur"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiSliderCtrl(ppOptionsDOFFarBlurMaxSlider) { + range = "0 1"; + ticks = "1000"; + snap = "0"; + value = "0"; + position = "120 34"; + extent = "224 17"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiSliderBoxProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiTextCtrl(ppOptionsDOFFocusRangeMinLabel) { + text = "Focus Range (Min)"; + maxLength = "1024"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "0"; + anchorLeft = "1"; + anchorRight = "0"; + position = "13 61"; + extent = "90 16"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiTextProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + tooltip = "The distance range around the focal distance that remains in focus (in meters, minimum distance in focus) focal distance it is\r\ndependant on the visible distance set in your level"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiSliderCtrl(ppOptionsDOFFocusRangeMinSlider) { + range = "0.01 1e+003"; + ticks = "1000"; + snap = "0"; + value = "0.01"; + position = "120 61"; + extent = "224 17"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiSliderBoxProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiTextCtrl(ppOptionsDOFFocusRangeMaxLabel) { + text = "Focus Range (Max)"; + maxLength = "1024"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "0"; + anchorLeft = "1"; + anchorRight = "0"; + position = "9 88"; + extent = "95 16"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiTextProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + tooltip = "The distance range around the focal distance that remains in focus (in meters, maximum distance in focus) focal distance it is\r\ndependant on the visible distance set in your level"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiSliderCtrl(ppOptionsDOFFocusRangeMaxSlider) { + range = "0.01 1e+003"; + ticks = "1000"; + snap = "0"; + value = "0.01"; + position = "119 87"; + extent = "224 17"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiSliderBoxProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiTextCtrl(ppOptionsDOFBurCurveNearLabel) { + text = "Blur Curve Near"; + maxLength = "1024"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "0"; + anchorLeft = "1"; + anchorRight = "0"; + position = "27 114"; + extent = "77 16"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiTextProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + tooltip = "A small number causes bluriness to increase gradually\r\nat distances closer than the focal distance. A large number causes bluriness to \r\nincrease quickly"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiSliderCtrl(ppOptionsDOFBlurCurveNearSlider) { + range = "0 50"; + ticks = "1000"; + snap = "0"; + value = "0"; + position = "119 114"; + extent = "225 17"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiSliderBoxProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiTextCtrl(ppOptionsDOFBlurCurveFarLabel) { + text = "Blur Curve Far"; + maxLength = "1024"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "0"; + anchorLeft = "1"; + anchorRight = "0"; + position = "33 139"; + extent = "70 16"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiTextProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + tooltip = "A small number causes bluriness to increase gradually\r\nat distances closer than the focal distance. A large number causes bluriness to \r\nincrease quickly"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiSliderCtrl(ppOptionsDOFBlurCurveFarSlider) { + range = "0 50"; + ticks = "1000"; + snap = "0"; + value = "0"; + position = "119 141"; + extent = "224 17"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiSliderBoxProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + }; + }; + new GuiCheckBoxCtrl(ppOptionsEnableDOF) { + useInactiveState = "0"; + text = "Enable"; + groupNum = "-1"; + buttonType = "ToggleButton"; + useMouseEvents = "0"; + position = "329 7"; + extent = "53 20"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiCheckBoxProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + tooltip = "Enable/Disable the Depth of field postFX"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + }; + new GuiTabPageCtrl(ppOptionsVignetteTab) { + fitBook = "0"; + text = "Vignette"; + maxLength = "1024"; + docking = "Client"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "1"; + anchorLeft = "1"; + anchorRight = "1"; + position = "0 40"; + extent = "394 193"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiTabPageProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + tooltip = "Options for the Vignette postFX"; + hovertime = "1000"; + isContainer = "1"; + canSave = "1"; + canSaveDynamicFields = "0"; + Enabled = "1"; + + new GuiCheckBoxCtrl(ppOptionsEnableVignette) { + text = "Enable"; + groupNum = "-1"; + buttonType = "ToggleButton"; + useMouseEvents = "0"; + position = "329 7"; + extent = "53 20"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiCheckBoxProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + tooltip = "Enable/Disable the vignette postFX"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiSliderCtrl(ppOptionsVignetteVMax) { + range = "0.001 5"; + ticks = "1000"; + snap = "0"; + value = "0.6"; + position = "96 46"; + extent = "221 17"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiSliderBoxProfile"; + visible = "1"; + active = "1"; + variable = "$VignettePostEffect::VMax"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiTextCtrl(ppOptionsVignetteVMaxLabel) { + text = "Radius"; + maxLength = "1024"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "0"; + anchorLeft = "1"; + anchorRight = "0"; + position = "26 48"; + extent = "41 18"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiTextProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + tooltip = "Controls the maximum exposure of vignetting."; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + }; + new GuiTabPageCtrl() { + fitBook = "0"; + text = "Color Correction"; + maxLength = "1024"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "0"; + anchorLeft = "1"; + anchorRight = "0"; + position = "8 27"; + extent = "376 200"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiTabPageProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "1"; + internalName = "ColorCorrectionTab"; + canSave = "1"; + canSaveDynamicFields = "0"; + + new GuiTextCtrl() { + text = "Color Correction Ramp"; + maxLength = "1024"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "0"; + anchorLeft = "1"; + anchorRight = "0"; + position = "6 7"; + extent = "118 13"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiTextProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "1"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiTextEditCtrl() { + historySize = "0"; + tabComplete = "0"; + sinkAllKeyEvents = "0"; + password = "0"; + passwordMask = "*"; + text = "core/postFX/images/null_color_ramp.png"; + maxLength = "1024"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "0"; + anchorLeft = "1"; + anchorRight = "0"; + position = "6 29"; + extent = "365 18"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiTextEditProfile"; + visible = "1"; + active = "1"; + altCommand = "ppColorCorrection_selectFileHandler( $thisControl.getText() );"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "1"; + internalName = "ColorCorrectionFileName"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiButtonCtrl() { + text = "Select..."; + groupNum = "-1"; + buttonType = "PushButton"; + useMouseEvents = "0"; + position = "252 54"; + extent = "56 22"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiButtonProfile"; + visible = "1"; + active = "1"; + command = "ppColorCorrection_selectFile();"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + internalName = "ColorCorrectionButton"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiButtonCtrl() { + text = "Reset"; + groupNum = "-1"; + buttonType = "PushButton"; + useMouseEvents = "0"; + position = "315 54"; + extent = "56 22"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiButtonProfile"; + visible = "1"; + active = "1"; + command = "ppColorCorrection_selectFileHandler( \"\" );"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + internalName = "ColorCorrectionReset"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + }; + }; + new GuiButtonCtrl(ppOptionsApply) { + text = "Apply"; + groupNum = "-1"; + buttonType = "PushButton"; + useMouseEvents = "0"; + position = "309 302"; + extent = "93 23"; + minExtent = "8 8"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiButtonProfile"; + visible = "1"; + active = "1"; + command = "PostFXManager.settingsApplyAll(); Canvas.popDialog(PostFXManager);"; + tooltipProfile = "GuiToolTipProfile"; + tooltip = "Apply the settings and close this dialog"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiButtonCtrl(ppOptionsSavePreset) { + text = "Save Preset..."; + groupNum = "-1"; + buttonType = "PushButton"; + useMouseEvents = "0"; + position = "111 302"; + extent = "93 23"; + minExtent = "8 8"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiButtonProfile"; + visible = "1"; + active = "1"; + command = "PostFXManager.savePresetFile();"; + tooltipProfile = "GuiToolTipProfile"; + tooltip = "Save the preset to a file to disk for later use (use postfx::applyPreset)"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiButtonCtrl(ppOptionsLoadPreset) { + text = "Load Preset..."; + groupNum = "-1"; + buttonType = "PushButton"; + useMouseEvents = "0"; + position = "12 302"; + extent = "93 23"; + minExtent = "8 8"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiButtonProfile"; + visible = "1"; + active = "1"; + command = "PostFXManager.loadPresetFile();"; + tooltipProfile = "GuiToolTipProfile"; + tooltip = "Load a post FX preset file from disk"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiCheckBoxCtrl(ppOptionsEnable) { + useInactiveState = "0"; + text = "Enable PostFX System"; + groupNum = "-1"; + buttonType = "ToggleButton"; + useMouseEvents = "0"; + position = "13 24"; + extent = "127 30"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiCheckBoxProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + tooltip = "Enable or Disable the postFX system"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiPopUpMenuCtrl(ppOptionsQuality) { + maxPopupHeight = "200"; + sbUsesNAColor = "0"; + reverseTextList = "0"; + bitmapBounds = "16 16"; + maxLength = "1024"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "0"; + anchorLeft = "1"; + anchorRight = "0"; + position = "278 30"; + extent = "122 21"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiPopUpMenuProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + tooltip = "Used to adjust the quality/performance settings of the PostFX system. Some PostFX may not adhere to the settings in this dialog."; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiTextCtrl(ppOptionsQualityLabel) { + text = "Quality"; + maxLength = "1024"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "0"; + anchorLeft = "1"; + anchorRight = "0"; + position = "238 32"; + extent = "39 12"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiTextProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + tooltip = "Used to adjust the quality/performance settings of the PostFX system. Some PostFX may not adhere to the settings in this dialog."; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiButtonCtrl(ppOptionsOk1) { + text = "Revert"; + groupNum = "-1"; + buttonType = "PushButton"; + useMouseEvents = "0"; + position = "210 302"; + extent = "93 23"; + minExtent = "8 8"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiButtonProfile"; + visible = "1"; + active = "1"; + command = "postProcessOptionsDlg.applySettings(); Canvas.popDialog(postProcessOptionsDlg);"; + tooltipProfile = "GuiToolTipProfile"; + tooltip = "Revert any changes made since opening the dialog"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + }; +}; +//--- OBJECT WRITE END --- diff --git a/Templates/BaseGame/game/core/postFX/images/AreaMap33.dds b/Templates/BaseGame/game/core/postFX/images/AreaMap33.dds new file mode 100644 index 0000000000000000000000000000000000000000..e01982a94528594a375ae6e61c44780a8e1c0b68 GIT binary patch literal 109028 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 RBF+E+002ovPDHLkV1nj@91s8i literal 0 HcmV?d00001 diff --git a/Templates/BaseGame/game/core/postFX/images/caustics_2.png b/Templates/BaseGame/game/core/postFX/images/caustics_2.png new file mode 100644 index 0000000000000000000000000000000000000000..99097fa0ed112c28958363f2951478a0955218ec GIT binary patch literal 33963 zcmXt91yGw^(+y53?yfEF?$Dy8g%+3M!L7Kv7cIrzrC6ZAi$fsA-5r9v75D$?H}i+d z1Tq8M+}(Tk>^Wz@e^F7u!XU>0fk0Rv6lK*wAOzrB1Q0qZ@S^WrW&ymQntoJ}1-<{B*J+^mJH=Z0)c2jA7tNYcrK2# zpW1?TQ{H+T>If3!6Vtt)H{*UsobAdZM{S;@binkkX7PQ?*DS}=_aD3F>&8Z8hY`-k&jPI zObj`_d$F{%guQ%LQ3-#^&B?(Y>lr)yw*7GD>wi|~ak@$+etLJ;oSmKBu)Dh(V!IJ= z=OQ5~`CngO-}U3;vctD;Oa7fS{@1s+^Vbi4KK}mHIUxb(k+Vv3;dAJ7qld2U?t;D? z#L@2V?z1YNKQApT=w_;v!fcP-TdyxKrv)>WmyX@-8Vmde-amVgH zj>@;*-rm0hV7bb3v&VP_wvC^cbEKrCXl6Yna~tyz0nM%&|jn;46ZC%aK@xu zB68PoPQPcytSOgHb}8Ih*$Ny|kH`56l2Jo@_vo^?Fx z?p!plRK~~0A75U&ay!^zx@}%#Hj7E$*B#ZJU0t-tV2=z8d{{cYF(^$W3#_ZF6U-fx zVc^ak1J>f_lz09(Vlg#3I*L6@Wb5JWy_l1eW4Ih(_|=VjLGQ4`G536>)ni{|L*ViH z_^apGt((dCCC`Ak-b{fB9&3V3eXS$I-AhxtFuD$@ovV0<-^2BWo_ni-n1~3OA<`Vq zSQOGT5JOHbuBFY*%^*5x_&98*?cINp6J2EBH%{3JBrZAH5T3=N+pjkrXOGDW^#gZ) zXJls?P4cAd9i=nqfj9l8wN?*L&rozI_h0Jx7?8r3lfXK<$e6(AxVdbsy67(pUCq0) zmWg9H^!;}6?cAVr1)m{>ox7O_hUGsI&{(sfUBMXg^e2C*Hfo>QeOGVCLLey@x3|rK zJvlx(ak$O)4p(}ED~B+#Zd~XN#2NQ_vyPoO`o9&2h%ti?Gt2U$*rc5_3VLn%%M!zq zB%M+UYUFq|PH~bEJ^?FSBqSs-iOpRg8E5ru8yg#8KEH!74yX$>c3VrNCRR1^jx2Q6#9eb?oiad8Q@>XFPxJ$*(sB;M)c&)zMw^Aa?qQ-uW0x zHCq*6?}WEzVqU{t>Qws+%2pTmFFO4m+;N{>ls4PiUuIg3Jr);#GUKV=lpj(TbrB7s@K=oO%!V#A&pDNKs=sJ3d?WU zAM`0v%z88hA5rsuWtcSLp72THC4i|(YLBFy1XJI$*m#tjZzqHJa*C-2hn&RVe z7o*{vK0H2(%f3ExoAx}jh@1=>#;rk^_@X0(6Y-l;z7?sDG}4=$(kd15*VgHTteCT{ z)_Wq9T+Fa;kb01sO#_Uq>`leDqj9 zf=>AHJF6(({9NlxTXj14djaiZ%$!~){Mg`LICm@pHa4*g+%gZB`%^zG8)p}R104}* z+_~0xl|`dWxK`u7TJ;q)zT^*nxISJw z^Wp+dgF|CouU=u`hpj6Hw$;~Hyh$P$PYG-Akabk+`S_k~$E*v>YiD0ae*GO=^=Ta! zwb1GVO#`!^>qrv(sSp}3$!~@lh&2w8T9o7ASi_KkO#Z(e5}*rG?wY?ojUO6{FuC@X z%E<38Y*k99+?|}99Dl%BNTPd;t&A}}kBteNhNFJ7m4;JdanJvHFcHjbpO>*|+r99z zLSNQhR|KKrVuv#5Xdv>hqzT7o&ouJMN+BhBo4mM+`mLwWGe}BF;RwkO2_*DIzP|)+ zkDZIV8U*3pow+L7ngqPaoIXf#ZzSXexQ@=m^}9TMeeI%qHsp$sKZkK$ec@c`hn5>! z^NG&uTa3_yZkibi36JylsB2V>VO`rAC^KhbM~x8?5$-N7d>X`GwAW5=(3bI(iJCIH zR0>Jnwpz)@F5TVT)u1ik0k^k(gC5qesE(Wx7NFX2y@N7W&f(zOFB|UnhS`Cf2)7j+ z4i!bQk*98Ed}D=3oh{g_9p3nT#$}mCYQp7KLUMf)-X6~o4$+x6%V4ZkfY;Mv+}zfg zuY05@$@$2})|PNqravRU@<%2tu z1y>nhJ3FOK7Y1$O4r8z#gt74h96RvrG>MLoxQm2lc$Rr*)A$OwEjR;!t&pj1T{;dw zBQ$(XgsF^ha&i(rmPN+eUTvev^zbReR2W8)>>zUB+~CSsZzT#>vY>q1rO3OkSix4e za3m*(oUm^vXbW6eNY98!wZI>Gsh}HYmR46h5;LSoCAMujnoXEPAATnruh$h=*dv*1 zW>=_`Lqpfl|3P0dgaUbN3=$&BHszF%%2L)N#E*!;7iuuTES%(f=EZk`aZ^YXI)502n{V9i;JFWRhaTbz9|qU`x{rVB2>d)d;QBE zb#x4Zq(^w3iz^~H-xqnb4+zFndI`nE@4Js5`>OSRoSW9a4?zo5lKt-C;Q>UwVZ}j6 z7GcGdwS@?Idj_g|<5$zmmTn{wax%3V**9( zq`K~je%T8%bK5JMCk#_KBQ)xuhbwg`1U7aGiJT!IGWezdT1Hr-*$(NrFI4^8b?DuA1Gns+|vrcle(U zHYVi9)KFcew9Dicb9tAYKXMs$VBXk>X8+e?>V#`e=RE!}+T0@g`j{oM0QBUGO}VSa zL-F^{cNIvW#hDpR04p7DY;3?+FPfKuL@vu4b_4Z%r}`S0#7oULX%Q2NR{bEE{Qhas?&zj^{& zqf=+Q;}2C?S22+r_gDq2A2g_4KsF6UM^@cr5r(nY{qKCKC{?qwvg%t~Td%i=Qjx$& z&{&!*J?o}1yj(DLxx(0Nrn<3(EN?MY0=)tqaMF)=c6I`jMJD7a#_0{xO8YreE1MoS z`X!W>Wc_>0CF?CM@}-Dt6q+WGN?upWgYsTU>67DcyEgp-Gk5ut&bT1mIHsW@>0@Hb z8~$0R!wcLc|GLOdgTdV;}Z{w0ZC_q1!jlb$|5 zH1Bp`U;sWtROt&8AZ|oX=S+~qG*&!QS8IjaAxxR8bF|wOYpl65^FpR1+orrgnveq7;I+d1K+^-~Pk4aI zbfKOwL<~FT!8e&XZ!UV04}^^a4`^=XFPE(0DN9nVE8)M)pL~E7mI)ALB6{d zI^KqF?~EoWm;9Z%c(S3=mBwcEbP{wj)8EFOv)P0&LkO*Mo8?GPZcE^`Fz|3Na?030 z`EDwDQs*2mGfh5omr?9wWDPpzdSFAv4e-bPxn;CoS zFfKE3o>`PqfB!ZNU7?@7wQg&{$6VZhB@GC(3`_K@_m7Yg@e@OfIg+r2g)2)?HIkFh zfm~ZS<*|l(U=)HQoeyD98KSBMCLvClEHaT+=@Qq!1bKS6L6Q$jI^XPz=K`(1T6`<= zN!A~aBe*Wcw?CV58mMPohwBpj%a*v@f8T(E1Xr1Ln6KdzB@=U&l=OcsRIQm>y6}F< zdtuv17aYnmm$CD~kz3-b@szN@5W-Y4L`y<`@2G;&GN*9JSFCrZ+|97lGtN{DE93%| zo|%)rBF1D_o(c;CBO@BhzYBJ=Dggeq6QrOg7Jkgk%rsI5RR^^$I&!(X(hysN*o!vM z(WT}ekU-N~TG&_>UheLZGqh)@2l=bmp~KE=)D^slvy>j4rdzl9pPC{)pi(Xy461V( zDWOz)$1#l`vnla79y-5rb;PT{_;`EU0DT_NYvrPlbZB2&K_Ws~PJ}CN z9}lluBmg*pOj{IQnSKkvU2bwFpjLrKcF)8vnkFJleq$*hQU0w+Rkz{LruWW#Gh}VB zN=}CC83Z(u3(CaF)O}@$a$fv)rmkGhw5L0QuG24f$mx29kr-ZyorsC#<(zQ4i~D%=SkyJwi{D2gLuaXL6D z845Xz+>H``E4_V*7j#55V@Zg_@eAA5dUsEy+DFwA2|jJJaFY?4wU7m=1q#6e>Xj0l zI9w&JI^t9d2BC%qJ`qcM>+#omD7czv>uSlYQu!IE!b-K1-Rt`e$LV4!OnULNxLima zok*2-(%{-h$zl3w6ChHTmqX*%8%}(BF zP&nhLDBFxc-7MbElY3ZQOKIYLR9Phv100n9>1TQHr1qLvfvW|TH6Hel{Mq?GI5;?h z1)f0cN=r-84%ebn^!v+2>{F&WeRm0#(TeykH*X?R!No}V zGd@@JzZsvG*H6D2G=+>U@Ael8%aNYI=FSZAE+ z&z48}bco&Rak`K{kqyNa21ec=(qk?6@hpPU=c@L|Yz~A45lN%ZHR_4kAO;^eRwUgM zNbbpMh*_=U>Lj|>T|#h|?b?{*H~WLOlapBb|KyboyVU9 zC+B((!&{?!W)Z~ABnA9laX|Zv4*qIcN ziOGUv{B*pSQ)O7LJe5-x`c9dKn?174lw?M*rMM9Pu-}c;4E*>kT9SE@(idu>TAfVy z+`dlMPVOau=;+nyzG;ru##D~CT|(Y#i(JCLzwau_JRz?!2XHOiBh0+Wq^5UYX`FX7 zV|uLO+W)ho?wy|o4-3f7V~Dw|1T1Fqkb;D`I1uwRWZz6CZvJp?T%vMCyw(%Xp6}E7 zxS}4iKj5bgd)d2dxpg=LGwSx(PwHm3sQq>xn-a91C5G>|c5%ejmhs*3U-ie_fAzi_ z#Ei!9=XcLF-^vFo4TI^)=Lq02ZSwa7bGy|b$M~>n~2zsGT2&6{Ow#9Kbh1|XU znNYpeJrOiOA8Ln-@v=IyFr_?zua=dmy_ns%inBtRVB`FzeuI&-_H1ipWMuq%S>cfG zFVfR}blE-)^<}y_Lbjn1wug;0=I$pyccXX?iECB`^81RN-q6<5d5|nL(IKw?w+zjX zi=nb#bd%Q#1ga$xQYBj{R9ift&!MU{S z5waH#g;DVGcjtrh6L?7Z=4wold*QG8KCMuT>FS*`G^XH5h{b{&Z?lD>LTMWIK@%Z* zzM(IBq%njx8l-%6HDK6F|J2Q3zyz)e=e{{OyYPDtHm=+#WwN2q9T-`y1>fLL%OAHI z%#_25Kx9p=U-0U7C7ChX_eLBLEk?>;bVmqb?d4->{Uv&ce#b4s#T&2G1ymWwxr2nf ziv={>CBHdp(M}@d*o`c+*EJ4Tl&j69TdrF}s(0!Bs@$g=G+_mfhIxKV5WB8<-SJW> z6>(^eLhpdI>*dunhiTd(@v|1hkj1D}5!Kv)=<62t=s&l zd+SpJ2`Iwwt4Ok`p2#C>YjHDUptQY`2~wU6&)riYizrdO+i>WT;eLFkC-08FxnaJH zJyp%UUf`4$i=c4=F~YM&-2x^p=ixA)BRXZEz(wlNcF^N>+S69cC%zC|&E(%EMeRw~ z9Is>{vF>qxSh2m~7I{{IbV7F;x?YQ~`dub9Z!kglqA3~^S}qjWRD50)mBg9be-kWS z0}I^GnnO-4T124gU1LhrFM1(xWQi;x_Yhg9Z(k;7Y_JtP#a+R*I`zlyOW9=b$(G?l zg~upN-)$L4{oX-RWlrL+BD=nnXK$4ufpj^T5|b`j$y|xQo zD^S`X*6?H$^OkGf!IhCh&o+x>T+R9)e%`q5v}Y#?N4=kPd2$mst1n6ew@$xrUjo;S76+t*T9aF6l z6A0j6cSkN3YF3ZblmmMr<8(CbYDTC2nwfpQkNTF5%xECX=!gxK-;BA`nRdfto(#2W z13f)G+!0h#GNRDUbgv`)F_HLQeFfj=9K1-(KtzAZI1iw;GSrIjViS zc0;yLzKlFpYi|sX#u%SxxcsQtP(AjmZ%v=D*%sNZlJvr{JC_9phy{|u=)3#3|>HIrJnoCKlT=C%Cfs`Ojk<9#WaIQ9wC;Kzy?n>2*)H(~tZ z+Q|Be7?8w^wn3A~vYGZXk?!_eKFgNmrvGZqO2A4}oa7_&k*$7(8?99hol3#xZaWw_ zi^+!tC=qzV0DUh0>Km;+`}*8Fy&p6E73EUNKPJM`;>g8wk*o-; zh&|qSrn7E)Kb#_7)15|`Ac;gyNn%#Q6+!Z=BkV`Y0-`%Vu1e5El>T$!O~4aobgL*S zI{Jc32OcxYb{jKSeJ)ZHb(yUybxzDL#H0my#{U3TA_9j7yVr1Sd709aUWXgC=$7&P zT~(ausT@c*TWaxB26@vOTiGnQq8Ym_sx(@>(EY8b3_B=7T0>tuREw$=xG8)R3ACYxrutWSf+F{9)8 zlT7*5d)%TZMeSb+6KKZ2@lruNRc1h!FHOr%!Ir`OJC4}G_lpXJ1~%(ZDj#GYJ3#RM zLl^(ejh^l9q%I^v^7UaIb0CqQPtIos>6j=FlNJZ(B(w&K9}EbdFSCn*uW8BmW-2Q3 zUA_gze*DgVy8Ez^l}~}E&9QccsgpETF`-qHj$qL4Fqg2fjc^Hyqn`Tofuv0PuLgld z-1h`%wYm$I50@xshooM!$x5f$ z%DER-kZ~D@7rKief{;^SSaOkwBKUA01M9HrG70lg9%XF-L{-%CR<3k>CkRa*$(`J2 zBo-)Ax5dL-J&Z}BsOEQm9e&1ZkMp{J5>Ze5%k$ccPv(fl@lYyPNQAJMm@V)FsZTMb z+X}a?9-Q3{71=_{BVQ8xhng-!4`s(M2e4?tr)26w@klY*lQS^}cuay1b_XSnG0^(~ z^ehk_L(KZUiLi=WX~Cj5rex(u=@fILy@3qNwQs7Fk`aw*C>*NA_ixH!cwR4EAdUMt zwzm7o2S`LzyAbY1=R<2}9poiK>Tw z8$C1vMV$89hm$K)H6hiOd(BrUI)T-Z1;r4xv{36c;H*?UnHu;r$yCZIwp*a+g1*y$ zmxq5j%+>km{H511B44Pbm1$#w4@Abi`(92G9oybR6(#=0z3s}1Sl>*8w;(2^U59>^ z4xT|`TSgs=4tqe{Qil}F(<%uR{xsQInWts3X6Man`PRU`SI#6p#4C0QCiVBdEewGy z6C~;K)N!-MU%09ChO;cJ#}m3Fy+f-Vxbu~y?Op%_WZaYgnpVXOZb^1-E{^pdhenFP zE-M#H%w8L68fBQ~h#S_!m9)HfL>y09y(UxbadoD3$70eJW|6nQ9K28|sN$Cxxo~R0 z0&dOjF8LD)NfKu2$1 zXEL}>ujxFxr{L+tqmzvT;In4FpfmwWha`MuWhFWjM$e>T-)K6l?@yXsu#C=(D#j3+ zih~t^$|%t+Xpb!dh;cZfdJN#7VWSR;j1*rKGGohH@qE7cV7a%h1WgMIBT}L?A(34D zGK=_Zx!D}2iE1g(=OGWTqOQKA^zs#!dZcFI2O~uOq?%bQmP-V?PWGV-)ZADyoZ-Bj z;T(T^-uWiaLHO(sNEQ9H1mcbbMMU@?ic2UFK26B#Fm_oH;w6_CyvuKQ(o>b)3{=E^ z(6kY^L9eh`5E(%|3IPOBfC--}nX+!}?3DUKAPNX;((h{C7gDC2B3$7A9?9`LzIh0$ zfDisB!R^UDGIz{#_1LoO=XDBO>Lz#PsK5nnHRA_=fBUsVp*fzW-t~*GW8Amr z=;N|f`^~aKVhTch4^lyF-Wq!>T179@wBlftWKAysRyc?(;kV404|`Vqz;SU2UQ96{gre;O4=B1g zpdc?TEv-{;UN~#heKSNeKFFK4QZ8_qQKiA`oRP zz|HN-^iqgm&+|zQGcWj7+xCU@?KXYj8jw$Dp)^1q#nor38?^?9`JmTYt*)Lb>;Rj_VPIPPhW6ow9SN%1p^C9A7*9J>LyNWi75Zy3jpS%Iv7FRTC+B%lj$(9m&EvXE+(te_unrq zHCb(YYWLD~&!kloriNj*#;^|{Ty ziJ#mBqKWyZ8KBtcV&y#;jhK*vCfc(pzdnq0Ytg0y9}HlFuL1Te=;ozV>S;f$Wz4u6ig__mx^7IjckM$+1twwnpFvkF|O|(-oh~Nj&TY zh9gxESQ4(+VG#&d3T|&(s{uTSG`sPp&_nAmrP?wF&qoI$^?V+Wmic_KI|c~1|GnHv zy;uSoojsuM0U!8!GhT{1Ml4(bi2&D}9-FT4*&d67k6)zqJ491KE!=qePvM#v06GOv zmCUh;MlI0WHk zz;9f13`AR#R5?)b2dQ7lKqA}CPD8;|dNcrVH&j)BR4oxVJE0)oB$%jM^n>66n_ zU~#rm&$nRU2y-#l4=1421bvC^c@H8lFA0p&W3I5P#M|3%yLvOJf!EZBF_lDH0TH|B zG}2B|YHL7t*J^hR59C2eRpSIK6fQ06e_`tiJ)u+; z1fIWEhrYiy@X7u-(?%nUlJxX12`%cZ0Y&Hd{=Vf2@^aM~UK7x6h;vYThWZIQj+;Re zn`|A}bTQUE`<0Amrv<>W{Wo-Lp8J_!_1^;wohVgZ{UHCjqXY8 zU^ov63*M}(7%ZmdFMgM>E7qPl82BFFyhg^UM#UZc5C_?IUXb*?b(GGxEcoJHRoUwG z1MzZvD#on)tyDIJhnt%~AhGe^r^k!2|1IoxGae8MO8lN5z511d4y44z>w(C-2L!wn z;Gw+GyAE9*Ps40KTAs?APe4hbeO1={n4NzkX#LcjTiV-SN5A{1hZ<3!$lm)z zjv6;5ALe^P=O@21MwX9F{1&*zXu1Nc{ot9;JU+I6*e}fu7soN79aO7+7(QQKDD0xO@*3DD7q%r8 z$UGa-fE>=E8btJ^gi^wL%x8u{P;}XKsn`B3zbC%>_$#XllLwh)P<)6V`-QKAVP{di zJO|gFa7?9!&PV&R!cE4w%~1o5Y$bDPNVOVK6ZZl&1esHLmJ9rDRy_U*l~`hcMDujm z`3%V4?!abw3qQ85oXGJhy$StgC#piw6jM~M-Dpxi$O-OlUxh|0QR#SLW`u~w`p5F> z^k(u9UYCdt>^J5ZK_1vLK6K6PO@d-ET;W!(kpiyQVkD)RYks4!0N2>G8m1GyX zFM$2S5a6?_a~IEF&sMW}hFOty5*O?QW%&muPQ!M~LkX)SCKFZzNi0gKkr1^}7c6cy zLOHCWy-*J>9#jf4e|m9R*q)al@_irjdwA*q>gjcA=c9Sq)#=THyN{1p=u5RfBqLbq z=a{@sw$v1_nv_ZG zZDbLQ{aQNEiKt@vk$&q-4W6gBcIUCu_*Xw^zmlF&qrJACW!PjD--`{Z|7T`UPi7__ z&A#mZiEb6#BU^=!mJ55C^`}BSAL8o7Ot}Eg(aPEy4M_9o&Ihw~kDJe2U97VpB!3_J zwO}pzixhzm{EP_7jFf~OG7($lcQ#yP#&viJVwF)}D|izr8E1!qqrg{f%X@I?I%%ca z0m<^A-Ca1FFzhLf2-!PqS{DNKlCiHHyQ7&)=hU797BB#>A4zM?S&M$3)?k3g;&f63 zq1e!Wj_+Dmh@g3`QvUZ-{Q8dbTXXyUi>xM#trhRhY}PwJt#a^}xVPDt&C*ZJx=gl` zrg&;v&F{3Sx@Aw=T<}-%tQINSXI&`C+vQfg<_UabW3+kCCQTtAzcCRe7@jt8SmFQ=F$_q0&mf$7*fkU&dPR&_X29eA^in~ zvx^|l?o7b1qPCJ3C%>wNlZxTl!ANv~7kt}NKO&R~8*i0Vt|hEAWG9xn)B7Mm{@mK} z#Qx&Js?^@#3?4Kl1e`KKFsPf!&JMsGp4})p$s_mRTM(?&aN6yN*tbQptDNmml>&eQ ztsAG?FO*aGu~HFVRjW|0QWhc3e=vIBebU58%qmlc(73w1a}F9yVjK=E$b1ZfzfvuZ z!O+)DUeyrtuJV?uj$uKVTW8OzsvY+~auhS?|@Yco%>N*KNp`Ny%< z{F)*#+w8?lBoLYDL}7$YrFq%SJ=~lck&;kfRVC=`7_g~3d0UsbpxVnerQ zSQUrv9QikSGS~7(EiqBYqs14bFGL+Xk^Lk5LgiVKmbf@M-*3cY7o-a#&s*ooA)?$$ z2wu2~+5>@&1mz+0tr+(G_{Pfs7fdWcSWu3-1)W&f5aKEmMxlmtrVd>LRu7UpDM6~g zf-9gl|2W;=e9@eECCnH;hGp(qcIfxHou5B_Aj}y3W}80dRfeMdD+zdD-puAac~G-I z>iFNBxV;|T&+o7D)x+v*KYlG-vFvGIvlB#9rSdNgrL8=am9aDs)@Irts>Fef7e(!0YBz-1wv#|R)du8)qvxzmkbcf ze9l+W^qI%*cDgJX_vE!BH6UF=Tmk8;a7W>q0k3DEeMB#Wf}lt)EJ*_*l=mWLIz5`M zn+}4RA#Evcx4J%%-7p5HAK<}|_KvF@V@txHmcbRQ6RRJo*v!vuq8*d&&m=dQrNx9A zHlWyo4mOG~rmt`wlU_&m29B%UuwVX3WX8gVwjio0b8cdITc;(3dplB8v0t>+3x5=k1n) z4+;)oXYxKQf%$3S$5C`yX|ODQ6sBA;VVazS?#b~z6Fp8fmc?TudX=h)@onOjhMW)guS|xOU}givs8i22EDV|VNh^LZ-1)df>FtTv zV~#^E>$Nb4$JSHD%t4-acf<>T&(Ypen=7%t>&@?NYi`Qwn*zMT-;84DLf|M73EpK{ zBwinh)@w07aMHV=zOnUiA6AxBEOWTpTVCj>4i1UqE~@|5hhxkInOg-r=K!9Q?--WM z;HXyw=np~c0WVKCNRgq@O|7jyUE=pr=aKzyMftc)qvSZc7OvQWn93gl?k}ws(V+8S z!<(zCtLT9?@`FRr=Uq9^ZXBNwzzYY!b!?@mHj96*=6o%7W6V~F+TmFDmf`%VT4tom z$)w)14>dbq?id;jBl~Gq?;pbjI5I)6jh(ROz>^c4Emk&FzN&ROZ1Y={^RH)) zuA^Wg?LM42TFFYE2xqHAEYB!Ij)UmGX`+x8uFPiIlWHO_yD;FM0X75J7BMK;ZUo`4 z+}q9=&g^3G!5Hwu9cAxQ*%GAHOj%Us9Fjfo~y0jg9-CY<$DdeFa5*2={ zwsBUUmmEyQeONEhGK}NBt7)p;nfQ@b1_{1mEbKIAG?=znBGCBmNw~1JulV!^GVIvVO_c57C} zA#1knhBSezzBCQlX|F_e&9sUUZ(_<=<*ij9HfjzQ2)TXVcj|7t*U<{FY*?%+@1={z z`4Bt9cE_M}#vt!AA603Mo6$jkJM{Y1xO+)V1Z1@aU5qt8=PDa6UDiKR5gOzHbfMdk z!L=xH$g7BOa&ViQJq&vvfAPHSei?EF$aSbo7Rf znU=cvO;0Gq&{ce5x%<^yD6YP~K4m@W!MaldsG>vkjTbvL?m(iY5V;+ToGRa`q&$V{ z;bFhJm*T6J*9Gy^{#Y+pe%Z5~A3X{p*-US;b8@IrQYf7<^S)xz`kOZV?~lY`nGAE055}%~}T=vyQ>oveA<)LsSqFI_#Q_ zpnhh@cTBm};bx(DLT;dNz;rfeC?(UmQd1cqQ4QSro2OW4R-PjzQ@7?E$W#yrSPFuA zh)r<7Y}}f?7WFAgE9MDbw9=ig96X<`%!E5j5BZF-K~szGF!ZXlkY1?KKAjVmsx5Dp zHaS~_W;$v7aAW_w`(5OW*i(G!WXs|&AQgDP=A}l zKWK$`h+B8i-Fta^?WK94`<~G`6&n&)jqlBF$UtH`b4V&E4R2ng`Er}TNBY)Pz5xF9s!@{KjYCq!_g`s5hACMQ)@-X zXGjrYm{PivV<_#27+p$LN1Q{F~OVqB>RRjBFNTD4Zi^}nX#4e2s1ktXP>zB|La!kRrR zn7M*=@FN2b#RoYPhWDeFh?BJ-a%vxps0^4<%VlfJcV^Wi)F zM~mI81+4ksu16rjueY|$ezeYVg)U9FX4&ZxoVw`0z5oRxFn@HG%*8RzBgfyxEq{!( zv2N7U8VOtns8u7Zz`xOMQ%(0Q-AX$4Z4#%wO;0m0gS)>!(_5NnSiXM_|cN z-{fQceHsIbsC-;tYuFsVsB`rZbSq;Tz0*5A#Y{>`YsR6D2mlD%Sastkb9(B8zA;9j zEB?18Z4(S2CR8=tYyQ$kY&2;?LBVM$)E5y8(t+2wKVbB2+|IO(k&(E#j3x}70Wbb( zcm4qZQkR%D$Ajz0(7PvxaL0<$Lo?hh=rYg__wZRL9v zB2Wx{ij@vafi8!tp`l^8DQlESdkF?ES#2Y!1>Xcx{_H2ASKS)e|D47?o}O0!L|qv3 zmsip%Jq9*e9?q9Qvran1>r&2!M=`wpIB{`%276$*?CaG3wkv4R_(5M*t*X$n{ErIG z7!~dDS5oz$J?pg#0b^3MkFFtB;jkBAaK-;_I~5q~0Gd0mS{0kL-k%OxA(8Z$k6D>p z!W@q3VRfu?wi+oFP)BnK#uHk{rm@1tyIsIG_0JLt@bX;`fZ-Pq2phX_q3FviEC0rk zxRVfnNfY;WTD-SsB-`1kkt-r3>6Nb(?NgDt-wKxyM*8vLn_N|u@2!EQu|`YOp!Ljh zGd;!u|D#(aWybLHQozHve{Nvux7Fud0e3^uwr=k;z!Ielx#oY}&>!wx01c)y&6H4} ziz-u1j@GOG89X}prez_WGmByl`42@UOOA4!lZkk>l29H7tp@*#cc3v2^7nC9N_@@7 z*u5e4&;#sF^1#R_%3mj1!g#{Ci>E_0xd+{nBdyL@c;XxeBygD~VJ^pf#a$WFBSl81?bHnX}KaKhmg+WC|ayzbVmQ zAv6MH7hsc2%P`?3h=j-)gUaN>{L)5rRaq0Ed^2-~Zv!KYTYB6I3mVcRzJ5wLby3W{ zx)h`SLkj21T#Rm8Q*PIc61*Vxj1jKD*Dl8b_vYKa8u0>z%ZJWy0EAulktfPRN9t#8 zAUh%WoisoG+7Zw*)D*-fY<%>j zYqarj+W8F_)*@y6w0?g2@_dSR7?Gf(iTuQI%aA}EqU3!cxxbGhI&AXkIVYK{&Y_PV zu`G#D|J8Syk!@!YfSV6wZ$*ZXVU=xp+kF1{pi}Mj2MLb#`iTDh!=3Tw1^r6^fV(~8 zeya2aN~Uk`HjEE6KZ;DJo%{B&&%k}+_Siqx@m3>`Kkl8qY)U;Bnx~i=88@+eFh3Kc zNp8kBSd#^#S@b*Yj{Z`s!wdS>UqI3n$EJ=KHXe`kE%_u2jEk743?t>1o( zZ%Amca`^$*9?`A^)y#=DxAMDAcAQEKMfnS?OMgc(4)WxrrX(Jkb21G!DVaL~bJ_ZQ zua~}fnk8Vc3eblBS9$K|UXItEs{n&%V{X86vwmz@=tv*6;PJw^>M}4Rzy;a{!yX$E z+l;~x%s65a`rx`QF$m0x-7fpwW1l#|Xs#S&iC$$_^cm7z;H3_kKlBAWDpc^C z0|P1JkLn*pev=1m2dSu#viH~q-of3ng9$1~%o7gM7%O7aljkXug!Oc z<}HZhwvJE$R1leZ)b7~-ge?oFy*ScmcEbmt=m27?2YBq~$6YBJOzxgdfIg4{jBdfYSUl?NJgA;pC4V~$c6hfoirprkt00Dznn|it>SEAjC-;VK`hZ(^>9u+ zmI*=*L*z|LILP*|0oROE`)VU@)Yto?b2R5oXAw z;S9(TSbp|@fJj*l%pP3tO1*d)KQ#9}Jv|}B>bbq9&+Z0aGWv+)wPFA8C0cU5jaQ$I z5@ldRyA?>T&N0bsD-qlm$3Z4am|Iz1#jxnd;*idv|*IQ8FrNM>k#_ym33IzVJp3e-F@UiB;`=B zgjzkzf*8~kK#mBvuwIiWW@pwUY^tf(`uCMa&@iKF`O%0FSb*Iiz=+j4c0P=_b}f&FINCp6NrLaN{)0E%q-x zpt6SP%qq}Na)btGoAo#wv~zCJJ3bfQttL0{FTKTCta97Vg%Q{Fcp|i=d)I8P*GV97Ofs*qD9iN1GY9F+;RNm`MV#GOh5#zfu4zdV^lp!n2PjAjJ2x9cev> zMBt;zi&Ot;%pcn@gFY)`vq`tN^y8$bYi!zOzP$0d8#h7FZeaQ2vd9J4g;VUpKf_ig zP~G5!d|S9!Rs(o=p{#TjLK7@4-v%UoIOzWDZ^sjjlu?#gZRW>BJ#-pEmP~6&v84WJF7d{4r18PDZDht+*wV znTvbMTv%ukI%j_?!v^lFHg0@Yq$=u#edvBSk8lqiYlpOxxi?cal}Oo+-$Yt9b@XXf zVc@E)UY|+dE?7d|_!Z}vyNI3Oy4D(rfOAnWI{`3f32>-iK8Is>23tol1x1Wc#SZTc zN?_*A;T>WJ5a!3d`^)AT?t+|5M!bR!Pa6=A85Ls-M~Z|E$;d&=o#jC$f`g7Nbl$XY zIy<9`&pIFVNhvJ+YSDU5$M0sATsbwKIam?W15qeID(%1f^Mv|mwr8;|14}KDMs4G5 zFfeg2K~oM_(y}rim))-4taz)c5O#z-SM{!HVt8xjDeeFEfcqqEu8uKP*Om$)gxjty z?ChMqqNaipa4~1FjPsx}KnEbIgwEGC)5QPk2K_S(*Yxr-|D zbo4Ki`CPtbq<^|y;I%#!0vDeSw#oQ64;5a}jF7-YQJrv)g`6Spw*_v)AUTo-(Wl;= zD79i!)vKdqR}Pyw4>Xn}wKs{Wyw-eJ zaQSlu5yI*p6+a^RK%loi*ni+v+?Dst&C0_3Lo&PJfeJe9p)&LyPgkQjzcecRwkNI) z5sMp2qg3NdPVVb!uGMQFjGsN9DRa5W0x!^QX)_GTzpLPD*E$%qix_;je{B2QuKu{5 zusU(U8{1u*T*QvyxEcTj@!FWVo0X6^6~h8pJX0k|KnO98qcYzN{wU z4ah?HGRT)RXHKAn;K|^RI1OM)aOV+r>q3;aePJ92;yd+>Vd9*D$DJM@)z)Nc@VN9t3kFVP>P|0vGzwVuP< zI2SKYu7iD6KB00O5na4`Y+UTd{9Duz-(zDbXGiD9YG^GXoMz}P^t5`4&r@QiycncG& z=Wi)a{WD#`d+8c~!rq!kXb33<^#HHCB!#5m6 zk!ahh2=CvnpI0eL=ea&5U3K6Q9*+cVfD*FwVVeoVNZ}p*mXeSp9CKCk=FU}YPcstK zp!nvUE7S3%_TDTN_Gmgj3uqoj*W7IoY(8RIHrqldg;p=~jj&T2o(~T3$Jok9;XJ&5 zySJ6|wy3rGSAQPXrqSE_*gMKXsS$I$&4^t41O_TKXlc2ZLN*9->6y*U(B5yzMDv`g z5Pvbf@G0P#{j0K9bLb@-7I<*C_jSUxV1LVJy)o5d)_E-@?EEG*XI63UlPQGrGx;aa zn5|A1uQCsp2DY}XRcmD0H(_M6ScaU&$26nc*QO4mj4{Rt^`CZ$rbI$H+G3eG8ZSqr zi_Mm45D9vNOQu!yVnrw^{w&{1OBRKBYr~IEQ{VvMpNPl+?j7!}chAH8cB9kJq`Z3Z0H(Nd)qVpx12$Kg&3zcP;`f*GcRM-@J05)cm-<`0dkM^5!Bu$GgbX zkWp+!f>-39H3X8W*4tVbO3H%gz#YTCI$-UYz9+FNWaZXxB(D|3`)8Mb*tP_PKHV(h zZzX;(Pd^VdDM6T*-9yKB#F-%$ORq$<^S%KOnbO5ac<#FuT}y6YhRfBnChvVz2X#~Q z(z@8>u0ldj8=o+n`7l$=qorUMs-w@OGhZNYnCUhp+bksmrnljk5)riYyiC)NLdmTv zj2je*sOl~HryyNVQUsiFti#8$sszq0O*{R$3Duz*OghaN9=x|GQMCM4YHo4e?V|Fzt}_u6WiD57y`zPUg*$b?%Vf9a#)pa{kuFSJdcsJUBR8(2rn4LT26=y16g9%Ir7G69`Wa_FOIfaC+>q zFTbd)1bH)~*w3->q}@SY0Gsf-6tXRFcDjZ|m9C{zWKPur{{kMJ9;)7DHMz z)YO2tMEKrtyOy7HwR10e!WyUwQ^7a7GbW!K_(@b!iQ~O zw5twGTc*{W4!W}ItAjH?zum`Kp_3*?{%Heg{f%pG#V{cM;3r^X z*(Vf^6q2NK;Qg9uxlHwZ#J=V1zV@(w<>VzHh%5_8D1W=Vr2y@Vqy|SfQhDsq36kn}H{{NG336p*-X3armj) z+V5z9@!rw#39_(?I>JpqJdj5Sgqd@Aq!It@FZD)O$C5UBVk4Q$n4*HhQe_f3Y!dxL=aWEY zfF}JHILJkz$3bBAqM=wKLFw2RQ=LV01F?Ds(Znk4SMSR$wECIws8fnlqW?p=Y-8YI z5bP``E^*oY^2_F0tWw_qxg2oJa)6^@5ct)Y(42i;5NF)vjtiOw*c!q?U}338zm_ty zVA9QU(Po1LYx+*@zlUCB3Btq{{3G(Yqk6VC#k(fE({N+CVx#|p!DoET=IqgA5*oeb zHTHUSfO-EC){`D0+Pk{~d7H4Ra(S8uA?8cQ!AlHC`3lK#(MVSTI6N;1igvfvM-Ebo zPT3m=pa<|$(g#jHK>Ej$+)^-y5AX3c%u#eu!U?CBddTE{eo05_zxv~LebL;{P3qKw z=t9jY5>MU6<1bc4u_PcB04SPc5Vfh-d9>^dvt7&8X)A0E-2!Pn-szG1V_7fzW6$O; z_M>}Oy8I!nb=YtTZt8U$5hcER18G|qlP4VbRX{E;Y!td{2qf{al$c_Uc=4k=uO?v2 zhhB9pDwJge+Z@ycLjK%S>hSa!Gii7T@hq=_r}NcQ3TlYuVP_bQ9dPQtzrTNhE&-=Y zAYu4&$OW|$8niX{3z`{BPMs&?^l}NXg9NR$&+U0ZEhWdk@?2TzBEC`eq3^?N4+5b#*RnQK!LeVhUy zLqJ5eln1f=n;MFlfy-$e2d6z;DL1`TfN%rhFl5@%G&rGBOU(5j`M^1rnG=wE_)F*Z%A>ZZf(kkQS zq{Jd1#{x`;|A1%;0Gl$f6rm%(efc|Ut;3d8LQsi?!j)s=% zHczMA)U7VmGdRB4Vxle`GOtDw8-pOLKeLt|0q;f5eL+N2iUN(=8&A?-_z`{45XeCP zR(j;khm)5qWA@Z4&hCN+wkJGbdk$-guEMkxu1Gl|ra?JWl9@Elg2ekI`#s)|y_J^J z6yW8AubNlCK(HiAdP1Qw(8S`CSA~DJj7Ax*SoMIQ-NQ6!_j~BD7PoxI_>P9eQ>AQW zy5>%je=Q|^Vkx8A`rc&c}zHnw%to-(PsR;oT&ASLlM9;TBp0#riW0%C5t+<5E z^^pl=^hMvWbw6h^!9R;$fSfe*M(kW&t$GY!KwGEA`|K?*b`0?>C-7OkWR?L-d;##v z<5>-ZZw;Q#z9R*IdD+2B_rH33ApATd=<-D zqlTzplM#vkx`aWtWMgUSRRs-b7l0it0Fl+w>5`WuGC&A>8uY(qL#t*6yWDhAJ&nB- zdCs;z1B>_wh!`M=1X)cCT}}1(G=Dp^`S^gbdqA7`>LW2O^;C6r7vYW)tFf~9IMd&Q zl!e052A6ZJ(rZDac&wE^P$ff+8Mh7&M)Wq2)dh6uJ)br2b|+16b!4b9;YH~aYm~bd z$@JG^6<49JXy#0<8-ME@B%YDsNQIXgD3V5?n|mM*T{Ad1X!P+PP)}N*dOAgGVg=kE z0HKrn5^U{Mx55;R!K}=4(F}KVNI;cjTo*^qJ`|kpa5$P}6jmX?EkNuIu9}{ro~Up! z62umXCK2Jf{;P@RAsH6^aRdpGtprI^Y%P===GSBLp{_Xqk*tLmh#A%MP47!itL6FWKIn{A2Fd@N z&z~y^489I*-yrBz0LT8hu^HTj5&5(%N9bqg4XuL^a9vfPRg;{nOb0jK3JhH!%<^=X zFZ6p96woY1(G_-ES9{RJY%gj{YpVmm1klsdqp;PmCHZArG`pG=!!+Z_Xhx0Rlst*0`hNHOCBo} zLqDNTfSM&CfCsPBhj(5~V#)4}ug3lNx-ltzaDZJEKe=Wi%WX>!$oT>P*l9<)bW&g6 z8Kfw$SNYxa!kVE5&fpvvp}D`*_vZTkG2X>ECV|!W>7fCTXlelflqW0NTMh(=8|4Iey6!7#$d19$mn%<4 zE7+dh*0rP^PXM1SKn~NS?H*|~>gvzuoVa(>kjam{()g&5i$bL7O@>tf)Y6T}i80E@ z-+|DxEo9Oo;PNyoP_J0F#i^{WzaNv-vF5QH6SFrtsrHg!2b@n-DBr`;(UJ0(mX;QK z0H4DsL(@1v9$K6al8+TEq><%gU-5BAT&OSTy8x;?ceDU;@BZQT9AO=f3caUs9kU_m zw(MGa@qYgTkgL!s%)CQUzlZ;MV=tk4fRl!{&l`<&ya9X~2sxkWRRkzMK`c&5g0hjm z7$LvUU~Wg`-0KQ3IDKLX`<0#MJj9i{zmMj$q$X^pas1FhjGcGB5A0>oKp8%c_N8X; zn^{rI04uN!)b+mevJJ`T9BDC9PEJKq4MHSnerG$KVgn2LWUA8D70Cujceg=rg1GfNx6vUQfjjvJW(SpzZHX)h~Y>6!j%jLWCu_Ya|L3FYC z3gp&i(V^`O`urLz-CVb z=e)gdra_WM_2uBn+|0B$G6=$q*Cp43AMHd)>NU@AePyQ|M-7qViG%>x2q^OaSqp4* zry=Yv0pq~TgQIX+S8%PL{6+7qyR-9|CM9%P$it4s_oxOj!} z=(AsmVVM+(>N1lY%Dsdbz51K2z1{#vk{HTmfb&6Ka$InScHo&g+Y9HlbMd@nf_F1D z@c?AbSU9+mZ(HEJ2Il3iNF9jP{!-7&LHhv?J`Pp4{4H!B7-%F|gh&?u>Mb5ywuhZ! z|1Hm&AFon7I4}#LNZmbU|Mdy{P>k3MGC0!sT$36mF3hL$DvM&AV@1hbs9aPk=GU2K zkK8l_`4g0iQPep1>!I(e-cH&VS8{4UkydjDbKf|Ud}p&}0(fXwTsN3s}~4i5Q@thonNS3&FccR-X-3i!Z+CewpX0sqSzFg2K8B)pF%BcAerW! zSO$yHQ-hB@X5-qgrW3UBRG8COv{F?w_SEX#oX^?8apU)|NCloLu>bJV2n6Mrxhe=$ z&*RQ3lM((rGD5;9-^Q#r%EmD!Rk`U;{%^m&R1&0}l2!o1zAzy-26nPaKSY2>^CRMY zczz}UzGKu$M?X4(CKk%O3QK%kGNtC&$|URWL>Yive)^ytlLm{@)6}=|pJq}2M+obW zT@D&_)=3yAsO5}c>OkxP{d@p8D1s?U*^BrJ^xW^ZxC1I_`1Tg0P%v5=bE?5cLl}WY zWADRCVXo9)*!kr1b8&FT9WDhF(N$rlo-PJ@dbI#0^rc6JaEP#Q*a)UeK&xvLDwy5c z5bnvc(eCMq+^ors6w~nWK;pS|;D$q_v*?&A(NyEMa|OOH`~e70hOLsBt|qUzVBlbI z=o=&D*dGb~Q!ZUccc|PQ6AZK^_2hYy+(wlsnmv;$Mv9>y=uG*E)M1$1Jq)JHrgeX@ zeC@FO0oQN^c)A1I@Sq$MdkI(NX)Y-}Z+?Qt92hg673Jy)-Kc?8S>)NNtz9NB!lYfT z!H;I8seo-vXeoaYz02B(jcJ{?93-tu$|@@TL%@{yyMZ}@_V~QbkzqF-uyU3RL5!q| z)jX);olE3Trabjwj#8J^(l9*PVrfRA3h0O9O&3{fXxvGp6rvvQ2kZvI(@OP6r$gMTzVVJ&%IX!r(%d1bSL~6mnf%In^<*NaT22lqG#=yQm2zre zws$2&rqc2|*lp<4y%wYJGIhQVp)|A{n_meQZVTKZD{nszX`6YltkJzL?y*KbLu6Qe z(;rYOK4;5|gaD*lDR%p~3`wTLmMkdqp3-6fDNAftlvE}&BxKq;lI#}@E8K~C55RcI zChx=Gu3U{i+G~b?P+l{y&_raarjF zC=0l~TTbsVa_)k6av=iW#^6(T%oc7FU$Sj)3Y$oNT2TGx%KM!)(PjU?MrlUh3Sgr! z*5>5pB_QR0{YwO&a?2&H7mZsMhq`hb@2srGOW*g@o!G*!}OtW+a9A>u?J zX;#F$UW};NTD>iwf3~47zZjs{xQ4Co04MQc-LDRBT;25EoAlwBs90cI^kAr8x!zQF z7Qa6J6E6TG^$pL*f0}C(z0K=hf8OITpwu-&I_&h9 z>s4tkKzQEp%Fx6X7SKu2Gbvymw}b%56g~+N#LOTZxG3i7z;1MTUqbLRw~J>f9GW_xS2<33<@E zv?7e5_jH9_BWi=0JKB-dgRjTne z6q}apNz4Zhf}GAxa)&ERloPXlIvLn^LOLfbYh2x{s~i21d5g1OA+Z6>&o=Lp!gc`P zYtZUf>mBHz?LGh+)4$f|`L+*xWUt^xL|?KE?2~;YYVZolR~t{g`9-BIxzjU$89kX2 ze$QhgTD&dbJ3fvZuOGXDG}Kc_O)7FZX4Z@cYW8IRxsmGPVPbl-jNw}nDHSX5P@+Gy z><4(+&j1_)Z8p*ChyLApvdc+N*)Rumo#an0Uo3OFm!mxC{QVLKKvQ@&7V_-E9u(uB zW!yo<(=aW|9r*W)vn;JY5{vn8xT~=ScpK1tWobu{v5(`xoVN)uT&=zMe4ndJD+dB zgNf_8Dl`Wc(}*}ypdZQ2&~Kpc_)-xtbyNSI(c@+wMEzjl82?Emb{!*d;7jlw?9Bd3 zf1GlVwydNVUPwupT0Jnzp7TZ9&m^;NuIf(m+;+NbvJ)QOAZJyYrr^qu7i2Krbn@>X zb4g9Sy>Y5}CL>O8vPH`|^4m;jH9$n%sJ%RuK_mqmbkvG=ZooB4-TnMT7M19amS6XC zSse^*T+QVOQ?saz3}gF9F&1}hAL=QgD0_IyC2`hswN+y>jT_f!zCX1rQyUGVOb<#m z_7riD)8KD^28)*`F?z4aND|DJAsrNVihI!jZxJZ;r7P#>=QoxcG1?g^JC2;s;w{ia zw(dYdxWMti8H2p|;p#~lK^4O>StDC|`24zRji}c%KMQYAXS`ZjYqo5*njMub9NREX z=9?5F-0rzNRyO?<)g_0v1voIWNt^#GTwCnXcGUbbQZt;3ljQa@hxl(ZTH|q21j@Vx z=&SA<$^VEus|38-uga$Y}T-Nzbg^KQR?=f z-?dTmKKIOq=t*-fVt%f1;3SXxKO6T!Pi7SZ0I_TL_vi|OCc*<+0Oc-Ikx84Cxp9mQ zeG4&NC`$|xKiwu|+?2%~f27!f4B@x+bPDnDpq4F`1m~6g%=w0D3jLchv&0Z$l20|U zdn4MXtRjdHCbrio-kw+SJSn8$U@chP2DTFjqb6{oF{7B*P==7)ONY>5U|o zNcT)^$*XXYpub<{$be^It1-wHRKYm+g&nnxEjKK|#nP^L3nw-VpX8`GyM9JpuR?!! zI7wcYYv(Q&4LYub=SWzK8`q6MPEA&TCL9wWkBbh!rGy!WIgtiN7X`u zpCSeAzG?u2F!|tTC(5tUG>#4a$;p@e-0TE+ICW|@p^<55(m9Q# z?_`WpNfR7aS|}{fN{@9%51Me9jAsP$f@o;U_6p_12^ZIDQN{RLDc|rtSA^ZYVCTd9 z8+3JoMyl}ul4NGqO3PQD09^~iq~oZf0Ys#Hyu!gm!m!9cemzv-sA1}ReT4EzKL)K> zr5B$lP2xjLy$g(%m4p^OI=n>wcQ=U95+lZqmkpZlLS(_?DTk4Yf2vco{>VOIj&|?( z0iZm9o1J1{Q`OA3A5I2b@i{Ouf-D=0w?`kM9s8e_s2M4Dae>@Y=rXwm6^z|jnb^~OYyoM2DnC5mdLrgF{Vi z;HI=?BbH{y`LRSRiN>Rt+V7tU!DJcf@;HHcILq|-sA2KMRpO33pM>L;Lxx#!vpV0> zzMrm_YF~XtT>b&PU*h>bEN))+!|!zf10eiDkHT+k|8aNC@>>U?+qEh>v|qb8`IWG3 zo70W<;bhEakA-qsC#;rR-rQLIT~&|_z+)$c3SZymKFl)`7Pt7Ri@4(jPHx8eX|_8O zjP3>OHV=@nS>a4DuyA&MZ}w>Jf9JMXoiW4(=8?ZpxsHr#TAERRWu+>3n+CCf58zg-2NZ+Ksh0pGpvh+FN7?v z6(BPKiD8GJQ^`wa6Qrwnjpd>Tf!lMN@B#gq$~qcDRL~kU4&SqxX~X0 z;?n?v1>lu9DuFGWgzIPIbCeOO6q5$R5SGnpx52)EB1B2L$m%#Yn4X{u(Aco(Co7U*gM|EKccm>65{RXXi(xA zqf%|gik}%<6C5b;yqT3E&KfNizbym?bQGlrK*9wC41`{)^q}V2H)OQ&Xf!+yu1gts z{Ie2I)tyv(ElmWdXg{8be!Mo$6{L#egI>M4P>*vn*^O})-RKq+@ z9nmca*9aET2s}7Ev@L3C!ZRItZPsQ0 zLCX}5`;1gok%2>}H0ETI&-Lp86Ui}5H21o3%wSMnsQvqMcXPL6oNU9)Rss3)x!~@z z5s71Kd%df{!v_>Dininc-$o1XFa!GAGZ%hZ$CJGZgkRp5ZBvIiQ?9Y>dD@x6NTBjj zAh4L;7WprqSoq=QBX@iPfgv(2;wx;CKV^eTbc2}`PbSjBGUFY9MD{XU;{MT(df2i4 zCrbm1ZYg)_g-)OzK2F_5$@pqTM&~`ihefzCiKB92$$ce&_wO}74)2a}CI9KErl#i0 zzzGmZYWBtB^-37(f9Z2cV9=9%qznH>Z)_}{hXRb)7u?X+d=W1syV)C(1aMhM`oJ=5)#nec*&H%pmse`8hIS)J#zuV zHGqp?-(`QAeZDg|s`vO0&mxNo#Hio#TJ=1Mut(jw{nt)KNjV|m2>{@@t$@P6UC}?|M8_235Lbwj=x;kt{B>8-| z${y>zu&J{pVs z=qR)8C>Q{%R7g$s54Ngjkp1fkPT2~IW#d5?KB3}CK9yGg&qw;o>E@*l*Xi%&H4n@* z0RZluE9|>>$#J`Gl_D=!sIUKG5dupul#K+*H(<2wfQYB?vXB=NHoWVCi^6|l(7qiW zd+1I6p8U98=v9Mp=CGFt4?i?nviYxqEuUFnIG} zwOv75BVNq}r!SO@Q8E=~F<*wZPtfa~&gbV|Bs^p$0{-0>3_PG} zY|=`ymyvd3Ldr=^3D)+9qA9CJrKw9prM|g0@_95Z!5N|3QaV^gu~aiL9jJkyXihb3 zbCxU%FxGzZMYSNJn^Tj=VS7xN3NL@mw_1&kAtUQ%s7+p71j#LD*Z%+@T@w5m2>z_m zZl?HzGG@|gT!wf0(U52bx6^r|sE}X!t7(8$y2s;%m{g9SS*)wcAXD2&3Aw%J=mFhC zzS&-E0iscjeDuDn6f|#1pM}iT6P-_Z)KzQsXZ!HB&K=gUn5YfkN|y+sV&gFvHBLgx zE-)p}_x|Yvf7wX=I~d9kIF1fIxbYR6V>WJk*J0=PRTAYmXUhUj7pPGMjb__;d3k}| z)j5CCb;zDJvhxq|INEA?jQTK1;JxZgh^#juNRfjf3{p2$`Os$&)2^&N6n50jcJ3{( z`0TgDg1Cte$cJN|1wW{1!g_Tkot(h|xB(8gh;tv9>U$w*Vv8bT^wm#@~p zXUd}QLq(kR_3;4!F!R}MU3L}1d6&Ra28d{#NvFW*8^ClScD3fk29#vBffW#fUN}WT zdqNfLc&Uu>ze$KGUCtXP;qnMULg5FXuO7w-6%oL|V?JM?h4(|rCZPJ|Lhk#=9C%_< z4=-it5YJEU6|~B1CAf}S@E8W)u^R!yfi(wlU#D3DJrnoL@z5=9$%CylB(ASMfcZZ9 zL$sAa2DpT=e^6LS59}IS6fo7X9m#g7SD(paDgso;{#QIfvm(se8Ts^EhVC$Y2U%k- zFQcVCT=2t#?l?a?NNbY;N7UU{#gzKV;j5`xGi9aZ!N^TnT1UP0E2=Afo7yU@JUO}G zGiGRd!Ix&)IGh0IE$t;>Xb-ijGayNSj7E;^#Eb0^eJSquP}2?rwI7PHNMKcALuCO3 zemQ@)ioMvog~{F6TaKFtY^se**K^9b_KvYiJjcDa6I2aMP05IcX1AO)5c@Es>RT{i@h2ny1bjH5^hStTG+`tFSouujj*u z{Perj+@P$GS#kwV6tBsP8LU&X19>X_0^QMeqwPiV2_`X3^g2fm#(cp3wn9Imr70(6mygz!W z@sc4NwFz&E{{2G;od~c!^<4DinE^4h7j>wGZ~m?7mmg^>MhM^j5Zetc(etz)bqpUW zPO+id_Q5(iQV$~U3$s}_;<6_tJjGH(;j|Bp%;s+=+Bu|$u>IIur1&894qt63NugJ9 z`4{P%N8ug|qkq8UriWbQ{Pf)3%w4>sDRybK?{vR}c@SA^J%^`KcN^!^8Go;0TDz|@ zZx-*i2+(a1xY7pb@FLs#R!5Rpp6LD_jQ9I*RAA8pcv&^SDG}6*Nn>96hEHE6kZeyz z@!NLMty{;X|9~ehdS;=CQh4{p0b5?#qoq_6gmA`7gA&Y*P^&cLqy{L0xh$5{i*MZqa{GH{us*}k{P^_o-~D&D?qp`6X{e1T7K zelfGEy}3k1MHMC#gEwBenX4bWuwi%}xc)L&s$x|O?p27P1-Zp+7VvET^kIB$_R{#< zCzPl)EFwlGtNKzL>HA)d@SAFDsxUI9#8+0PjPOnc+J2|6&y?o5sI7I^wPhut+4SML z<8xz}NwrrR+~d`{iy=3H7rEcRH}TGu^|pi|NIuS`@|nfqyoo=5GI7OV7U1(y`e{fm zWuNNm9v2l44zN`;OeU2MQe!%&tyZRDB=*rFwzp98p`*+G$}kT~vmCDK@Bc%DjXq_q zq^?sY$v)qf(XXX!C;vo2Q}N&<9M1yn=Zl?$vLNpEb3yhG=;`TSDsrl;eb3caQYs^t zI>!tt+R2s@SvUt+V@WD5fj=ghzK$-|A>2p(4|%JmIrSgM4(h15#%lu!xK4?+Av-8lW6U3d=W(ay zV1`2}m&@!pib$M?JxdlNgVRlWZuO@(DOuk*U^)8>|8y#L6*m8s_SDiV?dWTkA`1RU zIEjmuFC|3~dapP|XDwT7k2#y#C471O`EuiOOjAac$|jzvlO6!>@%vCS=fxtZ(y^5V z$*cdZkYOLNp18@15p#{XTewLNKibvrm139|CO=Q*W}B&@miy}3XRF>KOjNxqg{e)j z*C?X*t__?(IVRB0GMNJ2AJ2)*&(hw(Hc+hAd-ta_5W^&(ddBYv7s(@IkOS|OI3(C4 zf>~IpJ;yEyv0l)1%2IVp?t&6SvY|6OtQjqXqH{0Y*{Muh{d#u)V{L#93m;8l$S9_* zG)v^vuih61DZFY`F+O)TCrR7zr)jAi{4T`1>7b$K8e43LJ#sneudE5YR)Po2hg%~U z`DbU3GnKR8rm<50?!FJ5zx<|hj}lv69brs@031N6s*l2?CsHQ5VJQaxYP+*nX*OMU zsd*iQ7$m5~^_MRX6AIi|(BiV+aKWo%8=&QyX(Sk@P!K2nE*4XXO)8?WGF#wnn#ei8 z6#}X(+scqvd_rY`D1zQ5mA#}Fl|9*L!5V+8ub#kozwWdFE}yQ_Wh3*M3nVYM z=i@CwxhotNrT^9&c*4&TP$%X&U+!U&tjAMj8jPHenpX$q5Xo04w|}BsOA3jdCIAgn z3I3M%0aeY+n}B{+roaE(UUho~`_sB!oI8i< zk)pdLQtIDzB1W6$Ww|xTlUJCzYybOI(*e1V+4uIe>-|O*4Co>uUG3C)9z>n7bdeXM zAk75l>5EWROk&8eN=dskTW-3w-+o$nY{a*!F@O0fXL+9NkK%p`T)JC3tV=4iBp*7% z-%}!#8DT(+`FnL1Eu*cE3ZHOqYk_&;lO;Gu*z?@I8)lJq@i$X+|77WwHV}Ey8yG9+ zXyh{hYeLJy5mjO`8V?5`f#kcx8*MJN*|hrOK)?S_V5h$a|Jd6%%`(A~nw0^zYLX^Z z6o#H<;>DiLCF8fhVvMJu(W&T{U&xM!ysr44nh9tU3q0_UMyB$=(Mw~LA0tVciDV(> z83?+C)ou|sSn#T&RH$|l^f11ORCcFDg2Ly~d&f$q)6LR1Ns`UEBi?g?Vu5n|dZpH< z+L;xykZGT#G9jH$c|C_=m3BuaGvf&HvH9@#%1~GmcTY(x%%e|aaE=ClgihLpWDy~JpjtQ8F}>z{NinCE6f&NrFOm>7w=gQs36&MkZK>RtNs}K9F&V?D8yq&N>go=Y8akDb z)nLB#-<5%a2XbyExRF!v7(QAUyB4d<8dA$Ks8>`Ip*_vsQ<+B_FdUDzOm5t+L5y@_hSACy)4T*Zs z)*4*%tsuyu(o5dj<9M%A3_M@OB|9)Ytm31XwpuZb*#udTq2BuLee z0Kt?LdJJlepRr4dypH1y+rQp3TF0(o$S@UZdsRpNI$Ao%52w#<0sAhTz-RHXhx2hH?x}}*&`*zDy zw{oi!rU=<6U~q3k_2f6|((%{95}a{;KeR<(Yw9M^Wmm1*+jX5#k9JJzaH=R=8K-W3 z7ojo`L?kzkz9Ey3A5Vu`Rr=E9b!t&alSVj7t`?9Yh~!Vll%@nqTP?bwKS(v^};e99oX8 zyu8g*6>X$)%z^w}m7_7voT-+|%NX~rcp}{sV$=^GTRlZDBvpS=L4r)vf|IOC(hJU74jh$u-JLG%>xT#Z#`*3{=EQyC&` zEc*xe75&R~qC7}Y5|eccxgs-q%F_OH^{yEpNmF~&l5%KdyzK_X7Jp_sinqB+ZTZSw(-xCeg01KpmWcBNgto9r z`b5!<^w12=ZM8g&u@>&>q}A)ruGq6}(Hu{n{u-I`T09ToTk3?JgR3X( zG`AS!i6QLNoh1YE&y^t>h{pH%`m4rKsyieYo4|R^po=n!Ak?)P&;iHlyW_T;ttQ_S zD@d6wmaTV*6_LJ&RlqkO0mw@X7B!_JMElxSrTZO zmO(5hq|5=!0Le4zT9<_gElBvrA+tQM3Z41O_ zMVe)BbI&`W{VfJP6D{g-cjnG$2N9o|Qo>diu8ERrY47t+B=QCpE`nJ`$FG3bKYeyt z;PB*IlJDV6h}xdNmUV3|b<-xo+kW9|r3_sbSl{*w$$ zOZ^uCB!m7jAf9{sup48=BHZ>|2+f&i>>x@r}K9PcQxszqlEQjhQ(o#|wBhVW5jL zX7!tz<|RL-i%f}klx9+uuxy_RqF}cw-(W>I4#9GID*SdQs zE%H=$Br*p{+awGpIfnf}14@(y%=rcSlD!J{y`%_42oY@x-LtL)zV7ZHF{uatTf9C# z)vVcPp46yH`&}Jbu0KMS@>y0+SqDCgmH_fM03!|01`DYUN)U$T-ZyAySJj$1@(fUM zkusrc)!Ty_54X5FN9Gi{^Vl(}0g>s_)->!#gek1q6%({f$10%Tog#wTtLQ3W?A4ry z1fLb^@2D)nBjI{i;C%||u1za7i~6I*g1V~YVrNSr33}<|t0F$BBJ>o^cTJxOAbX_$ zshiJ>7wtge+#ny87?XvnA!O~{08>A?Z3SN0mwli3?W314av)>#jl!?DqKpa80*(H| zgNj3d$(JjBit$Sq~Yk($=q$0BE4bgZwXp;p}M zdg2cB{CQgjt|ro+aimM=Tn8%I^sqDi8KqyZ=b8}4b3A4Qd>r^_1tfIA4;wjD89V1| ztql!cYmZB7Cti<-rzUjN|MgFRTC8+nV}GdZ8k)aZ$4v}xQj!D!ug3};#61LA$s1u* zT_!TP1@at7Fw!}Hh2Pw;kaEJ(9ZLF{2fbYUGm83@N$CZ-re=NFo>-eLrj|4Xb}BTj zwE<^N!k6nL?waHS&2K*OpTzd(MiZO_9%SV}Y!(=pJQjQC?1x3AEne)ckh(Mbqxd?m z!&l^?{A&4NXt0fAq@dOJb^>S|;6#T!2^R`k#Zp3CITxin{m}B6p70>HRgr4kW88zc zUZNJcOxlbT2QNNw_<9@r(9U^Kb5Dba0UMcyMM||-F#gV`%!1M(jA-ny?tRQ^ZnU_Z zdDBccy(`ROA>RN~qc+R{3v{r?rICZmEtglacI+!c75&+PdXI#S*lyQSnyLcii^EhQ zjZQjYZn90gU^`=8ewWDlb_Cn6hBv`v;HtKe3L8E_oH7!x6|IXu~-{$}lqg+0LT(tPgRR;>f|#|DJj)?iRQE z&z_5Pk;UYifdPS+57-q$`vZ`FqnP=w!~Z=jrw?z3eET+d-;4cwjPqM;o-{$*$W>u_RsrK^CYrs@Oa#R|G9Sid-be~r^Ijf--d+W8(+;|EV~9YGq z8xoaAO%$N@mX{i%FNk{rgnEE=gpe|=<1_w2<#w|EnV4{CNAqU3e8;5&xTRs{Hl zoDgn+NVNr|h=HFCP|;=~dJ%BP5wA*Or=ti8KT?W8%%)(mt}Zs*PKWaKhw<0gEozSe zgj?Otwyl<2{6vOR>*NVZxq>xkf87w-u?fH5EQXGN=1gMRfG`m@JFdd3+}4dzVsNSa zwnBt#D#kaUjoIJODe7+RG-JD^8W{a+cP985HSY|Vjl9}NLgKEM0Ja*E+D%+G-z)A{ zp9tenk-l=-j=LUPXTWOnWCQuD%;881+sKUE(Jt27%)b5JKZSn5yQ%!%$g>*_=)k;Y5`ww7 zts?-K_T}^<-aCrWVtt!pp&l*pJ#o1mzT1D<);1)e(Z!o_cenuvjyiI#jbl z92iIOFWk{Jz#KP1wP4n4VJ7wKWDDx2?^sPZ-6myyKop2{GTdiwM2 z;?w4{Y7PxZKqe;U7#O*b!E0gv0*16MpmPjZW87>X7KiM~Opv`3rbv*o(VEWuRID1m z2gZO$k54gqh*-fD(dJ+EPF3+PnbkKydd@60LBB8Q~bX(p=F%NopY9sr%liu4(ERLTL zMqE9!F%%zzpvXKKq?fO<^nrg!?BPYG^TXg~iI)Z*WWRyX8<4Dz%4j9F!>n2*JeZSc z^2riHy3DOG02|6zMyFYjhxuVbHLxCg;=haOs$lzU{R7q^@vi^obkA-(#GFKOn%n|8 zcjW_ISNmG_WCR?5!OwT4(vIkD=*89%dFF2j0$5<#s4hwSo_MjYsC3_i-Za}@OV)#KWrD;Tu=#@92S-KPI`C_ynrOh?eFA}y(LYIwtAnz-G9aJo2?l*+ z^0NC=9z?5bO|*TRts3SRYqEAc&N2S^2?f99)G(}%$t<57Jm8}2OyN`u1!`D`(@2GH zEB1i_PO@B~Md|_%z>6;7BSePn&Ucz;3eS=yg4$Ibc>^z zoRB_o4FtLqrq%z6zvW0zNwbrmxv>V&~VEovntN zq+#Dc8{m=Hx@;FaEqAs=0bi(lUh9@;O>1#!)Bkk;>(k7!^|KOW%7)>j`?}7n3P}%v zvX>+j12{er{fgeCFBt`b*p?tm>?;*L#%mhG-9|{+^^i z*kZ!NfoFjweR|iAm`4CYuH2oX=uKn6!#$`Tlo2m+vdXn?zyT5*Wc4wWtNhZ&lwRTi zty0lQ*g0ypk7FMD+a(;N+D%`ALqRBVb=R|wFuwBfuKofSq|61>6|gCJlo5meX>mU)oM1L=X=D0pK~g%Rj*Ee8CdEMjQ*? zEb*y46&I=j%MTK}-Fugso}?zYZak*Fh&jFFg>q8;VCG)>@d};1@yMJ#Msun!mnt*H zT}_U`Jcu?`IY)=rYdQq?hB)c#$^4fcIX>A8JO`n9Unb!k-KfpL>t?_6vRD~ty zI`z^`%QC1ps2GHdxeR1u`OES?&b#->z-&qrb9|)p*W2^vQ3x&8)0}QDQ_2s6c`q%d z2?{OHd-8q3L_1nAcsKKVaD`@nLdoLUvJtrn$ni7}{15!@``@5(`}uS!^hUcA>8twJ zKyCH!rfv43R%KZkPmh>PYpHyl)5*a$t~upzVimJ|Y95SKIW`K_{pZf%{~3LLL%xlU&$iTp;`M%rCDs{K4s{ zreRM&rh^Sz1dfj{(X%-qoY6kadboymM_%SabQ#?(#)R)tHBrbU^nq}{>?}Srq;jcz z{Au-Z8@0JYkvcPblir5GY|9c) zT0hc)Q89O(Jz`07Vj(OrOx(a|8f~!;rq3jcFK|ns9|1Pbv%o0x`>vSasOW}5*ZNkx wPx6^^W}6!C?24m_)Od^3pro&j&sU!PHBsYjs7~_SLBQ81DMiWhkA{K&2MO=rQ2+n{ literal 0 HcmV?d00001 diff --git a/Templates/BaseGame/game/core/postFX/images/inactive-overlay.png b/Templates/BaseGame/game/core/postFX/images/inactive-overlay.png new file mode 100644 index 0000000000000000000000000000000000000000..feab83209cc442c5ad8dc73c2b86e0a8115c4743 GIT binary patch literal 131 zcmeAS@N?(olHy`uVBq!ia0vp^A|TAc1|)ksWqE;=WQl7;NpOBzNqJ&XDuZK6ep0G} zXKrG8YEWuoN@d~6R2!foRZkbkkcwMLfBw9D?8~Obq{gPz9LVg>D`Q%4bP0l+XkKL$W0) literal 0 HcmV?d00001 diff --git a/Templates/BaseGame/game/core/postFX/images/materials.cs b/Templates/BaseGame/game/core/postFX/images/materials.cs new file mode 100644 index 000000000..a13c751b3 --- /dev/null +++ b/Templates/BaseGame/game/core/postFX/images/materials.cs @@ -0,0 +1,32 @@ +//----------------------------------------------------------------------------- +// 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. +//----------------------------------------------------------------------------- + +singleton Material( Empty ) +{ +}; + +singleton Material(WarningMaterial) { + detailMap[0] = "missingTexture"; + diffuseColor[0] = "25 16 0"; + emissive[0] = false; + translucent = false; +}; diff --git a/Templates/BaseGame/game/core/postFX/images/missingTexture.png b/Templates/BaseGame/game/core/postFX/images/missingTexture.png new file mode 100644 index 0000000000000000000000000000000000000000..80a7874da967ad523e1a3308f3f14c66d4eed503 GIT binary patch literal 10645 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 IM6N<$f@#CI-2eap literal 0 HcmV?d00001 diff --git a/Templates/BaseGame/game/core/postFX/images/null_color_ramp.png b/Templates/BaseGame/game/core/postFX/images/null_color_ramp.png new file mode 100644 index 0000000000000000000000000000000000000000..5f5a52186eb93cb7ace739e645e5e8f8e6b8050d GIT binary patch literal 2843 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 literal 0 HcmV?d00001 diff --git a/Templates/BaseGame/game/core/postFX/images/warnMat.dds b/Templates/BaseGame/game/core/postFX/images/warnMat.dds new file mode 100644 index 0000000000000000000000000000000000000000..ea99dcbd74a8b2ae49c5cff5a69743498a66e937 GIT binary patch literal 699192 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 literal 0 HcmV?d00001 diff --git a/Templates/BaseGame/game/core/postFX/scripts/GammaPostFX.cs b/Templates/BaseGame/game/core/postFX/scripts/GammaPostFX.cs new file mode 100644 index 000000000..293d44714 --- /dev/null +++ b/Templates/BaseGame/game/core/postFX/scripts/GammaPostFX.cs @@ -0,0 +1,73 @@ +//----------------------------------------------------------------------------- +// 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. +//----------------------------------------------------------------------------- + +singleton ShaderData( GammaShader ) +{ + DXVertexShaderFile = $Core::CommonShaderPath @ "/postFX/postFxV.hlsl"; + DXPixelShaderFile = $Core::CommonShaderPath @ "/postFX/gammaP.hlsl"; + + OGLVertexShaderFile = $Core::CommonShaderPath @ "/postFX/gl/postFxV.glsl"; + OGLPixelShaderFile = $Core::CommonShaderPath @ "/postFX/gl/gammaP.glsl"; + + samplerNames[0] = "$backBuffer"; + samplerNames[1] = "$colorCorrectionTex"; + + pixVersion = 2.0; +}; + +singleton GFXStateBlockData( GammaStateBlock : PFX_DefaultStateBlock ) +{ + samplersDefined = true; + samplerStates[0] = SamplerClampLinear; + samplerStates[1] = SamplerClampLinear; +}; + +singleton PostEffect( GammaPostFX ) +{ + isEnabled = true; + allowReflectPass = true; + + renderTime = "PFXBeforeBin"; + renderBin = "EditorBin"; + renderPriority = 9998; + + shader = GammaShader; + stateBlock = GammaStateBlock; + + texture[0] = "$backBuffer"; + texture[1] = $HDRPostFX::colorCorrectionRamp; + textureSRGB[1] = true; +}; + +function GammaPostFX::preProcess( %this ) +{ + if ( %this.texture[1] !$= $HDRPostFX::colorCorrectionRamp ) + %this.setTexture( 1, $HDRPostFX::colorCorrectionRamp ); +} + +function GammaPostFX::setShaderConsts( %this ) +{ + %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/BaseGame/game/core/postFX/scripts/MLAA.cs b/Templates/BaseGame/game/core/postFX/scripts/MLAA.cs new file mode 100644 index 000000000..491c98e4e --- /dev/null +++ b/Templates/BaseGame/game/core/postFX/scripts/MLAA.cs @@ -0,0 +1,186 @@ +//----------------------------------------------------------------------------- +// 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. +//----------------------------------------------------------------------------- + +// An implementation of "Practical Morphological Anti-Aliasing" from +// GPU Pro 2 by Jorge Jimenez, Belen Masia, Jose I. Echevarria, +// Fernando Navarro, and Diego Gutierrez. +// +// http://www.iryoku.com/mlaa/ + +// NOTE: This is currently disabled in favor of FXAA. See +// core\scripts\client\canvas.cs if you want to re-enable it. + +singleton GFXStateBlockData( MLAA_EdgeDetectStateBlock : PFX_DefaultStateBlock ) +{ + // Mark the edge pixels in stencil. + stencilDefined = true; + stencilEnable = true; + stencilPassOp = GFXStencilOpReplace; + stencilFunc = GFXCmpAlways; + stencilRef = 1; + + samplersDefined = true; + samplerStates[0] = SamplerClampLinear; +}; + +singleton ShaderData( MLAA_EdgeDetectionShader ) +{ + DXVertexShaderFile = $Core::CommonShaderPath @ "/postFX/mlaa/offsetV.hlsl"; + DXPixelShaderFile = $Core::CommonShaderPath @ "/postFX/mlaa/edgeDetectionP.hlsl"; + + OGLVertexShaderFile = $Core::CommonShaderPath @ "/postFX/mlaa/gl/offsetV.glsl"; + OGLPixelShaderFile = $Core::CommonShaderPath @ "/postFX/mlaa/gl/edgeDetectionP.glsl"; + + samplerNames[0] = "$colorMapG"; + samplerNames[1] = "$deferredMap"; + + pixVersion = 3.0; +}; + +singleton GFXStateBlockData( MLAA_BlendWeightCalculationStateBlock : PFX_DefaultStateBlock ) +{ + // Here we want to process only marked pixels. + stencilDefined = true; + stencilEnable = true; + stencilPassOp = GFXStencilOpKeep; + stencilFunc = GFXCmpEqual; + stencilRef = 1; + + samplersDefined = true; + samplerStates[0] = SamplerClampPoint; + samplerStates[1] = SamplerClampLinear; + samplerStates[2] = SamplerClampPoint; +}; + +singleton ShaderData( MLAA_BlendWeightCalculationShader ) +{ + DXVertexShaderFile = $Core::CommonShaderPath @ "/postFX/mlaa/passthruV.hlsl"; + DXPixelShaderFile = $Core::CommonShaderPath @ "/postFX/mlaa/blendWeightCalculationP.hlsl"; + + OGLVertexShaderFile = $Core::CommonShaderPath @ "/postFX/mlaa/gl/passthruV.glsl"; + OGLPixelShaderFile = $Core::CommonShaderPath @ "/postFX/mlaa/gl/blendWeightCalculationP.glsl"; + + samplerNames[0] = "$edgesMap"; + samplerNames[1] = "$edgesMapL"; + samplerNames[2] = "$areaMap"; + + pixVersion = 3.0; +}; + +singleton GFXStateBlockData( MLAA_NeighborhoodBlendingStateBlock : PFX_DefaultStateBlock ) +{ + // Here we want to process only marked pixels too. + stencilDefined = true; + stencilEnable = true; + stencilPassOp = GFXStencilOpKeep; + stencilFunc = GFXCmpEqual; + stencilRef = 1; + + samplersDefined = true; + samplerStates[0] = SamplerClampPoint; + samplerStates[1] = SamplerClampLinear; + samplerStates[2] = SamplerClampPoint; +}; + +singleton ShaderData( MLAA_NeighborhoodBlendingShader ) +{ + DXVertexShaderFile = $Core::CommonShaderPath @ "/postFX/mlaa/offsetV.hlsl"; + DXPixelShaderFile = $Core::CommonShaderPath @ "/postFX/mlaa/neighborhoodBlendingP.hlsl"; + + OGLVertexShaderFile = $Core::CommonShaderPath @ "/postFX/mlaa/gl/offsetV.glsl"; + OGLPixelShaderFile = $Core::CommonShaderPath @ "/postFX/mlaa/gl/neighborhoodBlendingP.glsl"; + + samplerNames[0] = "$blendMap"; + samplerNames[1] = "$colorMapL"; + samplerNames[2] = "$colorMap"; + + pixVersion = 3.0; +}; + + +singleton PostEffect( MLAAFx ) +{ + isEnabled = false; + + allowReflectPass = false; + renderTime = "PFXAfterDiffuse"; + + texture[0] = "$backBuffer"; //colorMapG + texture[1] = "#deferred"; // Used for depth detection + + target = "$outTex"; + targetClear = PFXTargetClear_OnDraw; + targetClearColor = "0 0 0 0"; + + stateBlock = MLAA_EdgeDetectStateBlock; + shader = MLAA_EdgeDetectionShader; + + // The luma calculation weights which can be user adjustable + // per-scene if nessasary. The default value of... + // + // 0.2126 0.7152 0.0722 + // + // ... is the HDTV ITU-R Recommendation BT. 709. + lumaCoefficients = "0.2126 0.7152 0.0722"; + + // The tweakable color threshold used to select + // the range of edge pixels to blend. + threshold = 0.1; + + // The depth delta threshold used to select + // the range of edge pixels to blend. + depthThreshold = 0.01; + + new PostEffect() + { + internalName = "blendingWeightsCalculation"; + + target = "$outTex"; + targetClear = PFXTargetClear_OnDraw; + + shader = MLAA_BlendWeightCalculationShader; + stateBlock = MLAA_BlendWeightCalculationStateBlock; + + texture[0] = "$inTex"; // Edges mask + texture[1] = "$inTex"; // Edges mask + texture[2] = "core/postFX/images/AreaMap33.dds"; + }; + + new PostEffect() + { + internalName = "neighborhoodBlending"; + + shader = MLAA_NeighborhoodBlendingShader; + stateBlock = MLAA_NeighborhoodBlendingStateBlock; + + texture[0] = "$inTex"; // Blend weights + texture[1] = "$backBuffer"; + texture[2] = "$backBuffer"; + }; +}; + +function MLAAFx::setShaderConsts(%this) +{ + %this.setShaderConst("$lumaCoefficients", %this.lumaCoefficients); + %this.setShaderConst("$threshold", %this.threshold); + %this.setShaderConst("$depthThreshold", %this.depthThreshold); +} \ No newline at end of file diff --git a/Templates/BaseGame/game/core/postFX/scripts/MotionBlurFx.cs b/Templates/BaseGame/game/core/postFX/scripts/MotionBlurFx.cs new file mode 100644 index 000000000..6919cc5a7 --- /dev/null +++ b/Templates/BaseGame/game/core/postFX/scripts/MotionBlurFx.cs @@ -0,0 +1,53 @@ +//----------------------------------------------------------------------------- +// 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. +//----------------------------------------------------------------------------- + +singleton ShaderData( PFX_MotionBlurShader ) +{ + DXVertexShaderFile = $Core::CommonShaderPath @ "/postFX/postFxV.hlsl"; //we use the bare-bones postFxV.hlsl + DXPixelShaderFile = $Core::CommonShaderPath @ "/postFX/motionBlurP.hlsl"; //new pixel shader + + OGLVertexShaderFile = $Core::CommonShaderPath @ "/postFX/gl/postFxV.glsl"; + OGLPixelShaderFile = $Core::CommonShaderPath @ "/postFX/gl/motionBlurP.glsl"; + + samplerNames[0] = "$backBuffer"; + samplerNames[1] = "$deferredTex"; + + pixVersion = 3.0; +}; + +singleton PostEffect(MotionBlurFX) +{ + isEnabled = false; + + renderTime = "PFXAfterDiffuse"; + + shader = PFX_MotionBlurShader; + stateBlock = PFX_DefaultStateBlock; + texture[0] = "$backbuffer"; + texture[1] = "#deferred"; + target = "$backBuffer"; +}; + +function MotionBlurFX::setShaderConsts(%this) +{ + %this.setShaderConst( "$velocityMultiplier", 3000 ); +} diff --git a/Templates/BaseGame/game/core/postFX/scripts/caustics.cs b/Templates/BaseGame/game/core/postFX/scripts/caustics.cs new file mode 100644 index 000000000..7dcea20a5 --- /dev/null +++ b/Templates/BaseGame/game/core/postFX/scripts/caustics.cs @@ -0,0 +1,64 @@ +//----------------------------------------------------------------------------- +// 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. +//----------------------------------------------------------------------------- + +singleton GFXStateBlockData( PFX_CausticsStateBlock : PFX_DefaultStateBlock ) +{ + blendDefined = true; + blendEnable = true; + blendSrc = GFXBlendOne; + blendDest = GFXBlendOne; + + samplersDefined = true; + samplerStates[0] = SamplerClampLinear; + samplerStates[1] = SamplerWrapLinear; + samplerStates[2] = SamplerWrapLinear; +}; + +singleton ShaderData( PFX_CausticsShader ) +{ + DXVertexShaderFile = $Core::CommonShaderPath @ "/postFX/postFxV.hlsl"; + DXPixelShaderFile = $Core::CommonShaderPath @ "/postFX/caustics/causticsP.hlsl"; + + OGLVertexShaderFile = $Core::CommonShaderPath @ "/postFX/gl/postFxV.glsl"; + OGLPixelShaderFile = $Core::CommonShaderPath @ "/postFX/caustics/gl/causticsP.glsl"; + + samplerNames[0] = "$deferredTex"; + samplerNames[1] = "$causticsTex0"; + samplerNames[2] = "$causticsTex1"; + + pixVersion = 3.0; +}; + +singleton PostEffect( CausticsPFX ) +{ + isEnabled = false; + renderTime = "PFXAfterDiffuse"; + renderBin = "ObjTranslucentBin"; + //renderPriority = 0.1; + + shader = PFX_CausticsShader; + stateBlock = PFX_CausticsStateBlock; + texture[0] = "#deferred"; + texture[1] = "core/postFX/images/caustics_1"; + texture[2] = "core/postFX/images/caustics_2"; + target = "$backBuffer"; +}; diff --git a/Templates/BaseGame/game/core/postFX/scripts/chromaticLens.cs b/Templates/BaseGame/game/core/postFX/scripts/chromaticLens.cs new file mode 100644 index 000000000..06b8d3988 --- /dev/null +++ b/Templates/BaseGame/game/core/postFX/scripts/chromaticLens.cs @@ -0,0 +1,77 @@ +//----------------------------------------------------------------------------- +// 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. +//----------------------------------------------------------------------------- + +/// +$CAPostFx::enabled = false; + +/// The lens distortion coefficient. +$CAPostFx::distCoeffecient = -0.05; + +/// The cubic distortion value. +$CAPostFx::cubeDistortionFactor = -0.1; + +/// The amount and direction of the maxium shift for +/// the red, green, and blue channels. +$CAPostFx::colorDistortionFactor = "0.005 -0.005 0.01"; + + +singleton GFXStateBlockData( PFX_DefaultChromaticLensStateBlock ) +{ + zDefined = true; + zEnable = false; + zWriteEnable = false; + samplersDefined = true; + samplerStates[0] = SamplerClampPoint; +}; + +singleton ShaderData( PFX_ChromaticLensShader ) +{ + DXVertexShaderFile = $Core::CommonShaderPath @ "/postFX/postFxV.hlsl"; + DXPixelShaderFile = $Core::CommonShaderPath @ "/postFX/chromaticLens.hlsl"; + + OGLVertexShaderFile = $Core::CommonShaderPath @ "/postFX/gl/postFxV.glsl"; + OGLPixelShaderFile = $Core::CommonShaderPath @ "/postFX/gl/chromaticLens.glsl"; + + samplerNames[0] = "$backBuffer"; + + pixVersion = 3.0; +}; + +singleton PostEffect( ChromaticLensPostFX ) +{ + renderTime = "PFXAfterDiffuse"; + renderPriority = 0.2; + isEnabled = false; + allowReflectPass = false; + + shader = PFX_ChromaticLensShader; + stateBlock = PFX_DefaultChromaticLensStateBlock; + texture[0] = "$backBuffer"; + target = "$backBuffer"; +}; + +function ChromaticLensPostFX::setShaderConsts( %this ) +{ + %this.setShaderConst( "$distCoeff", $CAPostFx::distCoeffecient ); + %this.setShaderConst( "$cubeDistort", $CAPostFx::cubeDistortionFactor ); + %this.setShaderConst( "$colorDistort", $CAPostFx::colorDistortionFactor ); +} diff --git a/Templates/BaseGame/game/core/postFX/scripts/default.postfxpreset.cs b/Templates/BaseGame/game/core/postFX/scripts/default.postfxpreset.cs new file mode 100644 index 000000000..6054d52ee --- /dev/null +++ b/Templates/BaseGame/game/core/postFX/scripts/default.postfxpreset.cs @@ -0,0 +1,72 @@ +//----------------------------------------------------------------------------- +// 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. +//----------------------------------------------------------------------------- +$PostFXManager::Settings::EnableVignette = "1"; +$PostFXManager::Settings::EnableDOF = "1"; +$PostFXManager::Settings::EnabledSSAO = "1"; +$PostFXManager::Settings::EnableHDR = "1"; +$PostFXManager::Settings::EnableLightRays = "1"; +$PostFXManager::Settings::EnablePostFX = "1"; +$PostFXManager::Settings::Vignette::VMax = "0.6"; +$PostFXManager::Settings::DOF::BlurCurveFar = ""; +$PostFXManager::Settings::DOF::BlurCurveNear = ""; +$PostFXManager::Settings::DOF::BlurMax = ""; +$PostFXManager::Settings::DOF::BlurMin = ""; +$PostFXManager::Settings::DOF::EnableAutoFocus = ""; +$PostFXManager::Settings::DOF::EnableDOF = ""; +$PostFXManager::Settings::DOF::FocusRangeMax = ""; +$PostFXManager::Settings::DOF::FocusRangeMin = ""; +$PostFXManager::Settings::HDR::adaptRate = "2"; +$PostFXManager::Settings::HDR::blueShiftColor = "1.05 0.97 1.27"; +$PostFXManager::Settings::HDR::brightPassThreshold = "1"; +$PostFXManager::Settings::HDR::enableBloom = "1"; +$PostFXManager::Settings::HDR::enableBlueShift = "0"; +$PostFXManager::Settings::HDR::enableToneMapping = "0.5"; +$PostFXManager::Settings::HDR::gaussMean = "0"; +$PostFXManager::Settings::HDR::gaussMultiplier = "0.3"; +$PostFXManager::Settings::HDR::gaussStdDev = "0.8"; +$PostFXManager::Settings::HDR::keyValue = "0.18"; +$PostFXManager::Settings::HDR::minLuminace = "0.001"; +$PostFXManager::Settings::HDR::whiteCutoff = "1"; +$PostFXManager::Settings::LightRays::brightScalar = "0.75"; +$PostFXManager::Settings::LightRays::decay = "1.0"; +$PostFXManager::Settings::LightRays::density = "0.94"; +$PostFXManager::Settings::LightRays::numSamples = "40"; +$PostFXManager::Settings::LightRays::weight = "5.65"; +$PostFXManager::Settings::SSAO::blurDepthTol = "0.001"; +$PostFXManager::Settings::SSAO::blurNormalTol = "0.95"; +$PostFXManager::Settings::SSAO::lDepthMax = "2"; +$PostFXManager::Settings::SSAO::lDepthMin = "0.2"; +$PostFXManager::Settings::SSAO::lDepthPow = "0.2"; +$PostFXManager::Settings::SSAO::lNormalPow = "2"; +$PostFXManager::Settings::SSAO::lNormalTol = "-0.5"; +$PostFXManager::Settings::SSAO::lRadius = "1"; +$PostFXManager::Settings::SSAO::lStrength = "10"; +$PostFXManager::Settings::SSAO::overallStrength = "2"; +$PostFXManager::Settings::SSAO::quality = "0"; +$PostFXManager::Settings::SSAO::sDepthMax = "1"; +$PostFXManager::Settings::SSAO::sDepthMin = "0.1"; +$PostFXManager::Settings::SSAO::sDepthPow = "1"; +$PostFXManager::Settings::SSAO::sNormalPow = "1"; +$PostFXManager::Settings::SSAO::sNormalTol = "0"; +$PostFXManager::Settings::SSAO::sRadius = "0.1"; +$PostFXManager::Settings::SSAO::sStrength = "6"; +$PostFXManager::Settings::ColorCorrectionRamp = "core/postFX/images/null_color_ramp.png"; diff --git a/Templates/BaseGame/game/core/postFX/scripts/dof.cs b/Templates/BaseGame/game/core/postFX/scripts/dof.cs new file mode 100644 index 000000000..736c288b2 --- /dev/null +++ b/Templates/BaseGame/game/core/postFX/scripts/dof.cs @@ -0,0 +1,599 @@ +//----------------------------------------------------------------------------- +// 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. +//----------------------------------------------------------------------------- + +/* + +================================================================================ + The DOFPostEffect API +================================================================================ + +DOFPostEffect::setFocalDist( %dist ) + +@summary +This method is for manually controlling the focus distance. It will have no +effect if auto focus is currently enabled. Makes use of the parameters set by +setFocusParams. + +@param dist +float distance in meters + +-------------------------------------------------------------------------------- + +DOFPostEffect::setAutoFocus( %enabled ) + +@summary +This method sets auto focus enabled or disabled. Makes use of the parameters set +by setFocusParams. When auto focus is enabled it determines the focal depth +by performing a raycast at the screen-center. + +@param enabled +bool + +-------------------------------------------------------------------------------- + +DOFPostEffect::setFocusParams( %nearBlurMax, %farBlurMax, %minRange, %maxRange, %nearSlope, %farSlope ) + +Set the parameters that control how the near and far equations are calculated +from the focal distance. If you are not using auto focus you will need to call +setFocusParams PRIOR to calling setFocalDist. + +@param nearBlurMax +float between 0.0 and 1.0 +The max allowed value of near blur. + +@param farBlurMax +float between 0.0 and 1.0 +The max allowed value of far blur. + +@param minRange/maxRange +float in meters +The distance range around the focal distance that remains in focus is a lerp +between the min/maxRange using the normalized focal distance as the parameter. +The point is to allow the focal range to expand as you focus farther away since this is +visually appealing. + +Note: since min/maxRange are lerped by the "normalized" focal distance it is +dependant on the visible distance set in your level. + +@param nearSlope +float less than zero +The slope of the near equation. A small number causes bluriness to increase gradually +at distances closer than the focal distance. A large number causes bluriness to +increase quickly. + +@param farSlope +float greater than zero +The slope of the far equation. A small number causes bluriness to increase gradually +at distances farther than the focal distance. A large number causes bluriness to +increase quickly. + +Note: To rephrase, the min/maxRange parameters control how much area around the +focal distance is completely in focus where the near/farSlope parameters control +how quickly or slowly bluriness increases at distances outside of that range. + +================================================================================ + Examples +================================================================================ + +Example1: Turn on DOF while zoomed in with a weapon. + +NOTE: These are not real callbacks! Hook these up to your code where appropriate! + +function onSniperZoom() +{ + // Parameterize how you want DOF to look. + DOFPostEffect.setFocusParams( 0.3, 0.3, 50, 500, -5, 5 ); + + // Turn on auto focus + DOFPostEffect.setAutoFocus( true ); + + // Turn on the PostEffect + DOFPostEffect.enable(); +} + +function onSniperUnzoom() +{ + // Turn off the PostEffect + DOFPostEffect.disable(); +} + +Example2: Manually control DOF with the mouse wheel. + +// Somewhere on startup... + +// Parameterize how you want DOF to look. +DOFPostEffect.setFocusParams( 0.3, 0.3, 50, 500, -5, 5 ); + +// Turn off auto focus +DOFPostEffect.setAutoFocus( false ); + +// Turn on the PostEffect +DOFPostEffect.enable(); + + +NOTE: These are not real callbacks! Hook these up to your code where appropriate! + +function onMouseWheelUp() +{ + // Since setFocalDist is really just a wrapper to assign to the focalDist + // dynamic field we can shortcut and increment it directly. + DOFPostEffect.focalDist += 8; +} + +function onMouseWheelDown() +{ + DOFPostEffect.focalDist -= 8; +} +*/ + +/// This method is for manually controlling the focal distance. It will have no +/// effect if auto focus is currently enabled. Makes use of the parameters set by +/// setFocusParams. +function DOFPostEffect::setFocalDist( %this, %dist ) +{ + %this.focalDist = %dist; +} + +/// This method sets auto focus enabled or disabled. Makes use of the parameters set +/// by setFocusParams. When auto focus is enabled it determine the focal depth +/// by performing a raycast at the screen-center. +function DOFPostEffect::setAutoFocus( %this, %enabled ) +{ + %this.autoFocusEnabled = %enabled; +} + +/// Set the parameters that control how the near and far equations are calculated +/// from the focal distance. If you are not using auto focus you will need to call +/// setFocusParams PRIOR to calling setFocalDist. +function DOFPostEffect::setFocusParams( %this, %nearBlurMax, %farBlurMax, %minRange, %maxRange, %nearSlope, %farSlope ) +{ + %this.nearBlurMax = %nearBlurMax; + %this.farBlurMax = %farBlurMax; + %this.minRange = %minRange; + %this.maxRange = %maxRange; + %this.nearSlope = %nearSlope; + %this.farSlope = %farSlope; +} + +/* + +More information... + +This DOF technique is based on this paper: +http://http.developer.nvidia.com/GPUGems3/gpugems3_ch28.html + +================================================================================ +1. Overview of how we represent "Depth of Field" +================================================================================ + +DOF is expressed as an amount of bluriness per pixel according to its depth. +We represented this by a piecewise linear curve depicted below. + +Note: we also refer to "bluriness" as CoC ( circle of confusion ) which is the term +used in the basis paper and in photography. + + +X-axis (depth) +x = 0.0----------------------------------------------x = 1.0 + +Y-axis (bluriness) +y = 1.0 + | + | ____(x1,y1) (x4,y4)____ + | (ns,nb)\ <--Line1 line2---> /(fe,fb) + | \ / + | \(x2,y2) (x3,y3)/ + | (ne,0)------(fs,0) +y = 0.0 + + +I have labeled the "corners" of this graph with (Xn,Yn) to illustrate that +this is in fact a collection of line segments where the x/y of each point +corresponds to the key below. + +key: +ns - (n)ear blur (s)tart distance +nb - (n)ear (b)lur amount (max value) +ne - (n)ear blur (e)nd distance +fs - (f)ar blur (s)tart distance +fe - (f)ar blur (e)nd distance +fb - (f)ar (b)lur amount (max value) + +Of greatest importance in this graph is Line1 and Line2. Where... +L1 { (x1,y1), (x2,y2) } +L2 { (x3,y3), (x4,y4) } + +Line one represents the amount of "near" blur given a pixels depth and line two +represents the amount of "far" blur at that depth. + +Both these equations are evaluated for each pixel and then the larger of the two +is kept. Also the output blur (for each equation) is clamped between 0 and its +maximum allowable value. + +Therefore, to specify a DOF "qualify" you need to specify the near-blur-line, +far-blur-line, and maximum near and far blur value. + +================================================================================ +2. Abstracting a "focal depth" +================================================================================ + +Although the shader(s) work in terms of a near and far equation it is more +useful to express DOF as an adjustable focal depth and derive the other parameters +"under the hood". + +Given a maximum near/far blur amount and a near/far slope we can calculate the +near/far equations for any focal depth. We extend this to also support a range +of depth around the focal depth that is also in focus and for that range to +shrink or grow as the focal depth moves closer or farther. + +Keep in mind this is only one implementation and depending on the effect you +desire you may which to express the relationship between focal depth and +the shader paramaters different. + +*/ + +//----------------------------------------------------------------------------- +// GFXStateBlockData / ShaderData +//----------------------------------------------------------------------------- + +singleton GFXStateBlockData( PFX_DefaultDOFStateBlock ) +{ + zDefined = true; + zEnable = false; + zWriteEnable = false; + + samplersDefined = true; + samplerStates[0] = SamplerClampPoint; + samplerStates[1] = SamplerClampPoint; +}; + +singleton GFXStateBlockData( PFX_DOFCalcCoCStateBlock ) +{ + zDefined = true; + zEnable = false; + zWriteEnable = false; + + samplersDefined = true; + samplerStates[0] = SamplerClampLinear; + samplerStates[1] = SamplerClampLinear; +}; + +singleton GFXStateBlockData( PFX_DOFDownSampleStateBlock ) +{ + zDefined = true; + zEnable = false; + zWriteEnable = false; + + samplersDefined = true; + samplerStates[0] = SamplerClampLinear; + samplerStates[1] = SamplerClampPoint; +}; + +singleton GFXStateBlockData( PFX_DOFBlurStateBlock ) +{ + zDefined = true; + zEnable = false; + zWriteEnable = false; + + samplersDefined = true; + samplerStates[0] = SamplerClampLinear; +}; + +singleton GFXStateBlockData( PFX_DOFFinalStateBlock ) +{ + zDefined = true; + zEnable = false; + zWriteEnable = false; + + samplersDefined = true; + samplerStates[0] = SamplerClampLinear; + samplerStates[1] = SamplerClampLinear; + samplerStates[2] = SamplerClampLinear; + samplerStates[3] = SamplerClampPoint; + + blendDefined = true; + blendEnable = true; + blendDest = GFXBlendInvSrcAlpha; + blendSrc = GFXBlendOne; +}; + +singleton ShaderData( PFX_DOFDownSampleShader ) +{ + DXVertexShaderFile = $Core::CommonShaderPath @ "/postFX/dof/DOF_DownSample_V.hlsl"; + DXPixelShaderFile = $Core::CommonShaderPath @ "/postFX/dof/DOF_DownSample_P.hlsl"; + + OGLVertexShaderFile = $Core::CommonShaderPath @ "/postFX/dof/gl/DOF_DownSample_V.glsl"; + OGLPixelShaderFile = $Core::CommonShaderPath @ "/postFX/dof/gl/DOF_DownSample_P.glsl"; + + samplerNames[0] = "$colorSampler"; + samplerNames[1] = "$depthSampler"; + + pixVersion = 3.0; +}; + +singleton ShaderData( PFX_DOFBlurYShader ) +{ + DXVertexShaderFile = $Core::CommonShaderPath @ "/postFX/dof/DOF_Gausian_V.hlsl"; + DXPixelShaderFile = $Core::CommonShaderPath @ "/postFX/dof/DOF_Gausian_P.hlsl"; + + OGLVertexShaderFile = $Core::CommonShaderPath @ "/postFX/dof/gl/DOF_Gausian_V.glsl"; + OGLPixelShaderFile = $Core::CommonShaderPath @ "/postFX/dof/gl/DOF_Gausian_P.glsl"; + + samplerNames[0] = "$diffuseMap"; + + pixVersion = 2.0; + defines = "BLUR_DIR=float2(0.0,1.0)"; +}; + +singleton ShaderData( PFX_DOFBlurXShader : PFX_DOFBlurYShader ) +{ + defines = "BLUR_DIR=float2(1.0,0.0)"; +}; + +singleton ShaderData( PFX_DOFCalcCoCShader ) +{ + DXVertexShaderFile = $Core::CommonShaderPath @ "/postFX/dof/DOF_CalcCoC_V.hlsl"; + DXPixelShaderFile = $Core::CommonShaderPath @ "/postFX/dof/DOF_CalcCoC_P.hlsl"; + + OGLVertexShaderFile = $Core::CommonShaderPath @ "/postFX/dof/gl/DOF_CalcCoC_V.glsl"; + OGLPixelShaderFile = $Core::CommonShaderPath @ "/postFX/dof/gl/DOF_CalcCoC_P.glsl"; + + samplerNames[0] = "$shrunkSampler"; + samplerNames[1] = "$blurredSampler"; + + pixVersion = 3.0; +}; + +singleton ShaderData( PFX_DOFSmallBlurShader ) +{ + DXVertexShaderFile = $Core::CommonShaderPath @ "/postFX/dof/DOF_SmallBlur_V.hlsl"; + DXPixelShaderFile = $Core::CommonShaderPath @ "/postFX/dof/DOF_SmallBlur_P.hlsl"; + + OGLVertexShaderFile = $Core::CommonShaderPath @ "/postFX/dof/gl/DOF_SmallBlur_V.glsl"; + OGLPixelShaderFile = $Core::CommonShaderPath @ "/postFX/dof/gl/DOF_SmallBlur_P.glsl"; + + samplerNames[0] = "$colorSampler"; + + pixVersion = 3.0; +}; + +singleton ShaderData( PFX_DOFFinalShader ) +{ + DXVertexShaderFile = $Core::CommonShaderPath @ "/postFX/dof/DOF_Final_V.hlsl"; + DXPixelShaderFile = $Core::CommonShaderPath @ "/postFX/dof/DOF_Final_P.hlsl"; + + OGLVertexShaderFile = $Core::CommonShaderPath @ "/postFX/dof/gl/DOF_Final_V.glsl"; + OGLPixelShaderFile = $Core::CommonShaderPath @ "/postFX/dof/gl/DOF_Final_P.glsl"; + + samplerNames[0] = "$colorSampler"; + samplerNames[1] = "$smallBlurSampler"; + samplerNames[2] = "$largeBlurSampler"; + samplerNames[3] = "$depthSampler"; + + pixVersion = 3.0; +}; + +//----------------------------------------------------------------------------- +// PostEffects +//----------------------------------------------------------------------------- + +function DOFPostEffect::onAdd( %this ) +{ + // The weighted distribution of CoC value to the three blur textures + // in the order small, medium, large. Most likely you will not need to + // change this value. + %this.setLerpDist( 0.2, 0.3, 0.5 ); + + // Fill out some default values but DOF really should not be turned on + // without actually specifying your own parameters! + %this.autoFocusEnabled = false; + %this.focalDist = 0.0; + %this.nearBlurMax = 0.5; + %this.farBlurMax = 0.5; + %this.minRange = 50; + %this.maxRange = 500; + %this.nearSlope = -5.0; + %this.farSlope = 5.0; +} + +function DOFPostEffect::setLerpDist( %this, %d0, %d1, %d2 ) +{ + %this.lerpScale = -1.0 / %d0 SPC -1.0 / %d1 SPC -1.0 / %d2 SPC 1.0 / %d2; + %this.lerpBias = 1.0 SPC ( 1.0 - %d2 ) / %d1 SPC 1.0 / %d2 SPC ( %d2 - 1.0 ) / %d2; +} + +singleton PostEffect( DOFPostEffect ) +{ + renderTime = "PFXAfterBin"; + renderBin = "GlowBin"; + renderPriority = 0.1; + + shader = PFX_DOFDownSampleShader; + stateBlock = PFX_DOFDownSampleStateBlock; + texture[0] = "$backBuffer"; + texture[1] = "#deferred"; + target = "#shrunk"; + targetScale = "0.25 0.25"; + + isEnabled = false; +}; + +singleton PostEffect( DOFBlurY ) +{ + shader = PFX_DOFBlurYShader; + stateBlock = PFX_DOFBlurStateBlock; + texture[0] = "#shrunk"; + target = "$outTex"; +}; + +DOFPostEffect.add( DOFBlurY ); + +singleton PostEffect( DOFBlurX ) +{ + shader = PFX_DOFBlurXShader; + stateBlock = PFX_DOFBlurStateBlock; + texture[0] = "$inTex"; + target = "#largeBlur"; +}; + +DOFPostEffect.add( DOFBlurX ); + +singleton PostEffect( DOFCalcCoC ) +{ + shader = PFX_DOFCalcCoCShader; + stateBlock = PFX_DOFCalcCoCStateBlock; + texture[0] = "#shrunk"; + texture[1] = "#largeBlur"; + target = "$outTex"; +}; + +DOFPostEffect.add( DOFCalcCoc ); + +singleton PostEffect( DOFSmallBlur ) +{ + shader = PFX_DOFSmallBlurShader; + stateBlock = PFX_DefaultDOFStateBlock; + texture[0] = "$inTex"; + target = "$outTex"; +}; + +DOFPostEffect.add( DOFSmallBlur ); + +singleton PostEffect( DOFFinalPFX ) +{ + shader = PFX_DOFFinalShader; + stateBlock = PFX_DOFFinalStateBlock; + texture[0] = "$backBuffer"; + texture[1] = "$inTex"; + texture[2] = "#largeBlur"; + texture[3] = "#deferred"; + target = "$backBuffer"; +}; + +DOFPostEffect.add( DOFFinalPFX ); + + +//----------------------------------------------------------------------------- +// Scripts +//----------------------------------------------------------------------------- + +function DOFPostEffect::setShaderConsts( %this ) +{ + if ( %this.autoFocusEnabled ) + %this.autoFocus(); + + %fd = %this.focalDist / $Param::FarDist; + + %range = mLerp( %this.minRange, %this.maxRange, %fd ) / $Param::FarDist * 0.5; + + // We work in "depth" space rather than real-world units for the + // rest of this method... + + // Given the focal distance and the range around it we want in focus + // we can determine the near-end-distance and far-start-distance + + %ned = getMax( %fd - %range, 0.0 ); + %fsd = getMin( %fd + %range, 1.0 ); + + // near slope + %nsl = %this.nearSlope; + + // Given slope of near blur equation and the near end dist and amount (x2,y2) + // solve for the y-intercept + // y = mx + b + // so... + // y - mx = b + + %b = 0.0 - %nsl * %ned; + + %eqNear = %nsl SPC %b SPC 0.0; + + // Do the same for the far blur equation... + + %fsl = %this.farSlope; + + %b = 0.0 - %fsl * %fsd; + + %eqFar = %fsl SPC %b SPC 1.0; + + %this.setShaderConst( "$dofEqWorld", %eqNear ); + DOFFinalPFX.setShaderConst( "$dofEqFar", %eqFar ); + + %this.setShaderConst( "$maxWorldCoC", %this.nearBlurMax ); + DOFFinalPFX.setShaderConst( "$maxFarCoC", %this.farBlurMax ); + + DOFFinalPFX.setShaderConst( "$dofLerpScale", %this.lerpScale ); + DOFFinalPFX.setShaderConst( "$dofLerpBias", %this.lerpBias ); +} + +function DOFPostEffect::autoFocus( %this ) +{ + if ( !isObject( ServerConnection ) || + !isObject( ServerConnection.getCameraObject() ) ) + { + return; + } + + %mask = $TypeMasks::StaticObjectType | $TypeMasks::TerrainObjectType; + %control = ServerConnection.getCameraObject(); + + %fvec = %control.getForwardVector(); + %start = %control.getPosition(); + + %end = VectorAdd( %start, VectorScale( %fvec, $Param::FarDist ) ); + + // Use the client container for this ray cast. + %result = containerRayCast( %start, %end, %mask, %control, true ); + + %hitPos = getWords( %result, 1, 3 ); + + if ( %hitPos $= "" ) + %focDist = $Param::FarDist; + else + %focDist = VectorDist( %hitPos, %start ); + + // For debuging + //$DOF::debug_dist = %focDist; + //$DOF::debug_depth = %focDist / $Param::FarDist; + //echo( "F: " @ %focDist SPC "D: " @ %delta ); + + %this.focalDist = %focDist; +} + + +// For debugging +/* +function reloadDOF() +{ + exec( "./dof.cs" ); + DOFPostEffect.reload(); + DOFPostEffect.disable(); + DOFPostEffect.enable(); +} + +function dofMetricsCallback() +{ + return " | DOF |" @ + " Dist: " @ $DOF::debug_dist @ + " Depth: " @ $DOF::debug_depth; +} +*/ \ No newline at end of file diff --git a/Templates/BaseGame/game/core/postFX/scripts/edgeAA.cs b/Templates/BaseGame/game/core/postFX/scripts/edgeAA.cs new file mode 100644 index 000000000..c3b4263fa --- /dev/null +++ b/Templates/BaseGame/game/core/postFX/scripts/edgeAA.cs @@ -0,0 +1,113 @@ +//----------------------------------------------------------------------------- +// 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. +//----------------------------------------------------------------------------- + + +singleton GFXStateBlockData( PFX_DefaultEdgeAAStateBlock ) +{ + zDefined = true; + zEnable = false; + zWriteEnable = false; + + samplersDefined = true; + samplerStates[0] = SamplerClampPoint; + //samplerStates[1] = SamplerWrapPoint; +}; + +singleton ShaderData( PFX_EdgeAADetectShader ) +{ + DXVertexShaderFile = $Core::CommonShaderPath @ "/postFX/postFxV.hlsl"; + DXPixelShaderFile = $Core::CommonShaderPath @ "/postFX/edgeaa/edgeDetectP.hlsl"; + + OGLVertexShaderFile = $Core::CommonShaderPath @ "/postFX/gl/postFxV.glsl"; + OGLPixelShaderFile = $Core::CommonShaderPath @ "/postFX/edgeaa/gl/edgeDetectP.glsl"; + + samplerNames[0] = "$deferredBuffer"; + + pixVersion = 3.0; +}; + +singleton ShaderData( PFX_EdgeAAShader ) +{ + DXVertexShaderFile = $Core::CommonShaderPath @ "/postFX/edgeaa/edgeAAV.hlsl"; + DXPixelShaderFile = $Core::CommonShaderPath @ "/postFX/edgeaa/edgeAAP.hlsl"; + + OGLVertexShaderFile = $Core::CommonShaderPath @ "/postFX/edgeaa/gl/edgeAAV.glsl"; + OGLPixelShaderFile = $Core::CommonShaderPath @ "/postFX/edgeaa/gl/edgeAAP.glsl"; + + samplerNames[0] = "$edgeBuffer"; + samplerNames[1] = "$backBuffer"; + + pixVersion = 3.0; +}; + +singleton ShaderData( PFX_EdgeAADebugShader ) +{ + DXVertexShaderFile = $Core::CommonShaderPath @ "/postFX/postFxV.hlsl"; + DXPixelShaderFile = $Core::CommonShaderPath @ "/postFX/edgeaa/dbgEdgeDisplayP.hlsl"; + + OGLVertexShaderFile = $Core::CommonShaderPath @ "/postFX/gl/postFxV.glsl"; + OGLPixelShaderFile = $Core::CommonShaderPath @ "/postFX/edgeaa/gl/dbgEdgeDisplayP.glsl"; + + samplerNames[0] = "$edgeBuffer"; + + pixVersion = 3.0; +}; + +singleton PostEffect( EdgeDetectPostEffect ) +{ + renderTime = "PFXBeforeBin"; + renderBin = "ObjTranslucentBin"; + //renderPriority = 0.1; + targetScale = "0.5 0.5"; + + shader = PFX_EdgeAADetectShader; + stateBlock = PFX_DefaultEdgeAAStateBlock; + texture[0] = "#deferred"; + target = "#edge"; + + isEnabled = true; +}; + +singleton PostEffect( EdgeAAPostEffect ) +{ + renderTime = "PFXAfterDiffuse"; + //renderBin = "ObjTranslucentBin"; + //renderPriority = 0.1; + + shader = PFX_EdgeAAShader; + stateBlock = PFX_DefaultEdgeAAStateBlock; + texture[0] = "#edge"; + texture[1] = "$backBuffer"; + target = "$backBuffer"; +}; + +singleton PostEffect( Debug_EdgeAAPostEffect ) +{ + renderTime = "PFXAfterDiffuse"; + //renderBin = "ObjTranslucentBin"; + //renderPriority = 0.1; + + shader = PFX_EdgeAADebugShader; + stateBlock = PFX_DefaultEdgeAAStateBlock; + texture[0] = "#edge"; + target = "$backBuffer"; +}; \ No newline at end of file diff --git a/Templates/BaseGame/game/core/postFX/scripts/flash.cs b/Templates/BaseGame/game/core/postFX/scripts/flash.cs new file mode 100644 index 000000000..1c97c6411 --- /dev/null +++ b/Templates/BaseGame/game/core/postFX/scripts/flash.cs @@ -0,0 +1,63 @@ +//----------------------------------------------------------------------------- +// 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. +//----------------------------------------------------------------------------- + +singleton ShaderData( PFX_FlashShader ) +{ + DXVertexShaderFile = $Core::CommonShaderPath @ "/postFX/postFxV.hlsl"; + DXPixelShaderFile = $Core::CommonShaderPath @ "/postFX/flashP.hlsl"; + + OGLVertexShaderFile = $Core::CommonShaderPath @ "/postFX/gl/postFxV.glsl"; + OGLPixelShaderFile = $Core::CommonShaderPath @ "/postFX/gl/flashP.glsl"; + + samplerNames[0] = "$backBuffer"; + + defines = "WHITE_COLOR=float4(1.0,1.0,1.0,0.0);MUL_COLOR=float4(1.0,0.25,0.25,0.0)"; + + pixVersion = 2.0; +}; + +singleton PostEffect( FlashFx ) +{ + isEnabled = false; + allowReflectPass = false; + + renderTime = "PFXAfterDiffuse"; + + shader = PFX_FlashShader; + texture[0] = "$backBuffer"; + renderPriority = 10; + stateBlock = PFX_DefaultStateBlock; +}; + +function FlashFx::setShaderConsts( %this ) +{ + if ( isObject( ServerConnection ) ) + { + %this.setShaderConst( "$damageFlash", ServerConnection.getDamageFlash() ); + %this.setShaderConst( "$whiteOut", ServerConnection.getWhiteOut() ); + } + else + { + %this.setShaderConst( "$damageFlash", 0 ); + %this.setShaderConst( "$whiteOut", 0 ); + } +} diff --git a/Templates/BaseGame/game/core/postFX/scripts/fog.cs b/Templates/BaseGame/game/core/postFX/scripts/fog.cs new file mode 100644 index 000000000..4b9bfc663 --- /dev/null +++ b/Templates/BaseGame/game/core/postFX/scripts/fog.cs @@ -0,0 +1,135 @@ +//----------------------------------------------------------------------------- +// 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. +//----------------------------------------------------------------------------- + +//------------------------------------------------------------------------------ +// Fog +//------------------------------------------------------------------------------ + +singleton ShaderData( FogPassShader ) +{ + DXVertexShaderFile = $Core::CommonShaderPath @ "/postFX/postFxV.hlsl"; + DXPixelShaderFile = $Core::CommonShaderPath @ "/postFX/fogP.hlsl"; + + OGLVertexShaderFile = $Core::CommonShaderPath @ "/postFX/gl/postFxV.glsl"; + OGLPixelShaderFile = $Core::CommonShaderPath @ "/postFX/gl/fogP.glsl"; + + samplerNames[0] = "$deferredTex"; + + pixVersion = 2.0; +}; + + +singleton GFXStateBlockData( FogPassStateBlock : PFX_DefaultStateBlock ) +{ + blendDefined = true; + blendEnable = true; + blendSrc = GFXBlendSrcAlpha; + blendDest = GFXBlendInvSrcAlpha; +}; + + +singleton PostEffect( FogPostFx ) +{ + // We forward render the reflection pass + // so it does its own fogging. + allowReflectPass = false; + + renderTime = "PFXBeforeBin"; + renderBin = "ObjTranslucentBin"; + + shader = FogPassShader; + stateBlock = FogPassStateBlock; + texture[0] = "#deferred"; + + renderPriority = 5; + + targetFormat = getBestHDRFormat(); + isEnabled = true; +}; + + +//------------------------------------------------------------------------------ +// UnderwaterFog +//------------------------------------------------------------------------------ + +singleton ShaderData( UnderwaterFogPassShader ) +{ + DXVertexShaderFile = $Core::CommonShaderPath @ "/postFX/postFxV.hlsl"; + DXPixelShaderFile = $Core::CommonShaderPath @ "/postFX/underwaterFogP.hlsl"; + + OGLVertexShaderFile = $Core::CommonShaderPath @ "/postFX/gl/postFxV.glsl"; + OGLPixelShaderFile = $Core::CommonShaderPath @ "/postFX/gl/underwaterFogP.glsl"; + + samplerNames[0] = "$deferredTex"; + samplerNames[1] = "$backbuffer"; + samplerNames[2] = "$waterDepthGradMap"; + + pixVersion = 2.0; +}; + + +singleton GFXStateBlockData( UnderwaterFogPassStateBlock : PFX_DefaultStateBlock ) +{ + samplersDefined = true; + samplerStates[0] = SamplerClampPoint; + samplerStates[1] = SamplerClampPoint; + samplerStates[2] = SamplerClampLinear; +}; + + +singleton PostEffect( UnderwaterFogPostFx ) +{ + oneFrameOnly = true; + onThisFrame = false; + + // Let the fog effect render during the + // reflection pass. + allowReflectPass = true; + + renderTime = "PFXBeforeBin"; + renderBin = "ObjTranslucentBin"; + + shader = UnderwaterFogPassShader; + stateBlock = UnderwaterFogPassStateBlock; + texture[0] = "#deferred"; + texture[1] = "$backBuffer"; + texture[2] = "#waterDepthGradMap"; + + // Needs to happen after the FogPostFx + renderPriority = 4; + + isEnabled = true; +}; + +function UnderwaterFogPostFx::onEnabled( %this ) +{ + TurbulenceFx.enable(); + CausticsPFX.enable(); + return true; +} + +function UnderwaterFogPostFx::onDisabled( %this ) +{ + TurbulenceFx.disable(); + CausticsPFX.disable(); + return false; +} diff --git a/Templates/BaseGame/game/core/postFX/scripts/fxaa.cs b/Templates/BaseGame/game/core/postFX/scripts/fxaa.cs new file mode 100644 index 000000000..4b81c6e19 --- /dev/null +++ b/Templates/BaseGame/game/core/postFX/scripts/fxaa.cs @@ -0,0 +1,64 @@ +//----------------------------------------------------------------------------- +// 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. +//----------------------------------------------------------------------------- + +// An implementation of "NVIDIA FXAA 3.11" by TIMOTHY LOTTES +// +// http://timothylottes.blogspot.com/ +// +// The shader is tuned for the defaul quality and good performance. +// See shaders\common\postFx\fxaa\fxaaP.hlsl to tweak the internal +// quality and performance settings. + +singleton GFXStateBlockData( FXAA_StateBlock : PFX_DefaultStateBlock ) +{ + samplersDefined = true; + samplerStates[0] = SamplerClampLinear; +}; + +singleton ShaderData( FXAA_ShaderData ) +{ + DXVertexShaderFile = $Core::CommonShaderPath @ "/postFX/fxaa/fxaaV.hlsl"; + DXPixelShaderFile = $Core::CommonShaderPath @ "/postFX/fxaa/fxaaP.hlsl"; + + OGLVertexShaderFile = $Core::CommonShaderPath @ "/postFX/fxaa/gl/fxaaV.glsl"; + OGLPixelShaderFile = $Core::CommonShaderPath @ "/postFX/fxaa/gl/fxaaP.glsl"; + + samplerNames[0] = "$colorTex"; + + pixVersion = 3.0; +}; + +singleton PostEffect( FXAA_PostEffect ) +{ + isEnabled = false; + + allowReflectPass = false; + renderTime = "PFXAfterDiffuse"; + + texture[0] = "$backBuffer"; + + target = "$backBuffer"; + + stateBlock = FXAA_StateBlock; + shader = FXAA_ShaderData; +}; + diff --git a/Templates/BaseGame/game/core/postFX/scripts/glow.cs b/Templates/BaseGame/game/core/postFX/scripts/glow.cs new file mode 100644 index 000000000..0f062f6f7 --- /dev/null +++ b/Templates/BaseGame/game/core/postFX/scripts/glow.cs @@ -0,0 +1,184 @@ +//----------------------------------------------------------------------------- +// 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. +//----------------------------------------------------------------------------- + + +singleton ShaderData( PFX_GlowBlurVertShader ) +{ + DXVertexShaderFile = $Core::CommonShaderPath @ "/postFX/glowBlurV.hlsl"; + DXPixelShaderFile = $Core::CommonShaderPath @ "/postFX/glowBlurP.hlsl"; + + OGLVertexShaderFile = $Core::CommonShaderPath @ "/postFX/gl/glowBlurV.glsl"; + OGLPixelShaderFile = $Core::CommonShaderPath @ "/postFX/gl/glowBlurP.glsl"; + + defines = "BLUR_DIR=float2(0.0,1.0)"; + + samplerNames[0] = "$diffuseMap"; + + pixVersion = 2.0; +}; + + +singleton ShaderData( PFX_GlowBlurHorzShader : PFX_GlowBlurVertShader ) +{ + defines = "BLUR_DIR=float2(1.0,0.0)"; +}; + + +singleton GFXStateBlockData( PFX_GlowCombineStateBlock : PFX_DefaultStateBlock ) +{ + // Use alpha test to save some fillrate + // on the non-glowing areas of the scene. + alphaDefined = true; + alphaTestEnable = true; + alphaTestRef = 1; + alphaTestFunc = GFXCmpGreaterEqual; + + // Do a one to one blend. + blendDefined = true; + blendEnable = true; + blendSrc = GFXBlendOne; + blendDest = GFXBlendOne; +}; + + +singleton PostEffect( GlowPostFx ) +{ + // 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 = "GlowBin"; + renderPriority = 1; + + // First we down sample the glow buffer. + shader = PFX_PassthruShader; + stateBlock = PFX_DefaultStateBlock; + texture[0] = "#glowbuffer"; + target = "$outTex"; + targetScale = "0.5 0.5"; + + isEnabled = true; + + // Blur vertically + new PostEffect() + { + shader = PFX_GlowBlurVertShader; + stateBlock = PFX_DefaultStateBlock; + texture[0] = "$inTex"; + target = "$outTex"; + }; + + // Blur horizontally + new PostEffect() + { + shader = PFX_GlowBlurHorzShader; + stateBlock = PFX_DefaultStateBlock; + 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"; + }; +}; + +singleton ShaderData( PFX_VolFogGlowBlurVertShader ) +{ + DXVertexShaderFile = $Core::CommonShaderPath @ "/postFX/glowBlurV.hlsl"; + DXPixelShaderFile = $Core::CommonShaderPath @ "/postFX/VolFogGlowP.hlsl"; + + OGLVertexShaderFile = $Core::CommonShaderPath @ "/postFX/gl/glowBlurV.glsl"; + OGLPixelShaderFile = $Core::CommonShaderPath @ "/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 = $Core::CommonShaderPath @ "/postFX/glowBlurV.hlsl"; + DXPixelShaderFile = $Core::CommonShaderPath @ "/postFX/VolFogGlowP.hlsl"; + + OGLVertexShaderFile = $Core::CommonShaderPath @ "/postFX/gl/glowBlurV.glsl"; + OGLPixelShaderFile = $Core::CommonShaderPath @ "/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/BaseGame/game/core/postFX/scripts/hdr.cs b/Templates/BaseGame/game/core/postFX/scripts/hdr.cs new file mode 100644 index 000000000..3b2de8b7b --- /dev/null +++ b/Templates/BaseGame/game/core/postFX/scripts/hdr.cs @@ -0,0 +1,529 @@ +//----------------------------------------------------------------------------- +// 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. +//----------------------------------------------------------------------------- + + +/// Blends between the scene and the tone mapped scene. +$HDRPostFX::enableToneMapping = 0.5; + +/// The tone mapping middle grey or exposure value used +/// to adjust the overall "balance" of the image. +/// +/// 0.18 is fairly common value. +/// +$HDRPostFX::keyValue = 0.18; + +/// The minimum luninace value to allow when tone mapping +/// the scene. Is particularly useful if your scene very +/// dark or has a black ambient color in places. +$HDRPostFX::minLuminace = 0.001; + +/// The lowest luminance value which is mapped to white. This +/// is usually set to the highest visible luminance in your +/// scene. By setting this to smaller values you get a contrast +/// enhancement. +$HDRPostFX::whiteCutoff = 1.0; + +/// The rate of adaptation from the previous and new +/// average scene luminance. +$HDRPostFX::adaptRate = 2.0; + +/// Blends between the scene and the blue shifted version +/// of the scene for a cinematic desaturated night effect. +$HDRPostFX::enableBlueShift = 0.0; + +/// The blue shift color value. +$HDRPostFX::blueShiftColor = "1.05 0.97 1.27"; + + +/// Blends between the scene and the bloomed scene. +$HDRPostFX::enableBloom = 1.0; + +/// The threshold luminace value for pixels which are +/// considered "bright" and need to be bloomed. +$HDRPostFX::brightPassThreshold = 1.0; + +/// These are used in the gaussian blur of the +/// bright pass for the bloom effect. +$HDRPostFX::gaussMultiplier = 0.3; +$HDRPostFX::gaussMean = 0.0; +$HDRPostFX::gaussStdDev = 0.8; + +/// The 1x255 color correction ramp texture used +/// by both the HDR shader and the GammaPostFx shader +/// for doing full screen color correction. +$HDRPostFX::colorCorrectionRamp = "core/postFX/images/null_color_ramp.png"; + + +singleton ShaderData( HDR_BrightPassShader ) +{ + DXVertexShaderFile = $Core::CommonShaderPath @ "/postFX/postFxV.hlsl"; + DXPixelShaderFile = $Core::CommonShaderPath @ "/postFX/hdr/brightPassFilterP.hlsl"; + OGLVertexShaderFile = $Core::CommonShaderPath @ "/postFX/gl/postFxV.glsl"; + OGLPixelShaderFile = $Core::CommonShaderPath @ "/postFX/hdr/gl/brightPassFilterP.glsl"; + + samplerNames[0] = "$inputTex"; + samplerNames[1] = "$luminanceTex"; + + pixVersion = 3.0; +}; + +singleton ShaderData( HDR_DownScale4x4Shader ) +{ + DXVertexShaderFile = $Core::CommonShaderPath @ "/postFX/hdr/downScale4x4V.hlsl"; + DXPixelShaderFile = $Core::CommonShaderPath @ "/postFX/hdr/downScale4x4P.hlsl"; + OGLVertexShaderFile = $Core::CommonShaderPath @ "/postFX/hdr/gl/downScale4x4V.glsl"; + OGLPixelShaderFile = $Core::CommonShaderPath @ "/postFX/hdr/gl/downScale4x4P.glsl"; + + samplerNames[0] = "$inputTex"; + + pixVersion = 2.0; +}; + +singleton ShaderData( HDR_BloomGaussBlurHShader ) +{ + DXVertexShaderFile = $Core::CommonShaderPath @ "/postFX/postFxV.hlsl"; + DXPixelShaderFile = $Core::CommonShaderPath @ "/postFX/hdr/bloomGaussBlurHP.hlsl"; + OGLVertexShaderFile = $Core::CommonShaderPath @ "/postFX/gl/postFxV.glsl"; + OGLPixelShaderFile = $Core::CommonShaderPath @ "/postFX/hdr/gl/bloomGaussBlurHP.glsl"; + + samplerNames[0] = "$inputTex"; + + pixVersion = 3.0; +}; + +singleton ShaderData( HDR_BloomGaussBlurVShader ) +{ + DXVertexShaderFile = $Core::CommonShaderPath @ "/postFX/postFxV.hlsl"; + DXPixelShaderFile = $Core::CommonShaderPath @ "/postFX/hdr/bloomGaussBlurVP.hlsl"; + OGLVertexShaderFile = $Core::CommonShaderPath @ "/postFX/gl/postFxV.glsl"; + OGLPixelShaderFile = $Core::CommonShaderPath @ "/postFX/hdr/gl/bloomGaussBlurVP.glsl"; + + samplerNames[0] = "$inputTex"; + + pixVersion = 3.0; +}; + +singleton ShaderData( HDR_SampleLumShader ) +{ + DXVertexShaderFile = $Core::CommonShaderPath @ "/postFX/postFxV.hlsl"; + DXPixelShaderFile = $Core::CommonShaderPath @ "/postFX/hdr/sampleLumInitialP.hlsl"; + OGLVertexShaderFile = $Core::CommonShaderPath @ "/postFX/gl/postFxV.glsl"; + OGLPixelShaderFile = $Core::CommonShaderPath @ "/postFX/hdr/gl/sampleLumInitialP.glsl"; + + samplerNames[0] = "$inputTex"; + + pixVersion = 3.0; +}; + +singleton ShaderData( HDR_DownSampleLumShader ) +{ + DXVertexShaderFile = $Core::CommonShaderPath @ "/postFX/postFxV.hlsl"; + DXPixelShaderFile = $Core::CommonShaderPath @ "/postFX/hdr/sampleLumIterativeP.hlsl"; + OGLVertexShaderFile = $Core::CommonShaderPath @ "/postFX/gl/postFxV.glsl"; + OGLPixelShaderFile = $Core::CommonShaderPath @ "/postFX/hdr/gl/sampleLumIterativeP.glsl"; + + samplerNames[0] = "$inputTex"; + + pixVersion = 3.0; +}; + +singleton ShaderData( HDR_CalcAdaptedLumShader ) +{ + DXVertexShaderFile = $Core::CommonShaderPath @ "/postFX/postFxV.hlsl"; + DXPixelShaderFile = $Core::CommonShaderPath @ "/postFX/hdr/calculateAdaptedLumP.hlsl"; + OGLVertexShaderFile = $Core::CommonShaderPath @ "/postFX/gl/postFxV.glsl"; + OGLPixelShaderFile = $Core::CommonShaderPath @ "/postFX/hdr/gl/calculateAdaptedLumP.glsl"; + + samplerNames[0] = "$currLum"; + samplerNames[1] = "$lastAdaptedLum"; + + pixVersion = 3.0; +}; + +singleton ShaderData( HDR_CombineShader ) +{ + DXVertexShaderFile = $Core::CommonShaderPath @ "/postFX/postFxV.hlsl"; + DXPixelShaderFile = $Core::CommonShaderPath @ "/postFX/hdr/finalPassCombineP.hlsl"; + OGLVertexShaderFile = $Core::CommonShaderPath @ "/postFX/gl/postFxV.glsl"; + OGLPixelShaderFile = $Core::CommonShaderPath @ "/postFX/hdr/gl/finalPassCombineP.glsl"; + + samplerNames[0] = "$sceneTex"; + samplerNames[1] = "$luminanceTex"; + samplerNames[2] = "$bloomTex"; + samplerNames[3] = "$colorCorrectionTex"; + samplerNames[4] = "deferredTex"; + + pixVersion = 3.0; +}; + + +singleton GFXStateBlockData( HDR_SampleStateBlock : PFX_DefaultStateBlock ) +{ + samplersDefined = true; + samplerStates[0] = SamplerClampPoint; + samplerStates[1] = SamplerClampPoint; +}; + +singleton GFXStateBlockData( HDR_DownSampleStateBlock : PFX_DefaultStateBlock ) +{ + samplersDefined = true; + samplerStates[0] = SamplerClampLinear; + samplerStates[1] = SamplerClampLinear; +}; + +singleton GFXStateBlockData( HDR_CombineStateBlock : PFX_DefaultStateBlock ) +{ + samplersDefined = true; + samplerStates[0] = SamplerClampPoint; + samplerStates[1] = SamplerClampLinear; + samplerStates[2] = SamplerClampLinear; + samplerStates[3] = SamplerClampLinear; +}; + +singleton GFXStateBlockData( HDRStateBlock ) +{ + samplersDefined = true; + samplerStates[0] = SamplerClampLinear; + samplerStates[1] = SamplerClampLinear; + samplerStates[2] = SamplerClampLinear; + samplerStates[3] = SamplerClampLinear; + + blendDefined = true; + blendDest = GFXBlendOne; + blendSrc = GFXBlendZero; + + zDefined = true; + zEnable = false; + zWriteEnable = false; + + cullDefined = true; + cullMode = GFXCullNone; +}; + + +function HDRPostFX::setShaderConsts( %this ) +{ + %this.setShaderConst( "$brightPassThreshold", $HDRPostFX::brightPassThreshold ); + %this.setShaderConst( "$g_fMiddleGray", $HDRPostFX::keyValue ); + + %bloomH = %this-->bloomH; + %bloomH.setShaderConst( "$gaussMultiplier", $HDRPostFX::gaussMultiplier ); + %bloomH.setShaderConst( "$gaussMean", $HDRPostFX::gaussMean ); + %bloomH.setShaderConst( "$gaussStdDev", $HDRPostFX::gaussStdDev ); + + %bloomV = %this-->bloomV; + %bloomV.setShaderConst( "$gaussMultiplier", $HDRPostFX::gaussMultiplier ); + %bloomV.setShaderConst( "$gaussMean", $HDRPostFX::gaussMean ); + %bloomV.setShaderConst( "$gaussStdDev", $HDRPostFX::gaussStdDev ); + + %minLuminace = $HDRPostFX::minLuminace; + if ( %minLuminace <= 0.0 ) + { + // The min should never be pure zero else the + // log() in the shader will generate INFs. + %minLuminace = 0.00001; + } + %this-->adaptLum.setShaderConst( "$g_fMinLuminace", %minLuminace ); + + %this-->finalLum.setShaderConst( "$adaptRate", $HDRPostFX::adaptRate ); + + %combinePass = %this-->combinePass; + %combinePass.setShaderConst( "$g_fEnableToneMapping", $HDRPostFX::enableToneMapping ); + %combinePass.setShaderConst( "$g_fMiddleGray", $HDRPostFX::keyValue ); + %combinePass.setShaderConst( "$g_fBloomScale", $HDRPostFX::enableBloom ); + %combinePass.setShaderConst( "$g_fEnableBlueShift", $HDRPostFX::enableBlueShift ); + %combinePass.setShaderConst( "$g_fBlueShiftColor", $HDRPostFX::blueShiftColor ); + + %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 ); + %combinePass.setShaderConst( "$g_fWhiteCutoff", %whiteCutoff ); +} + +function HDRPostFX::preProcess( %this ) +{ + %combinePass = %this-->combinePass; + + if ( %combinePass.texture[3] !$= $HDRPostFX::colorCorrectionRamp ) + %combinePass.setTexture( 3, $HDRPostFX::colorCorrectionRamp ); +} + +function HDRPostFX::onEnabled( %this ) +{ + // See what HDR format would be best. + %format = getBestHDRFormat(); + if ( %format $= "" || %format $= "GFXFormatR8G8B8A8" ) + { + // We didn't get a valid HDR format... so fail. + return false; + } + + // HDR does it's own gamma calculation so + // disable this postFx. + GammaPostFX.disable(); + + // Set the right global shader define for HDR. + if ( %format $= "GFXFormatR10G10B10A2" ) + addGlobalShaderMacro( "TORQUE_HDR_RGB10" ); + else if ( %format $= "GFXFormatR16G16B16A16" ) + addGlobalShaderMacro( "TORQUE_HDR_RGB16" ); + + echo( "HDR FORMAT: " @ %format ); + + // Change the format of the offscreen surface + // to an HDR compatible format. + AL_FormatToken.format = %format; + setReflectFormat( %format ); + + // Reset the light manager which will ensure the new + // hdr encoding takes effect in all the shaders and + // that the offscreen surface is enabled. + resetLightManager(); + + return true; +} + +function HDRPostFX::onDisabled( %this ) +{ + // Enable a special GammaCorrection PostFX when this is disabled. + GammaPostFX.enable(); + + // Restore the non-HDR offscreen surface format. + %format = getBestHDRFormat(); + AL_FormatToken.format = %format; + setReflectFormat( %format ); + + removeGlobalShaderMacro( "TORQUE_HDR_RGB10" ); + removeGlobalShaderMacro( "TORQUE_HDR_RGB16" ); + + // Reset the light manager which will ensure the new + // hdr encoding takes effect in all the shaders. + resetLightManager(); +} + +singleton PostEffect( HDRPostFX ) +{ + isEnabled = false; + allowReflectPass = false; + + // Resolve the HDR before we render any editor stuff + // and before we resolve the scene to the backbuffer. + renderTime = "PFXBeforeBin"; + renderBin = "EditorBin"; + renderPriority = 9999; + + // The bright pass generates a bloomed version of + // the scene for pixels which are brighter than a + // fixed threshold value. + // + // This is then used in the final HDR combine pass + // at the end of this post effect chain. + // + + shader = HDR_BrightPassShader; + stateBlock = HDR_DownSampleStateBlock; + texture[0] = "$backBuffer"; + texture[1] = "#adaptedLum"; + target = "$outTex"; + targetFormat = "GFXFormatR16G16B16A16F"; + targetScale = "0.5 0.5"; + + new PostEffect() + { + allowReflectPass = false; + shader = HDR_DownScale4x4Shader; + stateBlock = HDR_DownSampleStateBlock; + texture[0] = "$inTex"; + target = "$outTex"; + targetFormat = "GFXFormatR16G16B16A16F"; + targetScale = "0.25 0.25"; + }; + + new PostEffect() + { + allowReflectPass = false; + internalName = "bloomH"; + + shader = HDR_BloomGaussBlurHShader; + stateBlock = HDR_DownSampleStateBlock; + texture[0] = "$inTex"; + target = "$outTex"; + targetFormat = "GFXFormatR16G16B16A16F"; + }; + + new PostEffect() + { + allowReflectPass = false; + internalName = "bloomV"; + + shader = HDR_BloomGaussBlurVShader; + stateBlock = HDR_DownSampleStateBlock; + texture[0] = "$inTex"; + target = "#bloomFinal"; + targetFormat = "GFXFormatR16G16B16A16F"; + }; + + // BrightPass End + + // Now calculate the adapted luminance. + new PostEffect() + { + allowReflectPass = false; + internalName = "adaptLum"; + + shader = HDR_SampleLumShader; + stateBlock = HDR_DownSampleStateBlock; + texture[0] = "$backBuffer"; + target = "$outTex"; + targetScale = "0.0625 0.0625"; // 1/16th + targetFormat = "GFXFormatR16F"; + + new PostEffect() + { + allowReflectPass = false; + shader = HDR_DownSampleLumShader; + stateBlock = HDR_DownSampleStateBlock; + texture[0] = "$inTex"; + target = "$outTex"; + targetScale = "0.25 0.25"; // 1/4 + targetFormat = "GFXFormatR16F"; + }; + + new PostEffect() + { + allowReflectPass = false; + shader = HDR_DownSampleLumShader; + stateBlock = HDR_DownSampleStateBlock; + texture[0] = "$inTex"; + target = "$outTex"; + targetScale = "0.25 0.25"; // 1/4 + targetFormat = "GFXFormatR16F"; + }; + + new PostEffect() + { + allowReflectPass = false; + shader = HDR_DownSampleLumShader; + stateBlock = HDR_DownSampleStateBlock; + texture[0] = "$inTex"; + target = "$outTex"; + targetScale = "0.25 0.25"; // At this point the target should be 1x1. + targetFormat = "GFXFormatR16F"; + }; + + // Note that we're reading the adapted luminance + // from the previous frame when generating this new + // one... PostEffect takes care to manage that. + new PostEffect() + { + allowReflectPass = false; + internalName = "finalLum"; + shader = HDR_CalcAdaptedLumShader; + stateBlock = HDR_DownSampleStateBlock; + texture[0] = "$inTex"; + texture[1] = "#adaptedLum"; + target = "#adaptedLum"; + targetFormat = "GFXFormatR16F"; + targetClear = "PFXTargetClear_OnCreate"; + targetClearColor = "1 1 1 1"; + }; + }; + + // Output the combined bloom and toned mapped + // version of the scene. + new PostEffect() + { + allowReflectPass = false; + internalName = "combinePass"; + + shader = HDR_CombineShader; + stateBlock = HDR_CombineStateBlock; + texture[0] = "$backBuffer"; + texture[1] = "#adaptedLum"; + texture[2] = "#bloomFinal"; + texture[3] = $HDRPostFX::colorCorrectionRamp; + target = "$backBuffer"; + }; +}; + +singleton ShaderData( LuminanceVisShader ) +{ + DXVertexShaderFile = $Core::CommonShaderPath @ "/postFX/postFxV.hlsl"; + DXPixelShaderFile = $Core::CommonShaderPath @ "/postFX/hdr/luminanceVisP.hlsl"; + OGLVertexShaderFile = $Core::CommonShaderPath @ "/postFX/gl/postFxV.glsl"; + OGLPixelShaderFile = $Core::CommonShaderPath @ "/postFX/hdr/gl/luminanceVisP.glsl"; + + samplerNames[0] = "$inputTex"; + + pixVersion = 3.0; +}; + +singleton GFXStateBlockData( LuminanceVisStateBlock : PFX_DefaultStateBlock ) +{ + samplersDefined = true; + samplerStates[0] = SamplerClampLinear; +}; + +function LuminanceVisPostFX::setShaderConsts( %this ) +{ + %this.setShaderConst( "$brightPassThreshold", $HDRPostFX::brightPassThreshold ); +} + +singleton PostEffect( LuminanceVisPostFX ) +{ + isEnabled = false; + allowReflectPass = false; + + // Render before we do any editor rendering. + renderTime = "PFXBeforeBin"; + renderBin = "EditorBin"; + renderPriority = 9999; + + shader = LuminanceVisShader; + stateBlock = LuminanceVisStateBlock; + texture[0] = "$backBuffer"; + target = "$backBuffer"; + //targetScale = "0.0625 0.0625"; // 1/16th + //targetFormat = "GFXFormatR16F"; +}; + +function LuminanceVisPostFX::onEnabled( %this ) +{ + if ( !HDRPostFX.isEnabled() ) + { + HDRPostFX.enable(); + } + + HDRPostFX.skip = true; + + return true; +} + +function LuminanceVisPostFX::onDisabled( %this ) +{ + HDRPostFX.skip = false; +} + diff --git a/Templates/BaseGame/game/core/postFX/scripts/lightRay.cs b/Templates/BaseGame/game/core/postFX/scripts/lightRay.cs new file mode 100644 index 000000000..523b9bdea --- /dev/null +++ b/Templates/BaseGame/game/core/postFX/scripts/lightRay.cs @@ -0,0 +1,110 @@ +//----------------------------------------------------------------------------- +// 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. +//----------------------------------------------------------------------------- + + +$LightRayPostFX::brightScalar = 0.75; +$LightRayPostFX::numSamples = 40; +$LightRayPostFX::density = 0.94; +$LightRayPostFX::weight = 5.65; +$LightRayPostFX::decay = 1.0; +$LightRayPostFX::exposure = 0.0005; +$LightRayPostFX::resolutionScale = 1.0; + + +singleton ShaderData( LightRayOccludeShader ) +{ + DXVertexShaderFile = $Core::CommonShaderPath @ "/postFX/postFxV.hlsl"; + DXPixelShaderFile = $Core::CommonShaderPath @ "/postFX/lightRay/lightRayOccludeP.hlsl"; + + OGLVertexShaderFile = $Core::CommonShaderPath @ "/postFX/gl/postFxV.glsl"; + OGLPixelShaderFile = $Core::CommonShaderPath @ "/postFX/lightRay/gl/lightRayOccludeP.glsl"; + + samplerNames[0] = "$backBuffer"; + samplerNames[1] = "$deferredTex"; + + pixVersion = 3.0; +}; + +singleton ShaderData( LightRayShader ) +{ + DXVertexShaderFile = $Core::CommonShaderPath @ "/postFX/postFxV.hlsl"; + DXPixelShaderFile = $Core::CommonShaderPath @ "/postFX/lightRay/lightRayP.hlsl"; + + OGLVertexShaderFile = $Core::CommonShaderPath @ "/postFX/gl/postFxV.glsl"; + OGLPixelShaderFile = $Core::CommonShaderPath @ "/postFX/lightRay/gl/lightRayP.glsl"; + + samplerNames[0] = "$frameSampler"; + samplerNames[1] = "$backBuffer"; + + pixVersion = 3.0; +}; + +singleton GFXStateBlockData( LightRayStateBlock : PFX_DefaultStateBlock ) +{ + samplersDefined = true; + samplerStates[0] = SamplerClampLinear; + samplerStates[1] = SamplerClampLinear; +}; + +singleton PostEffect( LightRayPostFX ) +{ + isEnabled = false; + allowReflectPass = false; + + renderTime = "PFXBeforeBin"; + renderBin = "EditorBin"; + renderPriority = 10; + + shader = LightRayOccludeShader; + stateBlock = LightRayStateBlock; + texture[0] = "$backBuffer"; + texture[1] = "#deferred"; + target = "$outTex"; + targetFormat = "GFXFormatR16G16B16A16F"; + + new PostEffect() + { + shader = LightRayShader; + stateBlock = LightRayStateBlock; + internalName = "final"; + texture[0] = "$inTex"; + texture[1] = "$backBuffer"; + target = "$backBuffer"; + }; +}; + +function LightRayPostFX::preProcess( %this ) +{ + %this.targetScale = $LightRayPostFX::resolutionScale SPC $LightRayPostFX::resolutionScale; +} + +function LightRayPostFX::setShaderConsts( %this ) +{ + %this.setShaderConst( "$brightScalar", $LightRayPostFX::brightScalar ); + + %pfx = %this-->final; + %pfx.setShaderConst( "$numSamples", $LightRayPostFX::numSamples ); + %pfx.setShaderConst( "$density", $LightRayPostFX::density ); + %pfx.setShaderConst( "$weight", $LightRayPostFX::weight ); + %pfx.setShaderConst( "$decay", $LightRayPostFX::decay ); + %pfx.setShaderConst( "$exposure", $LightRayPostFX::exposure ); +} diff --git a/Templates/BaseGame/game/core/postFX/scripts/ovrBarrelDistortion.cs b/Templates/BaseGame/game/core/postFX/scripts/ovrBarrelDistortion.cs new file mode 100644 index 000000000..1ea280863 --- /dev/null +++ b/Templates/BaseGame/game/core/postFX/scripts/ovrBarrelDistortion.cs @@ -0,0 +1,167 @@ +//----------------------------------------------------------------------------- +// 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. +//----------------------------------------------------------------------------- + +// Only load these shaders if an Oculus VR device is present +if(!isFunction(isOculusVRDeviceActive)) + return; + +//----------------------------------------------------------------------------- +// Shader data +//----------------------------------------------------------------------------- + +singleton ShaderData( OVRMonoToStereoShader ) +{ + DXVertexShaderFile = $Core::CommonShaderPath @ "/postFX/postFxV.hlsl"; + DXPixelShaderFile = $Core::CommonShaderPath @ "/postFX/oculusvr/monoToStereoP.hlsl"; + + //OGLVertexShaderFile = $Core::CommonShaderPath @ "/postFX/gl/postFxV.hlsl"; + //OGLPixelShaderFile = $Core::CommonShaderPath @ "/postFX/oculusvr/gl/monoToStereoP.glsl"; + + samplerNames[0] = "$backBuffer"; + + pixVersion = 2.0; +}; + +singleton ShaderData( OVRBarrelDistortionShader ) +{ + DXVertexShaderFile = $Core::CommonShaderPath @ "/postFX/postFxV.hlsl"; + DXPixelShaderFile = $Core::CommonShaderPath @ "/postFX/oculusvr/barrelDistortionP.hlsl"; + + //OGLVertexShaderFile = $Core::CommonShaderPath @ "/postFX/gl/postFxV.glsl"; + //OGLPixelShaderFile = $Core::CommonShaderPath @ "/postFX/oculusvr/gl/barrelDistortionP.glsl"; + + samplerNames[0] = "$backBuffer"; + + pixVersion = 2.0; +}; + +singleton ShaderData( OVRBarrelDistortionChromaShader ) +{ + DXVertexShaderFile = $Core::CommonShaderPath @ "/postFX/postFxV.hlsl"; + DXPixelShaderFile = $Core::CommonShaderPath @ "/postFX/oculusvr/barrelDistortionChromaP.hlsl"; + + pixVersion = 2.0; +}; + +//----------------------------------------------------------------------------- +// GFX state blocks +//----------------------------------------------------------------------------- + +singleton GFXStateBlockData( OVRBarrelDistortionStateBlock : PFX_DefaultStateBlock ) +{ + samplersDefined = true; + samplerStates[0] = SamplerClampLinear; +}; + +//----------------------------------------------------------------------------- +// Barrel Distortion PostFx +// +// To be used with the Oculus Rift. +// Expects a stereo pair to exist on the back buffer and then applies the +// appropriate barrel distortion. +//----------------------------------------------------------------------------- +singleton BarrelDistortionPostEffect( OVRBarrelDistortionPostFX ) +{ + isEnabled = false; + allowReflectPass = false; + + renderTime = "PFXAfterDiffuse"; + renderPriority = 100; + + // The barrel distortion + shader = OVRBarrelDistortionShader; + stateBlock = OVRBarrelDistortionStateBlock; + + texture[0] = "$backBuffer"; + + scaleOutput = 1.25; +}; + +//----------------------------------------------------------------------------- +// Barrel Distortion with Chromatic Aberration Correction PostFx +// +// To be used with the Oculus Rift. +// Expects a stereo pair to exist on the back buffer and then applies the +// appropriate barrel distortion. +// This version applies a chromatic aberration correction during the +// barrel distortion. +//----------------------------------------------------------------------------- +singleton BarrelDistortionPostEffect( OVRBarrelDistortionChromaPostFX ) +{ + isEnabled = false; + allowReflectPass = false; + + renderTime = "PFXAfterDiffuse"; + renderPriority = 100; + + // The barrel distortion + shader = OVRBarrelDistortionChromaShader; + stateBlock = OVRBarrelDistortionStateBlock; + + texture[0] = "$backBuffer"; + + scaleOutput = 1.25; +}; + +//----------------------------------------------------------------------------- +// Barrel Distortion Mono PostFx +// +// To be used with the Oculus Rift. +// Takes a non-stereo image and turns it into a stereo pair with barrel +// distortion applied. Only a vertical slice around the center of the back +// buffer is used to generate the pseudo stereo pair. +//----------------------------------------------------------------------------- +singleton PostEffect( OVRBarrelDistortionMonoPostFX ) +{ + isEnabled = false; + allowReflectPass = false; + + renderTime = "PFXAfterDiffuse"; + renderPriority = 100; + + // Converts the mono display to a stereo one + shader = OVRMonoToStereoShader; + stateBlock = OVRBarrelDistortionStateBlock; + + texture[0] = "$backBuffer"; + target = "$outTex"; + + // The actual barrel distortion + new BarrelDistortionPostEffect(OVRBarrelDistortionMonoStage2PostFX) + { + shader = OVRBarrelDistortionShader; + stateBlock = OVRBarrelDistortionStateBlock; + texture[0] = "$inTex"; + target = "$backBuffer"; + + scaleOutput = 1.25; + }; + +}; + +function OVRBarrelDistortionMonoPostFX::setShaderConsts( %this ) +{ + %HMDIndex = 0; + + %xOffsets = getOVRHMDEyeXOffsets(%HMDIndex); + %this.setShaderConst( "$LensXOffsets", %xOffsets ); +} diff --git a/Templates/BaseGame/game/core/postFX/scripts/postFx.cs b/Templates/BaseGame/game/core/postFX/scripts/postFx.cs new file mode 100644 index 000000000..fe931a994 --- /dev/null +++ b/Templates/BaseGame/game/core/postFX/scripts/postFx.cs @@ -0,0 +1,88 @@ +//----------------------------------------------------------------------------- +// 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. +//----------------------------------------------------------------------------- + +singleton ShaderData( PFX_PassthruShader ) +{ + DXVertexShaderFile = $Core::CommonShaderPath @ "/postFX/postFxV.hlsl"; + DXPixelShaderFile = $Core::CommonShaderPath @ "/postFX/passthruP.hlsl"; + + OGLVertexShaderFile = $Core::CommonShaderPath @ "/postFX/gl/postFxV.glsl"; + OGLPixelShaderFile = $Core::CommonShaderPath @ "/postFX/gl/passthruP.glsl"; + + samplerNames[0] = "$inputTex"; + + pixVersion = 2.0; +}; + +function postFXInit() +{ + exec("core/postFX/guis/postFxManager.gui"); + + //Load the core postFX files themselves + if (!$Server::Dedicated) + { + //init the postFX + %pattern = "./*.cs"; + %file = findFirstFile( %pattern ); + if ( %file $= "" ) + { + // Try for DSOs next. + %pattern = "core/postFX/*.cs.dso"; + %file = findFirstFile( %pattern ); + } + + while( %file !$= "" ) + { + exec( %file ); + %file = findNextFile( %pattern ); + } + } +} + +function PostEffect::inspectVars( %this ) +{ + %name = %this.getName(); + %globals = "$" @ %name @ "::*"; + inspectVars( %globals ); +} + +function PostEffect::viewDisassembly( %this ) +{ + %file = %this.dumpShaderDisassembly(); + + if ( %file $= "" ) + { + echo( "PostEffect::viewDisassembly - no shader disassembly found." ); + } + else + { + echo( "PostEffect::viewDisassembly - shader disassembly file dumped ( " @ %file @ " )." ); + openFile( %file ); + } +} + +// Return true if we really want the effect enabled. +// By default this is the case. +function PostEffect::onEnabled( %this ) +{ + return true; +} \ No newline at end of file diff --git a/Templates/BaseGame/game/core/postFX/scripts/postFxManager.gui.cs b/Templates/BaseGame/game/core/postFX/scripts/postFxManager.gui.cs new file mode 100644 index 000000000..a6b0f0f01 --- /dev/null +++ b/Templates/BaseGame/game/core/postFX/scripts/postFxManager.gui.cs @@ -0,0 +1,446 @@ +//----------------------------------------------------------------------------- +// 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. +//----------------------------------------------------------------------------- + +$PostFXManager::vebose = true; +function postVerbose(%string) +{ + if($PostFXManager::vebose == true) + { + echo(%string); + } +} + +function PostFXManager::onDialogPush( %this ) +{ + //Apply the settings to the controls + postVerbose("% - PostFX Manager - Loading GUI."); + + %this.settingsRefreshAll(); +} + +// :: Controls for the overall postFX manager dialog +function ppOptionsEnable::onAction(%this) +{ + //Disable / Enable all PostFX + + if(ppOptionsEnable.getValue()) + { + %toEnable = true; + } + else + { + %toEnable = false; + } + + PostFXManager.settingsSetEnabled(%toEnable); + +} + +function PostFXManager::getEnableResultFromControl(%this, %control) +{ + %toEnable = -1; + %bTest = %control.getValue(); + if(%bTest == 1) + { + %toEnable = true; + } + else + { + %toEnable = false; + } + + return %toEnable; +} + +function ppOptionsEnableSSAO::onAction(%this) +{ + %toEnable = PostFXManager.getEnableResultFromControl(%this); + PostFXManager.settingsEffectSetEnabled("SSAO", %toEnable); +} + +function ppOptionsEnableHDR::onAction(%this) +{ + %toEnable = PostFXManager.getEnableResultFromControl(%this); + PostFXManager.settingsEffectSetEnabled("HDR", %toEnable); +} + +function ppOptionsEnableLightRays::onAction(%this) +{ + %toEnable = PostFXManager.getEnableResultFromControl(%this); + PostFXManager.settingsEffectSetEnabled("LightRays", %toEnable); +} + +function ppOptionsEnableDOF::onAction(%this) +{ + %toEnable = PostFXManager.getEnableResultFromControl(%this); + PostFXManager.settingsEffectSetEnabled("DOF", %toEnable); +} + +function ppOptionsEnableVignette::onAction(%this) +{ + %toEnable = PostFXManager.getEnableResultFromControl(%this); + PostFXManager.settingsEffectSetEnabled("Vignette", %toEnable); +} + +function ppOptionsSavePreset::onClick(%this) +{ + //Stores the current settings into a preset file for loading and use later on +} + +function ppOptionsLoadPreset::onClick(%this) +{ + //Loads and applies the settings from a postfxpreset file +} + + +//Other controls, Quality dropdown +function ppOptionsSSAOQuality::onSelect( %this, %id, %text ) +{ + if(%id > -1 && %id < 3) + { + $SSAOPostFx::quality = %id; + } +} + +//SSAO Slider controls +//General Tab +function ppOptionsSSAOOverallStrength::onMouseDragged(%this) +{ + $SSAOPostFx::overallStrength = %this.value; + %this.ToolTip = "Value : " @ %this.value; +} + +function ppOptionsSSAOBlurDepth::onMouseDragged(%this) +{ + $SSAOPostFx::blurDepthTol = %this.value; + %this.ToolTip = "Value : " @ %this.value; +} + +function ppOptionsSSAOBlurNormal::onMouseDragged(%this) +{ + $SSAOPostFx::blurNormalTol = %this.value; + %this.ToolTip = "Value : " @ %this.value; +} + +//Near Tab +function ppOptionsSSAONearRadius::onMouseDragged(%this) +{ + $SSAOPostFx::sRadius = %this.value; + %this.ToolTip = "Value : " @ %this.value; +} + +function ppOptionsSSAONearStrength::onMouseDragged(%this) +{ + $SSAOPostFx::sStrength = %this.value; + %this.ToolTip = "Value : " @ %this.value; +} + +function ppOptionsSSAONearDepthMin::onMouseDragged(%this) +{ + $SSAOPostFx::sDepthMin = %this.value; + %this.ToolTip = "Value : " @ %this.value; +} + +function ppOptionsSSAONearDepthMax::onMouseDragged(%this) +{ + $SSAOPostFx::sDepthMax = %this.value; + %this.ToolTip = "Value : " @ %this.value; +} + +function ppOptionsSSAONearToleranceNormal::onMouseDragged(%this) +{ + $SSAOPostFx::sNormalTol = %this.value; + %this.ToolTip = "Value : " @ %this.value; +} + +function ppOptionsSSAONearTolerancePower::onMouseDragged(%this) +{ + $SSAOPostFx::sNormalPow = %this.value; + %this.ToolTip = "Value : " @ %this.value; +} + +//Far Tab +function ppOptionsSSAOFarRadius::onMouseDragged(%this) +{ + $SSAOPostFx::lRadius = %this.value; + %this.ToolTip = "Value : " @ %this.value; +} +function ppOptionsSSAOFarStrength::onMouseDragged(%this) +{ + $SSAOPostFx::lStrength = %this.value; + %this.ToolTip = "Value : " @ %this.value; +} +function ppOptionsSSAOFarDepthMin::onMouseDragged(%this) +{ + $SSAOPostFx::lDepthMin = %this.value; + %this.ToolTip = "Value : " @ %this.value; +} +function ppOptionsSSAOFarDepthMax::onMouseDragged(%this) +{ + $SSAOPostFx::lDepthMax = %this.value; + %this.ToolTip = "Value : " @ %this.value; +} +function ppOptionsSSAOFarToleranceNormal::onMouseDragged(%this) +{ + $SSAOPostFx::lNormalTol = %this.value; + %this.ToolTip = "Value : " @ %this.value; +} +function ppOptionsSSAOFarTolerancePower::onMouseDragged(%this) +{ + $SSAOPostFx::lNormalPow = %this.value; + %this.ToolTip = "Value : " @ %this.value; +} + +//HDR Slider Controls +//Brighness tab + +function ppOptionsHDRToneMappingAmount::onMouseDragged(%this) +{ + + $HDRPostFX::enableToneMapping = %this.value; + %this.ToolTip = "value : " @ %this.value; +} + +function ppOptionsHDRKeyValue::onMouseDragged(%this) +{ + $HDRPostFX::keyValue = %this.value; + %this.ToolTip = "Value : " @ %this.value; +} + +function ppOptionsHDRMinLuminance::onMouseDragged(%this) +{ + $HDRPostFX::minLuminace = %this.value; + %this.ToolTip = "Value : " @ %this.value; +} + +function ppOptionsHDRWhiteCutoff::onMouseDragged(%this) +{ + $HDRPostFX::whiteCutoff = %this.value; + %this.ToolTip = "Value : " @ %this.value; +} + +function ppOptionsHDRBrightnessAdaptRate::onMouseDragged(%this) +{ + $HDRPostFX::adaptRate = %this.value; + %this.ToolTip = "Value : " @ %this.value; +} + +//Blur tab +function ppOptionsHDRBloomBlurBrightPassThreshold::onMouseDragged(%this) +{ + $HDRPostFX::brightPassThreshold = %this.value; + %this.ToolTip = "Value : " @ %this.value; +} + +function ppOptionsHDRBloomBlurMultiplier::onMouseDragged(%this) +{ + $HDRPostFX::gaussMultiplier = %this.value; + %this.ToolTip = "Value : " @ %this.value; +} + +function ppOptionsHDRBloomBlurMean::onMouseDragged(%this) +{ + $HDRPostFX::gaussMean = %this.value; + %this.ToolTip = "Value : " @ %this.value; +} + +function ppOptionsHDRBloomBlurStdDev::onMouseDragged(%this) +{ + $HDRPostFX::gaussStdDev = %this.value; + %this.ToolTip = "Value : " @ %this.value; +} + +function ppOptionsHDRBloom::onAction(%this) +{ + $HDRPostFX::enableBloom = %this.getValue(); +} + +function ppOptionsHDRToneMapping::onAction(%this) +{ + //$HDRPostFX::enableToneMapping = %this.getValue(); +} + +function ppOptionsHDREffectsBlueShift::onAction(%this) +{ + $HDRPostFX::enableBlueShift = %this.getValue(); +} + + +//Controls for color range in blue Shift dialog + +function ppOptionsHDREffectsBlueShiftColorBlend::onAction(%this) +{ + $HDRPostFX::blueShiftColor = %this.PickColor; + %this.ToolTip = "Color Values : " @ %this.PickColor; +} + +function ppOptionsHDREffectsBlueShiftColorBaseColor::onAction(%this) +{ + //This one feeds the one above + ppOptionsHDREffectsBlueShiftColorBlend.baseColor = %this.PickColor; + %this.ToolTip = "Color Values : " @ %this.PickColor; +} + + +//Light rays Brightness Slider Controls +function ppOptionsLightRaysBrightScalar::onMouseDragged(%this) +{ + $LightRayPostFX::brightScalar = %this.value; + %this.ToolTip = "Value : " @ %this.value; +} +//Light rays Number of Samples Slider Control +function ppOptionsLightRaysSampleScalar::onMouseDragged(%this) +{ + $LightRayPostFX::numSamples = %this.value; + %this.ToolTip = "Value : " @ %this.value; +} +//Light rays Density Slider Control +function ppOptionsLightRaysDensityScalar::onMouseDragged(%this) +{ + $LightRayPostFX::density = %this.value; + %this.ToolTip = "Value : " @ %this.value; +} +//Light rays Weight Slider Control +function ppOptionsLightRaysWeightScalar::onMouseDragged(%this) +{ + $LightRayPostFX::weight = %this.value; + %this.ToolTip = "Value : " @ %this.value; +} +//Light rays Decay Slider Control +function ppOptionsLightRaysDecayScalar::onMouseDragged(%this) +{ + $LightRayPostFX::decay = %this.value; + %this.ToolTip = "Value : " @ %this.value; +} + + +function ppOptionsUpdateDOFSettings() +{ + DOFPostEffect.setFocusParams( $DOFPostFx::BlurMin, $DOFPostFx::BlurMax, $DOFPostFx::FocusRangeMin, $DOFPostFx::FocusRangeMax, -($DOFPostFx::BlurCurveNear), $DOFPostFx::BlurCurveFar ); + + DOFPostEffect.setAutoFocus( $DOFPostFx::EnableAutoFocus ); + DOFPostEffect.setFocalDist(0); + + if($PostFXManager::PostFX::EnableDOF) + { + DOFPostEffect.enable(); + } + else + { + DOFPostEffect.disable(); + } +} + +//DOF General Tab +//DOF Toggles +function ppOptionsDOFEnableDOF::onAction(%this) +{ + $PostFXManager::PostFX::EnableDOF = %this.getValue(); + ppOptionsUpdateDOFSettings(); +} + + +function ppOptionsDOFEnableAutoFocus::onAction(%this) +{ + $DOFPostFx::EnableAutoFocus = %this.getValue(); + DOFPostEffect.setAutoFocus( %this.getValue() ); +} + +//DOF AutoFocus Slider controls +function ppOptionsDOFFarBlurMinSlider::onMouseDragged(%this) +{ + $DOFPostFx::BlurMin = %this.value; + ppOptionsUpdateDOFSettings(); +} + +function ppOptionsDOFFarBlurMaxSlider::onMouseDragged(%this) +{ + $DOFPostFx::BlurMax = %this.value; + ppOptionsUpdateDOFSettings(); +} + +function ppOptionsDOFFocusRangeMinSlider::onMouseDragged(%this) +{ + $DOFPostFx::FocusRangeMin = %this.value; + ppOptionsUpdateDOFSettings(); +} + +function ppOptionsDOFFocusRangeMaxSlider::onMouseDragged(%this) +{ + $DOFPostFx::FocusRangeMax = %this.value; + ppOptionsUpdateDOFSettings(); +} + +function ppOptionsDOFBlurCurveNearSlider::onMouseDragged(%this) +{ + $DOFPostFx::BlurCurveNear = %this.value; + ppOptionsUpdateDOFSettings(); +} + +function ppOptionsDOFBlurCurveFarSlider::onMouseDragged(%this) +{ + $DOFPostFx::BlurCurveFar = %this.value; + ppOptionsUpdateDOFSettings(); +} + +function ppOptionsEnableHDRDebug::onAction(%this) +{ + if ( %this.getValue() ) + LuminanceVisPostFX.enable(); + else + LuminanceVisPostFX.disable(); +} + +function ppOptionsUpdateVignetteSettings() +{ + if($PostFXManager::PostFX::EnableVignette) + { + VignettePostEffect.enable(); + } + else + { + VignettePostEffect.disable(); + } +} + +function ppOptionsVignetteEnableVignette::onAction(%this) +{ + $PostFXManager::PostFX::EnableVignette = %this.getValue(); + ppOptionsUpdateVignetteSettings(); +} + +function ppColorCorrection_selectFile() +{ + %filter = "Image Files (*.png, *.jpg, *.dds, *.bmp, *.gif, *.jng. *.tga)|*.png;*.jpg;*.dds;*.bmp;*.gif;*.jng;*.tga|All Files (*.*)|*.*|"; + getLoadFilename( %filter, "ppColorCorrection_selectFileHandler"); +} + +function ppColorCorrection_selectFileHandler( %filename ) +{ + if ( %filename $= "" || !isFile( %filename ) ) + %filename = "core/postFX/images/null_color_ramp.png"; + else + %filename = makeRelativePath( %filename, getMainDotCsDir() ); + + $HDRPostFX::colorCorrectionRamp = %filename; + PostFXManager-->ColorCorrectionFileName.Text = %filename; +} \ No newline at end of file diff --git a/Templates/BaseGame/game/core/postFX/scripts/postFxManager.gui.settings.cs b/Templates/BaseGame/game/core/postFX/scripts/postFxManager.gui.settings.cs new file mode 100644 index 000000000..eefcd9b7e --- /dev/null +++ b/Templates/BaseGame/game/core/postFX/scripts/postFxManager.gui.settings.cs @@ -0,0 +1,439 @@ +//----------------------------------------------------------------------------- +// 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. +//----------------------------------------------------------------------------- + +$PostFXManager::defaultPreset = "./default.postfxpreset.cs"; + +function PostFXManager::settingsSetEnabled(%this, %bEnablePostFX) +{ + $PostFXManager::PostFX::Enabled = %bEnablePostFX; + + //if to enable the postFX, apply the ones that are enabled + if ( %bEnablePostFX ) + { + //SSAO, HDR, LightRays, DOF + + if ( $PostFXManager::PostFX::EnableSSAO ) + SSAOPostFx.enable(); + else + SSAOPostFx.disable(); + + if ( $PostFXManager::PostFX::EnableHDR ) + HDRPostFX.enable(); + else + HDRPostFX.disable(); + + if ( $PostFXManager::PostFX::EnableLightRays ) + LightRayPostFX.enable(); + else + LightRayPostFX.disable(); + + if ( $PostFXManager::PostFX::EnableDOF ) + DOFPostEffect.enable(); + else + DOFPostEffect.disable(); + + if ( $PostFXManager::PostFX::EnableVignette ) + VignettePostEffect.enable(); + else + VignettePostEffect.disable(); + + postVerbose("% - PostFX Manager - PostFX enabled"); + } + else + { + //Disable all postFX + + SSAOPostFx.disable(); + HDRPostFX.disable(); + LightRayPostFX.disable(); + DOFPostEffect.disable(); + VignettePostEffect.disable(); + + postVerbose("% - PostFX Manager - PostFX disabled"); + } + + VolFogGlowPostFx.disable(); +} + +function PostFXManager::settingsEffectSetEnabled(%this, %sName, %bEnable) +{ + %postEffect = 0; + + //Determine the postFX to enable, and apply the boolean + if(%sName $= "SSAO") + { + %postEffect = SSAOPostFx; + $PostFXManager::PostFX::EnableSSAO = %bEnable; + //$pref::PostFX::SSAO::Enabled = %bEnable; + } + else if(%sName $= "HDR") + { + %postEffect = HDRPostFX; + $PostFXManager::PostFX::EnableHDR = %bEnable; + //$pref::PostFX::HDR::Enabled = %bEnable; + } + else if(%sName $= "LightRays") + { + %postEffect = LightRayPostFX; + $PostFXManager::PostFX::EnableLightRays = %bEnable; + //$pref::PostFX::LightRays::Enabled = %bEnable; + } + else if(%sName $= "DOF") + { + %postEffect = DOFPostEffect; + $PostFXManager::PostFX::EnableDOF = %bEnable; + //$pref::PostFX::DOF::Enabled = %bEnable; + } + else if(%sName $= "Vignette") + { + %postEffect = VignettePostEffect; + $PostFXManager::PostFX::EnableVignette = %bEnable; + //$pref::PostFX::Vignette::Enabled = %bEnable; + } + + // Apply the change + if ( %bEnable == true ) + { + %postEffect.enable(); + postVerbose("% - PostFX Manager - " @ %sName @ " enabled"); + } + else + { + %postEffect.disable(); + postVerbose("% - PostFX Manager - " @ %sName @ " disabled"); + } +} + +function PostFXManager::settingsRefreshSSAO(%this) +{ + //Apply the enabled flag + ppOptionsEnableSSAO.setValue($PostFXManager::PostFX::EnableSSAO); + + //Add the items we need to display + ppOptionsSSAOQuality.clear(); + ppOptionsSSAOQuality.add("Low", 0); + ppOptionsSSAOQuality.add("Medium", 1); + ppOptionsSSAOQuality.add("High", 2); + + //Set the selected, after adding the items! + ppOptionsSSAOQuality.setSelected($SSAOPostFx::quality); + + //SSAO - Set the values of the sliders, General Tab + ppOptionsSSAOOverallStrength.setValue($SSAOPostFx::overallStrength); + ppOptionsSSAOBlurDepth.setValue($SSAOPostFx::blurDepthTol); + ppOptionsSSAOBlurNormal.setValue($SSAOPostFx::blurNormalTol); + + //SSAO - Set the values for the near tab + ppOptionsSSAONearDepthMax.setValue($SSAOPostFx::sDepthMax); + ppOptionsSSAONearDepthMin.setValue($SSAOPostFx::sDepthMin); + ppOptionsSSAONearRadius.setValue($SSAOPostFx::sRadius); + ppOptionsSSAONearStrength.setValue($SSAOPostFx::sStrength); + ppOptionsSSAONearToleranceNormal.setValue($SSAOPostFx::sNormalTol); + ppOptionsSSAONearTolerancePower.setValue($SSAOPostFx::sNormalPow); + + //SSAO - Set the values for the far tab + ppOptionsSSAOFarDepthMax.setValue($SSAOPostFx::lDepthMax); + ppOptionsSSAOFarDepthMin.setValue($SSAOPostFx::lDepthMin); + ppOptionsSSAOFarRadius.setValue($SSAOPostFx::lRadius); + ppOptionsSSAOFarStrength.setValue($SSAOPostFx::lStrength); + ppOptionsSSAOFarToleranceNormal.setValue($SSAOPostFx::lNormalTol); + ppOptionsSSAOFarTolerancePower.setValue($SSAOPostFx::lNormalPow); +} + +function PostFXManager::settingsRefreshHDR(%this) +{ + //Apply the enabled flag + ppOptionsEnableHDR.setValue($PostFXManager::PostFX::EnableHDR); + + ppOptionsHDRBloom.setValue($HDRPostFX::enableBloom); + ppOptionsHDRBloomBlurBrightPassThreshold.setValue($HDRPostFX::brightPassThreshold); + ppOptionsHDRBloomBlurMean.setValue($HDRPostFX::gaussMean); + ppOptionsHDRBloomBlurMultiplier.setValue($HDRPostFX::gaussMultiplier); + ppOptionsHDRBloomBlurStdDev.setValue($HDRPostFX::gaussStdDev); + ppOptionsHDRBrightnessAdaptRate.setValue($HDRPostFX::adaptRate); + ppOptionsHDREffectsBlueShift.setValue($HDRPostFX::enableBlueShift); + ppOptionsHDREffectsBlueShiftColor.BaseColor = $HDRPostFX::blueShiftColor; + ppOptionsHDREffectsBlueShiftColor.PickColor = $HDRPostFX::blueShiftColor; + ppOptionsHDRKeyValue.setValue($HDRPostFX::keyValue); + ppOptionsHDRMinLuminance.setValue($HDRPostFX::minLuminace); + ppOptionsHDRToneMapping.setValue($HDRPostFX::enableToneMapping); + ppOptionsHDRToneMappingAmount.setValue($HDRPostFX::enableToneMapping); + ppOptionsHDRWhiteCutoff.setValue($HDRPostFX::whiteCutoff); + + %this-->ColorCorrectionFileName.Text = $HDRPostFX::colorCorrectionRamp; +} + +function PostFXManager::settingsRefreshLightrays(%this) +{ + //Apply the enabled flag + ppOptionsEnableLightRays.setValue($PostFXManager::PostFX::EnableLightRays); + + ppOptionsLightRaysBrightScalar.setValue($LightRayPostFX::brightScalar); + + ppOptionsLightRaysSampleScalar.setValue($LightRayPostFX::numSamples); + ppOptionsLightRaysDensityScalar.setValue($LightRayPostFX::density); + ppOptionsLightRaysWeightScalar.setValue($LightRayPostFX::weight); + ppOptionsLightRaysDecayScalar.setValue($LightRayPostFX::decay); +} + +function PostFXManager::settingsRefreshDOF(%this) +{ + //Apply the enabled flag + ppOptionsEnableDOF.setValue($PostFXManager::PostFX::EnableDOF); + + + //ppOptionsDOFEnableDOF.setValue($PostFXManager::PostFX::EnableDOF); + ppOptionsDOFEnableAutoFocus.setValue($DOFPostFx::EnableAutoFocus); + + ppOptionsDOFFarBlurMinSlider.setValue($DOFPostFx::BlurMin); + ppOptionsDOFFarBlurMaxSlider.setValue($DOFPostFx::BlurMax); + + ppOptionsDOFFocusRangeMinSlider.setValue($DOFPostFx::FocusRangeMin); + ppOptionsDOFFocusRangeMaxSlider.setValue($DOFPostFx::FocusRangeMax); + + ppOptionsDOFBlurCurveNearSlider.setValue($DOFPostFx::BlurCurveNear); + ppOptionsDOFBlurCurveFarSlider.setValue($DOFPostFx::BlurCurveFar); + +} + +function PostFXManager::settingsRefreshVignette(%this) +{ + //Apply the enabled flag + ppOptionsEnableVignette.setValue($PostFXManager::PostFX::EnableVignette); + +} + +function PostFXManager::settingsRefreshAll(%this) +{ + $PostFXManager::PostFX::Enabled = $pref::enablePostEffects; + $PostFXManager::PostFX::EnableSSAO = SSAOPostFx.isEnabled(); + $PostFXManager::PostFX::EnableHDR = HDRPostFX.isEnabled(); + $PostFXManager::PostFX::EnableLightRays = LightRayPostFX.isEnabled(); + $PostFXManager::PostFX::EnableDOF = DOFPostEffect.isEnabled(); + $PostFXManager::PostFX::EnableVignette = VignettePostEffect.isEnabled(); + + //For all the postFX here, apply the active settings in the system + //to the gui controls. + + %this.settingsRefreshSSAO(); + %this.settingsRefreshHDR(); + %this.settingsRefreshLightrays(); + %this.settingsRefreshDOF(); + %this.settingsRefreshVignette(); + + ppOptionsEnable.setValue($PostFXManager::PostFX::Enabled); + + postVerbose("% - PostFX Manager - GUI values updated."); +} + +function PostFXManager::settingsApplyFromPreset(%this) +{ + postVerbose("% - PostFX Manager - Applying from preset"); + + //SSAO Settings + $SSAOPostFx::blurDepthTol = $PostFXManager::Settings::SSAO::blurDepthTol; + $SSAOPostFx::blurNormalTol = $PostFXManager::Settings::SSAO::blurNormalTol; + $SSAOPostFx::lDepthMax = $PostFXManager::Settings::SSAO::lDepthMax; + $SSAOPostFx::lDepthMin = $PostFXManager::Settings::SSAO::lDepthMin; + $SSAOPostFx::lDepthPow = $PostFXManager::Settings::SSAO::lDepthPow; + $SSAOPostFx::lNormalPow = $PostFXManager::Settings::SSAO::lNormalPow; + $SSAOPostFx::lNormalTol = $PostFXManager::Settings::SSAO::lNormalTol; + $SSAOPostFx::lRadius = $PostFXManager::Settings::SSAO::lRadius; + $SSAOPostFx::lStrength = $PostFXManager::Settings::SSAO::lStrength; + $SSAOPostFx::overallStrength = $PostFXManager::Settings::SSAO::overallStrength; + $SSAOPostFx::quality = $PostFXManager::Settings::SSAO::quality; + $SSAOPostFx::sDepthMax = $PostFXManager::Settings::SSAO::sDepthMax; + $SSAOPostFx::sDepthMin = $PostFXManager::Settings::SSAO::sDepthMin; + $SSAOPostFx::sDepthPow = $PostFXManager::Settings::SSAO::sDepthPow; + $SSAOPostFx::sNormalPow = $PostFXManager::Settings::SSAO::sNormalPow; + $SSAOPostFx::sNormalTol = $PostFXManager::Settings::SSAO::sNormalTol; + $SSAOPostFx::sRadius = $PostFXManager::Settings::SSAO::sRadius; + $SSAOPostFx::sStrength = $PostFXManager::Settings::SSAO::sStrength; + + //HDR settings + $HDRPostFX::adaptRate = $PostFXManager::Settings::HDR::adaptRate; + $HDRPostFX::blueShiftColor = $PostFXManager::Settings::HDR::blueShiftColor; + $HDRPostFX::brightPassThreshold = $PostFXManager::Settings::HDR::brightPassThreshold; + $HDRPostFX::enableBloom = $PostFXManager::Settings::HDR::enableBloom; + $HDRPostFX::enableBlueShift = $PostFXManager::Settings::HDR::enableBlueShift; + $HDRPostFX::enableToneMapping = $PostFXManager::Settings::HDR::enableToneMapping; + $HDRPostFX::gaussMean = $PostFXManager::Settings::HDR::gaussMean; + $HDRPostFX::gaussMultiplier = $PostFXManager::Settings::HDR::gaussMultiplier; + $HDRPostFX::gaussStdDev = $PostFXManager::Settings::HDR::gaussStdDev; + $HDRPostFX::keyValue = $PostFXManager::Settings::HDR::keyValue; + $HDRPostFX::minLuminace = $PostFXManager::Settings::HDR::minLuminace; + $HDRPostFX::whiteCutoff = $PostFXManager::Settings::HDR::whiteCutoff; + $HDRPostFX::colorCorrectionRamp = $PostFXManager::Settings::ColorCorrectionRamp; + + //Light rays settings + $LightRayPostFX::brightScalar = $PostFXManager::Settings::LightRays::brightScalar; + + $LightRayPostFX::numSamples = $PostFXManager::Settings::LightRays::numSamples; + $LightRayPostFX::density = $PostFXManager::Settings::LightRays::density; + $LightRayPostFX::weight = $PostFXManager::Settings::LightRays::weight; + $LightRayPostFX::decay = $PostFXManager::Settings::LightRays::decay; + + //DOF settings + $DOFPostFx::EnableAutoFocus = $PostFXManager::Settings::DOF::EnableAutoFocus; + $DOFPostFx::BlurMin = $PostFXManager::Settings::DOF::BlurMin; + $DOFPostFx::BlurMax = $PostFXManager::Settings::DOF::BlurMax; + $DOFPostFx::FocusRangeMin = $PostFXManager::Settings::DOF::FocusRangeMin; + $DOFPostFx::FocusRangeMax = $PostFXManager::Settings::DOF::FocusRangeMax; + $DOFPostFx::BlurCurveNear = $PostFXManager::Settings::DOF::BlurCurveNear; + $DOFPostFx::BlurCurveFar = $PostFXManager::Settings::DOF::BlurCurveFar; + + //Vignette settings + $VignettePostEffect::VMax = $PostFXManager::Settings::Vignette::VMax; + $VignettePostEffect::VMin = $PostFXManager::Settings::Vignette::VMin; + + if ( $PostFXManager::forceEnableFromPresets ) + { + $PostFXManager::PostFX::Enabled = $PostFXManager::Settings::EnablePostFX; + $PostFXManager::PostFX::EnableDOF = $pref::PostFX::EnableDOF ? $PostFXManager::Settings::EnableDOF : false; + $PostFXManager::PostFX::EnableVignette = $pref::PostFX::EnableVignette ? $PostFXManager::Settings::EnableVignette : false; + $PostFXManager::PostFX::EnableLightRays = $pref::PostFX::EnableLightRays ? $PostFXManager::Settings::EnableLightRays : false; + $PostFXManager::PostFX::EnableHDR = $pref::PostFX::EnableHDR ? $PostFXManager::Settings::EnableHDR : false; + $PostFXManager::PostFX::EnableSSAO = $pref::PostFX::EnabledSSAO ? $PostFXManager::Settings::EnableSSAO : false; + + %this.settingsSetEnabled( true ); + } + + //make sure we apply the correct settings to the DOF + ppOptionsUpdateDOFSettings(); + + // Update the actual GUI controls if its awake ( otherwise it will when opened ). + if ( PostFXManager.isAwake() ) + %this.settingsRefreshAll(); +} + +function PostFXManager::settingsApplySSAO(%this) +{ + $PostFXManager::Settings::SSAO::blurDepthTol = $SSAOPostFx::blurDepthTol; + $PostFXManager::Settings::SSAO::blurNormalTol = $SSAOPostFx::blurNormalTol; + $PostFXManager::Settings::SSAO::lDepthMax = $SSAOPostFx::lDepthMax; + $PostFXManager::Settings::SSAO::lDepthMin = $SSAOPostFx::lDepthMin; + $PostFXManager::Settings::SSAO::lDepthPow = $SSAOPostFx::lDepthPow; + $PostFXManager::Settings::SSAO::lNormalPow = $SSAOPostFx::lNormalPow; + $PostFXManager::Settings::SSAO::lNormalTol = $SSAOPostFx::lNormalTol; + $PostFXManager::Settings::SSAO::lRadius = $SSAOPostFx::lRadius; + $PostFXManager::Settings::SSAO::lStrength = $SSAOPostFx::lStrength; + $PostFXManager::Settings::SSAO::overallStrength = $SSAOPostFx::overallStrength; + $PostFXManager::Settings::SSAO::quality = $SSAOPostFx::quality; + $PostFXManager::Settings::SSAO::sDepthMax = $SSAOPostFx::sDepthMax; + $PostFXManager::Settings::SSAO::sDepthMin = $SSAOPostFx::sDepthMin; + $PostFXManager::Settings::SSAO::sDepthPow = $SSAOPostFx::sDepthPow; + $PostFXManager::Settings::SSAO::sNormalPow = $SSAOPostFx::sNormalPow; + $PostFXManager::Settings::SSAO::sNormalTol = $SSAOPostFx::sNormalTol; + $PostFXManager::Settings::SSAO::sRadius = $SSAOPostFx::sRadius; + $PostFXManager::Settings::SSAO::sStrength = $SSAOPostFx::sStrength; + + postVerbose("% - PostFX Manager - Settings Saved - SSAO"); + +} + +function PostFXManager::settingsApplyHDR(%this) +{ + $PostFXManager::Settings::HDR::adaptRate = $HDRPostFX::adaptRate; + $PostFXManager::Settings::HDR::blueShiftColor = $HDRPostFX::blueShiftColor; + $PostFXManager::Settings::HDR::brightPassThreshold = $HDRPostFX::brightPassThreshold; + $PostFXManager::Settings::HDR::enableBloom = $HDRPostFX::enableBloom; + $PostFXManager::Settings::HDR::enableBlueShift = $HDRPostFX::enableBlueShift; + $PostFXManager::Settings::HDR::enableToneMapping = $HDRPostFX::enableToneMapping; + $PostFXManager::Settings::HDR::gaussMean = $HDRPostFX::gaussMean; + $PostFXManager::Settings::HDR::gaussMultiplier = $HDRPostFX::gaussMultiplier; + $PostFXManager::Settings::HDR::gaussStdDev = $HDRPostFX::gaussStdDev; + $PostFXManager::Settings::HDR::keyValue = $HDRPostFX::keyValue; + $PostFXManager::Settings::HDR::minLuminace = $HDRPostFX::minLuminace; + $PostFXManager::Settings::HDR::whiteCutoff = $HDRPostFX::whiteCutoff; + $PostFXManager::Settings::ColorCorrectionRamp = $HDRPostFX::colorCorrectionRamp; + + postVerbose("% - PostFX Manager - Settings Saved - HDR"); +} + +function PostFXManager::settingsApplyLightRays(%this) +{ + $PostFXManager::Settings::LightRays::brightScalar = $LightRayPostFX::brightScalar; + + $PostFXManager::Settings::LightRays::numSamples = $LightRayPostFX::numSamples; + $PostFXManager::Settings::LightRays::density = $LightRayPostFX::density; + $PostFXManager::Settings::LightRays::weight = $LightRayPostFX::weight; + $PostFXManager::Settings::LightRays::decay = $LightRayPostFX::decay; + + postVerbose("% - PostFX Manager - Settings Saved - Light Rays"); + +} + +function PostFXManager::settingsApplyDOF(%this) +{ + $PostFXManager::Settings::DOF::EnableAutoFocus = $DOFPostFx::EnableAutoFocus; + $PostFXManager::Settings::DOF::BlurMin = $DOFPostFx::BlurMin; + $PostFXManager::Settings::DOF::BlurMax = $DOFPostFx::BlurMax; + $PostFXManager::Settings::DOF::FocusRangeMin = $DOFPostFx::FocusRangeMin; + $PostFXManager::Settings::DOF::FocusRangeMax = $DOFPostFx::FocusRangeMax; + $PostFXManager::Settings::DOF::BlurCurveNear = $DOFPostFx::BlurCurveNear; + $PostFXManager::Settings::DOF::BlurCurveFar = $DOFPostFx::BlurCurveFar; + + postVerbose("% - PostFX Manager - Settings Saved - DOF"); + +} + +function PostFXManager::settingsApplyVignette(%this) +{ + $PostFXManager::Settings::Vignette::VMax = $VignettePostEffect::VMax; + $PostFXManager::Settings::Vignette::VMin = $VignettePostEffect::VMin; + + postVerbose("% - PostFX Manager - Settings Saved - Vignette"); + +} + +function PostFXManager::settingsApplyAll(%this, %sFrom) +{ + // Apply settings which control if effects are on/off altogether. + $PostFXManager::Settings::EnablePostFX = $PostFXManager::PostFX::Enabled; + $PostFXManager::Settings::EnableDOF = $PostFXManager::PostFX::EnableDOF; + $PostFXManager::Settings::EnableVignette = $PostFXManager::PostFX::EnableVignette; + $PostFXManager::Settings::EnableLightRays = $PostFXManager::PostFX::EnableLightRays; + $PostFXManager::Settings::EnableHDR = $PostFXManager::PostFX::EnableHDR; + $PostFXManager::Settings::EnableSSAO = $PostFXManager::PostFX::EnableSSAO; + + // Apply settings should save the values in the system to the + // the preset structure ($PostFXManager::Settings::*) + + // SSAO Settings + %this.settingsApplySSAO(); + // HDR settings + %this.settingsApplyHDR(); + // Light rays settings + %this.settingsApplyLightRays(); + // DOF + %this.settingsApplyDOF(); + // Vignette + %this.settingsApplyVignette(); + + postVerbose("% - PostFX Manager - All Settings applied to $PostFXManager::Settings"); +} + +function PostFXManager::settingsApplyDefaultPreset(%this) +{ + PostFXManager::loadPresetHandler($PostFXManager::defaultPreset); +} + diff --git a/Templates/BaseGame/game/core/postFX/scripts/postFxManager.persistance.cs b/Templates/BaseGame/game/core/postFX/scripts/postFxManager.persistance.cs new file mode 100644 index 000000000..31fec95f1 --- /dev/null +++ b/Templates/BaseGame/game/core/postFX/scripts/postFxManager.persistance.cs @@ -0,0 +1,79 @@ +//----------------------------------------------------------------------------- +// 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. +//----------------------------------------------------------------------------- + + +// Used to name the saved files. +$PostFXManager::fileExtension = ".postfxpreset.cs"; + +// The filter string for file open/save dialogs. +$PostFXManager::fileFilter = "Post Effect Presets|*.postfxpreset.cs"; + +// Enable / disable PostFX when loading presets or just apply the settings? +$PostFXManager::forceEnableFromPresets = true; + +//Load a preset file from the disk, and apply the settings to the +//controls. If bApplySettings is true - the actual values in the engine +//will be changed to reflect the settings from the file. +function PostFXManager::loadPresetFile() +{ + //Show the dialog and set the flag + getLoadFilename($PostFXManager::fileFilter, "PostFXManager::loadPresetHandler"); +} + +function PostFXManager::loadPresetHandler( %filename ) +{ + //Check the validity of the file + if ( isScriptFile( %filename ) ) + { + %filename = expandFilename(%filename); + postVerbose("% - PostFX Manager - Executing " @ %filename); + exec(%filename); + + PostFXManager.settingsApplyFromPreset(); + } +} + +//Save a preset file to the specified file. The extension used +//is specified by $PostFXManager::fileExtension for on the fly +//name changes to the extension used. + +function PostFXManager::savePresetFile(%this) +{ + %defaultFile = filePath($Client::MissionFile) @ "/" @ fileBase($Client::MissionFile); + getSaveFilename($PostFXManager::fileFilter, "PostFXManager::savePresetHandler", %defaultFile); +} + +//Called from the PostFXManager::savePresetFile() function +function PostFXManager::savePresetHandler( %filename ) +{ + %filename = makeRelativePath( %filename, getMainDotCsDir() ); + if(strStr(%filename, ".") == -1) + %filename = %filename @ $PostFXManager::fileExtension; + + //Apply the current settings to the preset + PostFXManager.settingsApplyAll(); + + export("$PostFXManager::Settings::*", %filename, false); + + postVerbose("% - PostFX Manager - Save complete. Preset saved at : " @ %filename); +} + diff --git a/Templates/BaseGame/game/core/postFX/scripts/ssao.cs b/Templates/BaseGame/game/core/postFX/scripts/ssao.cs new file mode 100644 index 000000000..5fe405a82 --- /dev/null +++ b/Templates/BaseGame/game/core/postFX/scripts/ssao.cs @@ -0,0 +1,302 @@ +//----------------------------------------------------------------------------- +// 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. +//----------------------------------------------------------------------------- + + +/// +$SSAOPostFx::overallStrength = 2.0; + +// TODO: Add small/large param docs. + +// The small radius SSAO settings. +$SSAOPostFx::sRadius = 0.1; +$SSAOPostFx::sStrength = 6.0; +$SSAOPostFx::sDepthMin = 0.1; +$SSAOPostFx::sDepthMax = 1.0; +$SSAOPostFx::sDepthPow = 1.0; +$SSAOPostFx::sNormalTol = 0.0; +$SSAOPostFx::sNormalPow = 1.0; + +// The large radius SSAO settings. +$SSAOPostFx::lRadius = 1.0; +$SSAOPostFx::lStrength = 10.0; +$SSAOPostFx::lDepthMin = 0.2; +$SSAOPostFx::lDepthMax = 2.0; +$SSAOPostFx::lDepthPow = 0.2; +$SSAOPostFx::lNormalTol = -0.5; +$SSAOPostFx::lNormalPow = 2.0; + +/// Valid values: 0, 1, 2 +$SSAOPostFx::quality = 0; + +/// +$SSAOPostFx::blurDepthTol = 0.001; + +/// +$SSAOPostFx::blurNormalTol = 0.95; + +/// +$SSAOPostFx::targetScale = "0.5 0.5"; + + +function SSAOPostFx::onAdd( %this ) +{ + %this.wasVis = "Uninitialized"; + %this.quality = "Uninitialized"; +} + +function SSAOPostFx::preProcess( %this ) +{ + if ( $SSAOPostFx::quality !$= %this.quality ) + { + %this.quality = mClamp( mRound( $SSAOPostFx::quality ), 0, 2 ); + + %this.setShaderMacro( "QUALITY", %this.quality ); + } + + %this.targetScale = $SSAOPostFx::targetScale; +} + +function SSAOPostFx::setShaderConsts( %this ) +{ + %this.setShaderConst( "$overallStrength", $SSAOPostFx::overallStrength ); + + // Abbreviate is s-small l-large. + + %this.setShaderConst( "$sRadius", $SSAOPostFx::sRadius ); + %this.setShaderConst( "$sStrength", $SSAOPostFx::sStrength ); + %this.setShaderConst( "$sDepthMin", $SSAOPostFx::sDepthMin ); + %this.setShaderConst( "$sDepthMax", $SSAOPostFx::sDepthMax ); + %this.setShaderConst( "$sDepthPow", $SSAOPostFx::sDepthPow ); + %this.setShaderConst( "$sNormalTol", $SSAOPostFx::sNormalTol ); + %this.setShaderConst( "$sNormalPow", $SSAOPostFx::sNormalPow ); + + %this.setShaderConst( "$lRadius", $SSAOPostFx::lRadius ); + %this.setShaderConst( "$lStrength", $SSAOPostFx::lStrength ); + %this.setShaderConst( "$lDepthMin", $SSAOPostFx::lDepthMin ); + %this.setShaderConst( "$lDepthMax", $SSAOPostFx::lDepthMax ); + %this.setShaderConst( "$lDepthPow", $SSAOPostFx::lDepthPow ); + %this.setShaderConst( "$lNormalTol", $SSAOPostFx::lNormalTol ); + %this.setShaderConst( "$lNormalPow", $SSAOPostFx::lNormalPow ); + + %blur = %this->blurY; + %blur.setShaderConst( "$blurDepthTol", $SSAOPostFx::blurDepthTol ); + %blur.setShaderConst( "$blurNormalTol", $SSAOPostFx::blurNormalTol ); + + %blur = %this->blurX; + %blur.setShaderConst( "$blurDepthTol", $SSAOPostFx::blurDepthTol ); + %blur.setShaderConst( "$blurNormalTol", $SSAOPostFx::blurNormalTol ); + + %blur = %this->blurY2; + %blur.setShaderConst( "$blurDepthTol", $SSAOPostFx::blurDepthTol ); + %blur.setShaderConst( "$blurNormalTol", $SSAOPostFx::blurNormalTol ); + + %blur = %this->blurX2; + %blur.setShaderConst( "$blurDepthTol", $SSAOPostFx::blurDepthTol ); + %blur.setShaderConst( "$blurNormalTol", $SSAOPostFx::blurNormalTol ); +} + +function SSAOPostFx::onEnabled( %this ) +{ + // This tells the AL shaders to reload and sample + // from our #ssaoMask texture target. + $AL::UseSSAOMask = true; + + return true; +} + +function SSAOPostFx::onDisabled( %this ) +{ + $AL::UseSSAOMask = false; +} + + +//----------------------------------------------------------------------------- +// GFXStateBlockData / ShaderData +//----------------------------------------------------------------------------- + +singleton GFXStateBlockData( SSAOStateBlock : PFX_DefaultStateBlock ) +{ + samplersDefined = true; + samplerStates[0] = SamplerClampPoint; + samplerStates[1] = SamplerWrapLinear; + samplerStates[2] = SamplerClampPoint; +}; + +singleton GFXStateBlockData( SSAOBlurStateBlock : PFX_DefaultStateBlock ) +{ + samplersDefined = true; + samplerStates[0] = SamplerClampLinear; + samplerStates[1] = SamplerClampPoint; +}; + +singleton ShaderData( SSAOShader ) +{ + DXVertexShaderFile = $Core::CommonShaderPath @ "/postFX/postFxV.hlsl"; + DXPixelShaderFile = $Core::CommonShaderPath @ "/postFX/ssao/SSAO_P.hlsl"; + + OGLVertexShaderFile = $Core::CommonShaderPath @ "/postFX/gl/postFxV.glsl"; + OGLPixelShaderFile = $Core::CommonShaderPath @ "/postFX/ssao/gl/SSAO_P.glsl"; + + samplerNames[0] = "$deferredMap"; + samplerNames[1] = "$randNormalTex"; + samplerNames[2] = "$powTable"; + + pixVersion = 3.0; +}; + +singleton ShaderData( SSAOBlurYShader ) +{ + DXVertexShaderFile = $Core::CommonShaderPath @ "/postFX/ssao/SSAO_Blur_V.hlsl"; + DXPixelShaderFile = $Core::CommonShaderPath @ "/postFX/ssao/SSAO_Blur_P.hlsl"; + + OGLVertexShaderFile = $Core::CommonShaderPath @ "/postFX/ssao/gl/SSAO_Blur_V.glsl"; + OGLPixelShaderFile = $Core::CommonShaderPath @ "/postFX/ssao/gl/SSAO_Blur_P.glsl"; + + samplerNames[0] = "$occludeMap"; + samplerNames[1] = "$deferredMap"; + + pixVersion = 3.0; + + defines = "BLUR_DIR=float2(0.0,1.0)"; +}; + +singleton ShaderData( SSAOBlurXShader : SSAOBlurYShader ) +{ + defines = "BLUR_DIR=float2(1.0,0.0)"; +}; + +//----------------------------------------------------------------------------- +// PostEffects +//----------------------------------------------------------------------------- + +singleton PostEffect( SSAOPostFx ) +{ + allowReflectPass = false; + + renderTime = "PFXBeforeBin"; + renderBin = "AL_LightBinMgr"; + renderPriority = 10; + + shader = SSAOShader; + stateBlock = SSAOStateBlock; + + texture[0] = "#deferred"; + texture[1] = "core/postFX/images/noise.png"; + texture[2] = "#ssao_pow_table"; + + target = "$outTex"; + targetScale = "0.5 0.5"; + targetViewport = "PFXTargetViewport_NamedInTexture0"; + + singleton PostEffect() + { + internalName = "blurY"; + + shader = SSAOBlurYShader; + stateBlock = SSAOBlurStateBlock; + + texture[0] = "$inTex"; + texture[1] = "#deferred"; + + target = "$outTex"; + }; + + singleton PostEffect() + { + internalName = "blurX"; + + shader = SSAOBlurXShader; + stateBlock = SSAOBlurStateBlock; + + texture[0] = "$inTex"; + texture[1] = "#deferred"; + + target = "$outTex"; + }; + + singleton PostEffect() + { + internalName = "blurY2"; + + shader = SSAOBlurYShader; + stateBlock = SSAOBlurStateBlock; + + texture[0] = "$inTex"; + texture[1] = "#deferred"; + + target = "$outTex"; + }; + + singleton PostEffect() + { + internalName = "blurX2"; + + shader = SSAOBlurXShader; + stateBlock = SSAOBlurStateBlock; + + texture[0] = "$inTex"; + texture[1] = "#deferred"; + + // We write to a mask texture which is then + // read by the lighting shaders to mask ambient. + target = "#ssaoMask"; + }; +}; + + +/// Just here for debug visualization of the +/// SSAO mask texture used during lighting. +singleton PostEffect( SSAOVizPostFx ) +{ + allowReflectPass = false; + + shader = PFX_PassthruShader; + stateBlock = PFX_DefaultStateBlock; + + texture[0] = "#ssaoMask"; + + target = "$backbuffer"; +}; + +singleton ShaderData( SSAOPowTableShader ) +{ + DXVertexShaderFile = $Core::CommonShaderPath @ "/postFX/ssao/SSAO_PowerTable_V.hlsl"; + DXPixelShaderFile = $Core::CommonShaderPath @ "/postFX/ssao/SSAO_PowerTable_P.hlsl"; + + OGLVertexShaderFile = $Core::CommonShaderPath @ "/postFX/ssao/gl/SSAO_PowerTable_V.glsl"; + OGLPixelShaderFile = $Core::CommonShaderPath @ "/postFX/ssao/gl/SSAO_PowerTable_P.glsl"; + + pixVersion = 2.0; +}; + +singleton PostEffect( SSAOPowTablePostFx ) +{ + shader = SSAOPowTableShader; + stateBlock = PFX_DefaultStateBlock; + + renderTime = "PFXTexGenOnDemand"; + + target = "#ssao_pow_table"; + + targetFormat = "GFXFormatR16F"; + targetSize = "256 1"; +}; \ No newline at end of file diff --git a/Templates/BaseGame/game/core/postFX/scripts/turbulence.cs b/Templates/BaseGame/game/core/postFX/scripts/turbulence.cs new file mode 100644 index 000000000..967c3b2bf --- /dev/null +++ b/Templates/BaseGame/game/core/postFX/scripts/turbulence.cs @@ -0,0 +1,57 @@ +//----------------------------------------------------------------------------- +// 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. +//----------------------------------------------------------------------------- + +singleton GFXStateBlockData( PFX_TurbulenceStateBlock : PFX_DefaultStateBlock) +{ + zDefined = false; + zEnable = false; + zWriteEnable = false; + + samplersDefined = true; + samplerStates[0] = SamplerClampLinear; +}; + +singleton ShaderData( PFX_TurbulenceShader ) +{ + DXVertexShaderFile = $Core::CommonShaderPath @ "/postFX/postFxV.hlsl"; + DXPixelShaderFile = $Core::CommonShaderPath @ "/postFX/turbulenceP.hlsl"; + + OGLVertexShaderFile = $Core::CommonShaderPath @ "/postFX/gl/postFxV.glsl"; + OGLPixelShaderFile = $Core::CommonShaderPath @ "/postFX/gl/turbulenceP.glsl"; + + samplerNames[0] = "$inputTex"; + pixVersion = 3.0; +}; + +singleton PostEffect( TurbulenceFx ) +{ + isEnabled = false; + allowReflectPass = true; + + renderTime = "PFXAfterDiffuse"; + renderBin = "GlowBin"; + renderPriority = 0.5; // Render after the glows themselves + + shader = PFX_TurbulenceShader; + stateBlock=PFX_TurbulenceStateBlock; + texture[0] = "$backBuffer"; + }; diff --git a/Templates/BaseGame/game/core/postFX/scripts/vignette.cs b/Templates/BaseGame/game/core/postFX/scripts/vignette.cs new file mode 100644 index 000000000..d22f7d14a --- /dev/null +++ b/Templates/BaseGame/game/core/postFX/scripts/vignette.cs @@ -0,0 +1,55 @@ +//----------------------------------------------------------------------------- +// 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. +//----------------------------------------------------------------------------- + +$VignettePostEffect::VMax = 0.6; +$VignettePostEffect::VMin = 0.2; + +singleton ShaderData( VignetteShader ) +{ + DXVertexShaderFile = $Core::CommonShaderPath @ "/postFX/postFxV.hlsl"; + DXPixelShaderFile = $Core::CommonShaderPath @ "/postFX/vignette/VignetteP.hlsl"; + + OGLVertexShaderFile = $Core::CommonShaderPath @ "/postFX/gl/postFxV.glsl"; + OGLPixelShaderFile = $Core::CommonShaderPath @ "/postFX/vignette/gl/VignetteP.glsl"; + + samplerNames[0] = "$backBuffer"; + + pixVersion = 2.0; +}; + +singleton PostEffect( VignettePostEffect ) +{ + isEnabled = false; + allowReflectPass = false; + renderTime = "PFXAfterBin"; + renderBin = "GlowBin"; + shader = VignetteShader; + stateBlock = PFX_DefaultStateBlock; + texture[0] = "$backBuffer"; + renderPriority = 10; +}; + +function VignettePostEffect::setShaderConsts(%this) +{ + %this.setShaderConst("$Vmax", $VignettePostEffect::VMax); + %this.setShaderConst("$Vmin", $VignettePostEffect::VMin); +} \ No newline at end of file diff --git a/Templates/BaseGame/game/core/rendering/Core_Rendering.cs b/Templates/BaseGame/game/core/rendering/Core_Rendering.cs new file mode 100644 index 000000000..d09e0cbe3 --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/Core_Rendering.cs @@ -0,0 +1,20 @@ + +function Core_Rendering::onCreate(%this) +{ + $Core::MissingTexturePath = "core/rendering/images/missingTexture"; + $Core::UnAvailableTexturePath = "core/rendering/images/unavailable"; + $Core::WarningTexturePath = "core/rendering/images/warnMat"; + $Core::CommonShaderPath = "core/rendering/shaders"; + + exec("./scripts/renderManager.cs"); + exec("./scripts/gfxData/clouds.cs"); + exec("./scripts/gfxData/commonMaterialData.cs"); + exec("./scripts/gfxData/scatterSky.cs"); + exec("./scripts/gfxData/shaders.cs"); + exec("./scripts/gfxData/terrainBlock.cs"); + exec("./scripts/gfxData/water.cs"); +} + +function Core_Rendering::onDestroy(%this) +{ +} \ No newline at end of file diff --git a/Templates/BaseGame/game/core/rendering/Core_Rendering.module b/Templates/BaseGame/game/core/rendering/Core_Rendering.module new file mode 100644 index 000000000..9dbbfc33a --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/Core_Rendering.module @@ -0,0 +1,9 @@ + + \ No newline at end of file diff --git a/Templates/BaseGame/game/core/rendering/images/materials.cs b/Templates/BaseGame/game/core/rendering/images/materials.cs new file mode 100644 index 000000000..a13c751b3 --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/images/materials.cs @@ -0,0 +1,32 @@ +//----------------------------------------------------------------------------- +// 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. +//----------------------------------------------------------------------------- + +singleton Material( Empty ) +{ +}; + +singleton Material(WarningMaterial) { + detailMap[0] = "missingTexture"; + diffuseColor[0] = "25 16 0"; + emissive[0] = false; + translucent = false; +}; diff --git a/Templates/BaseGame/game/core/rendering/images/missingTexture.png b/Templates/BaseGame/game/core/rendering/images/missingTexture.png new file mode 100644 index 0000000000000000000000000000000000000000..80a7874da967ad523e1a3308f3f14c66d4eed503 GIT binary patch literal 10645 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 literal 0 HcmV?d00001 diff --git a/Templates/BaseGame/game/core/rendering/images/warnMat.dds b/Templates/BaseGame/game/core/rendering/images/warnMat.dds new file mode 100644 index 0000000000000000000000000000000000000000..ea99dcbd74a8b2ae49c5cff5a69743498a66e937 GIT binary patch literal 699192 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 literal 0 HcmV?d00001 diff --git a/Templates/BaseGame/game/core/rendering/scripts/gfxData/clouds.cs b/Templates/BaseGame/game/core/rendering/scripts/gfxData/clouds.cs new file mode 100644 index 000000000..00d56d6d3 --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/scripts/gfxData/clouds.cs @@ -0,0 +1,55 @@ +//----------------------------------------------------------------------------- +// 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. +//----------------------------------------------------------------------------- + +//------------------------------------------------------------------------------ +// CloudLayer +//------------------------------------------------------------------------------ + +singleton ShaderData( CloudLayerShader ) +{ + DXVertexShaderFile = $Core::CommonShaderPath @ "/cloudLayerV.hlsl"; + DXPixelShaderFile = $Core::CommonShaderPath @ "/cloudLayerP.hlsl"; + + OGLVertexShaderFile = $Core::CommonShaderPath @ "/gl/cloudLayerV.glsl"; + OGLPixelShaderFile = $Core::CommonShaderPath @ "/gl/cloudLayerP.glsl"; + + samplerNames[0] = "$normalHeightMap"; + + pixVersion = 2.0; +}; + +//------------------------------------------------------------------------------ +// BasicClouds +//------------------------------------------------------------------------------ + +singleton ShaderData( BasicCloudsShader ) +{ + DXVertexShaderFile = $Core::CommonShaderPath @ "/basicCloudsV.hlsl"; + DXPixelShaderFile = $Core::CommonShaderPath @ "/basicCloudsP.hlsl"; + + OGLVertexShaderFile = $Core::CommonShaderPath @ "/gl/basicCloudsV.glsl"; + OGLPixelShaderFile = $Core::CommonShaderPath @ "/gl/basicCloudsP.glsl"; + + samplerNames[0] = "$diffuseMap"; + + pixVersion = 2.0; +}; diff --git a/Templates/BaseGame/game/core/rendering/scripts/gfxData/commonMaterialData.cs b/Templates/BaseGame/game/core/rendering/scripts/gfxData/commonMaterialData.cs new file mode 100644 index 000000000..c5d8ef5bc --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/scripts/gfxData/commonMaterialData.cs @@ -0,0 +1,79 @@ +//----------------------------------------------------------------------------- +// 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. +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// Anim flag settings - must match material.h +// These cannot be enumed through script becuase it cannot +// handle the "|" operation for combining them together +// ie. Scroll | Wave does not work. +//----------------------------------------------------------------------------- +$scroll = 1; +$rotate = 2; +$wave = 4; +$scale = 8; +$sequence = 16; + + +// Common stateblock definitions +new GFXSamplerStateData(SamplerClampLinear) +{ + textureColorOp = GFXTOPModulate; + addressModeU = GFXAddressClamp; + addressModeV = GFXAddressClamp; + addressModeW = GFXAddressClamp; + magFilter = GFXTextureFilterLinear; + minFilter = GFXTextureFilterLinear; + mipFilter = GFXTextureFilterLinear; +}; + +new GFXSamplerStateData(SamplerClampPoint) +{ + textureColorOp = GFXTOPModulate; + addressModeU = GFXAddressClamp; + addressModeV = GFXAddressClamp; + addressModeW = GFXAddressClamp; + magFilter = GFXTextureFilterPoint; + minFilter = GFXTextureFilterPoint; + mipFilter = GFXTextureFilterPoint; +}; + +new GFXSamplerStateData(SamplerWrapLinear) +{ + textureColorOp = GFXTOPModulate; + addressModeU = GFXTextureAddressWrap; + addressModeV = GFXTextureAddressWrap; + addressModeW = GFXTextureAddressWrap; + magFilter = GFXTextureFilterLinear; + minFilter = GFXTextureFilterLinear; + mipFilter = GFXTextureFilterLinear; +}; + +new GFXSamplerStateData(SamplerWrapPoint) +{ + textureColorOp = GFXTOPModulate; + addressModeU = GFXTextureAddressWrap; + addressModeV = GFXTextureAddressWrap; + addressModeW = GFXTextureAddressWrap; + magFilter = GFXTextureFilterPoint; + minFilter = GFXTextureFilterPoint; + mipFilter = GFXTextureFilterPoint; +}; diff --git a/Templates/BaseGame/game/core/rendering/scripts/gfxData/scatterSky.cs b/Templates/BaseGame/game/core/rendering/scripts/gfxData/scatterSky.cs new file mode 100644 index 000000000..5add01d8b --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/scripts/gfxData/scatterSky.cs @@ -0,0 +1,48 @@ +//----------------------------------------------------------------------------- +// 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. +//----------------------------------------------------------------------------- + +new GFXStateBlockData( ScatterSkySBData ) +{ + cullMode = "GFXCullNone"; + + zDefined = true; + zEnable = true; + zWriteEnable = false; + + samplersDefined = true; + samplerStates[0] = SamplerClampLinear; + samplerStates[1] = SamplerClampLinear; + vertexColorEnable = true; +}; + +singleton ShaderData( ScatterSkyShaderData ) +{ + DXVertexShaderFile = $Core::CommonShaderPath @ "/scatterSkyV.hlsl"; + DXPixelShaderFile = $Core::CommonShaderPath @ "/scatterSkyP.hlsl"; + + OGLVertexShaderFile = $Core::CommonShaderPath @ "/gl/scatterSkyV.glsl"; + OGLPixelShaderFile = $Core::CommonShaderPath @ "/gl/scatterSkyP.glsl"; + + samplerNames[0] = "$nightSky"; + + pixVersion = 2.0; +}; diff --git a/Templates/BaseGame/game/core/rendering/scripts/gfxData/shaders.cs b/Templates/BaseGame/game/core/rendering/scripts/gfxData/shaders.cs new file mode 100644 index 000000000..da3b7c864 --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/scripts/gfxData/shaders.cs @@ -0,0 +1,152 @@ +//----------------------------------------------------------------------------- +// 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. +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// This file contains shader data necessary for various engine utility functions +//----------------------------------------------------------------------------- + + +singleton ShaderData( ParticlesShaderData ) +{ + DXVertexShaderFile = $Core::CommonShaderPath @ "/particlesV.hlsl"; + DXPixelShaderFile = $Core::CommonShaderPath @ "/particlesP.hlsl"; + + OGLVertexShaderFile = $Core::CommonShaderPath @ "/gl/particlesV.glsl"; + OGLPixelShaderFile = $Core::CommonShaderPath @ "/gl/particlesP.glsl"; + + samplerNames[0] = "$diffuseMap"; + samplerNames[1] = "$deferredTex"; + samplerNames[2] = "$paraboloidLightMap"; + + pixVersion = 2.0; +}; + +singleton ShaderData( OffscreenParticleCompositeShaderData ) +{ + DXVertexShaderFile = $Core::CommonShaderPath @ "/particleCompositeV.hlsl"; + DXPixelShaderFile = $Core::CommonShaderPath @ "/particleCompositeP.hlsl"; + + OGLVertexShaderFile = $Core::CommonShaderPath @ "/gl/particleCompositeV.glsl"; + OGLPixelShaderFile = $Core::CommonShaderPath @ "/gl/particleCompositeP.glsl"; + + samplerNames[0] = "$colorSource"; + samplerNames[1] = "$edgeSource"; + + pixVersion = 2.0; +}; + +//----------------------------------------------------------------------------- +// Planar Reflection +//----------------------------------------------------------------------------- +new ShaderData( ReflectBump ) +{ + DXVertexShaderFile = $Core::CommonShaderPath @ "/planarReflectBumpV.hlsl"; + DXPixelShaderFile = $Core::CommonShaderPath @ "/planarReflectBumpP.hlsl"; + + OGLVertexShaderFile = $Core::CommonShaderPath @ "/gl/planarReflectBumpV.glsl"; + OGLPixelShaderFile = $Core::CommonShaderPath @ "/gl/planarReflectBumpP.glsl"; + + samplerNames[0] = "$diffuseMap"; + samplerNames[1] = "$refractMap"; + samplerNames[2] = "$bumpMap"; + + pixVersion = 2.0; +}; + +new ShaderData( Reflect ) +{ + DXVertexShaderFile = $Core::CommonShaderPath @ "/planarReflectV.hlsl"; + DXPixelShaderFile = $Core::CommonShaderPath @ "/planarReflectP.hlsl"; + + OGLVertexShaderFile = $Core::CommonShaderPath @ "/gl/planarReflectV.glsl"; + OGLPixelShaderFile = $Core::CommonShaderPath @ "/gl/planarReflectP.glsl"; + + samplerNames[0] = "$diffuseMap"; + samplerNames[1] = "$refractMap"; + + pixVersion = 1.4; +}; + +//----------------------------------------------------------------------------- +// fxFoliageReplicator +//----------------------------------------------------------------------------- +new ShaderData( fxFoliageReplicatorShader ) +{ + DXVertexShaderFile = $Core::CommonShaderPath @ "/fxFoliageReplicatorV.hlsl"; + DXPixelShaderFile = $Core::CommonShaderPath @ "/fxFoliageReplicatorP.hlsl"; + + OGLVertexShaderFile = $Core::CommonShaderPath @ "/gl/fxFoliageReplicatorV.glsl"; + OGLPixelShaderFile = $Core::CommonShaderPath @ "/gl/fxFoliageReplicatorP.glsl"; + + samplerNames[0] = "$diffuseMap"; + samplerNames[1] = "$alphaMap"; + + pixVersion = 1.4; +}; + +singleton ShaderData( VolumetricFogDeferredShader ) +{ + DXVertexShaderFile = $Core::CommonShaderPath @ "/VolumetricFog/VFogPreV.hlsl"; + DXPixelShaderFile = $Core::CommonShaderPath @ "/VolumetricFog/VFogPreP.hlsl"; + + OGLVertexShaderFile = $Core::CommonShaderPath @ "/VolumetricFog/gl/VFogPreV.glsl"; + OGLPixelShaderFile = $Core::CommonShaderPath @ "/VolumetricFog/gl/VFogPreP.glsl"; + + pixVersion = 3.0; +}; +singleton ShaderData( VolumetricFogShader ) +{ + DXVertexShaderFile = $Core::CommonShaderPath @ "/VolumetricFog/VFogV.hlsl"; + DXPixelShaderFile = $Core::CommonShaderPath @ "/VolumetricFog/VFogP.hlsl"; + + OGLVertexShaderFile = $Core::CommonShaderPath @ "/VolumetricFog/gl/VFogV.glsl"; + OGLPixelShaderFile = $Core::CommonShaderPath @ "/VolumetricFog/gl/VFogP.glsl"; + + samplerNames[0] = "$deferredTex"; + samplerNames[1] = "$depthBuffer"; + samplerNames[2] = "$frontBuffer"; + samplerNames[3] = "$density"; + + pixVersion = 3.0; +}; +singleton ShaderData( VolumetricFogReflectionShader ) +{ + DXVertexShaderFile = $Core::CommonShaderPath @ "/VolumetricFog/VFogPreV.hlsl"; + DXPixelShaderFile = $Core::CommonShaderPath @ "/VolumetricFog/VFogRefl.hlsl"; + + OGLVertexShaderFile = $Core::CommonShaderPath @ "/VolumetricFog/gl/VFogPreV.glsl"; + OGLPixelShaderFile = $Core::CommonShaderPath @ "/VolumetricFog/gl/VFogRefl.glsl"; + + pixVersion = 3.0; +}; +singleton ShaderData( CubemapSaveShader ) +{ + DXVertexShaderFile = "shaders/common/cubemapSaveV.hlsl"; + DXPixelShaderFile = "shaders/common/cubemapSaveP.hlsl"; + + OGLVertexShaderFile = "shaders/common/gl/cubemapSaveV.glsl"; + OGLPixelShaderFile = "shaders/common/gl/cubemapSaveP.glsl"; + + samplerNames[0] = "$cubemapTex"; + + pixVersion = 3.0; +}; \ No newline at end of file diff --git a/Templates/BaseGame/game/core/rendering/scripts/gfxData/terrainBlock.cs b/Templates/BaseGame/game/core/rendering/scripts/gfxData/terrainBlock.cs new file mode 100644 index 000000000..69802b1da --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/scripts/gfxData/terrainBlock.cs @@ -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. +//----------------------------------------------------------------------------- + +/// Used when generating the blended base texture. +singleton ShaderData( TerrainBlendShader ) +{ + DXVertexShaderFile = $Core::CommonShaderPath @ "/terrain/blendV.hlsl"; + DXPixelShaderFile = $Core::CommonShaderPath @ "/terrain/blendP.hlsl"; + + OGLVertexShaderFile = $Core::CommonShaderPath @ "/terrain/gl/blendV.glsl"; + OGLPixelShaderFile = $Core::CommonShaderPath @ "/terrain/gl/blendP.glsl"; + + samplerNames[0] = "layerTex"; + samplerNames[1] = "textureMap"; + + pixVersion = 2.0; +}; diff --git a/Templates/BaseGame/game/core/rendering/scripts/gfxData/water.cs b/Templates/BaseGame/game/core/rendering/scripts/gfxData/water.cs new file mode 100644 index 000000000..ec5e4be71 --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/scripts/gfxData/water.cs @@ -0,0 +1,208 @@ +//----------------------------------------------------------------------------- +// 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. +//----------------------------------------------------------------------------- + + + +//----------------------------------------------------------------------------- +// Water +//----------------------------------------------------------------------------- + +singleton ShaderData( WaterShader ) +{ + DXVertexShaderFile = $Core::CommonShaderPath @ "/water/waterV.hlsl"; + DXPixelShaderFile = $Core::CommonShaderPath @ "/water/waterP.hlsl"; + + OGLVertexShaderFile = $Core::CommonShaderPath @ "/water/gl/waterV.glsl"; + OGLPixelShaderFile = $Core::CommonShaderPath @ "/water/gl/waterP.glsl"; + + samplerNames[0] = "$bumpMap"; // noise + samplerNames[1] = "$deferredTex"; // #deferred + samplerNames[2] = "$reflectMap"; // $reflectbuff + samplerNames[3] = "$refractBuff"; // $backbuff + samplerNames[4] = "$skyMap"; // $cubemap + samplerNames[5] = "$foamMap"; // foam + samplerNames[6] = "$depthGradMap"; // depthMap ( color gradient ) + + pixVersion = 3.0; +}; + +new GFXSamplerStateData(WaterSampler) +{ + textureColorOp = GFXTOPModulate; + addressModeU = GFXAddressWrap; + addressModeV = GFXAddressWrap; + addressModeW = GFXAddressWrap; + magFilter = GFXTextureFilterLinear; + minFilter = GFXTextureFilterAnisotropic; + mipFilter = GFXTextureFilterLinear; + maxAnisotropy = 4; +}; + +singleton GFXStateBlockData( WaterStateBlock ) +{ + samplersDefined = true; + samplerStates[0] = WaterSampler; // noise + samplerStates[1] = SamplerClampPoint; // #deferred + samplerStates[2] = SamplerClampLinear; // $reflectbuff + samplerStates[3] = SamplerClampPoint; // $backbuff + samplerStates[4] = SamplerWrapLinear; // $cubemap + samplerStates[5] = SamplerWrapLinear; // foam + samplerStates[6] = SamplerClampLinear; // depthMap ( color gradient ) + cullDefined = true; + cullMode = "GFXCullCCW"; +}; + +singleton GFXStateBlockData( UnderWaterStateBlock : WaterStateBlock ) +{ + cullMode = "GFXCullCW"; +}; + +singleton CustomMaterial( WaterMat ) +{ + sampler["deferredTex"] = "#deferred"; + sampler["reflectMap"] = "$reflectbuff"; + sampler["refractBuff"] = "$backbuff"; + // These samplers are set in code not here. + // This is to allow different WaterObject instances + // to use this same material but override these textures + // per instance. + //sampler["bumpMap"] = ""; + //sampler["skyMap"] = ""; + //sampler["foamMap"] = ""; + //sampler["depthGradMap"] = ""; + + shader = WaterShader; + stateBlock = WaterStateBlock; + version = 3.0; + + useAnisotropic[0] = true; +}; + +//----------------------------------------------------------------------------- +// Underwater +//----------------------------------------------------------------------------- + +singleton ShaderData( UnderWaterShader : WaterShader ) +{ + defines = "UNDERWATER"; +}; + +singleton CustomMaterial( UnderwaterMat ) +{ + // These samplers are set in code not here. + // This is to allow different WaterObject instances + // to use this same material but override these textures + // per instance. + //sampler["bumpMap"] = "core/art/water/noise02"; + //sampler["foamMap"] = "core/art/water/foam"; + + sampler["deferredTex"] = "#deferred"; + sampler["refractBuff"] = "$backbuff"; + + shader = UnderWaterShader; + stateBlock = UnderWaterStateBlock; + specular = "0.75 0.75 0.75 1.0"; + specularPower = 48.0; + version = 3.0; +}; + +//----------------------------------------------------------------------------- +// Basic Water +//----------------------------------------------------------------------------- + +singleton ShaderData( WaterBasicShader ) +{ + DXVertexShaderFile = $Core::CommonShaderPath @ "/water/waterBasicV.hlsl"; + DXPixelShaderFile = $Core::CommonShaderPath @ "/water/waterBasicP.hlsl"; + + OGLVertexShaderFile = $Core::CommonShaderPath @ "/water/gl/waterBasicV.glsl"; + OGLPixelShaderFile = $Core::CommonShaderPath @ "/water/gl/waterBasicP.glsl"; + + samplerNames[0] = "$bumpMap"; + samplerNames[2] = "$reflectMap"; + samplerNames[3] = "$refractBuff"; + samplerNames[4] = "$skyMap"; + samplerNames[5] = "$depthGradMap"; + + pixVersion = 2.0; +}; + +singleton GFXStateBlockData( WaterBasicStateBlock ) +{ + samplersDefined = true; + samplerStates[0] = WaterSampler; // noise + samplerStates[2] = SamplerClampLinear; // $reflectbuff + samplerStates[3] = SamplerClampPoint; // $backbuff + samplerStates[4] = SamplerWrapLinear; // $cubemap + cullDefined = true; + cullMode = "GFXCullCCW"; +}; + +singleton GFXStateBlockData( UnderWaterBasicStateBlock : WaterBasicStateBlock ) +{ + cullMode = "GFXCullCW"; +}; + +singleton CustomMaterial( WaterBasicMat ) +{ + // These samplers are set in code not here. + // This is to allow different WaterObject instances + // to use this same material but override these textures + // per instance. + //sampler["bumpMap"] = "core/art/water/noise02"; + //sampler["skyMap"] = "$cubemap"; + + //sampler["deferredTex"] = "#deferred"; + sampler["reflectMap"] = "$reflectbuff"; + sampler["refractBuff"] = "$backbuff"; + + cubemap = NewLevelSkyCubemap; + shader = WaterBasicShader; + stateBlock = WaterBasicStateBlock; + version = 2.0; +}; + +//----------------------------------------------------------------------------- +// Basic UnderWater +//----------------------------------------------------------------------------- + +singleton ShaderData( UnderWaterBasicShader : WaterBasicShader) +{ + defines = "UNDERWATER"; +}; + +singleton CustomMaterial( UnderwaterBasicMat ) +{ + // These samplers are set in code not here. + // This is to allow different WaterObject instances + // to use this same material but override these textures + // per instance. + //sampler["bumpMap"] = "core/art/water/noise02"; + //samplers["skyMap"] = "$cubemap"; + + //sampler["deferredTex"] = "#deferred"; + sampler["refractBuff"] = "$backbuff"; + + shader = UnderWaterBasicShader; + stateBlock = UnderWaterBasicStateBlock; + version = 2.0; +}; \ No newline at end of file diff --git a/Templates/BaseGame/game/core/rendering/scripts/gfxprofile/D3D9.ATITechnologiesInc.cs b/Templates/BaseGame/game/core/rendering/scripts/gfxprofile/D3D9.ATITechnologiesInc.cs new file mode 100644 index 000000000..10c6bdf5b --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/scripts/gfxprofile/D3D9.ATITechnologiesInc.cs @@ -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. +//----------------------------------------------------------------------------- + +// ATI Vendor Profile Script +// +// This script is responsible for setting global +// capability strings based on the nVidia vendor. + +if(GFXCardProfiler::getVersion() < 64.44) +{ + $GFX::OutdatedDrivers = true; + $GFX::OutdatedDriversLink = "You can get newer drivers here.."; +} +else +{ + $GFX::OutdatedDrivers = false; +} diff --git a/Templates/BaseGame/game/core/rendering/scripts/gfxprofile/D3D9.NVIDIA.GeForce8600.cs b/Templates/BaseGame/game/core/rendering/scripts/gfxprofile/D3D9.NVIDIA.GeForce8600.cs new file mode 100644 index 000000000..328788dac --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/scripts/gfxprofile/D3D9.NVIDIA.GeForce8600.cs @@ -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. +//----------------------------------------------------------------------------- + +// nVidia Vendor Profile Script +// +// This script is responsible for setting global +// capability strings based on the nVidia vendor. + +if(GFXCardProfiler::getVersion() < 1.2) +{ + $GFX::OutdatedDrivers = true; + $GFX::OutdatedDriversLink = "You can get newer drivers here.."; +} +else +{ + $GFX::OutdatedDrivers = false; +} diff --git a/Templates/BaseGame/game/core/rendering/scripts/gfxprofile/D3D9.NVIDIA.QuadroFXGo1000.cs b/Templates/BaseGame/game/core/rendering/scripts/gfxprofile/D3D9.NVIDIA.QuadroFXGo1000.cs new file mode 100644 index 000000000..5681b2f6d --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/scripts/gfxprofile/D3D9.NVIDIA.QuadroFXGo1000.cs @@ -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. +//----------------------------------------------------------------------------- + +// nVidia Vendor Profile Script +// +// This script is responsible for setting global +// capability strings based on the nVidia vendor. + +if(GFXCardProfiler::getVersion() < 53.82) +{ + $GFX::OutdatedDrivers = true; + $GFX::OutdatedDriversLink = "You can get newer drivers here.."; +} +else +{ + $GFX::OutdatedDrivers = false; +} + +// Silly card has trouble with this! +GFXCardProfiler::setCapability("autoMipmapLevel", false); diff --git a/Templates/BaseGame/game/core/rendering/scripts/gfxprofile/D3D9.NVIDIA.cs b/Templates/BaseGame/game/core/rendering/scripts/gfxprofile/D3D9.NVIDIA.cs new file mode 100644 index 000000000..b33b8d5d3 --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/scripts/gfxprofile/D3D9.NVIDIA.cs @@ -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. +//----------------------------------------------------------------------------- + +// nVidia Vendor Profile Script +// +// This script is responsible for setting global +// capability strings based on the nVidia vendor. + +if(GFXCardProfiler::getVersion() < 56.72) +{ + $GFX::OutdatedDrivers = true; + $GFX::OutdatedDriversLink = "You can get newer drivers here.."; +} +else +{ + $GFX::OutdatedDrivers = false; +} diff --git a/Templates/BaseGame/game/core/rendering/scripts/gfxprofile/D3D9.cs b/Templates/BaseGame/game/core/rendering/scripts/gfxprofile/D3D9.cs new file mode 100644 index 000000000..e1e299341 --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/scripts/gfxprofile/D3D9.cs @@ -0,0 +1,26 @@ +//----------------------------------------------------------------------------- +// 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. +//----------------------------------------------------------------------------- + +// Direct3D 9 Renderer Profile Script +// +// This script is responsible for setting global +// capability strings based on the D3D9 renderer type. \ No newline at end of file diff --git a/Templates/BaseGame/game/core/rendering/scripts/renderManager.cs b/Templates/BaseGame/game/core/rendering/scripts/renderManager.cs new file mode 100644 index 000000000..4a80a45b1 --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/scripts/renderManager.cs @@ -0,0 +1,126 @@ +//----------------------------------------------------------------------------- +// 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 initRenderManager() +{ + assert( !isObject( DiffuseRenderPassManager ), "initRenderManager() - DiffuseRenderPassManager already initialized!" ); + + new RenderPassManager( DiffuseRenderPassManager ); + + // This token, and the associated render managers, ensure that driver MSAA + // does not get used for Advanced Lighting renders. The 'AL_FormatResolve' + // PostEffect copies the result to the backbuffer. + new RenderFormatToken(AL_FormatToken) + { + enabled = "false"; + + //When hdr is enabled this will be changed to the appropriate format + format = "GFXFormatR8G8B8A8_SRGB"; + depthFormat = "GFXFormatD24S8"; + aaLevel = 0; // -1 = match backbuffer + + // The contents of the back buffer before this format token is executed + // is provided in $inTex + copyEffect = "AL_FormatCopy"; + + // The contents of the render target created by this format token is + // provided in $inTex + resolveEffect = "AL_FormatCopy"; + }; + DiffuseRenderPassManager.addManager( new RenderPassStateBin() { renderOrder = 0.001; stateToken = AL_FormatToken; } ); + + // We really need to fix the sky to render after all the + // meshes... but that causes issues in reflections. + 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(BeginBin) { bintype = "Begin"; renderOrder = 0.2; processAddOrder = 0.2; } ); + // Normal mesh rendering. + DiffuseRenderPassManager.addManager( new RenderTerrainMgr(TerrainBin) { renderOrder = 0.4; processAddOrder = 0.4; basicOnly = true; } ); + DiffuseRenderPassManager.addManager( new RenderMeshMgr(MeshBin) { bintype = "Mesh"; renderOrder = 0.5; processAddOrder = 0.5; basicOnly = true; } ); + 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. + + // 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(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; } ); + + 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; } ); + + // We render any editor stuff from this bin. Note that the HDR is + // completed before this bin to keep editor elements from tone mapping. + DiffuseRenderPassManager.addManager( new RenderObjectMgr(EditorBin) { bintype = "Editor"; renderOrder = 1.6; processAddOrder = 1.6; } ); + + // Resolve format change token last. + DiffuseRenderPassManager.addManager( new RenderPassStateBin(FinalBin) { renderOrder = 1.7; stateToken = AL_FormatToken; } ); +} + +/// This is the Default PostFX state block. Put here to prevent any missing object +/// errors for below dependencies +singleton GFXStateBlockData( PFX_DefaultStateBlock ) +{ + zDefined = true; + zEnable = false; + zWriteEnable = false; + + samplersDefined = true; + samplerStates[0] = SamplerClampLinear; +}; + +/// This post effect is used to copy data from the non-MSAA back-buffer to the +/// device back buffer (which could be MSAA). It must be declared here so that +/// it is initialized when 'AL_FormatToken' is initialzed. +singleton GFXStateBlockData( AL_FormatTokenState : PFX_DefaultStateBlock ) +{ + samplersDefined = true; + samplerStates[0] = SamplerClampPoint; +}; + +singleton PostEffect( AL_FormatCopy ) +{ + // This PostEffect is used by 'AL_FormatToken' directly. It is never added to + // the PostEffectManager. Do not call enable() on it. + isEnabled = false; + allowReflectPass = true; + + shader = PFX_PassthruShader; + stateBlock = AL_FormatTokenState; + + texture[0] = "$inTex"; + target = "$backbuffer"; +}; diff --git a/Templates/BaseGame/game/core/rendering/shaders/VolumetricFog/VFogP.hlsl b/Templates/BaseGame/game/core/rendering/shaders/VolumetricFog/VFogP.hlsl new file mode 100644 index 000000000..7de14a87d --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/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 "../shaderModel.hlsl" +#include "../shaderModelAutoGen.hlsl" +#include "../torque.hlsl" + +TORQUE_UNIFORM_SAMPLER2D(deferredTex, 0); +TORQUE_UNIFORM_SAMPLER2D(depthBuffer, 1); +TORQUE_UNIFORM_SAMPLER2D(frontBuffer, 2); +TORQUE_UNIFORM_SAMPLER2D(density, 3); + +uniform float3 ambientColor; +uniform float accumTime; +uniform float4 fogColor; +uniform float4 modspeed;//xy speed layer 1, zw speed layer 2 +uniform float2 viewpoint; +uniform float2 texscale; +uniform float fogDensity; +uniform float preBias; +uniform float textured; +uniform float modstrength; +uniform float numtiles; +uniform float fadesize; +uniform float2 PixelSize; + +struct ConnectData +{ + float4 hpos : TORQUE_POSITION; + float4 htpos : TEXCOORD0; + float2 uv0 : TEXCOORD1; +}; + +float4 main( ConnectData IN ) : TORQUE_TARGET0 +{ + float2 uvscreen=((IN.htpos.xy/IN.htpos.w) + 1.0 ) / 2.0; + uvscreen.y = 1.0 - uvscreen.y; + + float obj_test = TORQUE_DEFERRED_UNCONDITION(deferredTex, uvscreen).w * preBias; + float depth = TORQUE_TEX2D(depthBuffer, uvscreen).r; + float front = TORQUE_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 = TORQUE_TEX2D(density, (offset + (modspeed.xy*accumTime))).rg; + float2 mod2 = TORQUE_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/BaseGame/game/core/rendering/shaders/VolumetricFog/VFogPreP.hlsl b/Templates/BaseGame/game/core/rendering/shaders/VolumetricFog/VFogPreP.hlsl new file mode 100644 index 000000000..9d5060935 --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/VolumetricFog/VFogPreP.hlsl @@ -0,0 +1,40 @@ +//----------------------------------------------------------------------------- +// 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 deferred pixel shader V1.00 +#include "../shaderModel.hlsl" + +struct ConnectData +{ + float4 hpos : TORQUE_POSITION; + float4 pos : TEXCOORD0; +}; + +float4 main( ConnectData IN ) : TORQUE_TARGET0 +{ + float OUT; + + clip( IN.pos.w ); + OUT = IN.pos.w; + + return float4(OUT,0,0,1); +} diff --git a/Templates/BaseGame/game/core/rendering/shaders/VolumetricFog/VFogPreV.hlsl b/Templates/BaseGame/game/core/rendering/shaders/VolumetricFog/VFogPreV.hlsl new file mode 100644 index 000000000..b736e0d0d --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/VolumetricFog/VFogPreV.hlsl @@ -0,0 +1,44 @@ +//----------------------------------------------------------------------------- +// 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 deferred vertex shader V1.00 + +#include "../shaderModel.hlsl" +#include "../hlslStructs.hlsl" + +struct ConnectData +{ + float4 hpos : TORQUE_POSITION; + float4 pos : TEXCOORD0; +}; + +uniform float4x4 modelView; + +ConnectData main( VertexIn_P IN) +{ + ConnectData OUT; + + OUT.hpos = mul(modelView, float4(IN.pos, 1.0)); + OUT.pos = OUT.hpos; + + return OUT; +} diff --git a/Templates/BaseGame/game/core/rendering/shaders/VolumetricFog/VFogRefl.hlsl b/Templates/BaseGame/game/core/rendering/shaders/VolumetricFog/VFogRefl.hlsl new file mode 100644 index 000000000..380233b5f --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/VolumetricFog/VFogRefl.hlsl @@ -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. +//----------------------------------------------------------------------------- + +// Volumetric Fog Reflection pixel shader V1.00 +#include "../shaderModel.hlsl" +uniform float4 fogColor; +uniform float fogDensity; +uniform float reflStrength; + +struct ConnectData +{ + float4 hpos : TORQUE_POSITION; + float4 pos : TEXCOORD0; +}; + +float4 main( ConnectData IN ) : TORQUE_TARGET0 +{ + return float4(fogColor.rgb,saturate(fogDensity*reflStrength)); +} diff --git a/Templates/BaseGame/game/core/rendering/shaders/VolumetricFog/VFogV.hlsl b/Templates/BaseGame/game/core/rendering/shaders/VolumetricFog/VFogV.hlsl new file mode 100644 index 000000000..167f83946 --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/VolumetricFog/VFogV.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 final vertex shader V1.00 + +#include "../shaderModel.hlsl" +#include "../hlslStructs.hlsl" + +struct ConnectData +{ + float4 hpos : TORQUE_POSITION; + float4 htpos : TEXCOORD0; + float2 uv0 : TEXCOORD1; +}; + +uniform float4x4 modelView; + +ConnectData main( VertexIn_PNTT IN) +{ + ConnectData OUT; + + OUT.hpos = mul(modelView, float4(IN.pos,1.0)); + OUT.htpos = OUT.hpos; + OUT.uv0 = IN.uv0; + + return OUT; +} diff --git a/Templates/BaseGame/game/core/rendering/shaders/VolumetricFog/gl/VFogP.glsl b/Templates/BaseGame/game/core/rendering/shaders/VolumetricFog/gl/VFogP.glsl new file mode 100644 index 000000000..fcfa31244 --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/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 deferredTex; +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 = deferredUncondition( deferredTex, 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/BaseGame/game/core/rendering/shaders/VolumetricFog/gl/VFogPreP.glsl b/Templates/BaseGame/game/core/rendering/shaders/VolumetricFog/gl/VFogPreP.glsl new file mode 100644 index 000000000..017ea6ef8 --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/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/BaseGame/game/core/rendering/shaders/VolumetricFog/gl/VFogPreV.glsl b/Templates/BaseGame/game/core/rendering/shaders/VolumetricFog/gl/VFogPreV.glsl new file mode 100644 index 000000000..2f2a1318a --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/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/BaseGame/game/core/rendering/shaders/VolumetricFog/gl/VFogRefl.glsl b/Templates/BaseGame/game/core/rendering/shaders/VolumetricFog/gl/VFogRefl.glsl new file mode 100644 index 000000000..78e149fbf --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/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/BaseGame/game/core/rendering/shaders/VolumetricFog/gl/VFogV.glsl b/Templates/BaseGame/game/core/rendering/shaders/VolumetricFog/gl/VFogV.glsl new file mode 100644 index 000000000..57b3ba87e --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/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/BaseGame/game/core/rendering/shaders/basicCloudsP.hlsl b/Templates/BaseGame/game/core/rendering/shaders/basicCloudsP.hlsl new file mode 100644 index 000000000..4b40e5e8c --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/basicCloudsP.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. +//----------------------------------------------------------------------------- + +#include "torque.hlsl" + +struct ConnectData +{ + float4 hpos : TORQUE_POSITION; + float2 texCoord : TEXCOORD0; +}; + +TORQUE_UNIFORM_SAMPLER2D(diffuseMap, 0); + +float4 main( ConnectData IN ) : TORQUE_TARGET0 +{ + float4 col = TORQUE_TEX2D(diffuseMap, IN.texCoord); + return hdrEncode( col ); +} \ No newline at end of file diff --git a/Templates/BaseGame/game/core/rendering/shaders/basicCloudsV.hlsl b/Templates/BaseGame/game/core/rendering/shaders/basicCloudsV.hlsl new file mode 100644 index 000000000..a176fdbcd --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/basicCloudsV.hlsl @@ -0,0 +1,58 @@ +//----------------------------------------------------------------------------- +// 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 "shaderModel.hlsl" + +struct CloudVert +{ + float3 pos : POSITION; + float2 uv0 : TEXCOORD0; +}; + +struct ConnectData +{ + float4 hpos : TORQUE_POSITION; + float2 texCoord : TEXCOORD0; +}; + +uniform float4x4 modelview; +uniform float2 texDirection; +uniform float2 texOffset; +uniform float accumTime; +uniform float texScale; + + +ConnectData main( CloudVert IN ) +{ + ConnectData OUT; + + OUT.hpos = mul(modelview, float4(IN.pos,1.0)); + + float2 uv = IN.uv0; + uv += texOffset; + uv *= texScale; + uv += accumTime * texDirection; + + OUT.texCoord = uv; + + return OUT; +} \ No newline at end of file diff --git a/Templates/BaseGame/game/core/rendering/shaders/cloudLayerP.hlsl b/Templates/BaseGame/game/core/rendering/shaders/cloudLayerP.hlsl new file mode 100644 index 000000000..efa8fe0b4 --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/cloudLayerP.hlsl @@ -0,0 +1,146 @@ +//----------------------------------------------------------------------------- +// 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 "shaderModel.hlsl" +#include "torque.hlsl" + +//----------------------------------------------------------------------------- +// Structures +//----------------------------------------------------------------------------- +struct ConnectData +{ + float4 hpos : TORQUE_POSITION; + float4 texCoord12 : TEXCOORD0; + float4 texCoord34 : TEXCOORD1; + float3 vLightTS : TEXCOORD2; // light vector in tangent space, denormalized + float3 vViewTS : TEXCOORD3; // view vector in tangent space, denormalized + float worldDist : TEXCOORD4; +}; + +//----------------------------------------------------------------------------- +// Uniforms +//----------------------------------------------------------------------------- +TORQUE_UNIFORM_SAMPLER2D(normalHeightMap, 0); +uniform float3 ambientColor; +uniform float3 sunColor; +uniform float cloudCoverage; +uniform float3 cloudBaseColor; +uniform float cloudExposure; + +//----------------------------------------------------------------------------- +// Globals +//----------------------------------------------------------------------------- +// The per-color weighting to be used for luminance calculations in RGB order. +static const float3 LUMINANCE_VECTOR = float3(0.2125f, 0.7154f, 0.0721f); + + +//----------------------------------------------------------------------------- +// Functions +//----------------------------------------------------------------------------- + +// Calculates the Rayleigh phase function +float getRayleighPhase( float angle ) +{ + return 0.75 * ( 1.0 + pow( angle, 2 ) ); +} + +// Returns the output rgb color given a texCoord and parameters it uses +// for lighting calculation. +float3 ComputeIllumination( float2 texCoord, + float3 vLightTS, + float3 vViewTS, + float3 vNormalTS ) +{ + //return noiseNormal; + //return vNormalTS; + + float3 vLightTSAdj = float3( -vLightTS.x, -vLightTS.y, vLightTS.z ); + + float dp = dot( vNormalTS, vLightTSAdj ); + + // Calculate the amount of illumination (lightTerm)... + + // We do both a rim lighting effect and a halfLambertian lighting effect + // and combine the result. + float halfLambertTerm = saturate( pow( dp * 0.5 + 0.5, 1 ) ); + float rimLightTerm = pow( ( 1.0 - dp ), 1.0 ); + float lightTerm = saturate( halfLambertTerm * 1.0 + rimLightTerm * dp ); + lightTerm *= 0.5; + + // Use a simple RayleighPhase function to simulate single scattering towards + // the camera. + float angle = dot( vLightTS, vViewTS ); + lightTerm *= getRayleighPhase( angle ); + + // Combine terms and colors into the output color. + //float3 lightColor = ( lightTerm * sunColor * fOcclusionShadow ) + ambientColor; + float3 lightColor = lerp( ambientColor, sunColor, lightTerm ); + //lightColor = lerp( lightColor, ambientColor, cloudCoverage ); + float3 finalColor = cloudBaseColor * lightColor; + + return finalColor; +} + +float4 main( ConnectData IN ) : TORQUE_TARGET0 +{ + // Normalize the interpolated vectors: + float3 vViewTS = normalize( IN.vViewTS ); + float3 vLightTS = normalize( IN.vLightTS ); + + float4 cResultColor = float4( 0, 0, 0, 1 ); + + float2 texSample = IN.texCoord12.xy; + + float4 noise1 = TORQUE_TEX2D( normalHeightMap, IN.texCoord12.zw ); + noise1 = normalize( ( noise1 - 0.5 ) * 2.0 ); + //return noise1; + + float4 noise2 = TORQUE_TEX2D(normalHeightMap, IN.texCoord34.xy); + noise2 = normalize( ( noise2 - 0.5 ) * 2.0 ); + //return noise2; + + float3 noiseNormal = normalize( noise1 + noise2 ).xyz; + //return float4( noiseNormal, 1.0 ); + + float noiseHeight = noise1.a * noise2.a * ( cloudCoverage / 2.0 + 0.5 ); + + float3 vNormalTS = normalize( TORQUE_TEX2D(normalHeightMap, texSample).xyz * 2.0 - 1.0); + vNormalTS += noiseNormal; + vNormalTS = normalize( vNormalTS ); + + // Compute resulting color for the pixel: + cResultColor.rgb = ComputeIllumination( texSample, vLightTS, vViewTS, vNormalTS ); + + float coverage = ( cloudCoverage - 0.5 ) * 2.0; + cResultColor.a = TORQUE_TEX2D(normalHeightMap, texSample).a + coverage + noiseHeight; + + if ( cloudCoverage > -1.0 ) + cResultColor.a /= 1.0 + coverage; + + cResultColor.a = saturate( cResultColor.a * pow( saturate(cloudCoverage), 0.25 ) ); + + cResultColor.a = lerp( cResultColor.a, 0.0, 1.0 - pow(IN.worldDist,2.0) ); + + cResultColor.rgb *= cloudExposure; + + return hdrEncode( cResultColor ); +} diff --git a/Templates/BaseGame/game/core/rendering/shaders/cloudLayerV.hlsl b/Templates/BaseGame/game/core/rendering/shaders/cloudLayerV.hlsl new file mode 100644 index 000000000..d60dd251d --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/cloudLayerV.hlsl @@ -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. +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// Structures +//----------------------------------------------------------------------------- +#include "shaderModel.hlsl" + +struct CloudVert +{ + float3 pos : POSITION; + float3 normal : NORMAL; + float3 binormal : BINORMAL; + float3 tangent : TANGENT; + float2 uv0 : TEXCOORD0; +}; + +struct ConnectData +{ + float4 hpos : TORQUE_POSITION; + float4 texCoord12 : TEXCOORD0; + float4 texCoord34 : TEXCOORD1; + float3 vLightTS : TEXCOORD2; // light vector in tangent space, denormalized + float3 vViewTS : TEXCOORD3; // view vector in tangent space, denormalized + float worldDist : TEXCOORD4; +}; + +//----------------------------------------------------------------------------- +// Uniforms +//----------------------------------------------------------------------------- +uniform float4x4 modelview; +uniform float3 eyePosWorld; +uniform float3 sunVec; +uniform float2 texOffset0; +uniform float2 texOffset1; +uniform float2 texOffset2; +uniform float3 texScale; + +//----------------------------------------------------------------------------- +// Main +//----------------------------------------------------------------------------- +ConnectData main( CloudVert IN ) +{ + ConnectData OUT; + + OUT.hpos = mul(modelview, float4(IN.pos,1.0)); + // Offset the uv so we don't have a seam directly over our head. + float2 uv = IN.uv0 + float2( 0.5, 0.5 ); + + OUT.texCoord12.xy = uv * texScale.x; + OUT.texCoord12.xy += texOffset0; + + OUT.texCoord12.zw = uv * texScale.y; + OUT.texCoord12.zw += texOffset1; + + OUT.texCoord34.xy = uv * texScale.z; + OUT.texCoord34.xy += texOffset2; + + OUT.texCoord34.z = IN.pos.z; + OUT.texCoord34.w = 0.0; + + // Transform the normal, tangent and binormal vectors from object space to + // homogeneous projection space: + float3 vNormalWS = -IN.normal; + float3 vTangentWS = -IN.tangent; + float3 vBinormalWS = -IN.binormal; + + // Compute position in world space: + float4 vPositionWS = float4(IN.pos, 1.0) + float4(eyePosWorld, 1); //mul( IN.pos, objTrans ); + + // Compute and output the world view vector (unnormalized): + float3 vViewWS = eyePosWorld - vPositionWS.xyz; + + // Compute denormalized light vector in world space: + float3 vLightWS = -sunVec; + + // Normalize the light and view vectors and transform it to the tangent space: + float3x3 mWorldToTangent = float3x3( vTangentWS, vBinormalWS, vNormalWS ); + + // Propagate the view and the light vectors (in tangent space): + OUT.vLightTS = mul( vLightWS, mWorldToTangent ); + OUT.vViewTS = mul( mWorldToTangent, vViewWS ); + + OUT.worldDist = saturate( pow( max( IN.pos.z, 0 ), 2 ) ); + + return OUT; +} diff --git a/Templates/BaseGame/game/core/rendering/shaders/fixedFunction/addColorTextureP.hlsl b/Templates/BaseGame/game/core/rendering/shaders/fixedFunction/addColorTextureP.hlsl new file mode 100644 index 000000000..d0577428f --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/fixedFunction/addColorTextureP.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. +//----------------------------------------------------------------------------- + +#include "../shaderModel.hlsl" + +struct Conn +{ + float4 HPOS : TORQUE_POSITION; + float4 color : COLOR; + float2 texCoord : TEXCOORD0; +}; + +TORQUE_UNIFORM_SAMPLER2D(diffuseMap, 0); + +float4 main( Conn IN ) : TORQUE_TARGET0 +{ + return float4(IN.color.rgb, IN.color.a * TORQUE_TEX2D(diffuseMap, IN.texCoord).a); +} \ No newline at end of file diff --git a/Templates/BaseGame/game/core/rendering/shaders/fixedFunction/addColorTextureV.hlsl b/Templates/BaseGame/game/core/rendering/shaders/fixedFunction/addColorTextureV.hlsl new file mode 100644 index 000000000..8bf4e88d8 --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/fixedFunction/addColorTextureV.hlsl @@ -0,0 +1,48 @@ +//----------------------------------------------------------------------------- +// 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 "../shaderModel.hlsl" + +struct Appdata +{ + float3 position : POSITION; + float4 color : COLOR; + float2 texCoord : TEXCOORD0; +}; + +struct Conn +{ + float4 HPOS : TORQUE_POSITION; + float4 color : COLOR; + float2 texCoord : TEXCOORD0; +}; + +uniform float4x4 modelview; + +Conn main( Appdata In ) +{ + Conn Out; + Out.HPOS = mul(modelview, float4(In.position,1.0)); + Out.color = In.color; + Out.texCoord = In.texCoord; + return Out; +} \ No newline at end of file diff --git a/Templates/BaseGame/game/core/rendering/shaders/fixedFunction/colorP.hlsl b/Templates/BaseGame/game/core/rendering/shaders/fixedFunction/colorP.hlsl new file mode 100644 index 000000000..dd9990e07 --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/fixedFunction/colorP.hlsl @@ -0,0 +1,34 @@ +//----------------------------------------------------------------------------- +// 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 "../shaderModel.hlsl" + +struct Conn +{ + float4 HPOS : TORQUE_POSITION; + float4 color : COLOR; +}; + +float4 main(Conn IN) : TORQUE_TARGET0 +{ + return IN.color; +} \ No newline at end of file diff --git a/Templates/BaseGame/game/core/rendering/shaders/fixedFunction/colorV.hlsl b/Templates/BaseGame/game/core/rendering/shaders/fixedFunction/colorV.hlsl new file mode 100644 index 000000000..d16dfb863 --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/fixedFunction/colorV.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. +//----------------------------------------------------------------------------- + +#include "../shaderModel.hlsl" + +struct Appdata +{ + float3 position : POSITION; + float4 color : COLOR; +}; + +struct Conn +{ + float4 HPOS : TORQUE_POSITION; + float4 color : COLOR; +}; + +uniform float4x4 modelview; + +Conn main( Appdata In ) +{ + Conn Out; + Out.HPOS = mul(modelview, float4(In.position,1.0)); + Out.color = In.color; + return Out; +} \ No newline at end of file diff --git a/Templates/BaseGame/game/core/rendering/shaders/fixedFunction/gl/addColorTextureP.glsl b/Templates/BaseGame/game/core/rendering/shaders/fixedFunction/gl/addColorTextureP.glsl new file mode 100644 index 000000000..b9a10adf3 --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/fixedFunction/gl/addColorTextureP.glsl @@ -0,0 +1,32 @@ +//----------------------------------------------------------------------------- +// 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 sampler2D diffuseMap; +in vec4 color; +in vec2 texCoord; + +out vec4 OUT_col; + +void main() +{ + OUT_col = vec4(color.rgb, color.a * texture(diffuseMap, texCoord).a); +} \ No newline at end of file diff --git a/Templates/BaseGame/game/core/rendering/shaders/fixedFunction/gl/addColorTextureV.glsl b/Templates/BaseGame/game/core/rendering/shaders/fixedFunction/gl/addColorTextureV.glsl new file mode 100644 index 000000000..5d7f10168 --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/fixedFunction/gl/addColorTextureV.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; +in vec4 vColor; +in vec2 vTexCoord0; + +uniform mat4 modelview; +out vec4 color; +out vec2 texCoord; + +void main() +{ + gl_Position = tMul(modelview, vPosition); + correctSSP(gl_Position); + color = vColor; + texCoord = vTexCoord0.st; +} \ No newline at end of file diff --git a/Templates/BaseGame/game/core/rendering/shaders/fixedFunction/gl/colorP.glsl b/Templates/BaseGame/game/core/rendering/shaders/fixedFunction/gl/colorP.glsl new file mode 100644 index 000000000..f9dfc3d4f --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/fixedFunction/gl/colorP.glsl @@ -0,0 +1,30 @@ +//----------------------------------------------------------------------------- +// 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. +//----------------------------------------------------------------------------- + +in vec4 color; + +out vec4 OUT_col; + +void main() +{ + OUT_col = color; +} \ No newline at end of file diff --git a/Templates/BaseGame/game/core/rendering/shaders/fixedFunction/gl/colorV.glsl b/Templates/BaseGame/game/core/rendering/shaders/fixedFunction/gl/colorV.glsl new file mode 100644 index 000000000..895917b55 --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/fixedFunction/gl/colorV.glsl @@ -0,0 +1,35 @@ +//----------------------------------------------------------------------------- +// 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; +in vec4 vColor; + +uniform mat4 modelview; +out vec4 color; + +void main() +{ + gl_Position = tMul(modelview, vPosition); + correctSSP(gl_Position); + color = vColor; +} \ No newline at end of file diff --git a/Templates/BaseGame/game/core/rendering/shaders/fixedFunction/gl/modColorTextureP.glsl b/Templates/BaseGame/game/core/rendering/shaders/fixedFunction/gl/modColorTextureP.glsl new file mode 100644 index 000000000..c24b9db12 --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/fixedFunction/gl/modColorTextureP.glsl @@ -0,0 +1,32 @@ +//----------------------------------------------------------------------------- +// 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 sampler2D diffuseMap; +in vec4 color; +in vec2 texCoord; + +out vec4 OUT_col; + +void main() +{ + OUT_col = texture(diffuseMap, texCoord) * color; +} \ No newline at end of file diff --git a/Templates/BaseGame/game/core/rendering/shaders/fixedFunction/gl/modColorTextureV.glsl b/Templates/BaseGame/game/core/rendering/shaders/fixedFunction/gl/modColorTextureV.glsl new file mode 100644 index 000000000..5d7f10168 --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/fixedFunction/gl/modColorTextureV.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; +in vec4 vColor; +in vec2 vTexCoord0; + +uniform mat4 modelview; +out vec4 color; +out vec2 texCoord; + +void main() +{ + gl_Position = tMul(modelview, vPosition); + correctSSP(gl_Position); + color = vColor; + texCoord = vTexCoord0.st; +} \ No newline at end of file diff --git a/Templates/BaseGame/game/core/rendering/shaders/fixedFunction/gl/targetRestoreP.glsl b/Templates/BaseGame/game/core/rendering/shaders/fixedFunction/gl/targetRestoreP.glsl new file mode 100644 index 000000000..770f8904d --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/fixedFunction/gl/targetRestoreP.glsl @@ -0,0 +1,31 @@ +//----------------------------------------------------------------------------- +// 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 sampler2D colorTarget0Texture ; + +vec4 main( vec2 ScreenPos : VPOS ) : COLOR0 +{ + vec2 TexCoord = ScreenPos; + vec4 diffuse; + asm { tfetch2D diffuse, TexCoord, colorTarget0Texture, UnnormalizedTextureCoords = true }; + return diffuse; +} \ No newline at end of file diff --git a/Templates/BaseGame/game/core/rendering/shaders/fixedFunction/gl/targetRestoreV.glsl b/Templates/BaseGame/game/core/rendering/shaders/fixedFunction/gl/targetRestoreV.glsl new file mode 100644 index 000000000..e99d2e537 --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/fixedFunction/gl/targetRestoreV.glsl @@ -0,0 +1,22 @@ +//----------------------------------------------------------------------------- +// 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. +//----------------------------------------------------------------------------- + diff --git a/Templates/BaseGame/game/core/rendering/shaders/fixedFunction/gl/textureP.glsl b/Templates/BaseGame/game/core/rendering/shaders/fixedFunction/gl/textureP.glsl new file mode 100644 index 000000000..50cef4bda --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/fixedFunction/gl/textureP.glsl @@ -0,0 +1,31 @@ +//----------------------------------------------------------------------------- +// 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 sampler2D diffuseMap; +in vec2 texCoord; + +out vec4 OUT_col; + +void main() +{ + OUT_col = texture(diffuseMap, texCoord); +} \ No newline at end of file diff --git a/Templates/BaseGame/game/core/rendering/shaders/fixedFunction/gl/textureV.glsl b/Templates/BaseGame/game/core/rendering/shaders/fixedFunction/gl/textureV.glsl new file mode 100644 index 000000000..20dbb6f10 --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/fixedFunction/gl/textureV.glsl @@ -0,0 +1,35 @@ +//----------------------------------------------------------------------------- +// 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; +in vec2 vTexCoord0; + +uniform mat4 modelview; +out vec2 texCoord; + +void main() +{ + gl_Position = tMul(modelview, vPosition); + correctSSP(gl_Position); + texCoord = vTexCoord0.st; +} \ No newline at end of file diff --git a/Templates/BaseGame/game/core/rendering/shaders/fixedFunction/modColorTextureP.hlsl b/Templates/BaseGame/game/core/rendering/shaders/fixedFunction/modColorTextureP.hlsl new file mode 100644 index 000000000..63afec2a4 --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/fixedFunction/modColorTextureP.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. +//----------------------------------------------------------------------------- + +#include "../shaderModel.hlsl" + +struct Conn +{ + float4 HPOS : TORQUE_POSITION; + float4 color : COLOR; + float2 texCoord : TEXCOORD0; +}; + +TORQUE_UNIFORM_SAMPLER2D(diffuseMap, 0); + +float4 main( Conn IN ) : TORQUE_TARGET0 +{ + return TORQUE_TEX2D(diffuseMap, IN.texCoord) * IN.color; +} \ No newline at end of file diff --git a/Templates/BaseGame/game/core/rendering/shaders/fixedFunction/modColorTextureV.hlsl b/Templates/BaseGame/game/core/rendering/shaders/fixedFunction/modColorTextureV.hlsl new file mode 100644 index 000000000..8bf4e88d8 --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/fixedFunction/modColorTextureV.hlsl @@ -0,0 +1,48 @@ +//----------------------------------------------------------------------------- +// 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 "../shaderModel.hlsl" + +struct Appdata +{ + float3 position : POSITION; + float4 color : COLOR; + float2 texCoord : TEXCOORD0; +}; + +struct Conn +{ + float4 HPOS : TORQUE_POSITION; + float4 color : COLOR; + float2 texCoord : TEXCOORD0; +}; + +uniform float4x4 modelview; + +Conn main( Appdata In ) +{ + Conn Out; + Out.HPOS = mul(modelview, float4(In.position,1.0)); + Out.color = In.color; + Out.texCoord = In.texCoord; + return Out; +} \ No newline at end of file diff --git a/Templates/BaseGame/game/core/rendering/shaders/fixedFunction/targetRestoreP.hlsl b/Templates/BaseGame/game/core/rendering/shaders/fixedFunction/targetRestoreP.hlsl new file mode 100644 index 000000000..9ef44f426 --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/fixedFunction/targetRestoreP.hlsl @@ -0,0 +1,31 @@ +//----------------------------------------------------------------------------- +// 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 sampler2D colorTarget0Texture : register(s0); + +float4 main( float2 ScreenPos : VPOS ) : COLOR0 +{ + float2 TexCoord = ScreenPos; + float4 diffuse; + asm { tfetch2D diffuse, TexCoord, colorTarget0Texture, UnnormalizedTextureCoords = true }; + return diffuse; +} \ No newline at end of file diff --git a/Templates/BaseGame/game/core/rendering/shaders/fixedFunction/targetRestoreV.hlsl b/Templates/BaseGame/game/core/rendering/shaders/fixedFunction/targetRestoreV.hlsl new file mode 100644 index 000000000..3c4aefaec --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/fixedFunction/targetRestoreV.hlsl @@ -0,0 +1,26 @@ +//----------------------------------------------------------------------------- +// 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. +//----------------------------------------------------------------------------- + +float4 main( const float2 inPosition : POSITION ) : POSITION +{ + return float4( inPosition, 0, 1 ); +} \ No newline at end of file diff --git a/Templates/BaseGame/game/core/rendering/shaders/fixedFunction/textureP.hlsl b/Templates/BaseGame/game/core/rendering/shaders/fixedFunction/textureP.hlsl new file mode 100644 index 000000000..82dbd4ce9 --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/fixedFunction/textureP.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. +//----------------------------------------------------------------------------- + +#include "../shaderModel.hlsl" + +TORQUE_UNIFORM_SAMPLER2D(diffuseMap, 0); + +struct Conn +{ + float4 hpos : TORQUE_POSITION; + float2 texCoord : TEXCOORD0; +}; + +float4 main(Conn IN) : TORQUE_TARGET0 +{ + return TORQUE_TEX2D(diffuseMap, IN.texCoord); +} \ No newline at end of file diff --git a/Templates/BaseGame/game/core/rendering/shaders/fixedFunction/textureV.hlsl b/Templates/BaseGame/game/core/rendering/shaders/fixedFunction/textureV.hlsl new file mode 100644 index 000000000..204cf9514 --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/fixedFunction/textureV.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. +//----------------------------------------------------------------------------- + +#include "../shaderModel.hlsl" + +struct Appdata +{ + float3 position : POSITION; + float4 color : COLOR; + float2 texCoord : TEXCOORD0; +}; + +struct Conn +{ + float4 hpos : TORQUE_POSITION; + float2 texCoord : TEXCOORD0; +}; + +uniform float4x4 modelview; + +Conn main( Appdata In ) +{ + Conn Out; + Out.hpos = mul(modelview, float4(In.position, 1.0)); + Out.texCoord = In.texCoord; + return Out; +} \ No newline at end of file diff --git a/Templates/BaseGame/game/core/rendering/shaders/foliage.hlsl b/Templates/BaseGame/game/core/rendering/shaders/foliage.hlsl new file mode 100644 index 000000000..9952c29d6 --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/foliage.hlsl @@ -0,0 +1,186 @@ +//----------------------------------------------------------------------------- +// 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. +//----------------------------------------------------------------------------- + +// CornerId corresponds to this arrangement +// from the perspective of the camera. +// +// 3 ---- 2 +// | | +// 0 ---- 1 +// + +#define MAX_COVERTYPES 8 + +uniform float2 gc_fadeParams; +uniform float2 gc_windDir; +uniform float3 gc_camRight; +uniform float3 gc_camUp; +uniform float4 gc_typeRects[MAX_COVERTYPES]; + +// .x = gust length +// .y = premultiplied simulation time and gust frequency +// .z = gust strength +uniform float3 gc_gustInfo; + +// .x = premultiplied simulation time and turbulance frequency +// .y = turbulance strength +uniform float2 gc_turbInfo; + + +static float sCornerRight[4] = { -0.5, 0.5, 0.5, -0.5 }; + +static float sCornerUp[4] = { 0, 0, 1, 1 }; + +static float sMovableCorner[4] = { 0, 0, 1, 1 }; + +static float2 sUVCornerExtent[4] = +{ + float2( 0, 1 ), + float2( 1, 1 ), + float2( 1, 0 ), + float2( 0, 0 ) +}; + + +/////////////////////////////////////////////////////////////////////////////// +// The following wind effect was derived from the GPU Gems 3 chapter... +// +// "Vegetation Procedural Animation and Shading in Crysis" +// by Tiago Sousa, Crytek +// + +float2 smoothCurve( float2 x ) +{ + return x * x * ( 3.0 - 2.0 * x ); +} + +float2 triangleWave( float2 x ) +{ + return abs( frac( x + 0.5 ) * 2.0 - 1.0 ); +} + +float2 smoothTriangleWave( float2 x ) +{ + return smoothCurve( triangleWave( x ) ); +} + +float windTurbulence( float bbPhase, float frequency, float strength ) +{ + // We create the input value for wave generation from the frequency and phase. + float2 waveIn = bbPhase.xx + frequency.xx; + + // We use two square waves to generate the effect which + // is then scaled by the overall strength. + float2 waves = ( frac( waveIn.xy * float2( 1.975, 0.793 ) ) * 2.0 - 1.0 ); + waves = smoothTriangleWave( waves ); + + // Sum up the two waves into a single wave. + return ( waves.x + waves.y ) * strength; +} + +float2 windEffect( float bbPhase, + float2 windDirection, + float gustLength, + float gustFrequency, + float gustStrength, + float turbFrequency, + float turbStrength ) +{ + // Calculate the ambient wind turbulence. + float turbulence = windTurbulence( bbPhase, turbFrequency, turbStrength ); + + // We simulate the overall gust via a sine wave. + float gustPhase = clamp( sin( ( bbPhase - gustFrequency ) / gustLength ) , 0, 1 ); + float gustOffset = ( gustPhase * gustStrength ) + ( ( 0.2 + gustPhase ) * turbulence ); + + // Return the final directional wind effect. + return gustOffset.xx * windDirection.xy; +} + +void foliageProcessVert( inout float3 position, + inout float4 diffuse, + inout float4 texCoord, + inout float3 normal, + inout float3 T, + in float3 eyePos ) +{ + // Assign the normal and tagent values. + //normal = float3( 0, 0, 1 );//cross( gc_camUp, gc_camRight ); + T = gc_camRight; + + // Pull out local vars we need for work. + int corner = ( diffuse.a * 255.0f ) + 0.5f; + float2 size = texCoord.xy; + int type = texCoord.z; + + // The billboarding is based on the camera direction. + float3 rightVec = gc_camRight * sCornerRight[corner]; + float3 upVec = gc_camUp * sCornerUp[corner]; + + // Figure out the corner position. + float3 outPos = ( upVec * size.y ) + ( rightVec * size.x ); + float len = length( outPos.xyz ); + + // We derive the billboard phase used for wind calculations from its position. + float bbPhase = dot( position.xyz, 1 ); + + // Get the overall wind gust and turbulence effects. + float3 wind; + wind.xy = windEffect( bbPhase, + gc_windDir, + gc_gustInfo.x, gc_gustInfo.y, gc_gustInfo.z, + gc_turbInfo.x, gc_turbInfo.y ); + wind.z = 0; + + // Add the summed wind effect into the point. + outPos.xyz += wind.xyz * texCoord.w; + + // Do a simple spherical clamp to keep the foliage + // from stretching too much by wind effect. + outPos.xyz = normalize( outPos.xyz ) * len; + + // Move the point into world space. + position += outPos; + + // Grab the uv set and setup the texture coord. + float4 uvSet = gc_typeRects[type]; + texCoord.x = uvSet.x + ( uvSet.z * sUVCornerExtent[corner].x ); + texCoord.y = uvSet.y + ( uvSet.w * sUVCornerExtent[corner].y ); + + // Animate the normal to get lighting changes + // across the the wind swept foliage. + // + // TODO: Expose the 10x as a factor to control + // how much the wind effects the lighting on the grass. + // + normal.xy += wind.xy * ( 10.0 * texCoord.w ); + normal = normalize( normal ); + + // Get the alpha fade value. + + float fadeStart = gc_fadeParams.x; + float fadeEnd = gc_fadeParams.y; + const float fadeRange = fadeEnd - fadeStart; + + float dist = distance( eyePos, position.xyz ) - fadeStart; + diffuse.a = 1 - clamp( dist / fadeRange, 0, 1 ); +} \ No newline at end of file diff --git a/Templates/BaseGame/game/core/rendering/shaders/fxFoliageReplicatorP.hlsl b/Templates/BaseGame/game/core/rendering/shaders/fxFoliageReplicatorP.hlsl new file mode 100644 index 000000000..a8bb68e28 --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/fxFoliageReplicatorP.hlsl @@ -0,0 +1,60 @@ +//----------------------------------------------------------------------------- +// 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 "shdrConsts.h" +#include "shaderModel.hlsl" +//----------------------------------------------------------------------------- +// Structures +//----------------------------------------------------------------------------- +struct ConnectData +{ + float4 hpos : TORQUE_POSITION; + float2 outTexCoord : TEXCOORD0; + float4 color : COLOR0; + float4 groundAlphaCoeff : COLOR1; + float2 alphaLookup : TEXCOORD1; +}; + +struct Fragout +{ + float4 col : TORQUE_TARGET0; +}; + +TORQUE_UNIFORM_SAMPLER2D(diffuseMap, 0); +TORQUE_UNIFORM_SAMPLER2D(alphaMap, 1); + +uniform float4 groundAlpha; +uniform float4 ambient; + +//----------------------------------------------------------------------------- +// Main +//----------------------------------------------------------------------------- +Fragout main( ConnectData IN ) +{ + Fragout OUT; + + float4 alpha = TORQUE_TEX2D(alphaMap, IN.alphaLookup); + OUT.col = float4( ambient.rgb * IN.lum.rgb, 1.0 ) * TORQUE_TEX2D(diffuseMap, IN.texCoord); + OUT.col.a = OUT.col.a * min(alpha, groundAlpha + IN.groundAlphaCoeff.x).x; + + return OUT; +} diff --git a/Templates/BaseGame/game/core/rendering/shaders/fxFoliageReplicatorV.hlsl b/Templates/BaseGame/game/core/rendering/shaders/fxFoliageReplicatorV.hlsl new file mode 100644 index 000000000..70ec9ff4c --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/fxFoliageReplicatorV.hlsl @@ -0,0 +1,129 @@ +//----------------------------------------------------------------------------- +// 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. +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// Structures +//----------------------------------------------------------------------------- + +#include "shaderModel.hlsl" + +struct VertData +{ + float3 position : POSITION; + float3 normal : NORMAL; + float2 texCoord : TEXCOORD0; + float2 waveScale : TEXCOORD1; +}; + +struct ConnectData +{ + float4 hpos : TORQUE_POSITION; + float2 outTexCoord : TEXCOORD0; + float4 color : COLOR0; + float4 groundAlphaCoeff : COLOR1; + float2 alphaLookup : TEXCOORD1; +}; + +uniform float4x4 projection : register(C0); +uniform float4x4 world : register(C4); +uniform float GlobalSwayPhase : register(C8); +uniform float SwayMagnitudeSide : register(C9); +uniform float SwayMagnitudeFront : register(C10); +uniform float GlobalLightPhase : register(C11); +uniform float LuminanceMagnitude : register(C12); +uniform float LuminanceMidpoint : register(C13); +uniform float DistanceRange : register(C14); +uniform float3 CameraPos : register(C15); +uniform float TrueBillboard : register(C16); + +//----------------------------------------------------------------------------- +// Main +//----------------------------------------------------------------------------- +ConnectData main( VertData IN ) +{ + ConnectData OUT; + + // Init a transform matrix to be used in the following steps + float4x4 trans = 0; + trans[0][0] = 1; + trans[1][1] = 1; + trans[2][2] = 1; + trans[3][3] = 1; + trans[0][3] = IN.position.x; + trans[1][3] = IN.position.y; + trans[2][3] = IN.position.z; + + // Billboard transform * world matrix + float4x4 o = world; + o = mul(o, trans); + + // Keep only the up axis result and position transform. + // This gives us "cheating" cylindrical billboarding. + o[0][0] = 1; + o[1][0] = 0; + o[2][0] = 0; + o[3][0] = 0; + o[0][1] = 0; + o[1][1] = 1; + o[2][1] = 0; + o[3][1] = 0; + + // Unless the user specified TrueBillboard, + // in which case we want the z axis to also be camera facing. + +#ifdef TRUE_BILLBOARD + + o[0][2] = 0; + o[1][2] = 0; + o[2][2] = 1; + o[3][2] = 0; + +#endif + + // Handle sway. Sway is stored in a texture coord. The x coordinate is the sway phase multiplier, + // the y coordinate determines if this vertex actually sways or not. + float xSway, ySway; + float wavePhase = GlobalSwayPhase * IN.waveScale.x; + sincos(wavePhase, ySway, xSway); + xSway = xSway * IN.waveScale.y * SwayMagnitudeSide; + ySway = ySway * IN.waveScale.y * SwayMagnitudeFront; + float4 p; + p = mul(o, float4(IN.normal.x + xSway, ySway, IN.normal.z, 1)); + + // Project the point + OUT.hpos = mul(projection, p); + + // Lighting + float Luminance = LuminanceMidpoint + LuminanceMagnitude * cos(GlobalLightPhase + IN.normal.y); + + // Alpha + float3 worldPos = IN.position; + float alpha = abs(distance(worldPos, CameraPos)) / DistanceRange; + alpha = clamp(alpha, 0.0f, 1.0f); //pass it through + + OUT.alphaLookup = float2(alpha, 0.0f); + OUT.groundAlphaCoeff = all(IN.normal.z); + OUT.outTexCoord = IN.texCoord; + OUT.color = float4(Luminance, Luminance, Luminance, 1.0f); + + return OUT; +} \ No newline at end of file diff --git a/Templates/BaseGame/game/core/rendering/shaders/gl/basicCloudsP.glsl b/Templates/BaseGame/game/core/rendering/shaders/gl/basicCloudsP.glsl new file mode 100644 index 000000000..5b3f50519 --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/gl/basicCloudsP.glsl @@ -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. +//----------------------------------------------------------------------------- + +#include "torque.glsl" +#include "hlslCompat.glsl" + +//ConnectData +in vec2 texCoord; +#define IN_texCoord texCoord + + +uniform sampler2D diffuseMap ; + +out vec4 OUT_col; + +void main() +{ + vec4 col = texture( diffuseMap, IN_texCoord ); + OUT_col = hdrEncode( col ); +} \ No newline at end of file diff --git a/Templates/BaseGame/game/core/rendering/shaders/gl/basicCloudsV.glsl b/Templates/BaseGame/game/core/rendering/shaders/gl/basicCloudsV.glsl new file mode 100644 index 000000000..cccbafa8c --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/gl/basicCloudsV.glsl @@ -0,0 +1,53 @@ +//----------------------------------------------------------------------------- +// 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 "hlslCompat.glsl" + +//CloudVert +in vec4 vPosition; +in vec2 vTexCoord0; + +#define IN_pos vPosition +#define IN_uv0 vTexCoord0 + +uniform mat4 modelview; +uniform float accumTime; +uniform float texScale; +uniform vec2 texDirection; +uniform vec2 texOffset; + +out vec2 texCoord; +#define OUT_texCoord texCoord + +void main() +{ + gl_Position = tMul(modelview, IN_pos); + + vec2 uv = IN_uv0; + uv += texOffset; + uv *= texScale; + uv += accumTime * texDirection; + + OUT_texCoord = uv; + + correctSSP(gl_Position); +} \ No newline at end of file diff --git a/Templates/BaseGame/game/core/rendering/shaders/gl/blurP.glsl b/Templates/BaseGame/game/core/rendering/shaders/gl/blurP.glsl new file mode 100644 index 000000000..a27538762 --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/gl/blurP.glsl @@ -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. +//----------------------------------------------------------------------------- + +//***************************************************************************** +// Glow Shader +//***************************************************************************** +uniform vec4 kernel; +uniform sampler2D diffuseMap; + +in vec2 texc0, texc1, texc2, texc3; + +out vec4 OUT_col; + +void main() +{ + OUT_col = texture(diffuseMap, texc0) * kernel.x; + OUT_col += texture(diffuseMap, texc1) * kernel.y; + OUT_col += texture(diffuseMap, texc2) * kernel.z; + OUT_col += texture(diffuseMap, texc3) * kernel.w; +} diff --git a/Templates/BaseGame/game/core/rendering/shaders/gl/blurV.glsl b/Templates/BaseGame/game/core/rendering/shaders/gl/blurV.glsl new file mode 100644 index 000000000..1bfb0cd1b --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/gl/blurV.glsl @@ -0,0 +1,48 @@ +//----------------------------------------------------------------------------- +// 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. +//----------------------------------------------------------------------------- + +//***************************************************************************** +// Glow shader +//***************************************************************************** + +in vec4 vPosition; +in vec4 vColor; +in vec2 vTexCoord0; + +uniform mat4 modelview; +uniform vec2 offset0, offset1, offset2, offset3; + +out vec2 texc0, texc1, texc2, texc3; + +void main() +{ + gl_Position = modelview * vPosition; + + vec2 tc = vTexCoord0.st; + tc.y = 1.0 - tc.y; + + texc0 = tc + offset0; + texc1 = tc + offset1; + texc2 = tc + offset2; + texc3 = tc + offset3; + gl_Position.y *= -1; +} \ No newline at end of file diff --git a/Templates/BaseGame/game/core/rendering/shaders/gl/cloudLayerP.glsl b/Templates/BaseGame/game/core/rendering/shaders/gl/cloudLayerP.glsl new file mode 100644 index 000000000..877a132da --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/gl/cloudLayerP.glsl @@ -0,0 +1,147 @@ +//----------------------------------------------------------------------------- +// 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 "hlslCompat.glsl" +#include "torque.glsl" +//----------------------------------------------------------------------------- +// Structures +//----------------------------------------------------------------------------- +//ConnectData +in vec4 texCoord12; +#define IN_texCoord12 texCoord12 +in vec4 texCoord34; +#define IN_texCoord34 texCoord34 +in vec3 vLightTS; // light vector in tangent space, denormalized +#define IN_vLightTS vLightTS +in vec3 vViewTS; // view vector in tangent space, denormalized +#define IN_vViewTS vViewTS +in float worldDist; +#define IN_worldDist worldDist + +//----------------------------------------------------------------------------- +// Uniforms +//----------------------------------------------------------------------------- +uniform sampler2D normalHeightMap; +uniform vec3 ambientColor; +uniform vec3 sunColor; +uniform float cloudCoverage; +uniform vec3 cloudBaseColor; +uniform float cloudExposure; + +out vec4 OUT_col; + +//----------------------------------------------------------------------------- +// Globals +//----------------------------------------------------------------------------- +// The per-color weighting to be used for luminance calculations in RGB order. +const vec3 LUMINANCE_VECTOR = vec3(0.2125f, 0.7154f, 0.0721f); + + +//----------------------------------------------------------------------------- +// Functions +//----------------------------------------------------------------------------- + +// Calculates the Rayleigh phase function +float getRayleighPhase( float angle ) +{ + return 0.75 * ( 1.0 + pow( angle, 2.0 ) ); +} + +// Returns the output rgb color given a texCoord and parameters it uses +// for lighting calculation. +vec3 ComputeIllumination( vec2 texCoord, + vec3 vLightTS, + vec3 vViewTS, + vec3 vNormalTS ) +{ + //return noiseNormal; + //return vNormalTS; + + vec3 vLightTSAdj = vec3( -vLightTS.x, -vLightTS.y, vLightTS.z ); + + float dp = dot( vNormalTS, vLightTSAdj ); + + // Calculate the amount of illumination (lightTerm)... + + // We do both a rim lighting effect and a halfLambertian lighting effect + // and combine the result. + float halfLambertTerm = clamp( pow( dp * 0.5 + 0.5, 1.0 ), 0.0, 1.0 ); + float rimLightTerm = pow( ( 1.0 - dp ), 1.0 ); + float lightTerm = clamp( halfLambertTerm * 1.0 + rimLightTerm * dp, 0.0, 1.0 ); + lightTerm *= 0.5; + + // Use a simple RayleighPhase function to simulate single scattering towards + // the camera. + float angle = dot( vLightTS, vViewTS ); + lightTerm *= getRayleighPhase( angle ); + + // Combine terms and colors into the output color. + //vec3 lightColor = ( lightTerm * sunColor * fOcclusionShadow ) + ambientColor; + vec3 lightColor = mix( ambientColor, sunColor, lightTerm ); + //lightColor = mix( lightColor, ambientColor, cloudCoverage ); + vec3 finalColor = cloudBaseColor * lightColor; + + return finalColor; +} + +void main() +{ + // Normalize the interpolated vectors: + vec3 vViewTS = normalize( vViewTS ); + vec3 vLightTS = normalize( vLightTS ); + + vec4 cResultColor = vec4( 0, 0, 0, 1 ); + + vec2 texSample = IN_texCoord12.xy; + + vec4 noise1 = texture( normalHeightMap, IN_texCoord12.zw ); + noise1 = normalize( ( noise1 - 0.5 ) * 2.0 ); + //return noise1; + + vec4 noise2 = texture( normalHeightMap, IN_texCoord34.xy ); + noise2 = normalize( ( noise2 - 0.5 ) * 2.0 ); + //return noise2; + + vec3 noiseNormal = normalize( noise1 + noise2 ).xyz; + //return vec4( noiseNormal, 1.0 ); + + float noiseHeight = noise1.a * noise2.a * ( cloudCoverage / 2.0 + 0.5 ); + + vec3 vNormalTS = normalize( texture( normalHeightMap, texSample ).xyz * 2.0 - 1.0 ); + vNormalTS += noiseNormal; + vNormalTS = normalize( vNormalTS ); + + // Compute resulting color for the pixel: + cResultColor.rgb = ComputeIllumination( texSample, vLightTS, vViewTS, vNormalTS ); + + float coverage = ( cloudCoverage - 0.5 ) * 2.0; + cResultColor.a = texture( normalHeightMap, texSample ).a + coverage + noiseHeight; + + if ( cloudCoverage > -1.0 ) + cResultColor.a /= 1.0 + coverage; + + cResultColor.a = clamp( cResultColor.a * pow( saturate(cloudCoverage), 0.25 ), 0.0, 1.0 ); + + cResultColor.a = mix( cResultColor.a, 0.0, 1.0 - pow(IN_worldDist,2.0) ); + + OUT_col = hdrEncode(cResultColor); +} diff --git a/Templates/BaseGame/game/core/rendering/shaders/gl/cloudLayerV.glsl b/Templates/BaseGame/game/core/rendering/shaders/gl/cloudLayerV.glsl new file mode 100644 index 000000000..395c6f286 --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/gl/cloudLayerV.glsl @@ -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. +//----------------------------------------------------------------------------- + +#include "hlslCompat.glsl" + +in vec4 vPosition; +in vec3 vNormal; +in vec3 vBinormal; +in vec3 vTangent; +in vec2 vTexCoord0; + +out vec4 texCoord12; +#define OUT_texCoord12 texCoord12 +out vec4 texCoord34; +#define OUT_texCoord34 texCoord34 +out vec3 vLightTS; // light vector in tangent space, denormalized +#define OUT_vLightTS vLightTS +out vec3 vViewTS; // view vector in tangent space, denormalized +#define OUT_vViewTS vViewTS +out float worldDist; +#define OUT_worldDist worldDist + +//----------------------------------------------------------------------------- +// Uniforms +//----------------------------------------------------------------------------- +uniform mat4 modelview; +uniform vec3 eyePosWorld; +uniform vec3 sunVec; +uniform vec2 texOffset0; +uniform vec2 texOffset1; +uniform vec2 texOffset2; +uniform vec3 texScale; + +//----------------------------------------------------------------------------- +// Main +//----------------------------------------------------------------------------- +void main() +{ + vec4 IN_pos = vPosition; + vec3 IN_normal = vNormal; + vec3 IN_binormal = vBinormal; + vec3 IN_tangent = vTangent; + vec2 IN_uv0 = vTexCoord0.st; + + gl_Position = modelview * IN_pos; + + // Offset the uv so we don't have a seam directly over our head. + vec2 uv = IN_uv0 + vec2( 0.5, 0.5 ); + + OUT_texCoord12.xy = uv * texScale.x; + OUT_texCoord12.xy += texOffset0; + + OUT_texCoord12.zw = uv * texScale.y; + OUT_texCoord12.zw += texOffset1; + + OUT_texCoord34.xy = uv * texScale.z; + OUT_texCoord34.xy += texOffset2; + + OUT_texCoord34.z = IN_pos.z; + OUT_texCoord34.w = 0.0; + + // Transform the normal, tangent and binormal vectors from object space to + // homogeneous projection space: + vec3 vNormalWS = -IN_normal; + vec3 vTangentWS = -IN_tangent; + vec3 vBinormalWS = -IN_binormal; + + // Compute position in world space: + vec4 vPositionWS = IN_pos + vec4( eyePosWorld, 1 ); //tMul( IN_pos, objTrans ); + + // Compute and output the world view vector (unnormalized): + vec3 vViewWS = eyePosWorld - vPositionWS.xyz; + + // Compute denormalized light vector in world space: + vec3 vLightWS = -sunVec; + + // Normalize the light and view vectors and transform it to the IN_tangent space: + mat3 mWorldToTangent = mat3( vTangentWS, vBinormalWS, vNormalWS ); + + // Propagate the view and the light vectors (in tangent space): + OUT_vLightTS = vLightWS * mWorldToTangent; + OUT_vViewTS = mWorldToTangent * vViewWS; + + OUT_worldDist = clamp( pow( max( IN_pos.z, 0 ), 2 ), 0.0, 1.0 ); + + correctSSP(gl_Position); +} diff --git a/Templates/BaseGame/game/core/rendering/shaders/gl/foliage.glsl b/Templates/BaseGame/game/core/rendering/shaders/gl/foliage.glsl new file mode 100644 index 000000000..38b66e767 --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/gl/foliage.glsl @@ -0,0 +1,186 @@ +//----------------------------------------------------------------------------- +// 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. +//----------------------------------------------------------------------------- + +// CornerId corresponds to this arrangement +// from the perspective of the camera. +// +// 3 ---- 2 +// | | +// 0 ---- 1 +// + +#define MAX_COVERTYPES 8 + +uniform vec3 gc_camRight; +uniform vec3 gc_camUp; +uniform vec4 gc_typeRects[MAX_COVERTYPES]; +uniform vec2 gc_fadeParams; +uniform vec2 gc_windDir; + +// .x = gust length +// .y = premultiplied simulation time and gust frequency +// .z = gust strength +uniform vec3 gc_gustInfo; + +// .x = premultiplied simulation time and turbulance frequency +// .y = turbulance strength +uniform vec2 gc_turbInfo; + + +const float sCornerRight[4] = float[]( -0.5, 0.5, 0.5, -0.5 ); + +const float sCornerUp[4] = float[]( 0, 0, 1, 1 ); + +const float sMovableCorner[4] = float[]( 0, 0, 1, 1 ); + +const vec2 sUVCornerExtent[4] = vec2[] +( + vec2( 0, 1 ), + vec2( 1, 1 ), + vec2( 1, 0 ), + vec2( 0, 0 ) +); + + +/////////////////////////////////////////////////////////////////////////////// +// The following wind effect was derived from the GPU Gems 3 chapter... +// +// "Vegetation Procedural Animation and Shading in Crysis" +// by Tiago Sousa, Crytek +// + +vec2 smoothCurve( vec2 x ) +{ + return x * x * ( 3.0 - 2.0 * x ); +} + +vec2 triangleWave( vec2 x ) +{ + return abs( fract( x + 0.5 ) * 2.0 - 1.0 ); +} + +vec2 smoothTriangleWave( vec2 x ) +{ + return smoothCurve( triangleWave( x ) ); +} + +float windTurbulence( float bbPhase, float frequency, float strength ) +{ + // We create the input value for wave generation from the frequency and phase. + vec2 waveIn = vec2( bbPhase + frequency ); + + // We use two square waves to generate the effect which + // is then scaled by the overall strength. + vec2 waves = ( fract( waveIn.xy * vec2( 1.975, 0.793 ) ) * 2.0 - 1.0 ); + waves = smoothTriangleWave( waves ); + + // Sum up the two waves into a single wave. + return ( waves.x + waves.y ) * strength; +} + +vec2 windEffect( float bbPhase, + vec2 windDirection, + float gustLength, + float gustFrequency, + float gustStrength, + float turbFrequency, + float turbStrength ) +{ + // Calculate the ambient wind turbulence. + float turbulence = windTurbulence( bbPhase, turbFrequency, turbStrength ); + + // We simulate the overall gust via a sine wave. + float gustPhase = clamp( sin( ( bbPhase - gustFrequency ) / gustLength ) , 0.0, 1.0 ); + float gustOffset = ( gustPhase * gustStrength ) + ( ( 0.2 + gustPhase ) * turbulence ); + + // Return the final directional wind effect. + return vec2(gustOffset) * windDirection.xy; +} + +void foliageProcessVert( inout vec3 position, + inout vec4 diffuse, + inout vec4 texCoord, + inout vec3 normal, + inout vec3 T, + in vec3 eyePos ) +{ + // Assign the normal and tagent values. + //normal = vec3( 0, 0, 1 );//cross( gc_camUp, gc_camRight ); + T = gc_camRight; + + // Pull out local vars we need for work. + int corner = int( ( diffuse.a * 255.0 ) + 0.5 ); + vec2 size = texCoord.xy; + int type = int( texCoord.z ); + + // The billboarding is based on the camera direction. + vec3 rightVec = gc_camRight * sCornerRight[corner]; + vec3 upVec = gc_camUp * sCornerUp[corner]; + + // Figure out the corner position. + vec3 outPos = ( upVec * size.y ) + ( rightVec * size.x ); + float len = length( outPos.xyz ); + + // We derive the billboard phase used for wind calculations from its position. + float bbPhase = dot( position.xyz, vec3( 1.0 ) ); + + // Get the overall wind gust and turbulence effects. + vec3 wind; + wind.xy = windEffect( bbPhase, + gc_windDir, + gc_gustInfo.x, gc_gustInfo.y, gc_gustInfo.z, + gc_turbInfo.x, gc_turbInfo.y ); + wind.z = 0.0; + + // Add the summed wind effect into the point. + outPos.xyz += wind.xyz * texCoord.w; + + // Do a simple spherical clamp to keep the foliage + // from stretching too much by wind effect. + outPos.xyz = normalize( outPos.xyz ) * len; + + // Move the point into world space. + position += outPos; + + // Grab the uv set and setup the texture coord. + vec4 uvSet = gc_typeRects[type]; + texCoord.x = uvSet.x + ( uvSet.z * sUVCornerExtent[corner].x ); + texCoord.y = uvSet.y + ( uvSet.w * sUVCornerExtent[corner].y ); + + // Animate the normal to get lighting changes + // across the the wind swept foliage. + // + // TODO: Expose the 10x as a factor to control + // how much the wind effects the lighting on the grass. + // + normal.xy += wind.xy * ( 10.0 * texCoord.w ); + normal = normalize( normal ); + + // Get the alpha fade value. + + float fadeStart = gc_fadeParams.x; + float fadeEnd = gc_fadeParams.y; + float fadeRange = fadeEnd - fadeStart; + + float dist = distance( eyePos, position.xyz ) - fadeStart; + diffuse.a = 1.0 - clamp( dist / fadeRange, 0.0, 1.0 ); +} diff --git a/Templates/BaseGame/game/core/rendering/shaders/gl/fxFoliageReplicatorP.glsl b/Templates/BaseGame/game/core/rendering/shaders/gl/fxFoliageReplicatorP.glsl new file mode 100644 index 000000000..b4d591486 --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/gl/fxFoliageReplicatorP.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. +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// Data +//----------------------------------------------------------------------------- +uniform sampler2D diffuseMap, alphaMap; +uniform vec4 groundAlpha; + +in vec4 color, groundAlphaCoeff; +in vec2 outTexCoord, alphaLookup; + +out vec4 OUT_col; + +//----------------------------------------------------------------------------- +// Main +//----------------------------------------------------------------------------- +void main() +{ + vec4 alpha = texture(alphaMap, alphaLookup); + OUT_col = color * texture(diffuseMap, outTexCoord); + OUT_col.a = OUT_col.a * min(alpha, groundAlpha + groundAlphaCoeff.x).x; +} diff --git a/Templates/BaseGame/game/core/rendering/shaders/gl/fxFoliageReplicatorV.glsl b/Templates/BaseGame/game/core/rendering/shaders/gl/fxFoliageReplicatorV.glsl new file mode 100644 index 000000000..c8dcf1ddb --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/gl/fxFoliageReplicatorV.glsl @@ -0,0 +1,99 @@ +//----------------------------------------------------------------------------- +// 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. +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// Data +//----------------------------------------------------------------------------- +in vec4 vPosition; +in vec3 vNormal; +in vec4 vColor; +in vec2 vTexCoord0; +in vec2 vTexCoord1; +in vec2 vTexCoord2; + +uniform mat4 projection, world; +uniform vec3 CameraPos; +uniform float GlobalSwayPhase, SwayMagnitudeSide, SwayMagnitudeFront, + GlobalLightPhase, LuminanceMagnitude, LuminanceMidpoint, DistanceRange; + +out vec4 color, groundAlphaCoeff; +out vec2 outTexCoord, alphaLookup; + +//----------------------------------------------------------------------------- +// Main +//----------------------------------------------------------------------------- +void main() +{ + // Init a transform matrix to be used in the following steps + mat4 trans = mat4(0.0); + trans[0][0] = 1.0; + trans[1][1] = 1.0; + trans[2][2] = 1.0; + trans[3][3] = 1.0; + trans[3][0] = vPosition.x; + trans[3][1] = vPosition.y; + trans[3][2] = vPosition.z; + + // Billboard transform * world matrix + mat4 o = world; + o = o * trans; + + // Keep only the up axis result and position transform. + // This gives us "cheating" cylindrical billboarding. + o[0][0] = 1.0; + o[0][1] = 0.0; + o[0][2] = 0.0; + o[0][3] = 0.0; + o[1][0] = 0.0; + o[1][1] = 1.0; + o[1][2] = 0.0; + o[1][3] = 0.0; + + // Handle sway. Sway is stored in a texture coord. The x coordinate is the sway phase multiplier, + // the y coordinate determines if this vertex actually sways or not. + float xSway, ySway; + float wavePhase = GlobalSwayPhase * vTexCoord1.x; + ySway = sin(wavePhase); + xSway = cos(wavePhase); + xSway = xSway * vTexCoord1.y * SwayMagnitudeSide; + ySway = ySway * vTexCoord1.y * SwayMagnitudeFront; + vec4 p; + p = o * vec4(vNormal.x + xSway, ySway, vNormal.z, 1.0); + + // Project the point + gl_Position = projection * p; + + // Lighting + float Luminance = LuminanceMidpoint + LuminanceMagnitude * cos(GlobalLightPhase + vNormal.y); + + // Alpha + vec3 worldPos = vec3(vPosition.x, vPosition.y, vPosition.z); + float alpha = abs(distance(worldPos, CameraPos)) / DistanceRange; + alpha = clamp(alpha, 0.0, 1.0); //pass it through + + alphaLookup = vec2(alpha, 0.0); + bool alphaCoeff = bool(vNormal.z); + groundAlphaCoeff = vec4(float(alphaCoeff)); + outTexCoord = vTexCoord0.st; + color = vec4(Luminance, Luminance, Luminance, 1.0); + gl_Position.y *= -1; +} \ No newline at end of file diff --git a/Templates/BaseGame/game/core/rendering/shaders/gl/guiMaterialV.glsl b/Templates/BaseGame/game/core/rendering/shaders/gl/guiMaterialV.glsl new file mode 100644 index 000000000..de3845ee7 --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/gl/guiMaterialV.glsl @@ -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. +//----------------------------------------------------------------------------- + +in vec4 vPosition; +in vec2 vTexCoord0; + +uniform mat4x4 modelview; + +out vec4 hpos; +out vec2 uv0; + + +void main() +{ + hpos = vec4( modelview * vPosition ); + gl_Position = hpos; + + uv0 = vTexCoord0.st; + gl_Position.y *= -1; +} diff --git a/Templates/BaseGame/game/core/rendering/shaders/gl/hlslCompat.glsl b/Templates/BaseGame/game/core/rendering/shaders/gl/hlslCompat.glsl new file mode 100644 index 000000000..b9a6e76d7 --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/gl/hlslCompat.glsl @@ -0,0 +1,101 @@ +//----------------------------------------------------------------------------- +// 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. +//----------------------------------------------------------------------------- + +// These are some simple wrappers for simple +// HLSL compatibility. + +#define float4 vec4 +#define float3 vec3 +#define float2 vec2 + +#define half float +#define half2 vec2 +#define half3 vec3 +#define half4 vec4 + +#define float4x4 mat4 +#define float3x3 mat3 +#define float2x2 mat2 + +#define texCUBE texture +#define tex2D texture +#define tex1D texture +#define tex2Dproj textureProj +#define tex2Dlod( sampler, texCoord ) textureLod(sampler, texCoord.xy, texCoord.w) + +#define samplerCUBE samplerCube + +#define frac fract + +#define lerp mix + +void tSetMatrixRow(inout float3x3 m, int row, float3 value) +{ + m[0][row] = value.x; + m[1][row] = value.y; + m[2][row] = value.z; +} + +void tSetMatrixRow(inout float4x4 m, int row, float4 value) +{ + m[0][row] = value.x; + m[1][row] = value.y; + m[2][row] = value.z; + m[3][row] = value.w; +} + +#define tGetMatrix3Row(matrix, row) float3(matrix[0][row], matrix[1][row], matrix[2][row]) +#define tGetMatrix4Row(matrix, row) float4(matrix[0][row], matrix[1][row], matrix[2][row], matrix[3][row]) + +float3x3 float4x4to3x3(float4x4 m) +{ + return float3x3( vec3(m[0]).xyz, m[1].xyz, m[2].xyz); +} + +float3x3 float4x4to3x3_(float4x4 m) +{ + return float3x3( vec3(m[0]), m[1].xyz, m[2].xyz); +} + +mat4 mat4FromRow( float r0c0, float r0c1, float r0c2, float r0c3, + float r1c0, float r1c1, float r1c2, float r1c3, + float r2c0, float r2c1, float r2c2, float r2c3, + float r3c0, float r3c1, float r3c2, float r3c3 ) +{ + return mat4( r0c0, r1c0, r2c0, r3c0, + r0c1, r1c1, r2c1, r3c1, + r0c2, r1c2, r2c2, r3c2, + r0c3, r1c3, r2c3, r3c3 ); +} + + +#define saturate( val ) clamp( val, 0.0, 1.0 ) + +#define round( n ) (sign( n ) * floor( abs( n ) + 0.5 )) + +#define tMul(a, b) (a*b) + +#define correctSSP(vec) vec.y *= -1 + +#ifdef TORQUE_PIXEL_SHADER + void clip(float a) { if(a < 0) discard;} +#endif diff --git a/Templates/BaseGame/game/core/rendering/shaders/gl/imposter.glsl b/Templates/BaseGame/game/core/rendering/shaders/gl/imposter.glsl new file mode 100644 index 000000000..20bc62688 --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/gl/imposter.glsl @@ -0,0 +1,161 @@ +//----------------------------------------------------------------------------- +// 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 "torque.glsl" + + +#define IMPOSTER_MAX_UVS 64 + + +void imposter_v( + // These parameters usually come from the vertex. + vec3 center, + int corner, + float halfSize, + vec3 imposterUp, + vec3 imposterRight, + + // These are from the imposter shader constant. + int numEquatorSteps, + int numPolarSteps, + float polarAngle, + bool includePoles, + + // Other shader constants. + vec3 camPos, + vec4 uvs[IMPOSTER_MAX_UVS], + + // The outputs of this function. + out vec3 outWsPosition, + out vec2 outTexCoord, + out mat3 outWorldToTangent + ) +{ + + float M_HALFPI_F = 1.57079632679489661923; + float M_PI_F = 3.14159265358979323846; + float M_2PI_F = 6.28318530717958647692; + + + float sCornerRight[4];// = float[]( -1.0, 1.0, 1.0, -1.0 ); + sCornerRight[0] = -1.0; + sCornerRight[1] = 1.0; + sCornerRight[2] = 1.0; + sCornerRight[3] = -1.0; + float sCornerUp[4];// = float[]( -1.0, -1.0, 1.0, 1.0 ); + sCornerUp[0] = -1.0; + sCornerUp[1] = -1.0; + sCornerUp[2] = 1.0; + sCornerUp[3] = 1.0; + vec2 sUVCornerExtent[4];// = vec2[](vec2( 0.0, 1.0 ), vec2( 1.0, 1.0 ), vec2( 1.0, 0.0 ), vec2( 0.0, 0.0 )); + sUVCornerExtent[0] = vec2( 0.0, 1.0 ); + sUVCornerExtent[1] = vec2( 1.0, 1.0 ); + sUVCornerExtent[2] = vec2( 1.0, 0.0 ); + sUVCornerExtent[3] = vec2( 0.0, 0.0 ); + + // TODO: This could all be calculated on the CPU. + float equatorStepSize = M_2PI_F / float( numEquatorSteps ); + float equatorHalfStep = ( equatorStepSize / 2.0 ) - 0.0001; + float polarStepSize = M_PI_F / float( numPolarSteps ); + float polarHalfStep = ( polarStepSize / 2.0 ) - 0.0001; + + // The vector between the camera and the billboard. + vec3 lookVec = normalize( camPos - center ); + + // Generate the camera up and right vectors from + // the object transform and camera forward. + vec3 camUp = imposterUp; + vec3 camRight = cross( -lookVec, camUp ); + + // The billboarding is based on the camera directions. + vec3 rightVec = camRight * sCornerRight[corner]; + vec3 upVec = camUp * sCornerUp[corner]; + + float lookPitch = acos( dot( imposterUp, lookVec ) ); + + // First check to see if we need to render the top billboard. + int index; + /* + if ( includePoles && ( lookPitch < polarAngle || lookPitch > sPi - polarAngle ) ) + { + index = numEquatorSteps * 3; + + // When we render the top/bottom billboard we always use + // a fixed vector that matches the rotation of the object. + rightVec = vec3( 1, 0, 0 ) * sCornerRight[corner]; + upVec = vec3( 0, 1, 0 ) * sCornerUp[corner]; + + if ( lookPitch > sPi - polarAngle ) + { + upVec = -upVec; + index++; + } + } + else + */ + { + // Calculate the rotation around the z axis then add the + // equator half step. This gets the images to switch a + // half step before the captured angle is met. + float lookAzimuth = atan( lookVec.y, lookVec.x ); + float azimuth = atan( imposterRight.y, imposterRight.x ); + float rotZ = ( lookAzimuth - azimuth ) + equatorHalfStep; + + // The y rotation is calculated from the look vector and + // the object up vector. + float rotY = lookPitch - polarHalfStep; + + // TODO: How can we do this without conditionals? + // Normalize the result to 0 to 2PI. + if ( rotZ < 0.0 ) + rotZ += M_2PI_F; + if ( rotZ > M_2PI_F ) + rotZ -= M_2PI_F; + if ( rotY < 0.0 ) + rotY += M_2PI_F; + if ( rotY > M_PI_F ) // Not M_2PI_F? + rotY -= M_2PI_F; + + float polarIdx = round( abs( rotY ) / polarStepSize ); + + // Get the index to the start of the right polar + // images for this viewing angle. + int numPolarOffset = int( float( numEquatorSteps ) * polarIdx ); + + // Calculate the final image index for lookup + // of the texture coords. + index = int( rotZ / equatorStepSize ) + numPolarOffset; + } + + // Generate the final world space position. + outWsPosition = center + ( upVec * halfSize ) + ( rightVec * halfSize ); + + // Grab the uv set and setup the texture coord. + vec4 uvSet = uvs[index]; + outTexCoord.x = uvSet.x + ( uvSet.z * sUVCornerExtent[corner].x ); + outTexCoord.y = uvSet.y + ( uvSet.w * sUVCornerExtent[corner].y ); + + // Needed for normal mapping and lighting. + outWorldToTangent[0] = vec3( 1, 0, 0 ); + outWorldToTangent[1] = vec3( 0, 1, 0 ); + outWorldToTangent[2] = vec3( 0, 0, -1 ); +} diff --git a/Templates/BaseGame/game/core/rendering/shaders/gl/lighting.glsl b/Templates/BaseGame/game/core/rendering/shaders/gl/lighting.glsl new file mode 100644 index 000000000..804ab1e3b --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/gl/lighting.glsl @@ -0,0 +1,249 @@ +//----------------------------------------------------------------------------- +// 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 "./torque.glsl" + +#ifndef TORQUE_SHADERGEN + +// These are the uniforms used by most lighting shaders. + +uniform vec4 inLightPos[3]; +uniform vec4 inLightInvRadiusSq; +uniform vec4 inLightColor[4]; + +#ifndef TORQUE_BL_NOSPOTLIGHT + uniform vec4 inLightSpotDir[3]; + uniform vec4 inLightSpotAngle; + uniform vec4 inLightSpotFalloff; +#endif + +uniform vec4 ambient; +#define ambientCameraFactor 0.3 +uniform float specularPower; +uniform vec4 specularColor; + +#endif // !TORQUE_SHADERGEN + + +void compute4Lights( vec3 wsView, + vec3 wsPosition, + vec3 wsNormal, + vec4 shadowMask, + + #ifdef TORQUE_SHADERGEN + + vec4 inLightPos[3], + vec4 inLightInvRadiusSq, + vec4 inLightColor[4], + vec4 inLightSpotDir[3], + vec4 inLightSpotAngle, + vec4 inLightSpotFalloff, + float specularPower, + vec4 specularColor, + + #endif // TORQUE_SHADERGEN + + out vec4 outDiffuse, + out vec4 outSpecular ) +{ + // NOTE: The light positions and spotlight directions + // are stored in SoA order, so inLightPos[0] is the + // x coord for all 4 lights... inLightPos[1] is y... etc. + // + // This is the key to fully utilizing the vector units and + // saving a huge amount of instructions. + // + // For example this change saved more than 10 instructions + // over a simple for loop for each light. + + int i; + + vec4 lightVectors[3]; + for ( i = 0; i < 3; i++ ) + lightVectors[i] = wsPosition[i] - inLightPos[i]; + + vec4 squareDists = vec4(0); + for ( i = 0; i < 3; i++ ) + squareDists += lightVectors[i] * lightVectors[i]; + + // Accumulate the dot product between the light + // vector and the normal. + // + // The normal is negated because it faces away from + // the surface and the light faces towards the + // surface... this keeps us from needing to flip + // the light vector direction which complicates + // the spot light calculations. + // + // We normalize the result a little later. + // + vec4 nDotL = vec4(0); + for ( i = 0; i < 3; i++ ) + nDotL += lightVectors[i] * -wsNormal[i]; + + vec4 rDotL = vec4(0); + #ifndef TORQUE_BL_NOSPECULAR + + // We're using the Phong specular reflection model + // here where traditionally Torque has used Blinn-Phong + // which has proven to be more accurate to real materials. + // + // We do so because its cheaper as do not need to + // calculate the half angle for all 4 lights. + // + // Advanced Lighting still uses Blinn-Phong, but the + // specular reconstruction it does looks fairly similar + // to this. + // + vec3 R = reflect( wsView, -wsNormal ); + + for ( i = 0; i < 3; i++ ) + rDotL += lightVectors[i] * R[i]; + + #endif + + // Normalize the dots. + // + // Notice we're using the half type here to get a + // much faster sqrt via the rsq_pp instruction at + // the loss of some precision. + // + // Unless we have some extremely large point lights + // i don't believe the precision loss will matter. + // + half4 correction = half4(inversesqrt( squareDists )); + nDotL = saturate( nDotL * correction ); + rDotL = clamp( rDotL * correction, 0.00001, 1.0 ); + + // First calculate a simple point light linear + // attenuation factor. + // + // If this is a directional light the inverse + // radius should be greater than the distance + // causing the attenuation to have no affect. + // + vec4 atten = saturate( 1.0 - ( squareDists * inLightInvRadiusSq ) ); + + #ifndef TORQUE_BL_NOSPOTLIGHT + + // The spotlight attenuation factor. This is really + // fast for what it does... 6 instructions for 4 spots. + + vec4 spotAtten = vec4(0); + for ( i = 0; i < 3; i++ ) + spotAtten += lightVectors[i] * inLightSpotDir[i]; + + vec4 cosAngle = ( spotAtten * correction ) - inLightSpotAngle; + atten *= saturate( cosAngle * inLightSpotFalloff ); + + #endif + + // Finally apply the shadow masking on the attenuation. + atten *= shadowMask; + + // Get the final light intensity. + vec4 intensity = nDotL * atten; + + // Combine the light colors for output. + outDiffuse = vec4(0); + for ( i = 0; i < 4; i++ ) + outDiffuse += intensity[i] * inLightColor[i]; + + // Output the specular power. + vec4 specularIntensity = pow( rDotL, vec4(specularPower) ) * atten; + + // Apply the per-light specular attenuation. + vec4 specular = vec4(0,0,0,1); + for ( i = 0; i < 4; i++ ) + specular += vec4( inLightColor[i].rgb * inLightColor[i].a * specularIntensity[i], 1 ); + + // Add the final specular intensity values together + // using a single dot product operation then get the + // final specular lighting color. + outSpecular = specularColor * specular; +} + + +// This value is used in AL as a constant power to raise specular values +// to, before storing them into the light info buffer. The per-material +// specular value is then computer by using the integer identity of +// exponentiation: +// +// (a^m)^n = a^(m*n) +// +// or +// +// (specular^constSpecular)^(matSpecular/constSpecular) = specular^(matSpecular*constSpecular) +// +#define AL_ConstantSpecularPower 12.0f + +/// The specular calculation used in Advanced Lighting. +/// +/// @param toLight Normalized vector representing direction from the pixel +/// being lit, to the light source, in world space. +/// +/// @param normal Normalized surface normal. +/// +/// @param toEye The normalized vector representing direction from the pixel +/// being lit to the camera. +/// +float AL_CalcSpecular( vec3 toLight, vec3 normal, vec3 toEye ) +{ + // (R.V)^c + float specVal = dot( normalize( -reflect( toLight, normal ) ), toEye ); + + // Return the specular factor. + return pow( max( specVal, 0.00001f ), AL_ConstantSpecularPower ); +} + +/// The output for Deferred Lighting +/// +/// @param toLight Normalized vector representing direction from the pixel +/// being lit, to the light source, in world space. +/// +/// @param normal Normalized surface normal. +/// +/// @param toEye The normalized vector representing direction from the pixel +/// being lit to the camera. +/// +vec4 AL_DeferredOutput( + vec3 lightColor, + vec3 diffuseColor, + vec4 matInfo, + vec4 ambient, + float specular, + float shadowAttenuation) +{ + vec3 specularColor = vec3(specular); + bool metalness = getFlag(matInfo.r, 3); + if ( metalness ) + { + specularColor = 0.04 * (1 - specular) + diffuseColor * specular; + } + + //specular = color * map * spec^gloss + float specularOut = (specularColor * matInfo.b * min(pow(max(specular,1.0f), max((matInfo.a / AL_ConstantSpecularPower),1.0f)),matInfo.a)).r; + + lightColor *= vec3(shadowAttenuation); + lightColor += ambient.rgb; + return vec4(lightColor.rgb, specularOut); +} diff --git a/Templates/BaseGame/game/core/rendering/shaders/gl/particleCompositeP.glsl b/Templates/BaseGame/game/core/rendering/shaders/gl/particleCompositeP.glsl new file mode 100644 index 000000000..e33c9bd97 --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/gl/particleCompositeP.glsl @@ -0,0 +1,62 @@ +//----------------------------------------------------------------------------- +// 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 "torque.glsl" +#include "hlslCompat.glsl" + +in vec4 offscreenPos; +in vec4 backbufferPos; + +#define IN_offscreenPos offscreenPos +#define IN_backbufferPos backbufferPos + +uniform sampler2D colorSource; +uniform vec4 offscreenTargetParams; + +#ifdef TORQUE_LINEAR_DEPTH +#define REJECT_EDGES +uniform sampler2D edgeSource; +uniform vec4 edgeTargetParams; +#endif + +out vec4 OUT_col; + +void main() +{ + // Off-screen particle source screenspace position in XY + // Back-buffer screenspace position in ZW + vec4 ssPos = vec4(offscreenPos.xy / offscreenPos.w, backbufferPos.xy / backbufferPos.w); + + vec4 uvScene = ( ssPos + 1.0 ) / 2.0; + uvScene.yw = 1.0 - uvScene.yw; + uvScene.xy = viewportCoordToRenderTarget(uvScene.xy, offscreenTargetParams); + +#ifdef REJECT_EDGES + // Cut out particles along the edges, this will create the stencil mask + uvScene.zw = viewportCoordToRenderTarget(uvScene.zw, edgeTargetParams); + float edge = texture( edgeSource, uvScene.zw ).r; + clip( -edge ); +#endif + + // Sample offscreen target and return + OUT_col = texture( colorSource, uvScene.xy ); +} \ No newline at end of file diff --git a/Templates/BaseGame/game/core/rendering/shaders/gl/particleCompositeV.glsl b/Templates/BaseGame/game/core/rendering/shaders/gl/particleCompositeV.glsl new file mode 100644 index 000000000..8c8f840d1 --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/gl/particleCompositeV.glsl @@ -0,0 +1,48 @@ +//----------------------------------------------------------------------------- +// 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 "hlslCompat.glsl" + +in vec2 vTexCoord0; +#define uvCoord vTexCoord0 + +out vec4 offscreenPos; +out vec4 backbufferPos; + +#define OUT_hpos gl_Position +#define OUT_offscreenPos offscreenPos +#define OUT_backbufferPos backbufferPos + +uniform vec4 screenRect; // point, extent + +void main() +{ + OUT_hpos = vec4(uvCoord.xy, 1.0, 1.0); + OUT_hpos.xy *= screenRect.zw; + OUT_hpos.xy += screenRect.xy; + + OUT_backbufferPos = OUT_hpos; + OUT_offscreenPos = OUT_hpos; + + correctSSP(gl_Position); +} + diff --git a/Templates/BaseGame/game/core/rendering/shaders/gl/particlesP.glsl b/Templates/BaseGame/game/core/rendering/shaders/gl/particlesP.glsl new file mode 100644 index 000000000..cf35e5f1b --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/gl/particlesP.glsl @@ -0,0 +1,113 @@ +//----------------------------------------------------------------------------- +// 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 "torque.glsl" +#include "hlslCompat.glsl" + +// With advanced lighting we get soft particles. +#ifdef TORQUE_LINEAR_DEPTH + #define SOFTPARTICLES +#endif + +#ifdef SOFTPARTICLES + + #include "shadergen:/autogenConditioners.h" + + uniform float oneOverSoftness; + uniform float oneOverFar; + uniform sampler2D deferredTex; + //uniform vec3 vEye; + uniform vec4 deferredTargetParams; +#endif + +#define CLIP_Z // TODO: Make this a proper macro + +in vec4 color; +in vec2 uv0; +in vec4 pos; + +#define IN_color color +#define IN_uv0 uv0 +#define IN_pos pos + +uniform sampler2D diffuseMap; + +uniform sampler2D paraboloidLightMap; + +vec4 lmSample( vec3 nrm ) +{ + bool calcBack = (nrm.z < 0.0); + if ( calcBack ) + nrm.z = nrm.z * -1.0; + + vec2 lmCoord; + lmCoord.x = (nrm.x / (2*(1 + nrm.z))) + 0.5; + lmCoord.y = 1-((nrm.y / (2*(1 + nrm.z))) + 0.5); + + + // If this is the back, offset in the atlas + if ( calcBack ) + lmCoord.x += 1.0; + + // Atlasing front and back maps, so scale + lmCoord.x *= 0.5; + + return texture(paraboloidLightMap, lmCoord); +} + + +uniform float alphaFactor; +uniform float alphaScale; + +out vec4 OUT_col; + +void main() +{ + float softBlend = 1; + + #ifdef SOFTPARTICLES + vec2 tc = IN_pos.xy * vec2(1.0, -1.0) / IN_pos.w; + tc = viewportCoordToRenderTarget(saturate( ( tc + 1.0 ) * 0.5 ), deferredTargetParams); + + float sceneDepth = deferredUncondition( deferredTex, tc ).w; + float depth = IN_pos.w * oneOverFar; + float diff = sceneDepth - depth; + #ifdef CLIP_Z + // If drawing offscreen, this acts as the depth test, since we don't line up with the z-buffer + // When drawing high-res, though, we want to be able to take advantage of hi-z + // so this is #ifdef'd out + //clip(diff); + #endif + softBlend = saturate( diff * oneOverSoftness ); + #endif + + vec4 diffuse = texture( diffuseMap, IN_uv0 ); + + //OUT_col = vec4( lmSample(vec3(0, 0, -1)).rgb, IN_color.a * diffuse.a * softBlend * alphaScale); + + // Scale output color by the alpha factor (turn LerpAlpha into pre-multiplied alpha) + vec3 colorScale = ( alphaFactor < 0.0 ? IN_color.rgb * diffuse.rgb : vec3( alphaFactor > 0.0 ? IN_color.a * diffuse.a * alphaFactor * softBlend : softBlend ) ); + + OUT_col = hdrEncode( vec4( IN_color.rgb * diffuse.rgb * colorScale, + IN_color.a * diffuse.a * softBlend * alphaScale ) ); +} + diff --git a/Templates/BaseGame/game/core/rendering/shaders/gl/particlesV.glsl b/Templates/BaseGame/game/core/rendering/shaders/gl/particlesV.glsl new file mode 100644 index 000000000..3d75a6fb6 --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/gl/particlesV.glsl @@ -0,0 +1,54 @@ +//----------------------------------------------------------------------------- +// 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 "hlslCompat.glsl" + +in vec4 vPosition; +in vec4 vColor; +in vec2 vTexCoord0; + +#define In_pos vPosition +#define In_color vColor +#define In_uv0 vTexCoord0 + +out vec4 color; +out vec2 uv0; +out vec4 pos; + +#define OUT_hpos gl_Position +#define OUT_color color +#define OUT_uv0 uv0 +#define OUT_pos pos + +uniform mat4 modelViewProj; +uniform mat4 fsModelViewProj; + +void main() +{ + OUT_hpos = tMul( modelViewProj, In_pos ); + OUT_pos = tMul( fsModelViewProj, In_pos ); + OUT_color = In_color; + OUT_uv0 = In_uv0; + + correctSSP(gl_Position); +} + diff --git a/Templates/BaseGame/game/core/rendering/shaders/gl/planarReflectBumpP.glsl b/Templates/BaseGame/game/core/rendering/shaders/gl/planarReflectBumpP.glsl new file mode 100644 index 000000000..db4250487 --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/gl/planarReflectBumpP.glsl @@ -0,0 +1,70 @@ +//----------------------------------------------------------------------------- +// 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. +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// Data +//----------------------------------------------------------------------------- +uniform sampler2D diffuseMap, refractMap, bumpMap; +uniform vec4 shadeColor; + +in vec2 TEX0; +in vec4 TEX1; + +out vec4 OUT_col; + +//----------------------------------------------------------------------------- +// Fade edges of axis for texcoord passed in +//----------------------------------------------------------------------------- +float fadeAxis( float val ) +{ + // Fades from 1.0 to 0.0 when less than 0.1 + float fadeLow = clamp( val * 10.0, 0.0, 1.0 ); + + // Fades from 1.0 to 0.0 when greater than 0.9 + float fadeHigh = 1.0 - clamp( (val - 0.9) * 10.0, 0.0, 1.0 ); + + return fadeLow * fadeHigh; +} + + +//----------------------------------------------------------------------------- +// Main +//----------------------------------------------------------------------------- +void main() +{ + vec3 bumpNorm = texture( bumpMap, TEX0 ).rgb * 2.0 - 1.0; + vec2 offset = vec2( bumpNorm.x, bumpNorm.y ); + vec4 texIndex = TEX1; + + // The fadeVal is used to "fade" the distortion at the edges of the screen. + // This is done so it won't sample the reflection texture out-of-bounds and create artifacts + // Note - this can be done more efficiently with a texture lookup + float fadeVal = fadeAxis( texIndex.x / texIndex.w ) * fadeAxis( texIndex.y / texIndex.w ); + + const float distortion = 0.2; + texIndex.xy += offset * distortion * fadeVal; + + vec4 diffuseColor = texture( diffuseMap, TEX0 ); + vec4 reflectColor = textureProj( refractMap, texIndex ); + + OUT_col = diffuseColor + reflectColor * diffuseColor.a; +} diff --git a/Templates/BaseGame/game/core/rendering/shaders/gl/planarReflectBumpV.glsl b/Templates/BaseGame/game/core/rendering/shaders/gl/planarReflectBumpV.glsl new file mode 100644 index 000000000..90bcd27d8 --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/gl/planarReflectBumpV.glsl @@ -0,0 +1,51 @@ +//----------------------------------------------------------------------------- +// 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. +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// Data +//----------------------------------------------------------------------------- +in vec4 vPosition; +in vec2 vTexCoord0; + +uniform mat4 modelview; + +out vec2 TEX0; +out vec4 TEX1; + +//----------------------------------------------------------------------------- +// Main +//----------------------------------------------------------------------------- +void main() +{ + mat4 texGenTest = mat4(0.5, 0.0, 0.0, 0.0, + 0.0, -0.5, 0.0, 0.0, + 0.0, 0.0, 1.0, 0.0, + 0.5, 0.5, 0.0, 1.0); + + gl_Position = modelview * vPosition; + + TEX0 = vTexCoord0.st; + + TEX1 = texGenTest * gl_Position; + TEX1.y = -TEX1.y; + gl_Position.y *= -1; +} diff --git a/Templates/BaseGame/game/core/rendering/shaders/gl/planarReflectP.glsl b/Templates/BaseGame/game/core/rendering/shaders/gl/planarReflectP.glsl new file mode 100644 index 000000000..384c16188 --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/gl/planarReflectP.glsl @@ -0,0 +1,43 @@ +//----------------------------------------------------------------------------- +// 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. +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// Data +//----------------------------------------------------------------------------- +uniform sampler2D diffuseMap, refractMap; +uniform vec4 shadeColor; + +in vec2 TEX0; +in vec4 TEX1; + +out vec4 OUT_col; + +//----------------------------------------------------------------------------- +// Main +//----------------------------------------------------------------------------- +void main() +{ + vec4 diffuseColor = texture( diffuseMap, TEX0 ); + vec4 reflectColor = textureProj( refractMap, TEX1 ); + + OUT_col = diffuseColor + reflectColor * diffuseColor.a; +} diff --git a/Templates/BaseGame/game/core/rendering/shaders/gl/planarReflectV.glsl b/Templates/BaseGame/game/core/rendering/shaders/gl/planarReflectV.glsl new file mode 100644 index 000000000..ba2484f66 --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/gl/planarReflectV.glsl @@ -0,0 +1,51 @@ +//----------------------------------------------------------------------------- +// 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. +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// Data +//----------------------------------------------------------------------------- +in vec4 vPosition; +in vec2 vTexCoord0; + +uniform mat4 modelview; + +out vec2 TEX0; +out vec4 TEX1; + +//----------------------------------------------------------------------------- +// Main +//----------------------------------------------------------------------------- +void main() +{ + mat4 texGenTest = mat4(0.5, 0.0, 0.0, 0.0, + 0.0, -0.5, 0.0, 0.0, + 0.0, 0.0, 1.0, 0.0, + 0.5, 0.5, 0.0, 1.0); + + gl_Position = modelview * vPosition; + + TEX0 = vTexCoord0; + + TEX1 = texGenTest * gl_Position; + TEX1.y = -TEX1.y; + +} diff --git a/Templates/BaseGame/game/core/rendering/shaders/gl/precipP.glsl b/Templates/BaseGame/game/core/rendering/shaders/gl/precipP.glsl new file mode 100644 index 000000000..102d0b0aa --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/gl/precipP.glsl @@ -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. +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// Data +//----------------------------------------------------------------------------- +uniform sampler2D diffuseMap; + +in vec4 color; +in vec2 texCoord; + +out vec4 OUT_col; + +//----------------------------------------------------------------------------- +// Main +//----------------------------------------------------------------------------- +void main() +{ + OUT_col = texture(diffuseMap, texCoord) * color; +} diff --git a/Templates/BaseGame/game/core/rendering/shaders/gl/precipV.glsl b/Templates/BaseGame/game/core/rendering/shaders/gl/precipV.glsl new file mode 100644 index 000000000..29f921630 --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/gl/precipV.glsl @@ -0,0 +1,54 @@ +//----------------------------------------------------------------------------- +// 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. +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// Data +//----------------------------------------------------------------------------- +in vec4 vPosition; +in vec2 vTexCoord0; + +uniform mat4 modelview; +uniform vec3 cameraPos, ambient; +uniform vec2 fadeStartEnd; + +out vec4 color; +out vec2 texCoord; + +//----------------------------------------------------------------------------- +// Main +//----------------------------------------------------------------------------- +void main() +{ + gl_Position = modelview * vPosition; + texCoord = vTexCoord0.st; + color = vec4( ambient.r, ambient.g, ambient.b, 1.0 ); + + // Do we need to do a distance fade? + if ( fadeStartEnd.x < fadeStartEnd.y ) + { + + float distance = length( cameraPos - vPosition.xyz ); + color.a = abs( clamp( ( distance - fadeStartEnd.x ) / ( fadeStartEnd.y - fadeStartEnd.x ), 0.0, 1.0 ) - 1.0 ); + } + gl_Position.y *= -1; +} + diff --git a/Templates/BaseGame/game/core/rendering/shaders/gl/projectedShadowP.glsl b/Templates/BaseGame/game/core/rendering/shaders/gl/projectedShadowP.glsl new file mode 100644 index 000000000..9b0ff0d0b --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/gl/projectedShadowP.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. +//----------------------------------------------------------------------------- + +in vec2 texCoord; +in vec4 color; +in float fade; + +out vec4 OUT_col; + +uniform sampler2D inputTex; +uniform vec4 ambient; + + +void main() +{ + float shadow = texture( inputTex, texCoord ).a * color.a; + OUT_col = ( ambient * shadow ) + ( 1 - shadow ); +} diff --git a/Templates/BaseGame/game/core/rendering/shaders/gl/projectedShadowV.glsl b/Templates/BaseGame/game/core/rendering/shaders/gl/projectedShadowV.glsl new file mode 100644 index 000000000..c8b6d2a92 --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/gl/projectedShadowV.glsl @@ -0,0 +1,49 @@ +//----------------------------------------------------------------------------- +// 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 "hlslCompat.glsl" + +in vec4 vPosition; +in vec4 vColor; +in vec2 vTexCoord0; +in vec2 vTexCoord1; + +out vec2 texCoord; +out vec4 color; +out float fade; + +uniform mat4 modelview; +uniform float shadowLength; +uniform vec3 shadowCasterPosition; + +void main() +{ + gl_Position = modelview * vec4(vPosition.xyz, 1.0); + + color = vColor; + texCoord = vTexCoord0.st; + + float fromCasterDist = length(vPosition.xyz - shadowCasterPosition) - shadowLength; + fade = 1.0 - clamp( fromCasterDist / shadowLength , 0.0, 1.0 ); + + correctSSP(gl_Position); +} diff --git a/Templates/BaseGame/game/core/rendering/shaders/gl/scatterSkyP.glsl b/Templates/BaseGame/game/core/rendering/shaders/gl/scatterSkyP.glsl new file mode 100644 index 000000000..6d4e3ea75 --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/gl/scatterSkyP.glsl @@ -0,0 +1,72 @@ +//----------------------------------------------------------------------------- +// 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 "torque.glsl" +#include "hlslCompat.glsl" + + +// Conn +in vec4 rayleighColor; +#define IN_rayleighColor rayleighColor +in vec4 mieColor; +#define IN_mieColor mieColor +in vec3 v3Direction; +#define IN_v3Direction v3Direction +in vec3 pos; +#define IN_pos pos + +uniform samplerCube nightSky ; +uniform vec4 nightColor; +uniform vec2 nightInterpAndExposure; +uniform float useCubemap; +uniform vec3 lightDir; +uniform vec3 sunDir; + +out vec4 OUT_col; + +void main() +{ + + float fCos = dot( lightDir, IN_v3Direction ) / length(IN_v3Direction); + float fCos2 = fCos*fCos; + + float g = -0.991; + float g2 = -0.991 * -0.991; + + float fMiePhase = 1.5 * ((1.0 - g2) / (2.0 + g2)) * (1.0 + fCos2) / pow(abs(1.0 + g2 - 2.0*g*fCos), 1.5); + + vec4 color = IN_rayleighColor + fMiePhase * IN_mieColor; + color.a = color.b; + + vec4 nightSkyColor = texture(nightSky, -v3Direction); + nightSkyColor = mix(nightColor, nightSkyColor, useCubemap); + + float fac = dot( normalize( pos ), sunDir ); + fac = max( nightInterpAndExposure.y, pow( clamp( fac, 0.0, 1.0 ), 2 ) ); + OUT_col = mix( color, nightSkyColor, nightInterpAndExposure.y ); + + OUT_col.a = 1; + + OUT_col = clamp(OUT_col, 0.0, 1.0); + + OUT_col = hdrEncode( OUT_col ); +} diff --git a/Templates/BaseGame/game/core/rendering/shaders/gl/scatterSkyV.glsl b/Templates/BaseGame/game/core/rendering/shaders/gl/scatterSkyV.glsl new file mode 100644 index 000000000..5780d2df9 --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/gl/scatterSkyV.glsl @@ -0,0 +1,154 @@ +//----------------------------------------------------------------------------- +// 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 "hlslCompat.glsl" + +// The scale equation calculated by Vernier's Graphical Analysis +float vernierScale(float fCos) +{ + float x = 1.0 - fCos; + float x5 = x * 5.25; + float x5p6 = (-6.80 + x5); + float xnew = (3.83 + x * x5p6); + float xfinal = (0.459 + x * xnew); + float xfinal2 = -0.00287 + x * xfinal; + float outx = exp( xfinal2 ); + return 0.25 * outx; +} + +in vec4 vPosition; + +// This is the shader input vertex structure. +#define IN_position vPosition + +// This is the shader output data. +out vec4 rayleighColor; +#define OUT_rayleighColor rayleighColor +out vec4 mieColor; +#define OUT_mieColor mieColor +out vec3 v3Direction; +#define OUT_v3Direction v3Direction +out vec3 pos; +#define OUT_pos pos + +uniform mat4 modelView; +uniform vec4 misc; +uniform vec4 sphereRadii; +uniform vec4 scatteringCoeffs; +uniform vec3 camPos; +uniform vec3 lightDir; +uniform vec4 invWaveLength; +uniform vec4 colorize; + +vec3 desaturate(const vec3 color, const float desaturation) +{ + const vec3 gray_conv = vec3 (0.30, 0.59, 0.11); + return mix(color, vec3(dot(gray_conv , color)), desaturation); +} + +void main() +{ + // Pull some variables out: + float camHeight = misc.x; + float camHeightSqr = misc.y; + + float scale = misc.z; + float scaleOverScaleDepth = misc.w; + + float outerRadius = sphereRadii.x; + float outerRadiusSqr = sphereRadii.y; + + float innerRadius = sphereRadii.z; + float innerRadiusSqr = sphereRadii.w; + + float rayleighBrightness = scatteringCoeffs.x; // Kr * ESun + float rayleigh4PI = scatteringCoeffs.y; // Kr * 4 * PI + + float mieBrightness = scatteringCoeffs.z; // Km * ESun + float mie4PI = scatteringCoeffs.w; // Km * 4 * PI + + // Get the ray from the camera to the vertex, + // and its length (which is the far point of the ray + // passing through the atmosphere). + vec3 v3Pos = vec3(IN_position / 6378000.0);// / outerRadius; + vec3 newCamPos = vec3( 0, 0, camHeight ); + v3Pos.z += innerRadius; + vec3 v3Ray = v3Pos.xyz - newCamPos; + float fFar = length(v3Ray); + v3Ray /= fFar; + + // Calculate the ray's starting position, + // then calculate its scattering offset. + vec3 v3Start = newCamPos; + float fHeight = length(v3Start); + float fDepth = exp(scaleOverScaleDepth * (innerRadius - camHeight)); + float fStartAngle = dot(v3Ray, v3Start) / fHeight; + + float fStartOffset = fDepth * vernierScale( fStartAngle ); + + // Initialize the scattering loop variables. + float fSampleLength = fFar / 2.0; + float fScaledLength = fSampleLength * scale; + vec3 v3SampleRay = v3Ray * fSampleLength; + vec3 v3SamplePoint = v3Start + v3SampleRay * 0.5; + + // Now loop through the sample rays + vec3 v3FrontColor = vec3(0.0, 0.0, 0.0); + for(int i=0; i<2; i++) + { + float fHeight = length(v3SamplePoint); + float fDepth = exp(scaleOverScaleDepth * (innerRadius - fHeight)); + float fLightAngle = dot(lightDir, v3SamplePoint) / fHeight; + float fCameraAngle = dot(v3Ray, v3SamplePoint) / fHeight; + + float vscale3 = vernierScale( fCameraAngle ); + float vscale2 = vernierScale( fLightAngle ); + + float fScatter = (fStartOffset + fDepth*(vscale2 - vscale3)); + vec3 v3Attenuate = exp(-fScatter * (invWaveLength.xyz * rayleigh4PI + mie4PI)); + v3FrontColor += v3Attenuate * (fDepth * fScaledLength); + v3SamplePoint += v3SampleRay; + } + + // Finally, scale the Mie and Rayleigh colors + // and set up the varying variables for the pixel shader. + gl_Position = modelView * IN_position; + OUT_mieColor.rgb = v3FrontColor * mieBrightness; + OUT_mieColor.a = 1.0; + OUT_rayleighColor.rgb = v3FrontColor * (invWaveLength.xyz * rayleighBrightness); + OUT_rayleighColor.a = 1.0; + OUT_v3Direction = newCamPos - v3Pos.xyz; + OUT_pos = IN_position.xyz; + +#ifdef USE_COLORIZE + + OUT_rayleighColor.rgb = desaturate(OUT_rayleighColor.rgb, 1) * colorize.a; + + OUT_rayleighColor.r *= colorize.r; + OUT_rayleighColor.g *= colorize.g; + OUT_rayleighColor.b *= colorize.b; + +#endif + + correctSSP(gl_Position); +} + diff --git a/Templates/BaseGame/game/core/rendering/shaders/gl/torque.glsl b/Templates/BaseGame/game/core/rendering/shaders/gl/torque.glsl new file mode 100644 index 000000000..6e369bd5e --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/gl/torque.glsl @@ -0,0 +1,339 @@ +//----------------------------------------------------------------------------- +// 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 _TORQUE_GLSL_ +#define _TORQUE_GLSL_ + + +float M_HALFPI_F = 1.57079632679489661923; +float M_PI_F = 3.14159265358979323846; +float M_2PI_F = 6.28318530717958647692; + +/// Calculate fog based on a start and end positions in worldSpace. +float computeSceneFog( vec3 startPos, + vec3 endPos, + float fogDensity, + float fogDensityOffset, + float fogHeightFalloff ) +{ + float f = length( startPos - endPos ) - fogDensityOffset; + float h = 1.0 - ( endPos.z * fogHeightFalloff ); + return exp( -fogDensity * f * h ); +} + + +/// Calculate fog based on a start and end position and a height. +/// Positions do not need to be in worldSpace but height does. +float computeSceneFog( vec3 startPos, + vec3 endPos, + float height, + float fogDensity, + float fogDensityOffset, + float fogHeightFalloff ) +{ + float f = length( startPos - endPos ) - fogDensityOffset; + float h = 1.0 - ( height * fogHeightFalloff ); + return exp( -fogDensity * f * h ); +} + + +/// Calculate fog based on a distance, height is not used. +float computeSceneFog( float dist, float fogDensity, float fogDensityOffset ) +{ + float f = dist - fogDensityOffset; + return exp( -fogDensity * f ); +} + + +/// Convert a vec4 uv in viewport space to render target space. +vec2 viewportCoordToRenderTarget( vec4 inCoord, vec4 rtParams ) +{ + vec2 outCoord = inCoord.xy / inCoord.w; + outCoord = ( outCoord * rtParams.zw ) + rtParams.xy; + return outCoord; +} + + +/// Convert a vec2 uv in viewport space to render target space. +vec2 viewportCoordToRenderTarget( vec2 inCoord, vec4 rtParams ) +{ + vec2 outCoord = ( inCoord * rtParams.zw ) + rtParams.xy; + return outCoord; +} + + +/// Convert a vec4 quaternion into a 3x3 matrix. +mat3x3 quatToMat( vec4 quat ) +{ + float xs = quat.x * 2.0; + float ys = quat.y * 2.0; + float zs = quat.z * 2.0; + + float wx = quat.w * xs; + float wy = quat.w * ys; + float wz = quat.w * zs; + + float xx = quat.x * xs; + float xy = quat.x * ys; + float xz = quat.x * zs; + + float yy = quat.y * ys; + float yz = quat.y * zs; + float zz = quat.z * zs; + + mat3x3 mat; + + mat[0][0] = 1.0 - (yy + zz); + mat[1][0] = xy - wz; + mat[2][0] = xz + wy; + + mat[0][1] = xy + wz; + mat[1][1] = 1.0 - (xx + zz); + mat[2][1] = yz - wx; + + mat[0][2] = xz - wy; + mat[1][2] = yz + wx; + mat[2][2] = 1.0 - (xx + yy); + + return mat; +} + + +/// The number of additional substeps we take when refining +/// the results of the offset parallax mapping function below. +/// +/// You should turn down the number of steps if your needing +/// more performance out of your parallax surfaces. Increasing +/// the number doesn't yeild much better results and is rarely +/// worth the additional cost. +/// +#define PARALLAX_REFINE_STEPS 3 + +/// Performs fast parallax offset mapping using +/// multiple refinement steps. +/// +/// @param texMap The texture map whos alpha channel we sample the parallax depth. +/// @param texCoord The incoming texture coordinate for sampling the parallax depth. +/// @param negViewTS The negative view vector in tangent space. +/// @param depthScale The parallax factor used to scale the depth result. +/// +vec2 parallaxOffset( sampler2D texMap, vec2 texCoord, vec3 negViewTS, float depthScale ) +{ + float depth = texture( texMap, texCoord ).a/(PARALLAX_REFINE_STEPS*2); + vec2 offset = negViewTS.xy * vec2( depth * depthScale )/vec2(PARALLAX_REFINE_STEPS*2); + + for ( int i=0; i < PARALLAX_REFINE_STEPS; i++ ) + { + depth = ( depth + texture( texMap, texCoord + offset ).a )/(PARALLAX_REFINE_STEPS*2); + offset = negViewTS.xy * vec2( depth * depthScale )/vec2(PARALLAX_REFINE_STEPS*2); + } + + return offset; +} + +/// Same as parallaxOffset but for dxtnm where depth is stored in the red channel instead of the alpha +vec2 parallaxOffsetDxtnm(sampler2D texMap, vec2 texCoord, vec3 negViewTS, float depthScale) +{ + float depth = texture(texMap, texCoord).r/(PARALLAX_REFINE_STEPS*2); + vec2 offset = negViewTS.xy * vec2(depth * depthScale)/vec2(PARALLAX_REFINE_STEPS*2); + + for (int i = 0; i < PARALLAX_REFINE_STEPS; i++) + { + depth = (depth + texture(texMap, texCoord + offset).r)/(PARALLAX_REFINE_STEPS*2); + offset = negViewTS.xy * vec2(depth * depthScale)/vec2(PARALLAX_REFINE_STEPS*2); + } + + return offset; +} + + +/// The maximum value for 16bit per component integer HDR encoding. +const float HDR_RGB16_MAX = 100.0; +/// The maximum value for 10bit per component integer HDR encoding. +const float HDR_RGB10_MAX = 4.0; + +/// Encodes an HDR color for storage into a target. +vec3 hdrEncode( vec3 _sample ) +{ + #if defined( TORQUE_HDR_RGB16 ) + + return _sample / HDR_RGB16_MAX; + + #elif defined( TORQUE_HDR_RGB10 ) + + return _sample / HDR_RGB10_MAX; + + #else + + // No encoding. + return _sample; + + #endif +} + +/// Encodes an HDR color for storage into a target. +vec4 hdrEncode( vec4 _sample ) +{ + return vec4( hdrEncode( _sample.rgb ), _sample.a ); +} + +/// Decodes an HDR color from a target. +vec3 hdrDecode( vec3 _sample ) +{ + #if defined( TORQUE_HDR_RGB16 ) + + return _sample * HDR_RGB16_MAX; + + #elif defined( TORQUE_HDR_RGB10 ) + + return _sample * HDR_RGB10_MAX; + + #else + + // No encoding. + return _sample; + + #endif +} + +/// Decodes an HDR color from a target. +vec4 hdrDecode( vec4 _sample ) +{ + return vec4( hdrDecode( _sample.rgb ), _sample.a ); +} + +/// Returns the luminance for an HDR pixel. +float hdrLuminance( vec3 _sample ) +{ + // There are quite a few different ways to + // calculate luminance from an rgb value. + // + // If you want to use a different technique + // then plug it in here. + // + + //////////////////////////////////////////////////////////////////////////// + // + // Max component luminance. + // + //float lum = max( _sample.r, max( _sample.g, _sample.b ) ); + + //////////////////////////////////////////////////////////////////////////// + // The perceptual relative luminance. + // + // See http://en.wikipedia.org/wiki/Luminance_(relative) + // + const vec3 RELATIVE_LUMINANCE = vec3( 0.2126, 0.7152, 0.0722 ); + float lum = dot( _sample, RELATIVE_LUMINANCE ); + + //////////////////////////////////////////////////////////////////////////// + // + // The average component luminance. + // + //const vec3 AVERAGE_LUMINANCE = vec3( 0.3333, 0.3333, 0.3333 ); + //float lum = dot( _sample, AVERAGE_LUMINANCE ); + + return lum; +} + +#ifdef TORQUE_PIXEL_SHADER +/// Called from the visibility feature to do screen +/// door transparency for fading of objects. +void fizzle(vec2 vpos, float visibility) +{ + // NOTE: The magic values below are what give us + // the nice even pattern during the fizzle. + // + // These values can be changed to get different + // patterns... some better than others. + // + // Horizontal Blinds - { vpos.x, 0.916, vpos.y, 0 } + // Vertical Lines - { vpos.x, 12.9898, vpos.y, 78.233 } + // + // I'm sure there are many more patterns here to + // discover for different effects. + + mat2x2 m = mat2x2( vpos.x, vpos.y, 0.916, 0.350 ); + if( (visibility - fract( determinant( m ) )) < 0 ) //if(a < 0) discard; + discard; +} +#endif //TORQUE_PIXEL_SHADER + +/// Basic assert macro. If the condition fails, then the shader will output color. +/// @param condition This should be a bvec[2-4]. If any items is false, condition is considered to fail. +/// @param color The color that should be outputted if the condition fails. +/// @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, float num) +{ + float process = round(flags * 255); + float squareNum = pow(2.0, num); + return (mod(process, pow(2.0, 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; +} +vec3 toLinear(vec3 tex) +{ + return tex; +} +// Encodes gamma. +vec3 toGamma(vec3 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); +} +// Sample in linear space. Decodes gamma. +vec3 toLinear(vec3 tex) +{ + return pow(abs(tex), vec3(2.2)); +} +// Encodes gamma. +vec3 toGamma(vec3 tex) +{ + return pow(abs(tex), vec3(1.0/2.2)); +} +#endif // + +#endif // _TORQUE_GLSL_ diff --git a/Templates/BaseGame/game/core/rendering/shaders/gl/wavesP.glsl b/Templates/BaseGame/game/core/rendering/shaders/gl/wavesP.glsl new file mode 100644 index 000000000..06c8a1a28 --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/gl/wavesP.glsl @@ -0,0 +1,57 @@ +//----------------------------------------------------------------------------- +// 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 sampler2D diffMap; +uniform sampler2D bumpMap; +uniform samplerCube cubeMap; +uniform vec4 specularColor; +uniform float specularPower; +uniform vec4 ambient; +uniform float accumTime; + +in vec2 TEX0; +in vec4 outLightVec; +in vec3 outPos; +in vec3 outEyePos; + +out vec4 OUT_col; + +void main() +{ + vec2 texOffset; + float sinOffset1 = sin( accumTime * 1.5 + TEX0.y * 6.28319 * 3.0 ) * 0.03; + float sinOffset2 = sin( accumTime * 3.0 + TEX0.y * 6.28319 ) * 0.04; + + texOffset.x = TEX0.x + sinOffset1 + sinOffset2; + texOffset.y = TEX0.y + cos( accumTime * 3.0 + TEX0.x * 6.28319 * 2.0 ) * 0.05; + + vec4 bumpNorm = texture(bumpMap, texOffset) * 2.0 - 1.0; + vec4 diffuse = texture(diffMap, texOffset); + + OUT_col = diffuse * (clamp(dot(outLightVec.xyz, bumpNorm.xyz), 0.0, 1.0) + ambient); + + vec3 eyeVec = normalize(outEyePos - outPos); + vec3 halfAng = normalize(eyeVec + outLightVec.xyz); + float specular = clamp(dot(bumpNorm.xyz, halfAng), 0.0, 1.0) * outLightVec.w; + specular = pow(specular, specularPower); + OUT_col += specularColor * specular; +} diff --git a/Templates/BaseGame/game/core/rendering/shaders/gl/wind.glsl b/Templates/BaseGame/game/core/rendering/shaders/gl/wind.glsl new file mode 100644 index 000000000..0ddb492b9 --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/gl/wind.glsl @@ -0,0 +1,101 @@ +//----------------------------------------------------------------------------- +// 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. +//----------------------------------------------------------------------------- + +// +// A tip of the hat.... +// +// The following wind effects were derived from the GPU Gems +// 3 chapter "Vegetation Procedural Animation and Shading in Crysis" +// by Tiago Sousa of Crytek. +// + +vec4 smoothCurve( vec4 x ) +{ + return x * x * ( 3.0 - 2.0 * x ); +} + +vec4 triangleWave( vec4 x ) +{ + return abs( fract( x + 0.5 ) * 2.0 - 1.0 ); +} + +vec4 smoothTriangleWave( vec4 x ) +{ + return smoothCurve( triangleWave( x ) ); +} + +vec3 windTrunkBending( vec3 vPos, vec2 vWind, float fBendFactor ) +{ + // Smooth the bending factor and increase + // the near by height limit. + fBendFactor += 1.0; + fBendFactor *= fBendFactor; + fBendFactor = fBendFactor * fBendFactor - fBendFactor; + + // Displace the vert. + vec3 vNewPos = vPos; + vNewPos.xy += vWind * fBendFactor; + + // Limit the length which makes the bend more + // spherical and prevents stretching. + float fLength = length( vPos ); + vPos = normalize( vNewPos ) * fLength; + + return vPos; +} + +vec3 windBranchBending( vec3 vPos, + vec3 vNormal, + + float fTime, + float fWindSpeed, + + float fBranchPhase, + float fBranchAmp, + float fBranchAtten, + + float fDetailPhase, + float fDetailAmp, + float fDetailFreq, + + float fEdgeAtten ) +{ + float fVertPhase = dot( vPos, vec3( fDetailPhase + fBranchPhase ) ); + + vec2 vWavesIn = fTime + vec2( fVertPhase, fBranchPhase ); + + vec4 vWaves = ( fract( vWavesIn.xxyy * + vec4( 1.975, 0.793, 0.375, 0.193 ) ) * + 2.0 - 1.0 ) * fWindSpeed * fDetailFreq; + + vWaves = smoothTriangleWave( vWaves ); + + vec2 vWavesSum = vWaves.xz + vWaves.yw; + + // We want the branches to bend both up and down. + vWavesSum.y = 1.0 - ( vWavesSum.y * 2.0 ); + + vPos += vWavesSum.xxy * vec3( fEdgeAtten * fDetailAmp * vNormal.xy, + fBranchAtten * fBranchAmp ); + + return vPos; +} diff --git a/Templates/BaseGame/game/core/rendering/shaders/guiMaterialV.hlsl b/Templates/BaseGame/game/core/rendering/shaders/guiMaterialV.hlsl new file mode 100644 index 000000000..5d725338f --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/guiMaterialV.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. +//----------------------------------------------------------------------------- + +#include "hlslStructs.hlsl" +#include "shaderModel.hlsl" + +struct MaterialDecoratorConnectV +{ + float4 hpos : TORQUE_POSITION; + float2 uv0 : TEXCOORD0; +}; + +uniform float4x4 modelview : register(C0); + +//----------------------------------------------------------------------------- +// Main +//----------------------------------------------------------------------------- +MaterialDecoratorConnectV main( VertexIn_PCT IN ) +{ + MaterialDecoratorConnectV OUT; + + OUT.hpos = mul(modelview, float4(IN.pos,1.0)); + OUT.uv0 = IN.uv0; + + return OUT; +} diff --git a/Templates/BaseGame/game/core/rendering/shaders/hlslStructs.h b/Templates/BaseGame/game/core/rendering/shaders/hlslStructs.h new file mode 100644 index 000000000..6a57e4db7 --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/hlslStructs.h @@ -0,0 +1,116 @@ +//----------------------------------------------------------------------------- +// 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. +//----------------------------------------------------------------------------- + +// The purpose of this file is to get all of our HLSL structures into one place. +// Please use the structures here instead of redefining input and output structures +// in each shader file. If structures are added, please adhere to the naming convention. + +//------------------------------------------------------------------------------ +// Vertex Input Structures +// +// These structures map to FVFs/Vertex Declarations in Torque. See gfxStructs.h +//------------------------------------------------------------------------------ + +// Notes +// +// Position should be specified as a float4. Right now our vertex structures in +// the engine output float3s for position. This does NOT mean that the POSITION +// binding should be float3, because it will assign 0 to the w coordinate, which +// results in the vertex not getting translated when it is transformed. + +struct VertexIn_P +{ + float4 pos : POSITION; +}; + +struct VertexIn_PT +{ + float4 pos : POSITION; + float2 uv0 : TEXCOORD0; +}; + +struct VertexIn_PTTT +{ + float4 pos : POSITION; + float2 uv0 : TEXCOORD0; + float2 uv1 : TEXCOORD1; + float2 uv2 : TEXCOORD2; +}; + +struct VertexIn_PC +{ + float4 pos : POSITION; + float4 color : DIFFUSE; +}; + +struct VertexIn_PNC +{ + float4 pos : POSITION; + float3 normal : NORMAL; + float4 color : DIFFUSE; +}; + +struct VertexIn_PCT +{ + float4 pos : POSITION; + float4 color : DIFFUSE; + float2 uv0 : TEXCOORD0; +}; + +struct VertexIn_PN +{ + float4 pos : POSITION; + float3 normal : NORMAL; +}; + +struct VertexIn_PNT +{ + float4 pos : POSITION; + float3 normal : NORMAL; + float2 uv0 : TEXCOORD0; +}; + +struct VertexIn_PNTT +{ + float4 pos : POSITION; + float3 normal : NORMAL; + float3 tangent : TANGENT; + float2 uv0 : TEXCOORD0; +}; + +struct VertexIn_PNCT +{ + float4 pos : POSITION; + float3 normal : NORMAL; + float4 color : DIFFUSE; + float2 uv0 : TEXCOORD0; +}; + +struct VertexIn_PNTTTB +{ + float4 pos : POSITION; + float3 normal : NORMAL; + float2 uv0 : TEXCOORD0; + float2 uv1 : TEXCOORD1; + float3 T : TEXCOORD2; + float3 B : TEXCOORD3; +}; \ No newline at end of file diff --git a/Templates/BaseGame/game/core/rendering/shaders/hlslStructs.hlsl b/Templates/BaseGame/game/core/rendering/shaders/hlslStructs.hlsl new file mode 100644 index 000000000..ce0ca305c --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/hlslStructs.hlsl @@ -0,0 +1,114 @@ +//----------------------------------------------------------------------------- +// 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. +//----------------------------------------------------------------------------- + +// The purpose of this file is to get all of our HLSL structures into one place. +// Please use the structures here instead of redefining input and output structures +// in each shader file. If structures are added, please adhere to the naming convention. + +//------------------------------------------------------------------------------ +// Vertex Input Structures +// +// These structures map to FVFs/Vertex Declarations in Torque. See gfxStructs.h +//------------------------------------------------------------------------------ + +// Notes +// +// Position should be specified as a float3 as our vertex structures in +// the engine output float3s for position. + +struct VertexIn_P +{ + float3 pos : POSITION; +}; + +struct VertexIn_PT +{ + float3 pos : POSITION; + float2 uv0 : TEXCOORD0; +}; + +struct VertexIn_PTTT +{ + float3 pos : POSITION; + float2 uv0 : TEXCOORD0; + float2 uv1 : TEXCOORD1; + float2 uv2 : TEXCOORD2; +}; + +struct VertexIn_PC +{ + float3 pos : POSITION; + float4 color : DIFFUSE; +}; + +struct VertexIn_PNC +{ + float3 pos : POSITION; + float3 normal : NORMAL; + float4 color : DIFFUSE; +}; + +struct VertexIn_PCT +{ + float3 pos : POSITION; + float4 color : DIFFUSE; + float2 uv0 : TEXCOORD0; +}; + +struct VertexIn_PN +{ + float3 pos : POSITION; + float3 normal : NORMAL; +}; + +struct VertexIn_PNT +{ + float3 pos : POSITION; + float3 normal : NORMAL; + float2 uv0 : TEXCOORD0; +}; + +struct VertexIn_PNTT +{ + float3 pos : POSITION; + float3 normal : NORMAL; + float3 tangent : TANGENT; + float2 uv0 : TEXCOORD0; +}; + +struct VertexIn_PNCT +{ + float3 pos : POSITION; + float3 normal : NORMAL; + float4 color : DIFFUSE; + float2 uv0 : TEXCOORD0; +}; + +struct VertexIn_PNTTTB +{ + float3 pos : POSITION; + float3 normal : NORMAL; + float2 uv0 : TEXCOORD0; + float2 uv1 : TEXCOORD1; + float3 T : TEXCOORD2; + float3 B : TEXCOORD3; +}; \ No newline at end of file diff --git a/Templates/BaseGame/game/core/rendering/shaders/imposter.hlsl b/Templates/BaseGame/game/core/rendering/shaders/imposter.hlsl new file mode 100644 index 000000000..bc700ba03 --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/imposter.hlsl @@ -0,0 +1,149 @@ +//----------------------------------------------------------------------------- +// 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 "torque.hlsl" + + +static float sCornerRight[4] = { -1, 1, 1, -1 }; +static float sCornerUp[4] = { -1, -1, 1, 1 }; +static float2 sUVCornerExtent[4] = +{ + float2( 0, 1 ), + float2( 1, 1 ), + float2( 1, 0 ), + float2( 0, 0 ) +}; + +#define IMPOSTER_MAX_UVS 64 + + +void imposter_v( + // These parameters usually come from the vertex. + float3 center, + int corner, + float halfSize, + float3 imposterUp, + float3 imposterRight, + + // These are from the imposter shader constant. + int numEquatorSteps, + int numPolarSteps, + float polarAngle, + bool includePoles, + + // Other shader constants. + float3 camPos, + float4 uvs[IMPOSTER_MAX_UVS], + + // The outputs of this function. + out float3 outWsPosition, + out float2 outTexCoord, + out float3x3 outWorldToTangent + ) +{ + // TODO: This could all be calculated on the CPU. + float equatorStepSize = M_2PI_F / numEquatorSteps; + float equatorHalfStep = ( equatorStepSize / 2.0 ) - 0.0001; + float polarStepSize = M_PI_F / numPolarSteps; + float polarHalfStep = ( polarStepSize / 2.0 ) - 0.0001; + + // The vector between the camera and the billboard. + float3 lookVec = normalize( camPos - center ); + + // Generate the camera up and right vectors from + // the object transform and camera forward. + float3 camUp = imposterUp; + float3 camRight = normalize( cross( -lookVec, camUp ) ); + + // The billboarding is based on the camera directions. + float3 rightVec = camRight * sCornerRight[corner]; + float3 upVec = camUp * sCornerUp[corner]; + + float lookPitch = acos( dot( imposterUp, lookVec ) ); + + // First check to see if we need to render the top billboard. + int index; + /* + if ( includePoles && ( lookPitch < polarAngle || lookPitch > sPi - polarAngle ) ) + { + index = numEquatorSteps * 3; + + // When we render the top/bottom billboard we always use + // a fixed vector that matches the rotation of the object. + rightVec = float3( 1, 0, 0 ) * sCornerRight[corner]; + upVec = float3( 0, 1, 0 ) * sCornerUp[corner]; + + if ( lookPitch > sPi - polarAngle ) + { + upVec = -upVec; + index++; + } + } + else + */ + { + // Calculate the rotation around the z axis then add the + // equator half step. This gets the images to switch a + // half step before the captured angle is met. + float lookAzimuth = atan2( lookVec.y, lookVec.x ); + float azimuth = atan2( imposterRight.y, imposterRight.x ); + float rotZ = ( lookAzimuth - azimuth ) + equatorHalfStep; + + // The y rotation is calculated from the look vector and + // the object up vector. + float rotY = lookPitch - polarHalfStep; + + // TODO: How can we do this without conditionals? + // Normalize the result to 0 to 2PI. + if ( rotZ < 0 ) + rotZ += M_2PI_F; + if ( rotZ > M_2PI_F ) + rotZ -= M_2PI_F; + if ( rotY < 0 ) + rotY += M_2PI_F; + if ( rotY > M_PI_F ) // Not M_2PI_F? + rotY -= M_2PI_F; + + float polarIdx = round( abs( rotY ) / polarStepSize ); + + // Get the index to the start of the right polar + // images for this viewing angle. + int numPolarOffset = numEquatorSteps * polarIdx; + + // Calculate the final image index for lookup + // of the texture coords. + index = ( rotZ / equatorStepSize ) + numPolarOffset; + } + + // Generate the final world space position. + outWsPosition = center + ( upVec * halfSize ) + ( rightVec * halfSize ); + + // Grab the uv set and setup the texture coord. + float4 uvSet = uvs[index]; + outTexCoord.x = uvSet.x + ( uvSet.z * sUVCornerExtent[corner].x ); + outTexCoord.y = uvSet.y + ( uvSet.w * sUVCornerExtent[corner].y ); + + // Needed for normal mapping and lighting. + outWorldToTangent[0] = float3( 1, 0, 0 ); + outWorldToTangent[1] = float3( 0, 1, 0 ); + outWorldToTangent[2] = float3( 0, 0, -1 ); +} diff --git a/Templates/BaseGame/game/core/rendering/shaders/lighting.hlsl b/Templates/BaseGame/game/core/rendering/shaders/lighting.hlsl new file mode 100644 index 000000000..a41b8a873 --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/lighting.hlsl @@ -0,0 +1,249 @@ +//----------------------------------------------------------------------------- +// 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 "./torque.hlsl" + +#ifndef TORQUE_SHADERGEN + +// These are the uniforms used by most lighting shaders. + +uniform float4 inLightPos[3]; +uniform float4 inLightInvRadiusSq; +uniform float4 inLightColor[4]; + +#ifndef TORQUE_BL_NOSPOTLIGHT + uniform float4 inLightSpotDir[3]; + uniform float4 inLightSpotAngle; + uniform float4 inLightSpotFalloff; +#endif + +uniform float4 ambient; +#define ambientCameraFactor 0.3 +uniform float specularPower; +uniform float4 specularColor; + +#endif // !TORQUE_SHADERGEN + + +void compute4Lights( float3 wsView, + float3 wsPosition, + float3 wsNormal, + float4 shadowMask, + + #ifdef TORQUE_SHADERGEN + + float4 inLightPos[3], + float4 inLightInvRadiusSq, + float4 inLightColor[4], + float4 inLightSpotDir[3], + float4 inLightSpotAngle, + float4 inLightSpotFalloff, + float specularPower, + float4 specularColor, + + #endif // TORQUE_SHADERGEN + + out float4 outDiffuse, + out float4 outSpecular ) +{ + // NOTE: The light positions and spotlight directions + // are stored in SoA order, so inLightPos[0] is the + // x coord for all 4 lights... inLightPos[1] is y... etc. + // + // This is the key to fully utilizing the vector units and + // saving a huge amount of instructions. + // + // For example this change saved more than 10 instructions + // over a simple for loop for each light. + + int i; + + float4 lightVectors[3]; + for ( i = 0; i < 3; i++ ) + lightVectors[i] = wsPosition[i] - inLightPos[i]; + + float4 squareDists = 0; + for ( i = 0; i < 3; i++ ) + squareDists += lightVectors[i] * lightVectors[i]; + + // Accumulate the dot product between the light + // vector and the normal. + // + // The normal is negated because it faces away from + // the surface and the light faces towards the + // surface... this keeps us from needing to flip + // the light vector direction which complicates + // the spot light calculations. + // + // We normalize the result a little later. + // + float4 nDotL = 0; + for ( i = 0; i < 3; i++ ) + nDotL += lightVectors[i] * -wsNormal[i]; + + float4 rDotL = 0; + #ifndef TORQUE_BL_NOSPECULAR + + // We're using the Phong specular reflection model + // here where traditionally Torque has used Blinn-Phong + // which has proven to be more accurate to real materials. + // + // We do so because its cheaper as do not need to + // calculate the half angle for all 4 lights. + // + // Advanced Lighting still uses Blinn-Phong, but the + // specular reconstruction it does looks fairly similar + // to this. + // + float3 R = reflect( wsView, -wsNormal ); + + for ( i = 0; i < 3; i++ ) + rDotL += lightVectors[i] * R[i]; + + #endif + + // Normalize the dots. + // + // Notice we're using the half type here to get a + // much faster sqrt via the rsq_pp instruction at + // the loss of some precision. + // + // Unless we have some extremely large point lights + // i don't believe the precision loss will matter. + // + half4 correction = (half4)rsqrt( squareDists ); + nDotL = saturate( nDotL * correction ); + rDotL = clamp( rDotL * correction, 0.00001, 1.0 ); + + // First calculate a simple point light linear + // attenuation factor. + // + // If this is a directional light the inverse + // radius should be greater than the distance + // causing the attenuation to have no affect. + // + float4 atten = saturate( 1.0 - ( squareDists * inLightInvRadiusSq ) ); + + #ifndef TORQUE_BL_NOSPOTLIGHT + + // The spotlight attenuation factor. This is really + // fast for what it does... 6 instructions for 4 spots. + + float4 spotAtten = 0; + for ( i = 0; i < 3; i++ ) + spotAtten += lightVectors[i] * inLightSpotDir[i]; + + float4 cosAngle = ( spotAtten * correction ) - inLightSpotAngle; + atten *= saturate( cosAngle * inLightSpotFalloff ); + + #endif + + // Finally apply the shadow masking on the attenuation. + atten *= shadowMask; + + // Get the final light intensity. + float4 intensity = nDotL * atten; + + // Combine the light colors for output. + outDiffuse = 0; + for ( i = 0; i < 4; i++ ) + outDiffuse += intensity[i] * inLightColor[i]; + + // Output the specular power. + float4 specularIntensity = pow( rDotL, specularPower.xxxx ) * atten; + + // Apply the per-light specular attenuation. + float4 specular = float4(0,0,0,1); + for ( i = 0; i < 4; i++ ) + specular += float4( inLightColor[i].rgb * inLightColor[i].a * specularIntensity[i], 1 ); + + // Add the final specular intensity values together + // using a single dot product operation then get the + // final specular lighting color. + outSpecular = specularColor * specular; +} + + +// This value is used in AL as a constant power to raise specular values +// to, before storing them into the light info buffer. The per-material +// specular value is then computer by using the integer identity of +// exponentiation: +// +// (a^m)^n = a^(m*n) +// +// or +// +// (specular^constSpecular)^(matSpecular/constSpecular) = specular^(matSpecular*constSpecular) +// +#define AL_ConstantSpecularPower 12.0f + +/// The specular calculation used in Advanced Lighting. +/// +/// @param toLight Normalized vector representing direction from the pixel +/// being lit, to the light source, in world space. +/// +/// @param normal Normalized surface normal. +/// +/// @param toEye The normalized vector representing direction from the pixel +/// being lit to the camera. +/// +float AL_CalcSpecular( float3 toLight, float3 normal, float3 toEye ) +{ + // (R.V)^c + float specVal = dot( normalize( -reflect( toLight, normal ) ), toEye ); + + // Return the specular factor. + return pow( max( specVal, 0.00001f ), AL_ConstantSpecularPower ); +} + +/// The output for Deferred Lighting +/// +/// @param toLight Normalized vector representing direction from the pixel +/// being lit, to the light source, in world space. +/// +/// @param normal Normalized surface normal. +/// +/// @param toEye The normalized vector representing direction from the pixel +/// being lit to the camera. +/// +float4 AL_DeferredOutput( + float3 lightColor, + float3 diffuseColor, + float4 matInfo, + float4 ambient, + float specular, + float shadowAttenuation) +{ + float3 specularColor = float3(specular, specular, specular); + bool metalness = getFlag(matInfo.r, 3); + if ( metalness ) + { + specularColor = 0.04 * (1 - specular) + diffuseColor * specular; + } + + //specular = color * map * spec^gloss + float specularOut = (specularColor * matInfo.b * min(pow(abs(specular), max(( matInfo.a/ AL_ConstantSpecularPower),1.0f)),matInfo.a)).r; + + lightColor *= shadowAttenuation; + lightColor += ambient.rgb; + return float4(lightColor.rgb, specularOut); +} diff --git a/Templates/BaseGame/game/core/rendering/shaders/lighting/advanced/convexGeometryV.hlsl b/Templates/BaseGame/game/core/rendering/shaders/lighting/advanced/convexGeometryV.hlsl new file mode 100644 index 000000000..064fcffa6 --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/lighting/advanced/convexGeometryV.hlsl @@ -0,0 +1,54 @@ +//----------------------------------------------------------------------------- +// 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 "../../hlslStructs.hlsl" +#include "../../shaderModel.hlsl" + +struct VertData +{ + float3 pos : POSITION; + float4 color : COLOR; +}; + +struct ConvexConnectV +{ + float4 hpos : TORQUE_POSITION; + float4 wsEyeDir : TEXCOORD0; + float4 ssPos : TEXCOORD1; + float4 vsEyeDir : TEXCOORD2; +}; + +ConvexConnectV main( VertData IN, + uniform float4x4 modelview, + uniform float4x4 objTrans, + uniform float4x4 worldViewOnly, + uniform float3 eyePosWorld ) +{ + ConvexConnectV OUT; + + OUT.hpos = mul( modelview, float4(IN.pos,1.0) ); + OUT.wsEyeDir = mul(objTrans, float4(IN.pos, 1.0)) - float4(eyePosWorld, 0.0); + OUT.vsEyeDir = mul(worldViewOnly, float4(IN.pos, 1.0)); + OUT.ssPos = OUT.hpos; + + return OUT; +} diff --git a/Templates/BaseGame/game/core/rendering/shaders/lighting/advanced/deferredClearGBufferP.hlsl b/Templates/BaseGame/game/core/rendering/shaders/lighting/advanced/deferredClearGBufferP.hlsl new file mode 100644 index 000000000..5ae05896e --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/lighting/advanced/deferredClearGBufferP.hlsl @@ -0,0 +1,54 @@ +//----------------------------------------------------------------------------- +// 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 "../../shaderModel.hlsl" + +struct Conn +{ + float4 hpos : TORQUE_POSITION; +}; + +struct Fragout +{ + float4 col : TORQUE_TARGET0; + float4 col1 : TORQUE_TARGET1; + float4 col2 : TORQUE_TARGET2; +}; + +//----------------------------------------------------------------------------- +// Main +//----------------------------------------------------------------------------- +Fragout main( Conn IN ) +{ + Fragout OUT; + + // Clear Deferred Buffer ( Normals/Depth ); + OUT.col = float4(1.0, 1.0, 1.0, 1.0); + + // Clear Color Buffer. + OUT.col1 = float4(0.0, 0.0, 0.0, 1.0); + + // Clear Material Info Buffer. + OUT.col2 = float4(0.0, 0.0, 0.0, 1.0); + + return OUT; +} diff --git a/Templates/BaseGame/game/core/rendering/shaders/lighting/advanced/deferredClearGBufferV.hlsl b/Templates/BaseGame/game/core/rendering/shaders/lighting/advanced/deferredClearGBufferV.hlsl new file mode 100644 index 000000000..20ba4d509 --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/lighting/advanced/deferredClearGBufferV.hlsl @@ -0,0 +1,43 @@ +//----------------------------------------------------------------------------- +// 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 "../../shaderModel.hlsl" + +struct Appdata +{ + float3 pos : POSITION; + float4 color : COLOR; +}; + +struct Conn +{ + float4 hpos : TORQUE_POSITION; +}; + +uniform float4x4 modelview; + +Conn main( Appdata In ) +{ + Conn Out; + Out.hpos = float4(In.pos,1.0); + return Out; +} diff --git a/Templates/BaseGame/game/core/rendering/shaders/lighting/advanced/deferredColorShaderP.hlsl b/Templates/BaseGame/game/core/rendering/shaders/lighting/advanced/deferredColorShaderP.hlsl new file mode 100644 index 000000000..d91d2eb38 --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/lighting/advanced/deferredColorShaderP.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. +//----------------------------------------------------------------------------- + +#include "../../shaderModel.hlsl" + +struct Fragout +{ + float4 col : TORQUE_TARGET0; + float4 col1 : TORQUE_TARGET1; + float4 col2 : TORQUE_TARGET2; +}; + +//----------------------------------------------------------------------------- +// Main +//----------------------------------------------------------------------------- +Fragout main( ) +{ + Fragout OUT; + + OUT.col = float4(0.0, 0.0, 0.0, 0.0); + OUT.col1 = float4(1.0, 1.0, 1.0, 1.0); + + // Draw on color buffer. + OUT.col2 = float4(1.0, 0.0, 0.0, 1.0); + + return OUT; +} diff --git a/Templates/BaseGame/game/core/rendering/shaders/lighting/advanced/deferredShadingP.hlsl b/Templates/BaseGame/game/core/rendering/shaders/lighting/advanced/deferredShadingP.hlsl new file mode 100644 index 000000000..ebd9ed72b --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/lighting/advanced/deferredShadingP.hlsl @@ -0,0 +1,54 @@ +//----------------------------------------------------------------------------- +// 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 "../../shaderModelAutoGen.hlsl" +#include "../../postfx/postFx.hlsl" +#include "../../torque.hlsl" + +TORQUE_UNIFORM_SAMPLER2D(colorBufferTex,0); +TORQUE_UNIFORM_SAMPLER2D(lightDeferredTex,1); +TORQUE_UNIFORM_SAMPLER2D(matInfoTex,2); +TORQUE_UNIFORM_SAMPLER2D(deferredTex,3); + +float4 main( PFXVertToPix IN ) : TORQUE_TARGET0 +{ + float4 lightBuffer = TORQUE_TEX2D( lightDeferredTex, IN.uv0 ); + float4 colorBuffer = TORQUE_TEX2D( colorBufferTex, IN.uv0 ); + float4 matInfo = TORQUE_TEX2D( matInfoTex, IN.uv0 ); + float specular = saturate(lightBuffer.a); + float depth = TORQUE_DEFERRED_UNCONDITION( deferredTex, IN.uv0 ).w; + + if (depth>0.9999) + return float4(0,0,0,0); + + // Diffuse Color Altered by Metalness + bool metalness = getFlag(matInfo.r, 3); + if ( metalness ) + { + colorBuffer *= (1.0 - colorBuffer.a); + } + + colorBuffer += float4(specular, specular, specular, 1.0); + colorBuffer *= float4(lightBuffer.rgb, 1.0); + + return hdrEncode( float4(colorBuffer.rgb, 1.0) ); +} diff --git a/Templates/BaseGame/game/core/rendering/shaders/lighting/advanced/farFrustumQuad.hlsl b/Templates/BaseGame/game/core/rendering/shaders/lighting/advanced/farFrustumQuad.hlsl new file mode 100644 index 000000000..543e21677 --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/lighting/advanced/farFrustumQuad.hlsl @@ -0,0 +1,47 @@ +//----------------------------------------------------------------------------- +// 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 "../../shaderModel.hlsl" + +struct FarFrustumQuadConnectV +{ + float4 hpos : TORQUE_POSITION; + float2 uv0 : TEXCOORD0; + float3 wsEyeRay : TEXCOORD1; + float3 vsEyeRay : TEXCOORD2; +}; + +struct FarFrustumQuadConnectP +{ + float4 hpos : TORQUE_POSITION; + float2 uv0 : TEXCOORD0; + float3 wsEyeRay : TEXCOORD1; + float3 vsEyeRay : TEXCOORD2; +}; + + +float2 getUVFromSSPos( float3 ssPos, float4 rtParams ) +{ + float2 outPos = ( ssPos.xy + 1.0 ) / 2.0; + outPos.y = 1.0 - outPos.y; + outPos = ( outPos * rtParams.zw ) + rtParams.xy; + return outPos; +} diff --git a/Templates/BaseGame/game/core/rendering/shaders/lighting/advanced/farFrustumQuadV.hlsl b/Templates/BaseGame/game/core/rendering/shaders/lighting/advanced/farFrustumQuadV.hlsl new file mode 100644 index 000000000..0167d901a --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/lighting/advanced/farFrustumQuadV.hlsl @@ -0,0 +1,43 @@ +//----------------------------------------------------------------------------- +// 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 "../../hlslStructs.hlsl" +#include "farFrustumQuad.hlsl" + + +FarFrustumQuadConnectV main( VertexIn_PNTT IN, + uniform float4 rtParams0 ) +{ + FarFrustumQuadConnectV OUT; + + OUT.hpos = float4( IN.uv0, 0, 1 ); + + // Get a RT-corrected UV from the SS coord + OUT.uv0 = getUVFromSSPos( OUT.hpos.xyz, rtParams0 ); + + // Interpolators will generate eye rays the + // from far-frustum corners. + OUT.wsEyeRay = IN.tangent; + OUT.vsEyeRay = IN.normal; + + return OUT; +} diff --git a/Templates/BaseGame/game/core/rendering/shaders/lighting/advanced/gl/convexGeometryV.glsl b/Templates/BaseGame/game/core/rendering/shaders/lighting/advanced/gl/convexGeometryV.glsl new file mode 100644 index 000000000..1807ac43f --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/lighting/advanced/gl/convexGeometryV.glsl @@ -0,0 +1,52 @@ +//----------------------------------------------------------------------------- +// 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_pos vPosition + +out vec4 wsEyeDir; +out vec4 ssPos; +out vec4 vsEyeDir; + +#define OUT_hpos gl_Position +#define OUT_wsEyeDir wsEyeDir +#define OUT_ssPos ssPos +#define OUT_vsEyeDir vsEyeDir + +uniform mat4 modelview; +uniform mat4 objTrans; +uniform mat4 worldViewOnly; +uniform vec3 eyePosWorld; + +void main() +{ + OUT_hpos = tMul( modelview, IN_pos ); + OUT_wsEyeDir = tMul( objTrans, IN_pos ) - vec4( eyePosWorld, 0.0 ); + OUT_vsEyeDir = tMul( worldViewOnly, IN_pos ); + OUT_ssPos = OUT_hpos; + + correctSSP(gl_Position); +} + diff --git a/Templates/BaseGame/game/core/rendering/shaders/lighting/advanced/gl/deferredClearGBufferP.glsl b/Templates/BaseGame/game/core/rendering/shaders/lighting/advanced/gl/deferredClearGBufferP.glsl new file mode 100644 index 000000000..b58f347bb --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/lighting/advanced/gl/deferredClearGBufferP.glsl @@ -0,0 +1,40 @@ +//----------------------------------------------------------------------------- +// 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. +//----------------------------------------------------------------------------- + +out vec4 OUT_col; +out vec4 OUT_col1; +out vec4 OUT_col2; + +//----------------------------------------------------------------------------- +// Main +//----------------------------------------------------------------------------- +void main() +{ + // Clear Deferred Buffer ( Normals/Depth ); + OUT_col = vec4(1.0, 1.0, 1.0, 1.0); + + // Clear Color Buffer. + OUT_col1 = vec4(0.0, 0.0, 0.0, 1.0); + + // Clear Material Info Buffer. + OUT_col2 = vec4(0.0, 0.0, 0.0, 1.0); +} diff --git a/Templates/BaseGame/game/core/rendering/shaders/lighting/advanced/gl/deferredColorShaderP.glsl b/Templates/BaseGame/game/core/rendering/shaders/lighting/advanced/gl/deferredColorShaderP.glsl new file mode 100644 index 000000000..85c553089 --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/lighting/advanced/gl/deferredColorShaderP.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. +//----------------------------------------------------------------------------- + +layout (location = 0) out vec4 col; +layout (location = 1) out vec4 col1; +layout (location = 2) out vec4 col2; + +//----------------------------------------------------------------------------- +// Main +//----------------------------------------------------------------------------- +void main() +{ + col = vec4(0.0, 0.0, 0.0, 0.0); + col1 = vec4(1.0, 1.0, 1.0, 1.0); + + // Draw on color buffer. + col2 = vec4(1.0, 0.0, 0.0, 1.0); +} diff --git a/Templates/BaseGame/game/core/rendering/shaders/lighting/advanced/gl/deferredShadingP.glsl b/Templates/BaseGame/game/core/rendering/shaders/lighting/advanced/gl/deferredShadingP.glsl new file mode 100644 index 000000000..0234d5fd1 --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/lighting/advanced/gl/deferredShadingP.glsl @@ -0,0 +1,59 @@ +//----------------------------------------------------------------------------- +// 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 "../../../postFx/gl/postFX.glsl" +#include "../../../gl/torque.glsl" + +uniform sampler2D colorBufferTex; +uniform sampler2D lightDeferredTex; +uniform sampler2D matInfoTex; +uniform sampler2D deferredTex; + +out vec4 OUT_col; + +void main() +{ + float depth = deferredUncondition( deferredTex, uv0 ).w; + if (depth>0.9999) + { + OUT_col = vec4(0.0); + return; + } + vec4 lightBuffer = texture( lightDeferredTex, uv0 ); + vec4 colorBuffer = texture( colorBufferTex, uv0 ); + vec4 matInfo = texture( matInfoTex, uv0 ); + float specular = clamp(lightBuffer.a,0.0,1.0); + + // Diffuse Color Altered by Metalness + bool metalness = getFlag(matInfo.r, 3); + if ( metalness ) + { + colorBuffer *= (1.0 - colorBuffer.a); + } + + colorBuffer += vec4(specular, specular, specular, 1.0); + colorBuffer *= vec4(lightBuffer.rgb, 1.0); + + OUT_col = hdrEncode( vec4(colorBuffer.rgb, 1.0) ); +} diff --git a/Templates/BaseGame/game/core/rendering/shaders/lighting/advanced/gl/farFrustumQuad.glsl b/Templates/BaseGame/game/core/rendering/shaders/lighting/advanced/gl/farFrustumQuad.glsl new file mode 100644 index 000000000..76054eb09 --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/lighting/advanced/gl/farFrustumQuad.glsl @@ -0,0 +1,30 @@ +//----------------------------------------------------------------------------- +// 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. +//----------------------------------------------------------------------------- + + +vec2 getUVFromSSPos( vec3 ssPos, vec4 rtParams ) +{ + vec2 outPos = ( ssPos.xy + 1.0 ) / 2.0; + outPos.y = 1.0 - outPos.y; + outPos = ( outPos * rtParams.zw ) + rtParams.xy; + return outPos; +} diff --git a/Templates/BaseGame/game/core/rendering/shaders/lighting/advanced/gl/farFrustumQuadV.glsl b/Templates/BaseGame/game/core/rendering/shaders/lighting/advanced/gl/farFrustumQuadV.glsl new file mode 100644 index 000000000..a80e856ed --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/lighting/advanced/gl/farFrustumQuadV.glsl @@ -0,0 +1,51 @@ +//----------------------------------------------------------------------------- +// 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 "farFrustumQuad.glsl" + +in vec4 vPosition; +in vec3 vNormal; +in vec3 vTangent; +in vec2 vTexCoord0; + +uniform vec4 rtParams0; +out vec4 hpos; +out vec2 uv0; +out vec3 wsEyeRay; +out vec3 vsEyeRay; + +void main() +{ + hpos = vec4( vTexCoord0, 0, 1 ); + + // Get a RT-corrected UV from the SS coord + uv0 = getUVFromSSPos( hpos.xyz, rtParams0 ); + gl_Position = hpos; + + // Interpolators will generate eye rays the + // from far-frustum corners. + wsEyeRay = vTangent; + vsEyeRay = vNormal; + + correctSSP(gl_Position); +} diff --git a/Templates/BaseGame/game/core/rendering/shaders/lighting/advanced/gl/lightingUtils.glsl b/Templates/BaseGame/game/core/rendering/shaders/lighting/advanced/gl/lightingUtils.glsl new file mode 100644 index 000000000..08af9231b --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/lighting/advanced/gl/lightingUtils.glsl @@ -0,0 +1,79 @@ +//----------------------------------------------------------------------------- +// 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. +//----------------------------------------------------------------------------- + + +float attenuate( vec4 lightColor, vec2 attParams, float dist ) +{ + // We're summing the results of a scaled constant, + // linear, and quadratic attenuation. + + #ifdef ACCUMULATE_LUV + return lightColor.w * ( 1.0 - dot( attParams, vec2( dist, dist * dist ) ) ); + #else + return 1.0 - dot( attParams, vec2( dist, dist * dist ) ); + #endif +} + +// Calculate the specular coefficent +// +// pxlToLight - Normalized vector representing direction from the pixel being lit, to the light source, in world space +// normal - Normalized surface normal +// pxlToEye - Normalized vector representing direction from pixel being lit, to the camera, in world space +// specPwr - Specular exponent +// specularScale - A scalar on the specular output used in RGB accumulation. +// +float calcSpecular( vec3 pxlToLight, vec3 normal, vec3 pxlToEye, float specPwr, float specularScale ) +{ +#ifdef PHONG_SPECULAR + // (R.V)^c + float specVal = dot( normalize( -reflect( pxlToLight, normal ) ), pxlToEye ); +#else + // (N.H)^c [Blinn-Phong, TGEA style, default] + float specVal = dot( normal, normalize( pxlToLight + pxlToEye ) ); +#endif + +#ifdef ACCUMULATE_LUV + return pow( max( specVal, 0.00001f ), specPwr ); +#else + // If this is RGB accumulation, than there is no facility for the luminance + // of the light to play in to the specular intensity. In LUV, the luminance + // of the light color gets rolled into N.L * Attenuation + return specularScale * pow( max( specVal, 0.00001f ), specPwr ); +#endif +} + +vec3 getDistanceVectorToPlane( vec3 origin, vec3 direction, vec4 plane ) +{ + float denum = dot( plane.xyz, direction.xyz ); + float num = dot( plane, vec4( origin, 1.0 ) ); + float t = -num / denum; + + return direction.xyz * t; +} + +vec3 getDistanceVectorToPlane( float negFarPlaneDotEye, vec3 direction, vec4 plane ) +{ + float denum = dot( plane.xyz, direction.xyz ); + float t = negFarPlaneDotEye / denum; + + return direction.xyz * t; +} \ No newline at end of file diff --git a/Templates/BaseGame/game/core/rendering/shaders/lighting/advanced/gl/pointLightP.glsl b/Templates/BaseGame/game/core/rendering/shaders/lighting/advanced/gl/pointLightP.glsl new file mode 100644 index 000000000..80869de25 --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/lighting/advanced/gl/pointLightP.glsl @@ -0,0 +1,273 @@ +//----------------------------------------------------------------------------- +// 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 "farFrustumQuad.glsl" +#include "lightingUtils.glsl" +#include "../../../gl/lighting.glsl" +#include "../../shadowMap/shadowMapIO_GLSL.h" +#include "softShadow.glsl" +#include "../../../gl/torque.glsl" + +in vec4 wsEyeDir; +in vec4 ssPos; +in vec4 vsEyeDir; +in vec4 color; + +#ifdef USE_COOKIE_TEX + +/// The texture for cookie rendering. +uniform samplerCube cookieMap ; + +#endif + + +#ifdef SHADOW_CUBE + + vec3 decodeShadowCoord( vec3 shadowCoord ) + { + return shadowCoord; + } + + vec4 shadowSample( samplerCube shadowMap, vec3 shadowCoord ) + { + return texture( shadowMap, shadowCoord ); + } + +#else + + vec3 decodeShadowCoord( vec3 paraVec ) + { + // Flip y and z + paraVec = paraVec.xzy; + + #ifndef SHADOW_PARABOLOID + + bool calcBack = (paraVec.z < 0.0); + if ( calcBack ) + { + paraVec.z = paraVec.z * -1.0; + + #ifdef SHADOW_DUALPARABOLOID + paraVec.x = -paraVec.x; + #endif + } + + #endif + + vec3 shadowCoord; + shadowCoord.x = (paraVec.x / (2*(1 + paraVec.z))) + 0.5; + shadowCoord.y = 1-((paraVec.y / (2*(1 + paraVec.z))) + 0.5); + shadowCoord.z = 0; + + // adjust the co-ordinate slightly if it is near the extent of the paraboloid + // this value was found via experementation + // NOTE: this is wrong, it only biases in one direction, not towards the uv + // center ( 0.5 0.5 ). + //shadowCoord.xy *= 0.997; + + #ifndef SHADOW_PARABOLOID + + // If this is the back, offset in the atlas + if ( calcBack ) + shadowCoord.x += 1.0; + + // Atlasing front and back maps, so scale + shadowCoord.x *= 0.5; + + #endif + + return shadowCoord; + } + +#endif + +uniform sampler2D deferredBuffer; + +#ifdef SHADOW_CUBE + uniform samplerCube shadowMap; +#else + uniform sampler2D shadowMap; + uniform sampler2D dynamicShadowMap; +#endif + +uniform sampler2D lightBuffer; +uniform sampler2D colorBuffer; +uniform sampler2D matInfoBuffer; + +uniform vec4 rtParams0; + +uniform vec3 lightPosition; +uniform vec4 lightColor; +uniform float lightBrightness; +uniform float lightRange; +uniform vec2 lightAttenuation; +uniform vec4 lightMapParams; +uniform vec4 vsFarPlane; +uniform mat3 viewToLightProj; +uniform mat3 dynamicViewToLightProj; +uniform vec4 lightParams; +uniform float shadowSoftness; + +out vec4 OUT_col; + +void main() +{ + // Compute scene UV + vec3 ssPos = ssPos.xyz / ssPos.w; + vec2 uvScene = getUVFromSSPos( ssPos, rtParams0 ); + + // Emissive. + vec4 matInfo = texture( matInfoBuffer, uvScene ); + bool emissive = getFlag( matInfo.r, 0 ); + if ( emissive ) + { + OUT_col = vec4(0.0, 0.0, 0.0, 0.0); + return; + } + + vec4 colorSample = texture( colorBuffer, uvScene ); + vec3 subsurface = vec3(0.0,0.0,0.0); + if (getFlag( matInfo.r, 1 )) + { + subsurface = colorSample.rgb; + if (colorSample.r>colorSample.g) + subsurface = vec3(0.772549, 0.337255, 0.262745); + else + subsurface = vec3(0.337255, 0.772549, 0.262745); + } + + // Sample/unpack the normal/z data + vec4 deferredSample = deferredUncondition( deferredBuffer, uvScene ); + vec3 normal = deferredSample.rgb; + float depth = deferredSample.a; + + // Eye ray - Eye -> Pixel + vec3 eyeRay = getDistanceVectorToPlane( -vsFarPlane.w, vsEyeDir.xyz, vsFarPlane ); + vec3 viewSpacePos = eyeRay * depth; + + // Build light vec, get length, clip pixel if needed + vec3 lightVec = lightPosition - viewSpacePos; + float lenLightV = length( lightVec ); + clip( lightRange - lenLightV ); + + // Get the attenuated falloff. + float atten = attenuate( lightColor, lightAttenuation, lenLightV ); + clip( atten - 1e-6 ); + + // Normalize lightVec + lightVec /= lenLightV; + + // If we can do dynamic branching then avoid wasting + // fillrate on pixels that are backfacing to the light. + float nDotL = dot( lightVec, normal ); + //DB_CLIP( nDotL < 0 ); + + #ifdef NO_SHADOW + + float shadowed = 1.0; + + #else + + // Get a linear depth from the light source. + float distToLight = lenLightV / lightRange; + + #ifdef SHADOW_CUBE + + // TODO: We need to fix shadow cube to handle soft shadows! + float occ = texture( shadowMap, tMul( viewToLightProj, -lightVec ) ).r; + float shadowed = saturate( exp( lightParams.y * ( occ - distToLight ) ) ); + + #else + + vec2 shadowCoord = decodeShadowCoord( tMul( viewToLightProj, -lightVec ) ).xy; + + float static_shadowed = softShadow_filter( shadowMap, + ssPos.xy, + shadowCoord, + shadowSoftness, + distToLight, + nDotL, + lightParams.y ); + + vec2 dynamicShadowCoord = decodeShadowCoord( tMul( dynamicViewToLightProj, -lightVec ) ).xy; + float dynamic_shadowed = softShadow_filter( dynamicShadowMap, + ssPos.xy, + dynamicShadowCoord, + shadowSoftness, + distToLight, + nDotL, + lightParams.y ); + + float shadowed = min(static_shadowed, dynamic_shadowed); + #endif + + #endif // !NO_SHADOW + + vec3 lightcol = lightColor.rgb; + #ifdef USE_COOKIE_TEX + + // Lookup the cookie sample. + vec4 cookie = texture( cookieMap, tMul( viewToLightProj, -lightVec ) ); + + // Multiply the light with the cookie tex. + lightcol *= cookie.rgb; + + // Use a maximum channel luminance to attenuate + // the lighting else we get specular in the dark + // regions of the cookie texture. + atten *= max( cookie.r, max( cookie.g, cookie.b ) ); + + #endif + + // NOTE: Do not clip on fully shadowed pixels as it would + // cause the hardware occlusion query to disable the shadow. + + // Specular term + float specular = AL_CalcSpecular( lightVec, + normal, + normalize( -eyeRay ) ) * lightBrightness * atten * shadowed; + + float Sat_NL_Att = saturate( nDotL * atten * shadowed ) * lightBrightness; + vec3 lightColorOut = lightMapParams.rgb * lightcol; + vec4 addToResult = vec4(0.0); + + // TODO: This needs to be removed when lightmapping is disabled + // as its extra work per-pixel on dynamic lit scenes. + // + // Special lightmapping pass. + if ( lightMapParams.a < 0.0 ) + { + // This disables shadows on the backsides of objects. + shadowed = nDotL < 0.0f ? 1.0f : shadowed; + + Sat_NL_Att = 1.0f; + shadowed = mix( 1.0f, shadowed, atten ); + lightColorOut = vec3(shadowed); + specular *= lightBrightness; + addToResult = ( 1.0 - shadowed ) * abs(lightMapParams); + } + + OUT_col = AL_DeferredOutput(lightColorOut+subsurface*(1.0-Sat_NL_Att), colorSample.rgb, matInfo, addToResult, specular, Sat_NL_Att); +} diff --git a/Templates/BaseGame/game/core/rendering/shaders/lighting/advanced/gl/softShadow.glsl b/Templates/BaseGame/game/core/rendering/shaders/lighting/advanced/gl/softShadow.glsl new file mode 100644 index 000000000..a14213946 --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/lighting/advanced/gl/softShadow.glsl @@ -0,0 +1,159 @@ +//----------------------------------------------------------------------------- +// 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. +//----------------------------------------------------------------------------- + + +#if defined( SOFTSHADOW ) && defined( SOFTSHADOW_HIGH_QUALITY ) + +#define NUM_PRE_TAPS 4 +#define NUM_TAPS 12 + +/// The non-uniform poisson disk used in the +/// high quality shadow filtering. +vec2 sNonUniformTaps[NUM_TAPS] = vec2[] +( + // These first 4 taps are located around the edges + // of the disk and are used to predict fully shadowed + // or unshadowed areas. + vec2( 0.992833, 0.979309 ), + vec2( -0.998585, 0.985853 ), + vec2( 0.949299, -0.882562 ), + vec2( -0.941358, -0.893924 ), + + // The rest of the samples. + vec2( 0.545055, -0.589072 ), + vec2( 0.346526, 0.385821 ), + vec2( -0.260183, 0.334412 ), + vec2( 0.248676, -0.679605 ), + vec2( -0.569502, -0.390637 ), + vec2( -0.614096, 0.212577 ), + vec2( -0.259178, 0.876272 ), + vec2( 0.649526, 0.864333 ) +); + +#else + +#define NUM_PRE_TAPS 5 + +/// The non-uniform poisson disk used in the +/// high quality shadow filtering. +vec2 sNonUniformTaps[NUM_PRE_TAPS] = vec2[] +( + vec2( 0.892833, 0.959309 ), + vec2( -0.941358, -0.873924 ), + vec2( -0.260183, 0.334412 ), + vec2( 0.348676, -0.679605 ), + vec2( -0.569502, -0.390637 ) +); + +#endif + + +/// The texture used to do per-pixel pseudorandom +/// rotations of the filter taps. +uniform sampler2D gTapRotationTex ; + + +float softShadow_sampleTaps( sampler2D shadowMap, + vec2 sinCos, + vec2 shadowPos, + float filterRadius, + float distToLight, + float esmFactor, + int startTap, + int endTap ) +{ + float shadow = 0; + + vec2 tap = vec2(0); + for ( int t = startTap; t < endTap; t++ ) + { + tap.x = ( sNonUniformTaps[t].x * sinCos.y - sNonUniformTaps[t].y * sinCos.x ) * filterRadius; + tap.y = ( sNonUniformTaps[t].y * sinCos.y + sNonUniformTaps[t].x * sinCos.x ) * filterRadius; + float occluder = tex2Dlod( shadowMap, vec4( shadowPos + tap, 0, 0 ) ).r; + + float esm = saturate( exp( esmFactor * ( occluder - distToLight ) ) ); + shadow += esm / float( endTap - startTap ); + } + + return shadow; +} + + +float softShadow_filter( sampler2D shadowMap, + vec2 vpos, + vec2 shadowPos, + float filterRadius, + float distToLight, + float dotNL, + float esmFactor ) +{ + #ifndef SOFTSHADOW + + // If softshadow is undefined then we skip any complex + // filtering... just do a single sample ESM. + + float occluder = tex2Dlod( shadowMap, vec4( shadowPos, 0, 0 ) ).r; + float shadow = saturate( exp( esmFactor * ( occluder - distToLight ) ) ); + + #else + + // Lookup the random rotation for this screen pixel. + vec2 sinCos = ( tex2Dlod( gTapRotationTex, vec4( vpos * 16, 0, 0 ) ).rg - 0.5 ) * 2; + + // Do the prediction taps first. + float shadow = softShadow_sampleTaps( shadowMap, + sinCos, + shadowPos, + filterRadius, + distToLight, + esmFactor, + 0, + NUM_PRE_TAPS ); + + // We live with only the pretap results if we don't + // have high quality shadow filtering enabled. + #ifdef SOFTSHADOW_HIGH_QUALITY + + // Only do the expensive filtering if we're really + // in a partially shadowed area. + if ( shadow * ( 1.0 - shadow ) * max( dotNL, 0 ) > 0.06 ) + { + shadow += softShadow_sampleTaps( shadowMap, + sinCos, + shadowPos, + filterRadius, + distToLight, + esmFactor, + NUM_PRE_TAPS, + NUM_TAPS ); + + // This averages the taps above with the results + // of the prediction samples. + shadow *= 0.5; + } + + #endif // SOFTSHADOW_HIGH_QUALITY + + #endif // SOFTSHADOW + + return shadow; +} \ No newline at end of file diff --git a/Templates/BaseGame/game/core/rendering/shaders/lighting/advanced/gl/spotLightP.glsl b/Templates/BaseGame/game/core/rendering/shaders/lighting/advanced/gl/spotLightP.glsl new file mode 100644 index 000000000..5fcf1b19c --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/lighting/advanced/gl/spotLightP.glsl @@ -0,0 +1,210 @@ +//----------------------------------------------------------------------------- +// 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 "farFrustumQuad.glsl" +#include "lightingUtils.glsl" +#include "../../shadowMap/shadowMapIO_GLSL.h" +#include "shadergen:/autogenConditioners.h" +#include "softShadow.glsl" +#include "../../../gl/lighting.glsl" +#include "../../../gl/torque.glsl" + +in vec4 wsEyeDir; +in vec4 ssPos; +in vec4 vsEyeDir; +in vec4 color; + +#define IN_wsEyeDir wsEyeDir +#define IN_ssPos ssPos +#define IN_vsEyeDir vsEyeDir +#define IN_color color + +#ifdef USE_COOKIE_TEX + +/// The texture for cookie rendering. +uniform sampler2D cookieMap; + +#endif + +uniform sampler2D deferredBuffer; +uniform sampler2D shadowMap; +uniform sampler2D dynamicShadowMap; + +uniform sampler2D lightBuffer; +uniform sampler2D colorBuffer; +uniform sampler2D matInfoBuffer; + +uniform vec4 rtParams0; + +uniform vec3 lightPosition; +uniform vec4 lightColor; +uniform float lightBrightness; +uniform float lightRange; +uniform vec2 lightAttenuation; +uniform vec3 lightDirection; +uniform vec4 lightSpotParams; +uniform vec4 lightMapParams; + +uniform vec4 vsFarPlane; +uniform mat4 viewToLightProj; +uniform mat4 dynamicViewToLightProj; + +uniform vec4 lightParams; +uniform float shadowSoftness; + +out vec4 OUT_col; + +void main() +{ + // Compute scene UV + vec3 ssPos = IN_ssPos.xyz / IN_ssPos.w; + vec2 uvScene = getUVFromSSPos( ssPos, rtParams0 ); + + // Emissive. + vec4 matInfo = texture( matInfoBuffer, uvScene ); + bool emissive = getFlag( matInfo.r, 0 ); + if ( emissive ) + { + OUT_col = vec4(0.0, 0.0, 0.0, 0.0); + return; + } + + vec4 colorSample = texture( colorBuffer, uvScene ); + vec3 subsurface = vec3(0.0,0.0,0.0); + if (getFlag( matInfo.r, 1 )) + { + subsurface = colorSample.rgb; + if (colorSample.r>colorSample.g) + subsurface = vec3(0.772549, 0.337255, 0.262745); + else + subsurface = vec3(0.337255, 0.772549, 0.262745); + } + + // Sample/unpack the normal/z data + vec4 deferredSample = deferredUncondition( deferredBuffer, uvScene ); + vec3 normal = deferredSample.rgb; + float depth = deferredSample.a; + + // Eye ray - Eye -> Pixel + vec3 eyeRay = getDistanceVectorToPlane( -vsFarPlane.w, IN_vsEyeDir.xyz, vsFarPlane ); + vec3 viewSpacePos = eyeRay * depth; + + // Build light vec, get length, clip pixel if needed + vec3 lightToPxlVec = viewSpacePos - lightPosition; + float lenLightV = length( lightToPxlVec ); + lightToPxlVec /= lenLightV; + + //lightDirection = vec3( -lightDirection.xy, lightDirection.z ); //vec3( 0, 0, -1 ); + float cosAlpha = dot( lightDirection, lightToPxlVec ); + clip( cosAlpha - lightSpotParams.x ); + clip( lightRange - lenLightV ); + + float atten = attenuate( lightColor, lightAttenuation, lenLightV ); + atten *= ( cosAlpha - lightSpotParams.x ) / lightSpotParams.y; + clip( atten - 1e-6 ); + atten = saturate( atten ); + + float nDotL = dot( normal, -lightToPxlVec ); + + // Get the shadow texture coordinate + vec4 pxlPosLightProj = tMul( viewToLightProj, vec4( viewSpacePos, 1 ) ); + vec2 shadowCoord = ( ( pxlPosLightProj.xy / pxlPosLightProj.w ) * 0.5 ) + vec2( 0.5, 0.5 ); + shadowCoord.y = 1.0f - shadowCoord.y; + + // Get the dynamic shadow texture coordinate + vec4 dynpxlPosLightProj = tMul( dynamicViewToLightProj, vec4( viewSpacePos, 1 ) ); + vec2 dynshadowCoord = ( ( dynpxlPosLightProj.xy / dynpxlPosLightProj.w ) * 0.5 ) + vec2( 0.5, 0.5 ); + dynshadowCoord.y = 1.0f - dynshadowCoord.y; + #ifdef NO_SHADOW + + float shadowed = 1.0; + + #else + + // Get a linear depth from the light source. + float distToLight = pxlPosLightProj.z / lightRange; + + float static_shadowed = softShadow_filter( shadowMap, + ssPos.xy, + shadowCoord, + shadowSoftness, + distToLight, + nDotL, + lightParams.y ); + + float dynamic_shadowed = softShadow_filter( dynamicShadowMap, + ssPos.xy, + dynshadowCoord, + shadowSoftness, + distToLight, + nDotL, + lightParams.y ); + float shadowed = min(static_shadowed, dynamic_shadowed); + #endif // !NO_SHADOW + + vec3 lightcol = lightColor.rgb; + #ifdef USE_COOKIE_TEX + + // Lookup the cookie sample. + vec4 cookie = texture( cookieMap, shadowCoord ); + + // Multiply the light with the cookie tex. + lightcol *= cookie.rgb; + + // Use a maximum channel luminance to attenuate + // the lighting else we get specular in the dark + // regions of the cookie texture. + atten *= max( cookie.r, max( cookie.g, cookie.b ) ); + + #endif + + // NOTE: Do not clip on fully shadowed pixels as it would + // cause the hardware occlusion query to disable the shadow. + + // Specular term + float specular = AL_CalcSpecular( -lightToPxlVec, + normal, + normalize( -eyeRay ) ) * lightBrightness * atten * shadowed; + + float Sat_NL_Att = saturate( nDotL * atten * shadowed ) * lightBrightness; + vec3 lightColorOut = lightMapParams.rgb * lightcol; + vec4 addToResult = vec4(0.0); + + // TODO: This needs to be removed when lightmapping is disabled + // as its extra work per-pixel on dynamic lit scenes. + // + // Special lightmapping pass. + if ( lightMapParams.a < 0.0 ) + { + // This disables shadows on the backsides of objects. + shadowed = nDotL < 0.0f ? 1.0f : shadowed; + + Sat_NL_Att = 1.0f; + shadowed = mix( 1.0f, shadowed, atten ); + lightColorOut = vec3(shadowed); + specular *= lightBrightness; + addToResult = ( 1.0 - shadowed ) * abs(lightMapParams); + } + + OUT_col = AL_DeferredOutput(lightColorOut+subsurface*(1.0-Sat_NL_Att), colorSample.rgb, matInfo, addToResult, specular, Sat_NL_Att); +} diff --git a/Templates/BaseGame/game/core/rendering/shaders/lighting/advanced/gl/vectorLightP.glsl b/Templates/BaseGame/game/core/rendering/shaders/lighting/advanced/gl/vectorLightP.glsl new file mode 100644 index 000000000..142e58b10 --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/lighting/advanced/gl/vectorLightP.glsl @@ -0,0 +1,327 @@ +//----------------------------------------------------------------------------- +// 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 "farFrustumQuad.glsl" +#include "../../../gl/torque.glsl" +#include "../../../gl/lighting.glsl" +#include "lightingUtils.glsl" +#include "../../shadowMap/shadowMapIO_GLSL.h" +#include "softShadow.glsl" + +in vec4 hpos; +in vec2 uv0; +in vec3 wsEyeRay; +in vec3 vsEyeRay; + +uniform sampler2D shadowMap; +uniform sampler2D dynamicShadowMap; + +#ifdef USE_SSAO_MASK +uniform sampler2D ssaoMask ; +uniform vec4 rtParams3; +#endif + +uniform sampler2D deferredBuffer; +uniform sampler2D lightBuffer; +uniform sampler2D colorBuffer; +uniform sampler2D matInfoBuffer; +uniform vec3 lightDirection; +uniform vec4 lightColor; +uniform float lightBrightness; +uniform vec4 lightAmbient; +uniform vec3 eyePosWorld; +uniform mat4x4 eyeMat; +uniform vec4 atlasXOffset; +uniform vec4 atlasYOffset; +uniform vec2 atlasScale; +uniform vec4 zNearFarInvNearFar; +uniform vec4 lightMapParams; +uniform vec2 fadeStartLength; +uniform vec4 overDarkPSSM; +uniform float shadowSoftness; + +//static shadowMap +uniform mat4x4 worldToLightProj; +uniform vec4 scaleX; +uniform vec4 scaleY; +uniform vec4 offsetX; +uniform vec4 offsetY; +uniform vec4 farPlaneScalePSSM; + +//dynamic shadowMap +uniform mat4x4 dynamicWorldToLightProj; +uniform vec4 dynamicScaleX; +uniform vec4 dynamicScaleY; +uniform vec4 dynamicOffsetX; +uniform vec4 dynamicOffsetY; +uniform vec4 dynamicFarPlaneScalePSSM; + +vec4 AL_VectorLightShadowCast( sampler2D _sourceshadowMap, + vec2 _texCoord, + mat4 _worldToLightProj, + vec4 _worldPos, + vec4 _scaleX, vec4 _scaleY, + vec4 _offsetX, vec4 _offsetY, + vec4 _farPlaneScalePSSM, + vec4 _atlasXOffset, vec4 _atlasYOffset, + vec2 _atlasScale, + float _shadowSoftness, + float _dotNL , + vec4 _overDarkPSSM +) +{ + + // Compute shadow map coordinate + vec4 pxlPosLightProj = tMul(_worldToLightProj, _worldPos); + vec2 baseShadowCoord = pxlPosLightProj.xy / pxlPosLightProj.w; + + // Distance to light, in shadowMap space + float distToLight = pxlPosLightProj.z / pxlPosLightProj.w; + + // Figure out which split to sample from. Basically, we compute the shadowMap sample coord + // for all of the splits and then check if its valid. + vec4 shadowCoordX = vec4( baseShadowCoord.x ); + vec4 shadowCoordY = vec4( baseShadowCoord.y ); + vec4 farPlaneDists = vec4( distToLight ); + shadowCoordX *= _scaleX; + shadowCoordY *= _scaleY; + shadowCoordX += _offsetX; + shadowCoordY += _offsetY; + farPlaneDists *= _farPlaneScalePSSM; + + // If the shadow sample is within -1..1 and the distance + // to the light for this pixel is less than the far plane + // of the split, use it. + vec4 finalMask; + if ( shadowCoordX.x > -0.99 && shadowCoordX.x < 0.99 && + shadowCoordY.x > -0.99 && shadowCoordY.x < 0.99 && + farPlaneDists.x < 1.0 ) + finalMask = vec4(1, 0, 0, 0); + + else if ( shadowCoordX.y > -0.99 && shadowCoordX.y < 0.99 && + shadowCoordY.y > -0.99 && shadowCoordY.y < 0.99 && + farPlaneDists.y < 1.0 ) + finalMask = vec4(0, 1, 0, 0); + + else if ( shadowCoordX.z > -0.99 && shadowCoordX.z < 0.99 && + shadowCoordY.z > -0.99 && shadowCoordY.z < 0.99 && + farPlaneDists.z < 1.0 ) + finalMask = vec4(0, 0, 1, 0); + + else + finalMask = vec4(0, 0, 0, 1); + + vec3 debugColor = vec3(0); + + #ifdef NO_SHADOW + debugColor = vec3(1.0); + #endif + + #ifdef PSSM_DEBUG_RENDER + if ( finalMask.x > 0 ) + debugColor += vec3( 1, 0, 0 ); + else if ( finalMask.y > 0 ) + debugColor += vec3( 0, 1, 0 ); + else if ( finalMask.z > 0 ) + debugColor += vec3( 0, 0, 1 ); + else if ( finalMask.w > 0 ) + debugColor += vec3( 1, 1, 0 ); + #endif + + // Here we know what split we're sampling from, so recompute the _texCoord location + // Yes, we could just use the result from above, but doing it this way actually saves + // shader instructions. + vec2 finalScale; + finalScale.x = dot(finalMask, _scaleX); + finalScale.y = dot(finalMask, _scaleY); + + vec2 finalOffset; + finalOffset.x = dot(finalMask, _offsetX); + finalOffset.y = dot(finalMask, _offsetY); + + vec2 shadowCoord; + shadowCoord = baseShadowCoord * finalScale; + shadowCoord += finalOffset; + + // Convert to _texCoord space + shadowCoord = 0.5 * shadowCoord + vec2(0.5, 0.5); + shadowCoord.y = 1.0f - shadowCoord.y; + + // Move around inside of atlas + vec2 aOffset; + aOffset.x = dot(finalMask, _atlasXOffset); + aOffset.y = dot(finalMask, _atlasYOffset); + + shadowCoord *= _atlasScale; + shadowCoord += aOffset; + + // Each split has a different far plane, take this into account. + float farPlaneScale = dot( _farPlaneScalePSSM, finalMask ); + distToLight *= farPlaneScale; + + return vec4(debugColor, + softShadow_filter( _sourceshadowMap, + _texCoord, + shadowCoord, + farPlaneScale * _shadowSoftness, + distToLight, + _dotNL, + dot( finalMask, _overDarkPSSM ) ) ); +} + +out vec4 OUT_col; +void main() +{ + // Emissive. + float4 matInfo = texture( matInfoBuffer, uv0 ); + bool emissive = getFlag( matInfo.r, 0 ); + if ( emissive ) + { + OUT_col = vec4(1.0, 1.0, 1.0, 0.0); + return; + } + + vec4 colorSample = texture( colorBuffer, uv0 ); + vec3 subsurface = vec3(0.0,0.0,0.0); + if (getFlag( matInfo.r, 1 )) + { + subsurface = colorSample.rgb; + if (colorSample.r>colorSample.g) + subsurface = vec3(0.772549, 0.337255, 0.262745); + else + subsurface = vec3(0.337255, 0.772549, 0.262745); + } + + // Sample/unpack the normal/z data + vec4 deferredSample = deferredUncondition( deferredBuffer, uv0 ); + vec3 normal = deferredSample.rgb; + float depth = deferredSample.a; + + // Use eye ray to get ws pos + vec4 worldPos = vec4(eyePosWorld + wsEyeRay * depth, 1.0f); + + // Get the light attenuation. + float dotNL = dot(-lightDirection, normal); + + #ifdef PSSM_DEBUG_RENDER + vec3 debugColor = vec3(0); + #endif + + #ifdef NO_SHADOW + + // Fully unshadowed. + float shadowed = 1.0; + + #ifdef PSSM_DEBUG_RENDER + debugColor = vec3(1.0); + #endif + + #else + + vec4 static_shadowed_colors = AL_VectorLightShadowCast( shadowMap, + uv0.xy, + worldToLightProj, + worldPos, + scaleX, scaleY, + offsetX, offsetY, + farPlaneScalePSSM, + atlasXOffset, atlasYOffset, + atlasScale, + shadowSoftness, + dotNL, + overDarkPSSM); + vec4 dynamic_shadowed_colors = AL_VectorLightShadowCast( dynamicShadowMap, + uv0.xy, + dynamicWorldToLightProj, + worldPos, + dynamicScaleX, dynamicScaleY, + dynamicOffsetX, dynamicOffsetY, + dynamicFarPlaneScalePSSM, + atlasXOffset, atlasYOffset, + atlasScale, + shadowSoftness, + dotNL, + overDarkPSSM); + float static_shadowed = static_shadowed_colors.a; + float dynamic_shadowed = dynamic_shadowed_colors.a; + + #ifdef PSSM_DEBUG_RENDER + debugColor = static_shadowed_colors.rgb*0.5+dynamic_shadowed_colors.rgb*0.5; + #endif + + // Fade out the shadow at the end of the range. + vec4 zDist = vec4(zNearFarInvNearFar.x + zNearFarInvNearFar.y * depth); + float fadeOutAmt = ( zDist.x - fadeStartLength.x ) * fadeStartLength.y; + + static_shadowed = mix( static_shadowed, 1.0, saturate( fadeOutAmt ) ); + dynamic_shadowed = mix( dynamic_shadowed, 1.0, saturate( fadeOutAmt ) ); + + // temp for debugging. uncomment one or the other. + //float shadowed = static_shadowed; + //float shadowed = dynamic_shadowed; + float shadowed = min(static_shadowed, dynamic_shadowed); + + #ifdef PSSM_DEBUG_RENDER + if ( fadeOutAmt > 1.0 ) + debugColor = vec3(1.0); + #endif + + #endif // !NO_SHADOW + + // Specular term + float specular = AL_CalcSpecular( -lightDirection, + normal, + normalize(-vsEyeRay) ) * lightBrightness * shadowed; + + float Sat_NL_Att = saturate( dotNL * shadowed ) * lightBrightness; + vec3 lightColorOut = lightMapParams.rgb * lightColor.rgb; + vec4 addToResult = (lightAmbient * (1 - ambientCameraFactor)) + ( lightAmbient * ambientCameraFactor * saturate(dot(normalize(-vsEyeRay), normal)) ); + + // TODO: This needs to be removed when lightmapping is disabled + // as its extra work per-pixel on dynamic lit scenes. + // + // Special lightmapping pass. + if ( lightMapParams.a < 0.0 ) + { + // This disables shadows on the backsides of objects. + shadowed = dotNL < 0.0f ? 1.0f : shadowed; + + Sat_NL_Att = 1.0f; + lightColorOut = vec3(shadowed); + specular *= lightBrightness; + addToResult = ( 1.0 - shadowed ) * abs(lightMapParams); + } + + // Sample the AO texture. + #ifdef USE_SSAO_MASK + float ao = 1.0 - texture( ssaoMask, viewportCoordToRenderTarget( uv0.xy, rtParams3 ) ).r; + addToResult *= ao; + #endif + + #ifdef PSSM_DEBUG_RENDER + lightColorOut = debugColor; + #endif + + OUT_col = AL_DeferredOutput(lightColorOut+subsurface*(1.0-Sat_NL_Att), colorSample.rgb, matInfo, addToResult, specular, Sat_NL_Att); +} diff --git a/Templates/BaseGame/game/core/rendering/shaders/lighting/advanced/lightingUtils.hlsl b/Templates/BaseGame/game/core/rendering/shaders/lighting/advanced/lightingUtils.hlsl new file mode 100644 index 000000000..2bff18999 --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/lighting/advanced/lightingUtils.hlsl @@ -0,0 +1,51 @@ +//----------------------------------------------------------------------------- +// 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. +//----------------------------------------------------------------------------- + + +float attenuate( float4 lightColor, float2 attParams, float dist ) +{ + // We're summing the results of a scaled constant, + // linear, and quadratic attenuation. + + #ifdef ACCUMULATE_LUV + return lightColor.w * ( 1.0 - dot( attParams, float2( dist, dist * dist ) ) ); + #else + return 1.0 - dot( attParams, float2( dist, dist * dist ) ); + #endif +} + +float3 getDistanceVectorToPlane( float3 origin, float3 direction, float4 plane ) +{ + float denum = dot( plane.xyz, direction.xyz ); + float num = dot( plane, float4( origin, 1.0 ) ); + float t = -num / denum; + + return direction.xyz * t; +} + +float3 getDistanceVectorToPlane( float negFarPlaneDotEye, float3 direction, float4 plane ) +{ + float denum = dot( plane.xyz, direction.xyz ); + float t = negFarPlaneDotEye / denum; + + return direction.xyz * t; +} diff --git a/Templates/BaseGame/game/core/rendering/shaders/lighting/advanced/particlePointLightP.hlsl b/Templates/BaseGame/game/core/rendering/shaders/lighting/advanced/particlePointLightP.hlsl new file mode 100644 index 000000000..a0156eb85 --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/lighting/advanced/particlePointLightP.hlsl @@ -0,0 +1,76 @@ +//----------------------------------------------------------------------------- +// 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 "farFrustumQuad.hlsl" +#include "lightingUtils.hlsl" +#include "../../lighting.hlsl" +#include "../../shaderModel.hlsl" +#include "../../shaderModelAutoGen.hlsl" + + +struct ConvexConnectP +{ + float4 pos : TORQUE_POSITION; + float4 ssPos : TEXCOORD0; + float3 vsEyeDir : TEXCOORD1; +}; + +TORQUE_UNIFORM_SAMPLER2D(deferredBuffer, 0); + +uniform float4 lightPosition; +uniform float4 lightColor; +uniform float lightRange; +uniform float4 vsFarPlane; +uniform float4 rtParams0; + +float4 main( ConvexConnectP IN ) : TORQUE_TARGET0 +{ + // Compute scene UV + float3 ssPos = IN.ssPos.xyz / IN.ssPos.w; + float2 uvScene = getUVFromSSPos(ssPos, rtParams0); + + // Sample/unpack the normal/z data + float4 deferredSample = TORQUE_DEFERRED_UNCONDITION(deferredBuffer, uvScene); + float3 normal = deferredSample.rgb; + float depth = deferredSample.a; + + // Eye ray - Eye -> Pixel + float3 eyeRay = getDistanceVectorToPlane(-vsFarPlane.w, IN.vsEyeDir, vsFarPlane); + float3 viewSpacePos = eyeRay * depth; + + // Build light vec, get length, clip pixel if needed + float3 lightVec = lightPosition.xyz - viewSpacePos; + float lenLightV = length(lightVec); + clip(lightRange - lenLightV); + + // Do a very simple falloff instead of real attenuation + float atten = 1.0 - saturate(lenLightV / lightRange); + + // Normalize lightVec + lightVec /= lenLightV; + + // N.L * Attenuation + float Sat_NL_Att = saturate(dot(lightVec, normal)) * atten; + + // Output, no specular + return lightinfoCondition(lightColor.rgb, Sat_NL_Att, 0.0, 0.0); +} diff --git a/Templates/BaseGame/game/core/rendering/shaders/lighting/advanced/particlePointLightV.hlsl b/Templates/BaseGame/game/core/rendering/shaders/lighting/advanced/particlePointLightV.hlsl new file mode 100644 index 000000000..faa2ec115 --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/lighting/advanced/particlePointLightV.hlsl @@ -0,0 +1,48 @@ +//----------------------------------------------------------------------------- +// 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 "../../hlslStructs.hlsl" +#include "../../shaderModel.hlsl" + +struct ConvexConnectV +{ + float4 hpos : TORQUE_POSITION; + float4 ssPos : TEXCOORD0; + float3 vsEyeDir : TEXCOORD1; +}; + +uniform float4x4 viewProj; +uniform float4x4 view; +uniform float3 particlePosWorld; +uniform float lightRange; + +ConvexConnectV main( VertexIn_P IN ) +{ + ConvexConnectV OUT; + float4 pos = float4(IN.pos, 0.0); + float4 vPosWorld = pos + float4(particlePosWorld, 0.0) + pos * lightRange; + OUT.hpos = mul(viewProj, vPosWorld); + OUT.vsEyeDir = mul(view, vPosWorld); + OUT.ssPos = OUT.hpos; + + return OUT; +} diff --git a/Templates/BaseGame/game/core/rendering/shaders/lighting/advanced/pointLightP.hlsl b/Templates/BaseGame/game/core/rendering/shaders/lighting/advanced/pointLightP.hlsl new file mode 100644 index 000000000..317feb0b3 --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/lighting/advanced/pointLightP.hlsl @@ -0,0 +1,277 @@ +//----------------------------------------------------------------------------- +// 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 "../../shaderModelAutoGen.hlsl" + +#include "farFrustumQuad.hlsl" +#include "lightingUtils.hlsl" +#include "../../lighting.hlsl" +#include "../shadowMap/shadowMapIO_HLSL.h" +#include "softShadow.hlsl" +#include "../../torque.hlsl" + +struct ConvexConnectP +{ + float4 pos : TORQUE_POSITION; + float4 wsEyeDir : TEXCOORD0; + float4 ssPos : TEXCOORD1; + float4 vsEyeDir : TEXCOORD2; +}; + + +#ifdef USE_COOKIE_TEX + +/// The texture for cookie rendering. +TORQUE_UNIFORM_SAMPLERCUBE(cookieMap, 3); + +#endif + + +#ifdef SHADOW_CUBE + + float3 decodeShadowCoord( float3 shadowCoord ) + { + return shadowCoord; + } + + float4 shadowSample( TORQUE_SAMPLERCUBE(shadowMap), float3 shadowCoord ) + { + return TORQUE_TEXCUBE( shadowMap, shadowCoord ); + } + +#else + + float3 decodeShadowCoord( float3 paraVec ) + { + // Flip y and z + paraVec = paraVec.xzy; + + #ifndef SHADOW_PARABOLOID + + bool calcBack = (paraVec.z < 0.0); + if ( calcBack ) + { + paraVec.z = paraVec.z * -1.0; + + #ifdef SHADOW_DUALPARABOLOID + paraVec.x = -paraVec.x; + #endif + } + + #endif + + float3 shadowCoord; + shadowCoord.x = (paraVec.x / (2*(1 + paraVec.z))) + 0.5; + shadowCoord.y = 1-((paraVec.y / (2*(1 + paraVec.z))) + 0.5); + shadowCoord.z = 0; + + // adjust the co-ordinate slightly if it is near the extent of the paraboloid + // this value was found via experementation + // NOTE: this is wrong, it only biases in one direction, not towards the uv + // center ( 0.5 0.5 ). + //shadowCoord.xy *= 0.997; + + #ifndef SHADOW_PARABOLOID + + // If this is the back, offset in the atlas + if ( calcBack ) + shadowCoord.x += 1.0; + + // Atlasing front and back maps, so scale + shadowCoord.x *= 0.5; + + #endif + + return shadowCoord; + } + +#endif + +TORQUE_UNIFORM_SAMPLER2D(deferredBuffer, 0); + +#ifdef SHADOW_CUBE +TORQUE_UNIFORM_SAMPLERCUBE(shadowMap, 1); +#else +TORQUE_UNIFORM_SAMPLER2D(shadowMap, 1); +TORQUE_UNIFORM_SAMPLER2D(dynamicShadowMap, 2); +#endif + +TORQUE_UNIFORM_SAMPLER2D(lightBuffer, 5); +TORQUE_UNIFORM_SAMPLER2D(colorBuffer, 6); +TORQUE_UNIFORM_SAMPLER2D(matInfoBuffer, 7); + +uniform float4 rtParams0; +uniform float4 lightColor; + +uniform float lightBrightness; +uniform float3 lightPosition; + +uniform float4 lightMapParams; +uniform float4 vsFarPlane; +uniform float4 lightParams; + +uniform float lightRange; +uniform float shadowSoftness; +uniform float2 lightAttenuation; + +uniform float3x3 viewToLightProj; +uniform float3x3 dynamicViewToLightProj; + +float4 main( ConvexConnectP IN ) : TORQUE_TARGET0 +{ + // Compute scene UV + float3 ssPos = IN.ssPos.xyz / IN.ssPos.w; + float2 uvScene = getUVFromSSPos( ssPos, rtParams0 ); + + // Emissive. + float4 matInfo = TORQUE_TEX2D( matInfoBuffer, uvScene ); + bool emissive = getFlag( matInfo.r, 0 ); + if ( emissive ) + { + return float4(0.0, 0.0, 0.0, 0.0); + } + float4 colorSample = TORQUE_TEX2D( colorBuffer, uvScene ); + float3 subsurface = float3(0.0,0.0,0.0); + if (getFlag( matInfo.r, 1 )) + { + subsurface = colorSample.rgb; + if (colorSample.r>colorSample.g) + subsurface = float3(0.772549, 0.337255, 0.262745); + else + subsurface = float3(0.337255, 0.772549, 0.262745); + } + + // Sample/unpack the normal/z data + float4 deferredSample = TORQUE_DEFERRED_UNCONDITION( deferredBuffer, uvScene ); + float3 normal = deferredSample.rgb; + float depth = deferredSample.a; + + // Eye ray - Eye -> Pixel + float3 eyeRay = getDistanceVectorToPlane( -vsFarPlane.w, IN.vsEyeDir.xyz, vsFarPlane ); + float3 viewSpacePos = eyeRay * depth; + + // Build light vec, get length, clip pixel if needed + float3 lightVec = lightPosition - viewSpacePos; + float lenLightV = length( lightVec ); + clip( lightRange - lenLightV ); + + // Get the attenuated falloff. + float atten = attenuate( lightColor, lightAttenuation, lenLightV ); + clip( atten - 1e-6 ); + + // Normalize lightVec + lightVec /= lenLightV; + + // If we can do dynamic branching then avoid wasting + // fillrate on pixels that are backfacing to the light. + float nDotL = dot( lightVec, normal ); + //DB_CLIP( nDotL < 0 ); + + #ifdef NO_SHADOW + + float shadowed = 1.0; + + #else + + // Get a linear depth from the light source. + float distToLight = lenLightV / lightRange; + + #ifdef SHADOW_CUBE + + // TODO: We need to fix shadow cube to handle soft shadows! + float occ = TORQUE_TEXCUBE( shadowMap, mul( viewToLightProj, -lightVec ) ).r; + float shadowed = saturate( exp( lightParams.y * ( occ - distToLight ) ) ); + + #else + + // Static + float2 shadowCoord = decodeShadowCoord( mul( viewToLightProj, -lightVec ) ).xy; + float static_shadowed = softShadow_filter( TORQUE_SAMPLER2D_MAKEARG(shadowMap), + ssPos.xy, + shadowCoord, + shadowSoftness, + distToLight, + nDotL, + lightParams.y ); + + // Dynamic + float2 dynamicShadowCoord = decodeShadowCoord( mul( dynamicViewToLightProj, -lightVec ) ).xy; + float dynamic_shadowed = softShadow_filter( TORQUE_SAMPLER2D_MAKEARG(dynamicShadowMap), + ssPos.xy, + dynamicShadowCoord, + shadowSoftness, + distToLight, + nDotL, + lightParams.y ); + + float shadowed = min(static_shadowed, dynamic_shadowed); + + #endif + + #endif // !NO_SHADOW + + float3 lightcol = lightColor.rgb; + #ifdef USE_COOKIE_TEX + + // Lookup the cookie sample. + float4 cookie = TORQUE_TEXCUBE( cookieMap, mul( viewToLightProj, -lightVec ) ); + + // Multiply the light with the cookie tex. + lightcol *= cookie.rgb; + + // Use a maximum channel luminance to attenuate + // the lighting else we get specular in the dark + // regions of the cookie texture. + atten *= max( cookie.r, max( cookie.g, cookie.b ) ); + + #endif + + // NOTE: Do not clip on fully shadowed pixels as it would + // cause the hardware occlusion query to disable the shadow. + + // Specular term + float specular = AL_CalcSpecular( lightVec, + normal, + normalize( -eyeRay ) ) * lightBrightness * atten * shadowed; + + float Sat_NL_Att = saturate( nDotL * atten * shadowed ) * lightBrightness; + float3 lightColorOut = lightMapParams.rgb * lightcol; + float4 addToResult = 0.0; + + // TODO: This needs to be removed when lightmapping is disabled + // as its extra work per-pixel on dynamic lit scenes. + // + // Special lightmapping pass. + if ( lightMapParams.a < 0.0 ) + { + // This disables shadows on the backsides of objects. + shadowed = nDotL < 0.0f ? 1.0f : shadowed; + + Sat_NL_Att = 1.0f; + shadowed = lerp( 1.0f, shadowed, atten ); + lightColorOut = shadowed; + specular *= lightBrightness; + addToResult = ( 1.0 - shadowed ) * abs(lightMapParams); + } + + return AL_DeferredOutput(lightColorOut+subsurface*(1.0-Sat_NL_Att), colorSample.rgb, matInfo, addToResult, specular, Sat_NL_Att); +} diff --git a/Templates/BaseGame/game/core/rendering/shaders/lighting/advanced/softShadow.hlsl b/Templates/BaseGame/game/core/rendering/shaders/lighting/advanced/softShadow.hlsl new file mode 100644 index 000000000..0faf3e1fb --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/lighting/advanced/softShadow.hlsl @@ -0,0 +1,158 @@ +//----------------------------------------------------------------------------- +// 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 "../../shaderModel.hlsl" + +#if defined( SOFTSHADOW ) && defined( SOFTSHADOW_HIGH_QUALITY ) + +#define NUM_PRE_TAPS 4 +#define NUM_TAPS 12 + +/// The non-uniform poisson disk used in the +/// high quality shadow filtering. +static float2 sNonUniformTaps[NUM_TAPS] = +{ + // These first 4 taps are located around the edges + // of the disk and are used to predict fully shadowed + // or unshadowed areas. + { 0.992833, 0.979309 }, + { -0.998585, 0.985853 }, + { 0.949299, -0.882562 }, + { -0.941358, -0.893924 }, + + // The rest of the samples. + { 0.545055, -0.589072 }, + { 0.346526, 0.385821 }, + { -0.260183, 0.334412 }, + { 0.248676, -0.679605 }, + { -0.569502, -0.390637 }, + { -0.614096, 0.212577 }, + { -0.259178, 0.876272 }, + { 0.649526, 0.864333 }, +}; + +#else + +#define NUM_PRE_TAPS 5 + +/// The non-uniform poisson disk used in the +/// high quality shadow filtering. +static float2 sNonUniformTaps[NUM_PRE_TAPS] = +{ + { 0.892833, 0.959309 }, + { -0.941358, -0.873924 }, + { -0.260183, 0.334412 }, + { 0.348676, -0.679605 }, + { -0.569502, -0.390637 }, +}; + +#endif + + +/// The texture used to do per-pixel pseudorandom +/// rotations of the filter taps. +TORQUE_UNIFORM_SAMPLER2D(gTapRotationTex, 4); + +float softShadow_sampleTaps( TORQUE_SAMPLER2D(shadowMap1), + float2 sinCos, + float2 shadowPos, + float filterRadius, + float distToLight, + float esmFactor, + int startTap, + int endTap ) +{ + float shadow = 0; + + float2 tap = 0; + for ( int t = startTap; t < endTap; t++ ) + { + tap.x = ( sNonUniformTaps[t].x * sinCos.y - sNonUniformTaps[t].y * sinCos.x ) * filterRadius; + tap.y = ( sNonUniformTaps[t].y * sinCos.y + sNonUniformTaps[t].x * sinCos.x ) * filterRadius; + float occluder = TORQUE_TEX2DLOD( shadowMap1, float4( shadowPos + tap, 0, 0 ) ).r; + + float esm = saturate( exp( esmFactor * ( occluder - distToLight ) ) ); + shadow += esm / float( endTap - startTap ); + } + + return shadow; +} + + +float softShadow_filter( TORQUE_SAMPLER2D(shadowMap), + float2 vpos, + float2 shadowPos, + float filterRadius, + float distToLight, + float dotNL, + float esmFactor ) +{ + #ifndef SOFTSHADOW + + // If softshadow is undefined then we skip any complex + // filtering... just do a single sample ESM. + + float occluder = TORQUE_TEX2DLOD(shadowMap, float4(shadowPos, 0, 0)).r; + float shadow = saturate( exp( esmFactor * ( occluder - distToLight ) ) ); + + #else + // Lookup the random rotation for this screen pixel. + float2 sinCos = ( TORQUE_TEX2DLOD(gTapRotationTex, float4(vpos * 16, 0, 0)).rg - 0.5) * 2; + + // Do the prediction taps first. + float shadow = softShadow_sampleTaps( TORQUE_SAMPLER2D_MAKEARG(shadowMap), + sinCos, + shadowPos, + filterRadius, + distToLight, + esmFactor, + 0, + NUM_PRE_TAPS ); + + // We live with only the pretap results if we don't + // have high quality shadow filtering enabled. + #ifdef SOFTSHADOW_HIGH_QUALITY + + // Only do the expensive filtering if we're really + // in a partially shadowed area. + if ( shadow * ( 1.0 - shadow ) * max( dotNL, 0 ) > 0.06 ) + { + shadow += softShadow_sampleTaps( TORQUE_SAMPLER2D_MAKEARG(shadowMap), + sinCos, + shadowPos, + filterRadius, + distToLight, + esmFactor, + NUM_PRE_TAPS, + NUM_TAPS ); + + // This averages the taps above with the results + // of the prediction samples. + shadow *= 0.5; + } + + #endif // SOFTSHADOW_HIGH_QUALITY + + #endif // SOFTSHADOW + + return shadow; +} \ No newline at end of file diff --git a/Templates/BaseGame/game/core/rendering/shaders/lighting/advanced/spotLightP.hlsl b/Templates/BaseGame/game/core/rendering/shaders/lighting/advanced/spotLightP.hlsl new file mode 100644 index 000000000..196286dc2 --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/lighting/advanced/spotLightP.hlsl @@ -0,0 +1,209 @@ +//----------------------------------------------------------------------------- +// 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 "../../shaderModel.hlsl" +#include "../../shaderModelAutoGen.hlsl" + +#include "farFrustumQuad.hlsl" +#include "lightingUtils.hlsl" +#include "../../lighting.hlsl" +#include "../shadowMap/shadowMapIO_HLSL.h" +#include "softShadow.hlsl" +#include "../../torque.hlsl" + +struct ConvexConnectP +{ + float4 pos : TORQUE_POSITION; + float4 wsEyeDir : TEXCOORD0; + float4 ssPos : TEXCOORD1; + float4 vsEyeDir : TEXCOORD2; +}; + +TORQUE_UNIFORM_SAMPLER2D(deferredBuffer, 0); +TORQUE_UNIFORM_SAMPLER2D(shadowMap, 1); +TORQUE_UNIFORM_SAMPLER2D(dynamicShadowMap,2); + +#ifdef USE_COOKIE_TEX + +/// The texture for cookie rendering. +TORQUE_UNIFORM_SAMPLER2D(cookieMap, 3); + +#endif + +TORQUE_UNIFORM_SAMPLER2D(lightBuffer, 5); +TORQUE_UNIFORM_SAMPLER2D(colorBuffer, 6); +TORQUE_UNIFORM_SAMPLER2D(matInfoBuffer, 7); + +uniform float4 rtParams0; + +uniform float lightBrightness; +uniform float3 lightPosition; + +uniform float4 lightColor; + +uniform float lightRange; +uniform float3 lightDirection; + +uniform float4 lightSpotParams; +uniform float4 lightMapParams; +uniform float4 vsFarPlane; +uniform float4x4 viewToLightProj; +uniform float4 lightParams; +uniform float4x4 dynamicViewToLightProj; + +uniform float2 lightAttenuation; +uniform float shadowSoftness; + +float4 main( ConvexConnectP IN ) : TORQUE_TARGET0 +{ + // Compute scene UV + float3 ssPos = IN.ssPos.xyz / IN.ssPos.w; + float2 uvScene = getUVFromSSPos( ssPos, rtParams0 ); + + // Emissive. + float4 matInfo = TORQUE_TEX2D( matInfoBuffer, uvScene ); + bool emissive = getFlag( matInfo.r, 0 ); + if ( emissive ) + { + return float4(0.0, 0.0, 0.0, 0.0); + } + + float4 colorSample = TORQUE_TEX2D( colorBuffer, uvScene ); + float3 subsurface = float3(0.0,0.0,0.0); + if (getFlag( matInfo.r, 1 )) + { + subsurface = colorSample.rgb; + if (colorSample.r>colorSample.g) + subsurface = float3(0.772549, 0.337255, 0.262745); + else + subsurface = float3(0.337255, 0.772549, 0.262745); + } + + // Sample/unpack the normal/z data + float4 deferredSample = TORQUE_DEFERRED_UNCONDITION( deferredBuffer, uvScene ); + float3 normal = deferredSample.rgb; + float depth = deferredSample.a; + + // Eye ray - Eye -> Pixel + float3 eyeRay = getDistanceVectorToPlane( -vsFarPlane.w, IN.vsEyeDir.xyz, vsFarPlane ); + float3 viewSpacePos = eyeRay * depth; + + // Build light vec, get length, clip pixel if needed + float3 lightToPxlVec = viewSpacePos - lightPosition; + float lenLightV = length( lightToPxlVec ); + lightToPxlVec /= lenLightV; + + //lightDirection = float3( -lightDirection.xy, lightDirection.z ); //float3( 0, 0, -1 ); + float cosAlpha = dot( lightDirection, lightToPxlVec ); + clip( cosAlpha - lightSpotParams.x ); + clip( lightRange - lenLightV ); + + float atten = attenuate( lightColor, lightAttenuation, lenLightV ); + atten *= ( cosAlpha - lightSpotParams.x ) / lightSpotParams.y; + clip( atten - 1e-6 ); + atten = saturate( atten ); + + float nDotL = dot( normal, -lightToPxlVec ); + + // Get the shadow texture coordinate + float4 pxlPosLightProj = mul( viewToLightProj, float4( viewSpacePos, 1 ) ); + float2 shadowCoord = ( ( pxlPosLightProj.xy / pxlPosLightProj.w ) * 0.5 ) + float2( 0.5, 0.5 ); + shadowCoord.y = 1.0f - shadowCoord.y; + + // Get the dynamic shadow texture coordinate + float4 dynpxlPosLightProj = mul( dynamicViewToLightProj, float4( viewSpacePos, 1 ) ); + float2 dynshadowCoord = ( ( dynpxlPosLightProj.xy / dynpxlPosLightProj.w ) * 0.5 ) + float2( 0.5, 0.5 ); + dynshadowCoord.y = 1.0f - dynshadowCoord.y; + + #ifdef NO_SHADOW + + float shadowed = 1.0; + + #else + + // Get a linear depth from the light source. + float distToLight = pxlPosLightProj.z / lightRange; + + float static_shadowed = softShadow_filter( TORQUE_SAMPLER2D_MAKEARG(shadowMap), + ssPos.xy, + shadowCoord, + shadowSoftness, + distToLight, + nDotL, + lightParams.y ); + + float dynamic_shadowed = softShadow_filter( TORQUE_SAMPLER2D_MAKEARG(dynamicShadowMap), + ssPos.xy, + dynshadowCoord, + shadowSoftness, + distToLight, + nDotL, + lightParams.y ); + float shadowed = min(static_shadowed, dynamic_shadowed); + #endif // !NO_SHADOW + + float3 lightcol = lightColor.rgb; + #ifdef USE_COOKIE_TEX + + // Lookup the cookie sample. + float4 cookie = TORQUE_TEX2D( cookieMap, shadowCoord ); + + // Multiply the light with the cookie tex. + lightcol *= cookie.rgb; + + // Use a maximum channel luminance to attenuate + // the lighting else we get specular in the dark + // regions of the cookie texture. + atten *= max( cookie.r, max( cookie.g, cookie.b ) ); + + #endif + + // NOTE: Do not clip on fully shadowed pixels as it would + // cause the hardware occlusion query to disable the shadow. + + // Specular term + float specular = AL_CalcSpecular( -lightToPxlVec, + normal, + normalize( -eyeRay ) ) * lightBrightness * atten * shadowed; + + float Sat_NL_Att = saturate( nDotL * atten * shadowed ) * lightBrightness; + float3 lightColorOut = lightMapParams.rgb * lightcol; + float4 addToResult = 0.0; + + // TODO: This needs to be removed when lightmapping is disabled + // as its extra work per-pixel on dynamic lit scenes. + // + // Special lightmapping pass. + if ( lightMapParams.a < 0.0 ) + { + // This disables shadows on the backsides of objects. + shadowed = nDotL < 0.0f ? 1.0f : shadowed; + + Sat_NL_Att = 1.0f; + shadowed = lerp( 1.0f, shadowed, atten ); + lightColorOut = shadowed; + specular *= lightBrightness; + addToResult = ( 1.0 - shadowed ) * abs(lightMapParams); + } + + return AL_DeferredOutput(lightColorOut+subsurface*(1.0-Sat_NL_Att), colorSample.rgb, matInfo, addToResult, specular, Sat_NL_Att); +} diff --git a/Templates/BaseGame/game/core/rendering/shaders/lighting/advanced/vectorLightP.hlsl b/Templates/BaseGame/game/core/rendering/shaders/lighting/advanced/vectorLightP.hlsl new file mode 100644 index 000000000..c5efde242 --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/lighting/advanced/vectorLightP.hlsl @@ -0,0 +1,328 @@ +//----------------------------------------------------------------------------- +// 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 "../../shaderModel.hlsl" +#include "../../shaderModelAutoGen.hlsl" + +#include "farFrustumQuad.hlsl" +#include "../../torque.hlsl" +#include "../../lighting.hlsl" +#include "lightingUtils.hlsl" +#include "../shadowMap/shadowMapIO_HLSL.h" +#include "softShadow.hlsl" + +TORQUE_UNIFORM_SAMPLER2D(deferredBuffer, 0); +TORQUE_UNIFORM_SAMPLER2D(shadowMap, 1); +TORQUE_UNIFORM_SAMPLER2D(dynamicShadowMap, 2); + +#ifdef USE_SSAO_MASK +TORQUE_UNIFORM_SAMPLER2D(ssaoMask, 3); +uniform float4 rtParams3; +#endif +//register 4? +TORQUE_UNIFORM_SAMPLER2D(lightBuffer, 5); +TORQUE_UNIFORM_SAMPLER2D(colorBuffer, 6); +TORQUE_UNIFORM_SAMPLER2D(matInfoBuffer, 7); + +uniform float lightBrightness; +uniform float3 lightDirection; + +uniform float4 lightColor; +uniform float4 lightAmbient; + +uniform float shadowSoftness; +uniform float3 eyePosWorld; + +uniform float4 atlasXOffset; +uniform float4 atlasYOffset; +uniform float4 zNearFarInvNearFar; +uniform float4 lightMapParams; +uniform float4 farPlaneScalePSSM; +uniform float4 overDarkPSSM; + +uniform float2 fadeStartLength; +uniform float2 atlasScale; + +uniform float4x4 eyeMat; + +// Static Shadows +uniform float4x4 worldToLightProj; +uniform float4 scaleX; +uniform float4 scaleY; +uniform float4 offsetX; +uniform float4 offsetY; +// Dynamic Shadows +uniform float4x4 dynamicWorldToLightProj; +uniform float4 dynamicScaleX; +uniform float4 dynamicScaleY; +uniform float4 dynamicOffsetX; +uniform float4 dynamicOffsetY; +uniform float4 dynamicFarPlaneScalePSSM; + +float4 AL_VectorLightShadowCast( TORQUE_SAMPLER2D(sourceShadowMap), + float2 texCoord, + float4x4 worldToLightProj, + float4 worldPos, + float4 scaleX, + float4 scaleY, + float4 offsetX, + float4 offsetY, + float4 farPlaneScalePSSM, + float4 atlasXOffset, + float4 atlasYOffset, + float2 atlasScale, + float shadowSoftness, + float dotNL , + float4 overDarkPSSM) +{ + // Compute shadow map coordinate + float4 pxlPosLightProj = mul(worldToLightProj, worldPos); + float2 baseShadowCoord = pxlPosLightProj.xy / pxlPosLightProj.w; + + // Distance to light, in shadowmap space + float distToLight = pxlPosLightProj.z / pxlPosLightProj.w; + + // Figure out which split to sample from. Basically, we compute the shadowmap sample coord + // for all of the splits and then check if its valid. + float4 shadowCoordX = baseShadowCoord.xxxx; + float4 shadowCoordY = baseShadowCoord.yyyy; + float4 farPlaneDists = distToLight.xxxx; + shadowCoordX *= scaleX; + shadowCoordY *= scaleY; + shadowCoordX += offsetX; + shadowCoordY += offsetY; + farPlaneDists *= farPlaneScalePSSM; + + // If the shadow sample is within -1..1 and the distance + // to the light for this pixel is less than the far plane + // of the split, use it. + float4 finalMask; + if ( shadowCoordX.x > -0.99 && shadowCoordX.x < 0.99 && + shadowCoordY.x > -0.99 && shadowCoordY.x < 0.99 && + farPlaneDists.x < 1.0 ) + finalMask = float4(1, 0, 0, 0); + + else if ( shadowCoordX.y > -0.99 && shadowCoordX.y < 0.99 && + shadowCoordY.y > -0.99 && shadowCoordY.y < 0.99 && + farPlaneDists.y < 1.0 ) + finalMask = float4(0, 1, 0, 0); + + else if ( shadowCoordX.z > -0.99 && shadowCoordX.z < 0.99 && + shadowCoordY.z > -0.99 && shadowCoordY.z < 0.99 && + farPlaneDists.z < 1.0 ) + finalMask = float4(0, 0, 1, 0); + + else + finalMask = float4(0, 0, 0, 1); + + float3 debugColor = float3(0,0,0); + + #ifdef NO_SHADOW + debugColor = float3(1.0,1.0,1.0); + #endif + + #ifdef PSSM_DEBUG_RENDER + if ( finalMask.x > 0 ) + debugColor += float3( 1, 0, 0 ); + else if ( finalMask.y > 0 ) + debugColor += float3( 0, 1, 0 ); + else if ( finalMask.z > 0 ) + debugColor += float3( 0, 0, 1 ); + else if ( finalMask.w > 0 ) + debugColor += float3( 1, 1, 0 ); + #endif + + // Here we know what split we're sampling from, so recompute the texcoord location + // Yes, we could just use the result from above, but doing it this way actually saves + // shader instructions. + float2 finalScale; + finalScale.x = dot(finalMask, scaleX); + finalScale.y = dot(finalMask, scaleY); + + float2 finalOffset; + finalOffset.x = dot(finalMask, offsetX); + finalOffset.y = dot(finalMask, offsetY); + + float2 shadowCoord; + shadowCoord = baseShadowCoord * finalScale; + shadowCoord += finalOffset; + + // Convert to texcoord space + shadowCoord = 0.5 * shadowCoord + float2(0.5, 0.5); + shadowCoord.y = 1.0f - shadowCoord.y; + + // Move around inside of atlas + float2 aOffset; + aOffset.x = dot(finalMask, atlasXOffset); + aOffset.y = dot(finalMask, atlasYOffset); + + shadowCoord *= atlasScale; + shadowCoord += aOffset; + + // Each split has a different far plane, take this into account. + float farPlaneScale = dot( farPlaneScalePSSM, finalMask ); + distToLight *= farPlaneScale; + + return float4(debugColor, + softShadow_filter( TORQUE_SAMPLER2D_MAKEARG(sourceShadowMap), + texCoord, + shadowCoord, + farPlaneScale * shadowSoftness, + distToLight, + dotNL, + dot( finalMask, overDarkPSSM ) ) ); +}; + +float4 main( FarFrustumQuadConnectP IN ) : TORQUE_TARGET0 +{ + // Emissive. + float4 matInfo = TORQUE_TEX2D( matInfoBuffer, IN.uv0 ); + bool emissive = getFlag( matInfo.r, 0 ); + if ( emissive ) + { + return float4(1.0, 1.0, 1.0, 0.0); + } + + float4 colorSample = TORQUE_TEX2D( colorBuffer, IN.uv0 ); + float3 subsurface = float3(0.0,0.0,0.0); + if (getFlag( matInfo.r, 1 )) + { + subsurface = colorSample.rgb; + if (colorSample.r>colorSample.g) + subsurface = float3(0.772549, 0.337255, 0.262745); + else + subsurface = float3(0.337255, 0.772549, 0.262745); + } + // Sample/unpack the normal/z data + float4 deferredSample = TORQUE_DEFERRED_UNCONDITION( deferredBuffer, IN.uv0 ); + float3 normal = deferredSample.rgb; + float depth = deferredSample.a; + + // Use eye ray to get ws pos + float4 worldPos = float4(eyePosWorld + IN.wsEyeRay * depth, 1.0f); + + // Get the light attenuation. + float dotNL = dot(-lightDirection, normal); + + #ifdef PSSM_DEBUG_RENDER + float3 debugColor = float3(0,0,0); + #endif + + #ifdef NO_SHADOW + + // Fully unshadowed. + float shadowed = 1.0; + + #ifdef PSSM_DEBUG_RENDER + debugColor = float3(1.0,1.0,1.0); + #endif + + #else + + float4 static_shadowed_colors = AL_VectorLightShadowCast( TORQUE_SAMPLER2D_MAKEARG(shadowMap), + IN.uv0.xy, + worldToLightProj, + worldPos, + scaleX, scaleY, + offsetX, offsetY, + farPlaneScalePSSM, + atlasXOffset, atlasYOffset, + atlasScale, + shadowSoftness, + dotNL, + overDarkPSSM); + float4 dynamic_shadowed_colors = AL_VectorLightShadowCast( TORQUE_SAMPLER2D_MAKEARG(dynamicShadowMap), + IN.uv0.xy, + dynamicWorldToLightProj, + worldPos, + dynamicScaleX, dynamicScaleY, + dynamicOffsetX, dynamicOffsetY, + dynamicFarPlaneScalePSSM, + atlasXOffset, atlasYOffset, + atlasScale, + shadowSoftness, + dotNL, + overDarkPSSM); + + float static_shadowed = static_shadowed_colors.a; + float dynamic_shadowed = dynamic_shadowed_colors.a; + + #ifdef PSSM_DEBUG_RENDER + debugColor = static_shadowed_colors.rgb*0.5+dynamic_shadowed_colors.rgb*0.5; + #endif + + // Fade out the shadow at the end of the range. + float4 zDist = (zNearFarInvNearFar.x + zNearFarInvNearFar.y * depth); + float fadeOutAmt = ( zDist.x - fadeStartLength.x ) * fadeStartLength.y; + + static_shadowed = lerp( static_shadowed, 1.0, saturate( fadeOutAmt ) ); + dynamic_shadowed = lerp( dynamic_shadowed, 1.0, saturate( fadeOutAmt ) ); + + // temp for debugging. uncomment one or the other. + //float shadowed = static_shadowed; + //float shadowed = dynamic_shadowed; + float shadowed = min(static_shadowed, dynamic_shadowed); + + #ifdef PSSM_DEBUG_RENDER + if ( fadeOutAmt > 1.0 ) + debugColor = 1.0; + #endif + + #endif // !NO_SHADOW + + // Specular term + float specular = AL_CalcSpecular( -lightDirection, + normal, + normalize(-IN.vsEyeRay) ) * lightBrightness * shadowed; + + float Sat_NL_Att = saturate( dotNL * shadowed ) * lightBrightness; + float3 lightColorOut = lightMapParams.rgb * lightColor.rgb; + + float4 addToResult = (lightAmbient * (1 - ambientCameraFactor)) + ( lightAmbient * ambientCameraFactor * saturate(dot(normalize(-IN.vsEyeRay), normal)) ); + + // TODO: This needs to be removed when lightmapping is disabled + // as its extra work per-pixel on dynamic lit scenes. + // + // Special lightmapping pass. + if ( lightMapParams.a < 0.0 ) + { + // This disables shadows on the backsides of objects. + shadowed = dotNL < 0.0f ? 1.0f : shadowed; + + Sat_NL_Att = 1.0f; + lightColorOut = shadowed; + specular *= lightBrightness; + addToResult = ( 1.0 - shadowed ) * abs(lightMapParams); + } + + // Sample the AO texture. + #ifdef USE_SSAO_MASK + float ao = 1.0 - TORQUE_TEX2D( ssaoMask, viewportCoordToRenderTarget( IN.uv0.xy, rtParams3 ) ).r; + addToResult *= ao; + #endif + + #ifdef PSSM_DEBUG_RENDER + lightColorOut = debugColor; + #endif + + return AL_DeferredOutput(lightColorOut+subsurface*(1.0-Sat_NL_Att), colorSample.rgb, matInfo, addToResult, specular, Sat_NL_Att); +} diff --git a/Templates/BaseGame/game/core/rendering/shaders/lighting/basic/gl/shadowFilterP.glsl b/Templates/BaseGame/game/core/rendering/shaders/lighting/basic/gl/shadowFilterP.glsl new file mode 100644 index 000000000..9b510e0cf --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/lighting/basic/gl/shadowFilterP.glsl @@ -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. +//----------------------------------------------------------------------------- + +#include "../../../gl/hlslCompat.glsl" + +uniform sampler2D diffuseMap; + +in vec2 uv; + +uniform vec2 oneOverTargetSize; + +const float offset[3] = float[]( 0.0, 1.3846153846, 3.2307692308 ); +const float weight[3] = float[]( 0.2270270270, 0.3162162162, 0.0702702703 ); + +out vec4 OUT_col; + +void main() +{ + OUT_col = texture( diffuseMap, uv ) * weight[0]; + + for ( int i=1; i < 3; i++ ) + { + vec2 _sample = (BLUR_DIR * offset[i]) * oneOverTargetSize; + OUT_col += texture( diffuseMap, uv + _sample ) * weight[i]; + OUT_col += texture( diffuseMap, uv - _sample ) * weight[i]; + } +} diff --git a/Templates/BaseGame/game/core/rendering/shaders/lighting/basic/gl/shadowFilterV.glsl b/Templates/BaseGame/game/core/rendering/shaders/lighting/basic/gl/shadowFilterV.glsl new file mode 100644 index 000000000..67b5f1378 --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/lighting/basic/gl/shadowFilterV.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/torque.glsl" + +in vec4 vPosition; +in vec2 vTexCoord0; + +uniform vec4 rtParams0; + +out vec2 uv; + +void main() +{ + gl_Position = vPosition; + uv = viewportCoordToRenderTarget( vTexCoord0.st, rtParams0 ); + gl_Position.y *= -1; //correct ssp +} diff --git a/Templates/BaseGame/game/core/rendering/shaders/lighting/basic/shadowFilterP.hlsl b/Templates/BaseGame/game/core/rendering/shaders/lighting/basic/shadowFilterP.hlsl new file mode 100644 index 000000000..cf819eed3 --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/lighting/basic/shadowFilterP.hlsl @@ -0,0 +1,50 @@ +//----------------------------------------------------------------------------- +// 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 "../../postFx/postFx.hlsl" + +TORQUE_UNIFORM_SAMPLER2D(diffuseMap, 0); + +struct VertToPix +{ + float4 hpos : TORQUE_POSITION; + float2 uv : TEXCOORD0; +}; + +static float offset[3] = { 0.0, 1.3846153846, 3.2307692308 }; +static float weight[3] = { 0.2270270270, 0.3162162162, 0.0702702703 }; + +uniform float2 oneOverTargetSize; + +float4 main( VertToPix IN ) : TORQUE_TARGET0 +{ + float4 OUT = TORQUE_TEX2D( diffuseMap, IN.uv ) * weight[0]; + + for ( int i=1; i < 3; i++ ) + { + float2 sample = (BLUR_DIR * offset[i]) * oneOverTargetSize; + OUT += TORQUE_TEX2D( diffuseMap, IN.uv + sample ) * weight[i]; + OUT += TORQUE_TEX2D(diffuseMap, IN.uv - sample) * weight[i]; + } + + return OUT; +} diff --git a/Templates/BaseGame/game/core/rendering/shaders/lighting/basic/shadowFilterV.hlsl b/Templates/BaseGame/game/core/rendering/shaders/lighting/basic/shadowFilterV.hlsl new file mode 100644 index 000000000..d0838016b --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/lighting/basic/shadowFilterV.hlsl @@ -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 "../../postFx/postFx.hlsl" +#include "../../torque.hlsl" + +float4 rtParams0; + +struct VertToPix +{ + float4 hpos : TORQUE_POSITION; + float2 uv : TEXCOORD0; +}; + +VertToPix main( PFXVert IN ) +{ + VertToPix OUT; + + OUT.hpos = float4(IN.pos,1.0); + OUT.uv = viewportCoordToRenderTarget( IN.uv, rtParams0 ); + + return OUT; +} diff --git a/Templates/BaseGame/game/core/rendering/shaders/lighting/shadowMap/boxFilterP.hlsl b/Templates/BaseGame/game/core/rendering/shaders/lighting/shadowMap/boxFilterP.hlsl new file mode 100644 index 000000000..a187c3c63 --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/lighting/shadowMap/boxFilterP.hlsl @@ -0,0 +1,82 @@ +//----------------------------------------------------------------------------- +// 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. +//----------------------------------------------------------------------------- + +//***************************************************************************** +// Box Filter +//***************************************************************************** +#include "../ShaderModel.hlsl" + +struct ConnectData +{ + float4 hpos : TORQUE_POSITION; + float2 tex0 : TEXCOORD0; +}; + +// If not defined from ShaderData then define +// the default blur kernel size here. +//#ifndef blurSamples +// #define blurSamples 4 +//#endif + +float log_conv ( float x0, float X, float y0, float Y ) +{ + return (X + log(x0 + (y0 * exp(Y - X)))); +} + +TORQUE_UNIFORM_SAMPLER2D(diffuseMap0, 0); +uniform float texSize : register(C0); +uniform float2 blurDimension : register(C2); +uniform float2 blurBoundaries : register(C3); + +float4 main( ConnectData IN ) : TORQUE_TARGET0 +{ + // 5x5 + if (IN.tex0.x <= blurBoundaries.x) + { + float texelSize = 1.2f / texSize; + float2 sampleOffset = texelSize * blurDimension; + //float2 offset = 0.5 * float( blurSamples ) * sampleOffset; + + float2 texCoord = IN.tex0; + + float accum = log_conv(0.3125, TORQUE_TEX2D(diffuseMap0, texCoord - sampleOffset), 0.375, tex2D(diffuseMap0, texCoord)); + accum = log_conv(1, accum, 0.3125, TORQUE_TEX2D(diffuseMap0, texCoord + sampleOffset)); + + return accum; + } else { + // 3x3 + if (IN.tex0.x <= blurBoundaries.y) + { + float texelSize = 1.3f / texSize; + float2 sampleOffset = texelSize * blurDimension; + //float2 offset = 0.5 * float( blurSamples ) * sampleOffset; + + float2 texCoord = IN.tex0; + float accum = log_conv(0.5, tex2D(diffuseMap0, texCoord - sampleOffset), 0.5, tex2D(diffuseMap0, texCoord + sampleOffset)); + + return accum; + } else { + return TORQUE_TEX2D(diffuseMap0, IN.tex0); + } + } +} + diff --git a/Templates/BaseGame/game/core/rendering/shaders/lighting/shadowMap/boxFilterV.hlsl b/Templates/BaseGame/game/core/rendering/shaders/lighting/shadowMap/boxFilterV.hlsl new file mode 100644 index 000000000..3679e41bb --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/lighting/shadowMap/boxFilterV.hlsl @@ -0,0 +1,57 @@ +//----------------------------------------------------------------------------- +// 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. +//----------------------------------------------------------------------------- + +//***************************************************************************** +// Box Filter +//***************************************************************************** +//----------------------------------------------------------------------------- +// Structures +//----------------------------------------------------------------------------- + +#include "../ShaderModel.hlsl" + +struct VertData +{ + float3 position : POSITION; + float2 texCoord : TEXCOORD0; +}; + +struct ConnectData +{ + float4 hpos : TORQUE_POSITION; + float2 tex0 : TEXCOORD0; +}; + + +//----------------------------------------------------------------------------- +// Main +//----------------------------------------------------------------------------- +ConnectData main( VertData IN, + uniform float4x4 modelview : register(C0)) +{ + ConnectData OUT; + + OUT.hpos = mul(modelview, float4(IN.position,1.0)); + OUT.tex0 = IN.texCoord; + + return OUT; +} diff --git a/Templates/BaseGame/game/core/rendering/shaders/lighting/shadowMap/gl/boxFilterP.glsl b/Templates/BaseGame/game/core/rendering/shaders/lighting/shadowMap/gl/boxFilterP.glsl new file mode 100644 index 000000000..d4e05132b --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/lighting/shadowMap/gl/boxFilterP.glsl @@ -0,0 +1,49 @@ +//----------------------------------------------------------------------------- +// 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. +//----------------------------------------------------------------------------- + +#define blurSamples 4.0 + +uniform sampler2D diffuseMap0; +uniform float texSize; +uniform vec2 blurDimension; + +in vec2 tex0; + +out vec4 OUT_col; + +void main() +{ + // Preshader + float TexelSize = 1.0 / texSize; + vec2 SampleOffset = TexelSize * blurDimension; + vec2 Offset = 0.5 * float(blurSamples - 1.0) * SampleOffset; + + vec2 BaseTexCoord = tex0 - Offset; + + vec4 accum = vec4(0.0, 0.0, 0.0, 0.0); + for(int i = 0; i < int(blurSamples); i++) + { + accum += texture(diffuseMap0, BaseTexCoord + float(i) * SampleOffset); + } + accum /= blurSamples; + OUT_col = accum; +} \ No newline at end of file diff --git a/Templates/BaseGame/game/core/rendering/shaders/lighting/shadowMap/gl/boxFilterV.glsl b/Templates/BaseGame/game/core/rendering/shaders/lighting/shadowMap/gl/boxFilterV.glsl new file mode 100644 index 000000000..9fc436f6c --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/lighting/shadowMap/gl/boxFilterV.glsl @@ -0,0 +1,34 @@ +//----------------------------------------------------------------------------- +// 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. +//----------------------------------------------------------------------------- + +in vec4 vPosition; +in vec2 vTexCoord0; + +uniform mat4 modelview; + +out vec2 tex0; + +void main() +{ + gl_Position = modelview * vPosition; + tex0 = vTexCoord0.st; +} \ No newline at end of file diff --git a/Templates/BaseGame/game/core/rendering/shaders/lighting/shadowMap/shadowMapIO.h b/Templates/BaseGame/game/core/rendering/shaders/lighting/shadowMap/shadowMapIO.h new file mode 100644 index 000000000..84ef6b6a8 --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/lighting/shadowMap/shadowMapIO.h @@ -0,0 +1,50 @@ +//----------------------------------------------------------------------------- +// 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. +//----------------------------------------------------------------------------- + +//#define SM_Fmt_R8G8B8A8 + +#define pkDepthBitShft 65536.0 +#define pkDepthChanMax 256.0 +#define bias -0.5/255.0 +#define coeff 0.9999991 +//#define coeff 1.0 + +float4 encodeShadowMap( float depth ) +{ +#if defined(SM_Fmt_R8G8B8A8) + return frac( float4(1.0, 255.0, 65025.0, 160581375.0) * depth ) + bias; + + //float4 packedValue = frac((depth / coeff) * float4(16777216.0, 65536.0, 256.0, 1.0)); + //return (packedValue - packedValue.xxyz * float4(0, 1.0 / 256, 1.0 / 256, 1.0 / 256)); +#else + return depth; +#endif +} + +float decodeShadowMap( float4 smSample ) +{ +#if defined(SM_Fmt_R8G8B8A8) + return dot( smSample, float4(1.0, 1/255.0, 1/65025.0, 1/160581375.0) ); +#else + return smSample.x; +#endif +} diff --git a/Templates/BaseGame/game/core/rendering/shaders/lighting/shadowMap/shadowMapIO_GLSL.h b/Templates/BaseGame/game/core/rendering/shaders/lighting/shadowMap/shadowMapIO_GLSL.h new file mode 100644 index 000000000..10d69b834 --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/lighting/shadowMap/shadowMapIO_GLSL.h @@ -0,0 +1,50 @@ +//----------------------------------------------------------------------------- +// 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. +//----------------------------------------------------------------------------- + +//#define SM_Fmt_R8G8B8A8 + +#define pkDepthBitShft 65536.0 +#define pkDepthChanMax 256.0 +#define bias -0.5/255.0 +#define coeff 0.9999991 +//#define coeff 1.0 + +vec4 encodeShadowMap( float depth ) +{ +#if defined(SM_Fmt_R8G8B8A8) + return frac( vec4(1.0, 255.0, 65025.0, 160581375.0) * depth ) + vec4(bias); + + //float4 packedValue = frac((depth / coeff) * float4(16777216.0, 65536.0, 256.0, 1.0)); + //return (packedValue - packedValue.xxyz * float4(0, 1.0 / 256, 1.0 / 256, 1.0 / 256)); +#else + return vec4(depth); +#endif +} + +float decodeShadowMap( vec4 smSample ) +{ +#if defined(SM_Fmt_R8G8B8A8) + return dot( smSample, vec4(1.0, 1/255.0, 1/65025.0, 1/160581375.0) ); +#else + return smSample.x; +#endif +} diff --git a/Templates/BaseGame/game/core/rendering/shaders/lighting/shadowMap/shadowMapIO_HLSL.h b/Templates/BaseGame/game/core/rendering/shaders/lighting/shadowMap/shadowMapIO_HLSL.h new file mode 100644 index 000000000..84ef6b6a8 --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/lighting/shadowMap/shadowMapIO_HLSL.h @@ -0,0 +1,50 @@ +//----------------------------------------------------------------------------- +// 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. +//----------------------------------------------------------------------------- + +//#define SM_Fmt_R8G8B8A8 + +#define pkDepthBitShft 65536.0 +#define pkDepthChanMax 256.0 +#define bias -0.5/255.0 +#define coeff 0.9999991 +//#define coeff 1.0 + +float4 encodeShadowMap( float depth ) +{ +#if defined(SM_Fmt_R8G8B8A8) + return frac( float4(1.0, 255.0, 65025.0, 160581375.0) * depth ) + bias; + + //float4 packedValue = frac((depth / coeff) * float4(16777216.0, 65536.0, 256.0, 1.0)); + //return (packedValue - packedValue.xxyz * float4(0, 1.0 / 256, 1.0 / 256, 1.0 / 256)); +#else + return depth; +#endif +} + +float decodeShadowMap( float4 smSample ) +{ +#if defined(SM_Fmt_R8G8B8A8) + return dot( smSample, float4(1.0, 1/255.0, 1/65025.0, 1/160581375.0) ); +#else + return smSample.x; +#endif +} diff --git a/Templates/BaseGame/game/core/rendering/shaders/particleCompositeP.hlsl b/Templates/BaseGame/game/core/rendering/shaders/particleCompositeP.hlsl new file mode 100644 index 000000000..6e26ddbdb --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/particleCompositeP.hlsl @@ -0,0 +1,61 @@ +//----------------------------------------------------------------------------- +// 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 "torque.hlsl" +#include "shaderModel.hlsl" + +TORQUE_UNIFORM_SAMPLER2D(colorSource, 0); +uniform float4 offscreenTargetParams; + +#ifdef TORQUE_LINEAR_DEPTH +#define REJECT_EDGES +TORQUE_UNIFORM_SAMPLER2D(edgeSource, 1); +uniform float4 edgeTargetParams; +#endif + +struct Conn +{ + float4 hpos : TORQUE_POSITION; + float4 offscreenPos : TEXCOORD0; + float4 backbufferPos : TEXCOORD1; +}; + + +float4 main(Conn IN) : TORQUE_TARGET0 +{ + // Off-screen particle source screenspace position in XY + // Back-buffer screenspace position in ZW + float4 ssPos = float4(IN.offscreenPos.xy / IN.offscreenPos.w, IN.backbufferPos.xy / IN.backbufferPos.w); + + float4 uvScene = ( ssPos + 1.0 ) / 2.0; + uvScene.yw = 1.0 - uvScene.yw; + uvScene.xy = viewportCoordToRenderTarget(uvScene.xy, offscreenTargetParams); + +#ifdef REJECT_EDGES + // Cut out particles along the edges, this will create the stencil mask + uvScene.zw = viewportCoordToRenderTarget(uvScene.zw, edgeTargetParams); + float edge = TORQUE_TEX2D( edgeSource, uvScene.zw ).r; + clip( -edge ); +#endif + + // Sample offscreen target and return + return TORQUE_TEX2D( colorSource, uvScene.xy ); +} \ No newline at end of file diff --git a/Templates/BaseGame/game/core/rendering/shaders/particleCompositeV.hlsl b/Templates/BaseGame/game/core/rendering/shaders/particleCompositeV.hlsl new file mode 100644 index 000000000..c4c51204a --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/particleCompositeV.hlsl @@ -0,0 +1,53 @@ +//----------------------------------------------------------------------------- +// 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 "shaderModel.hlsl" + +struct Vertex +{ + float3 pos : POSITION; + float4 uvCoord : COLOR0; +}; + +struct Conn +{ + float4 hpos : TORQUE_POSITION; + float4 offscreenPos : TEXCOORD0; + float4 backbufferPos : TEXCOORD1; +}; + +uniform float4 screenRect; // point, extent + +Conn main(Vertex IN) +{ + Conn OUT; + + OUT.hpos = float4(IN.uvCoord.xy, 1.0, 1.0); + OUT.hpos.xy *= screenRect.zw; + OUT.hpos.xy += screenRect.xy; + + OUT.backbufferPos = OUT.hpos; + OUT.offscreenPos = OUT.hpos; + + return OUT; +} + diff --git a/Templates/BaseGame/game/core/rendering/shaders/particlesP.hlsl b/Templates/BaseGame/game/core/rendering/shaders/particlesP.hlsl new file mode 100644 index 000000000..155107d8b --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/particlesP.hlsl @@ -0,0 +1,109 @@ +//----------------------------------------------------------------------------- +// 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 "torque.hlsl" +#include "shaderModel.hlsl" +// With advanced lighting we get soft particles. +#ifdef TORQUE_LINEAR_DEPTH + #define SOFTPARTICLES +#endif + +#ifdef SOFTPARTICLES + + #include "shaderModelAutoGen.hlsl" + + uniform float oneOverSoftness; + uniform float oneOverFar; + TORQUE_UNIFORM_SAMPLER2D(deferredTex, 1); + //uniform float3 vEye; + uniform float4 deferredTargetParams; +#endif + +#define CLIP_Z // TODO: Make this a proper macro + +struct Conn +{ + float4 hpos : TORQUE_POSITION; + float4 color : TEXCOORD0; + float2 uv0 : TEXCOORD1; + float4 pos : TEXCOORD2; +}; + +TORQUE_UNIFORM_SAMPLER2D(diffuseMap, 0); +TORQUE_UNIFORM_SAMPLER2D(paraboloidLightMap, 2); + +float4 lmSample( float3 nrm ) +{ + bool calcBack = (nrm.z < 0.0); + if ( calcBack ) + nrm.z = nrm.z * -1.0; + + float2 lmCoord; + lmCoord.x = (nrm.x / (2*(1 + nrm.z))) + 0.5; + lmCoord.y = 1-((nrm.y / (2*(1 + nrm.z))) + 0.5); + + + // If this is the back, offset in the atlas + if ( calcBack ) + lmCoord.x += 1.0; + + // Atlasing front and back maps, so scale + lmCoord.x *= 0.5; + + return TORQUE_TEX2D(paraboloidLightMap, lmCoord); +} + + +uniform float alphaFactor; +uniform float alphaScale; + +float4 main( Conn IN ) : TORQUE_TARGET0 +{ + float softBlend = 1; + + #ifdef SOFTPARTICLES + float2 tc = IN.pos.xy * float2(1.0, -1.0) / IN.pos.w; + tc = viewportCoordToRenderTarget(saturate( ( tc + 1.0 ) * 0.5 ), deferredTargetParams); + + float sceneDepth = TORQUE_DEFERRED_UNCONDITION(deferredTex, tc).w; + float depth = IN.pos.w * oneOverFar; + float diff = sceneDepth - depth; + #ifdef CLIP_Z + // If drawing offscreen, this acts as the depth test, since we don't line up with the z-buffer + // When drawing high-res, though, we want to be able to take advantage of hi-z + // so this is #ifdef'd out + //clip(diff); + #endif + softBlend = saturate( diff * oneOverSoftness ); + #endif + + float4 diffuse = TORQUE_TEX2D( diffuseMap, IN.uv0 ); + + //return float4( lmSample(float3(0, 0, -1)).rgb, IN.color.a * diffuse.a * softBlend * alphaScale); + + // Scale output color by the alpha factor (turn LerpAlpha into pre-multiplied alpha) + float3 colorScale = ( alphaFactor < 0.0 ? IN.color.rgb * diffuse.rgb : ( alphaFactor > 0.0 ? IN.color.a * diffuse.a * alphaFactor * softBlend : softBlend ) ); + + return hdrEncode( float4( IN.color.rgb * diffuse.rgb * colorScale, + IN.color.a * diffuse.a * softBlend * alphaScale ) ); +} + diff --git a/Templates/BaseGame/game/core/rendering/shaders/particlesV.hlsl b/Templates/BaseGame/game/core/rendering/shaders/particlesV.hlsl new file mode 100644 index 000000000..dbeff0cc2 --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/particlesV.hlsl @@ -0,0 +1,55 @@ +//----------------------------------------------------------------------------- +// 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 "shaderModel.hlsl" + +struct Vertex +{ + float3 pos : POSITION; + float4 color : COLOR0; + float2 uv0 : TEXCOORD0; +}; + +struct Conn +{ + float4 hpos : TORQUE_POSITION; + float4 color : TEXCOORD0; + float2 uv0 : TEXCOORD1; + float4 pos : TEXCOORD2; +}; + + +uniform float4x4 modelViewProj; +uniform float4x4 fsModelViewProj; + +Conn main( Vertex In ) +{ + Conn Out; + + Out.hpos = mul( modelViewProj, float4(In.pos,1.0) ); + Out.pos = mul(fsModelViewProj, float4(In.pos, 1.0) ); + Out.color = In.color; + Out.uv0 = In.uv0; + + return Out; +} + diff --git a/Templates/BaseGame/game/core/rendering/shaders/planarReflectBumpP.hlsl b/Templates/BaseGame/game/core/rendering/shaders/planarReflectBumpP.hlsl new file mode 100644 index 000000000..d18331fb6 --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/planarReflectBumpP.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. +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// Structures +//----------------------------------------------------------------------------- + +#include "shaderModel.hlsl" + +struct ConnectData +{ + float4 hpos : TORQUE_POSITION; + float2 texCoord : TEXCOORD0; + float4 tex2 : TEXCOORD1; +}; + + +struct Fragout +{ + float4 col : TORQUE_TARGET0; +}; + +TORQUE_UNIFORM_SAMPLER2D(texMap, 0); +TORQUE_UNIFORM_SAMPLER2D(refractMap, 1); +TORQUE_UNIFORM_SAMPLER2D(bumpMap, 2); + + +//----------------------------------------------------------------------------- +// Fade edges of axis for texcoord passed in +//----------------------------------------------------------------------------- +float fadeAxis( float val ) +{ + // Fades from 1.0 to 0.0 when less than 0.1 + float fadeLow = saturate( val * 10.0 ); + + // Fades from 1.0 to 0.0 when greater than 0.9 + float fadeHigh = 1.0 - saturate( (val - 0.9) * 10.0 ); + + return fadeLow * fadeHigh; +} + + +//----------------------------------------------------------------------------- +// Main +//----------------------------------------------------------------------------- +Fragout main( ConnectData IN ) +{ + Fragout OUT; + + float3 bumpNorm = TORQUE_TEX2D( bumpMap, IN.tex2 ) * 2.0 - 1.0; + float2 offset = float2( bumpNorm.x, bumpNorm.y ); + float4 texIndex = IN.texCoord; + + // The fadeVal is used to "fade" the distortion at the edges of the screen. + // This is done so it won't sample the reflection texture out-of-bounds and create artifacts + // Note - this can be done more efficiently with a texture lookup + float fadeVal = fadeAxis( texIndex.x / texIndex.w ) * fadeAxis( texIndex.y / texIndex.w ); + + const float distortion = 0.2; + texIndex.xy += offset * distortion * fadeVal; + + float4 reflectColor = TORQUE_TEX2DPROJ( refractMap, texIndex ); + float4 diffuseColor = TORQUE_TEX2D( texMap, IN.tex2 ); + + OUT.col = diffuseColor + reflectColor * diffuseColor.a; + + return OUT; +} diff --git a/Templates/BaseGame/game/core/rendering/shaders/planarReflectBumpV.hlsl b/Templates/BaseGame/game/core/rendering/shaders/planarReflectBumpV.hlsl new file mode 100644 index 000000000..d45adb574 --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/planarReflectBumpV.hlsl @@ -0,0 +1,67 @@ +//----------------------------------------------------------------------------- +// 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. +//----------------------------------------------------------------------------- + +#define IN_HLSL +#include "shdrConsts.h" +#include "shaderModel.hlsl" + +//----------------------------------------------------------------------------- +// Structures +//----------------------------------------------------------------------------- +struct VertData +{ + float3 position : POSITION; + float3 normal : NORMAL; + float2 texCoord : TEXCOORD0; + float2 lmCoord : TEXCOORD1; + float3 T : TEXCOORD2; + float3 B : TEXCOORD3; +}; + + +struct ConnectData +{ + float4 hpos : TORQUE_POSITION; + float4 texCoord : TEXCOORD0; + float2 tex2 : TEXCOORD1; +}; + +uniform float4x4 modelview; +//----------------------------------------------------------------------------- +// Main +//----------------------------------------------------------------------------- +ConnectData main( VertData IN ) +{ + ConnectData OUT; + OUT.hpos = mul(modelview, float4(IN.position,1.0)); + + float4x4 texGenTest = { 0.5, 0.0, 0.0, 0.5, + 0.0, -0.5, 0.0, 0.5, + 0.0, 0.0, 1.0, 0.0, + 0.0, 0.0, 0.0, 1.0 }; + + OUT.texCoord = mul( texGenTest, OUT.hpos ); + + OUT.tex2 = IN.texCoord; + + return OUT; +} diff --git a/Templates/BaseGame/game/core/rendering/shaders/planarReflectP.hlsl b/Templates/BaseGame/game/core/rendering/shaders/planarReflectP.hlsl new file mode 100644 index 000000000..43b420544 --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/planarReflectP.hlsl @@ -0,0 +1,58 @@ +//----------------------------------------------------------------------------- +// 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. +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// Structures +//----------------------------------------------------------------------------- + +#include "shaderModel.hlsl" + +struct ConnectData +{ + float4 hpos : TORQUE_POSITION; + float2 texCoord : TEXCOORD0; + float4 tex2 : TEXCOORD1; +}; + + +struct Fragout +{ + float4 col : TORQUE_TARGET0; +}; + +TORQUE_UNIFORM_SAMPLER2D(texMap, 0); +TORQUE_UNIFORM_SAMPLER2D(refractMap, 1); + +//----------------------------------------------------------------------------- +// Main +//----------------------------------------------------------------------------- +Fragout main( ConnectData IN ) +{ + Fragout OUT; + + float4 diffuseColor = TORQUE_TEX2D( texMap, IN.texCoord ); + float4 reflectColor = TORQUE_TEX2DPROJ(refractMap, IN.tex2); + + OUT.col = diffuseColor + reflectColor * diffuseColor.a; + + return OUT; +} diff --git a/Templates/BaseGame/game/core/rendering/shaders/planarReflectV.hlsl b/Templates/BaseGame/game/core/rendering/shaders/planarReflectV.hlsl new file mode 100644 index 000000000..1f2ca9d4f --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/planarReflectV.hlsl @@ -0,0 +1,57 @@ +//----------------------------------------------------------------------------- +// 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. +//----------------------------------------------------------------------------- + +#define IN_HLSL +#include "hlslStructs.hlsl" +#include "shaderModel.hlsl" + +//----------------------------------------------------------------------------- +// Structures +//----------------------------------------------------------------------------- + +struct ConnectData +{ + float4 hpos : TORQUE_POSITION; + float2 texCoord : TEXCOORD0; + float4 tex2 : TEXCOORD1; +}; + +uniform float4x4 modelview; + +//----------------------------------------------------------------------------- +// Main +//----------------------------------------------------------------------------- +ConnectData main( VertexIn_PNTTTB IN ) +{ + ConnectData OUT; + OUT.hpos = mul(modelview, float4(IN.pos,1.0)); + + float4x4 texGenTest = { 0.5, 0.0, 0.0, 0.5, + 0.0, -0.5, 0.0, 0.5, + 0.0, 0.0, 1.0, 0.0, + 0.0, 0.0, 0.0, 1.0 }; + + OUT.texCoord = IN.uv0; + OUT.tex2 = mul( texGenTest, OUT.hpos ); + + return OUT; +} diff --git a/Templates/BaseGame/game/core/rendering/shaders/postFX/VolFogGlowP.hlsl b/Templates/BaseGame/game/core/rendering/shaders/postFX/VolFogGlowP.hlsl new file mode 100644 index 000000000..c3adb3b55 --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/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" + +TORQUE_UNIFORM_SAMPLER2D(diffuseMap, 0); +uniform float strength; + +struct VertToPix +{ + float4 hpos : TORQUE_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 ) : TORQUE_TARGET0 +{ + float4 kernel = float4( 0.175, 0.275, 0.375, 0.475 ) * strength; + + float4 OUT = 0; + OUT += TORQUE_TEX2D( diffuseMap, IN.uv0 ) * kernel.x; + OUT += TORQUE_TEX2D( diffuseMap, IN.uv1 ) * kernel.y; + OUT += TORQUE_TEX2D( diffuseMap, IN.uv2 ) * kernel.z; + OUT += TORQUE_TEX2D( diffuseMap, IN.uv3 ) * kernel.w; + + OUT += TORQUE_TEX2D( diffuseMap, IN.uv4 ) * kernel.x; + OUT += TORQUE_TEX2D( diffuseMap, IN.uv5 ) * kernel.y; + OUT += TORQUE_TEX2D( diffuseMap, IN.uv6 ) * kernel.z; + OUT += TORQUE_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/BaseGame/game/core/rendering/shaders/postFX/caustics/causticsP.hlsl b/Templates/BaseGame/game/core/rendering/shaders/postFX/caustics/causticsP.hlsl new file mode 100644 index 000000000..8c8abd480 --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/postFX/caustics/causticsP.hlsl @@ -0,0 +1,77 @@ +//----------------------------------------------------------------------------- +// 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 "../postFx.hlsl" +#include "../../shaderModelAutoGen.hlsl" + +uniform float accumTime; +uniform float3 eyePosWorld; +uniform float4 rtParams0; +uniform float4 waterFogPlane; + +TORQUE_UNIFORM_SAMPLER2D(deferredTex, 0); +TORQUE_UNIFORM_SAMPLER2D(causticsTex0, 1); +TORQUE_UNIFORM_SAMPLER2D(causticsTex1, 2); + +float distanceToPlane(float4 plane, float3 pos) +{ + return (plane.x * pos.x + plane.y * pos.y + plane.z * pos.z) + plane.w; +} + +float4 main( PFXVertToPix IN ) : TORQUE_TARGET0 +{ + //Sample the pre-pass + float4 deferred = TORQUE_DEFERRED_UNCONDITION( deferredTex, IN.uv0 ); + + //Get depth + float depth = deferred.w; + if(depth > 0.9999) + return float4(0,0,0,0); + + //Get world position + float3 pos = eyePosWorld + IN.wsEyeRay * depth; + + // Check the water depth + float waterDepth = -distanceToPlane(waterFogPlane, pos); + if(waterDepth < 0) + return float4(0,0,0,0); + waterDepth = saturate(waterDepth); + + //Use world position X and Y to calculate caustics UV + float2 causticsUV0 = (abs(pos.xy * 0.25) % float2(1, 1)); + float2 causticsUV1 = (abs(pos.xy * 0.2) % float2(1, 1)); + + //Animate uvs + float timeSin = sin(accumTime); + causticsUV0.xy += float2(accumTime*0.1, timeSin*0.2); + causticsUV1.xy -= float2(accumTime*0.15, timeSin*0.15); + + //Sample caustics texture + float4 caustics = TORQUE_TEX2D(causticsTex0, causticsUV0); + caustics *= TORQUE_TEX2D(causticsTex1, causticsUV1); + + //Use normal Z to modulate caustics + //float waterDepth = 1 - saturate(pos.z + waterFogPlane.w + 1); + caustics *= saturate(deferred.z) * pow(abs(1-depth), 64) * waterDepth; + + return caustics; +} diff --git a/Templates/BaseGame/game/core/rendering/shaders/postFX/caustics/gl/causticsP.glsl b/Templates/BaseGame/game/core/rendering/shaders/postFX/caustics/gl/causticsP.glsl new file mode 100644 index 000000000..d002fd7e1 --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/postFX/caustics/gl/causticsP.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 "../../gl/postFX.glsl" +#include "shadergen:/autogenConditioners.h" + +uniform vec3 eyePosWorld; +uniform vec4 rtParams0; +uniform vec4 waterFogPlane; +uniform float accumTime; + +uniform sampler2D deferredTex; +uniform sampler2D causticsTex0; +uniform sampler2D causticsTex1; +uniform vec2 targetSize; + +out vec4 OUT_col; + +float distanceToPlane(vec4 plane, vec3 pos) +{ + return (plane.x * pos.x + plane.y * pos.y + plane.z * pos.z) + plane.w; +} + +void main() +{ + //Sample the pre-pass + vec4 deferred = deferredUncondition( deferredTex, IN_uv0 ); + + //Get depth + float depth = deferred.w; + if(depth > 0.9999) + { + OUT_col = vec4(0,0,0,0); + return; + } + + //Get world position + vec3 pos = eyePosWorld + IN_wsEyeRay * depth; + + // Check the water depth + float waterDepth = -distanceToPlane(waterFogPlane, pos); + if(waterDepth < 0) + { + OUT_col = vec4(0,0,0,0); + return; + } + waterDepth = saturate(waterDepth); + + //Use world position X and Y to calculate caustics UV + vec2 causticsUV0 = mod(abs(pos.xy * 0.25), vec2(1, 1)); + vec2 causticsUV1 = mod(abs(pos.xy * 0.2), vec2(1, 1)); + + //Animate uvs + float timeSin = sin(accumTime); + causticsUV0.xy += vec2(accumTime*0.1, timeSin*0.2); + causticsUV1.xy -= vec2(accumTime*0.15, timeSin*0.15); + + //Sample caustics texture + vec4 caustics = texture(causticsTex0, causticsUV0); + caustics *= texture(causticsTex1, causticsUV1); + + //Use normal Z to modulate caustics + //float waterDepth = 1 - saturate(pos.z + waterFogPlane.w + 1); + caustics *= saturate(deferred.z) * pow(1-depth, 64) * waterDepth; + + OUT_col = caustics; +} diff --git a/Templates/BaseGame/game/core/rendering/shaders/postFX/chromaticLens.hlsl b/Templates/BaseGame/game/core/rendering/shaders/postFX/chromaticLens.hlsl new file mode 100644 index 000000000..8fdca72b7 --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/postFX/chromaticLens.hlsl @@ -0,0 +1,60 @@ +//----------------------------------------------------------------------------- +// 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. +//----------------------------------------------------------------------------- + +// Based on 'Cubic Lens Distortion HLSL Shader' by François Tarlier +// www.francois-tarlier.com/blog/index.php/2009/11/cubic-lens-distortion-shader + +#include "./postFx.hlsl" +#include "./../torque.hlsl" + +TORQUE_UNIFORM_SAMPLER2D(backBuffer, 0); +uniform float distCoeff; +uniform float cubeDistort; +uniform float3 colorDistort; + + +float4 main( PFXVertToPix IN ) : TORQUE_TARGET0 +{ + float2 tex = IN.uv0; + + float f = 0; + float r2 = (tex.x - 0.5) * (tex.x - 0.5) + (tex.y - 0.5) * (tex.y - 0.5); + + // Only compute the cubic distortion if necessary. + if ( cubeDistort == 0.0 ) + f = 1 + r2 * distCoeff; + else + f = 1 + r2 * (distCoeff + cubeDistort * sqrt(r2)); + + // Distort each color channel seperately to get a chromatic distortion effect. + float3 outColor; + float3 distort = f.xxx + colorDistort; + + for ( int i=0; i < 3; i++ ) + { + float x = distort[i] * ( tex.x - 0.5 ) + 0.5; + float y = distort[i] * ( tex.y - 0.5 ) + 0.5; + outColor[i] = TORQUE_TEX2DLOD( backBuffer, float4(x,y,0,0) )[i]; + } + + return float4( outColor.rgb, 1 ); +} \ No newline at end of file diff --git a/Templates/BaseGame/game/core/rendering/shaders/postFX/dof/DOF_CalcCoC_P.hlsl b/Templates/BaseGame/game/core/rendering/shaders/postFX/dof/DOF_CalcCoC_P.hlsl new file mode 100644 index 000000000..2f5835fc2 --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/postFX/dof/DOF_CalcCoC_P.hlsl @@ -0,0 +1,53 @@ +//----------------------------------------------------------------------------- +// 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 "./../postFx.hlsl" + +// These are set by the game engine. +TORQUE_UNIFORM_SAMPLER2D(shrunkSampler, 0); // Output of DofDownsample() +TORQUE_UNIFORM_SAMPLER2D(blurredSampler, 1); // Blurred version of the shrunk sampler + + +// This is the pixel shader function that calculates the actual +// value used for the near circle of confusion. +// "texCoords" are 0 at the bottom left pixel and 1 at the top right. +float4 main( PFXVertToPix IN ) : TORQUE_TARGET0 +{ + float3 color; + float coc; + half4 blurred; + half4 shrunk; + + shrunk = half4(TORQUE_TEX2D( shrunkSampler, IN.uv0 )); + blurred = half4(TORQUE_TEX2D( blurredSampler, IN.uv1 )); + color = shrunk.rgb; + //coc = shrunk.a; + //coc = blurred.a; + //coc = max( blurred.a, shrunk.a ); + coc = 2 * max( blurred.a, shrunk.a ) - shrunk.a; + + + //return float4( coc.rrr, 1.0 ); + //return float4( color, 1.0 ); + return float4( color, coc ); + //return float4( 1.0, 0.0, 1.0, 1.0 ); +} \ No newline at end of file diff --git a/Templates/BaseGame/game/core/rendering/shaders/postFX/dof/DOF_CalcCoC_V.hlsl b/Templates/BaseGame/game/core/rendering/shaders/postFX/dof/DOF_CalcCoC_V.hlsl new file mode 100644 index 000000000..8131e45cd --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/postFX/dof/DOF_CalcCoC_V.hlsl @@ -0,0 +1,70 @@ +//----------------------------------------------------------------------------- +// 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 "./../postFx.hlsl" +#include "./../../torque.hlsl" + +uniform float4 rtParams0; +uniform float4 rtParams1; +uniform float4 rtParams2; +uniform float4 rtParams3; + +PFXVertToPix main( PFXVert IN ) +{ + PFXVertToPix OUT; + + /* + OUT.hpos = IN.pos; + OUT.uv0 = IN.uv; + OUT.uv1 = IN.uv; + OUT.uv2 = IN.uv; + OUT.uv3 = IN.uv; + */ + + /* + OUT.hpos = IN.pos; + OUT.uv0 = IN.uv + rtParams0.xy; + OUT.uv1 = IN.uv + rtParams1.xy; + OUT.uv2 = IN.uv + rtParams2.xy; + OUT.uv3 = IN.uv + rtParams3.xy; + */ + + /* + OUT.hpos = IN.pos; + OUT.uv0 = IN.uv * rtParams0.zw; + OUT.uv1 = IN.uv * rtParams1.zw; + OUT.uv2 = IN.uv * rtParams2.zw; + OUT.uv3 = IN.uv * rtParams3.zw; + */ + + + OUT.hpos = float4(IN.pos,1.0); + OUT.uv0 = viewportCoordToRenderTarget( IN.uv, rtParams0 ); + OUT.uv1 = viewportCoordToRenderTarget( IN.uv, rtParams1 ); + OUT.uv2 = viewportCoordToRenderTarget( IN.uv, rtParams2 ); + OUT.uv3 = viewportCoordToRenderTarget( IN.uv, rtParams3 ); + + + OUT.wsEyeRay = IN.wsEyeRay; + + return OUT; +} diff --git a/Templates/BaseGame/game/core/rendering/shaders/postFX/dof/DOF_DownSample_P.hlsl b/Templates/BaseGame/game/core/rendering/shaders/postFX/dof/DOF_DownSample_P.hlsl new file mode 100644 index 000000000..907c3d122 --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/postFX/dof/DOF_DownSample_P.hlsl @@ -0,0 +1,143 @@ +//----------------------------------------------------------------------------- +// 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 "../../shaderModel.hlsl" +#include "../../shaderModelAutoGen.hlsl" + +// These are set by the game engine. +// The render target size is one-quarter the scene rendering size. +TORQUE_UNIFORM_SAMPLER2D(colorSampler, 0); +TORQUE_UNIFORM_SAMPLER2D(depthSampler, 1); +uniform float2 dofEqWorld; +uniform float2 targetSize; +uniform float depthOffset; +uniform float maxWorldCoC; +//uniform float2 dofEqWeapon; +//uniform float2 dofRowDelta; // float2( 0, 0.25 / renderTargetHeight ) + +struct Pixel +{ + float4 position : TORQUE_POSITION; + float2 tcColor0 : TEXCOORD0; + float2 tcColor1 : TEXCOORD1; + float2 tcDepth0 : TEXCOORD2; + float2 tcDepth1 : TEXCOORD3; + float2 tcDepth2 : TEXCOORD4; + float2 tcDepth3 : TEXCOORD5; +}; + +half4 main( Pixel IN ) : TORQUE_TARGET0 +{ + //return float4( 1.0, 0.0, 1.0, 1.0 ); + + float2 dofRowDelta = float2( 0, 0.25 / targetSize.y ); + + //float2 dofEqWorld = float2( -60, 1.0 ); + + half3 color; + half maxCoc; + float4 depth; + half4 viewCoc; + half4 sceneCoc; + half4 curCoc; + half4 coc; + float2 rowOfs[4]; + + // "rowOfs" reduces how many moves PS2.0 uses to emulate swizzling. + rowOfs[0] = 0; + rowOfs[1] = dofRowDelta.xy; + rowOfs[2] = dofRowDelta.xy * 2; + rowOfs[3] = dofRowDelta.xy * 3; + + // Use bilinear filtering to average 4 color samples for free. + color = 0; + color += half3(TORQUE_TEX2D( colorSampler, IN.tcColor0.xy + rowOfs[0] ).rgb); + color += half3(TORQUE_TEX2D(colorSampler, IN.tcColor1.xy + rowOfs[0]).rgb); + color += half3(TORQUE_TEX2D(colorSampler, IN.tcColor0.xy + rowOfs[2]).rgb); + color += half3(TORQUE_TEX2D(colorSampler, IN.tcColor1.xy + rowOfs[2]).rgb); + color /= 4; + + //declare thse here to save doing it in each loop below + half4 zero4 = half4(0, 0, 0, 0); + coc = zero4; + half4 dofEqWorld4X = half4(dofEqWorld.xxxx); + half4 dofEqWorld4Y = half4(dofEqWorld.yyyy); + half4 maxWorldCoC4 = half4(maxWorldCoC, maxWorldCoC, maxWorldCoC, maxWorldCoC); + // Process 4 samples at a time to use vector hardware efficiently. + // The CoC will be 1 if the depth is negative, so use "min" to pick + // between "sceneCoc" and "viewCoc". + [unroll] // coc[i] causes this anyway + for (int i = 0; i < 4; i++) + { + depth[0] = TORQUE_DEFERRED_UNCONDITION(depthSampler, (IN.tcDepth0.xy + rowOfs[i])).w; + depth[1] = TORQUE_DEFERRED_UNCONDITION(depthSampler, (IN.tcDepth1.xy + rowOfs[i])).w; + depth[2] = TORQUE_DEFERRED_UNCONDITION(depthSampler, (IN.tcDepth2.xy + rowOfs[i])).w; + depth[3] = TORQUE_DEFERRED_UNCONDITION(depthSampler, (IN.tcDepth3.xy + rowOfs[i])).w; + + coc = max(coc, clamp(dofEqWorld4X * half4(depth)+dofEqWorld4Y, zero4, maxWorldCoC4)); + } + + /* + depth[0] = TORQUE_TEX2D( depthSampler, pixel.tcDepth0.xy + rowOfs[0] ).r; + depth[1] = TORQUE_TEX2D( depthSampler, pixel.tcDepth1.xy + rowOfs[0] ).r; + depth[2] = TORQUE_TEX2D( depthSampler, pixel.tcDepth2.xy + rowOfs[0] ).r; + depth[3] = TORQUE_TEX2D( depthSampler, pixel.tcDepth3.xy + rowOfs[0] ).r; + viewCoc = saturate( dofEqWeapon.x * -depth + dofEqWeapon.y ); + sceneCoc = saturate( dofEqWorld.x * depth + dofEqWorld.y ); + curCoc = min( viewCoc, sceneCoc ); + coc = curCoc; + + depth[0] = TORQUE_TEX2D( depthSampler, pixel.tcDepth0.xy + rowOfs[1] ).r; + depth[1] = TORQUE_TEX2D( depthSampler, pixel.tcDepth1.xy + rowOfs[1] ).r; + depth[2] = TORQUE_TEX2D( depthSampler, pixel.tcDepth2.xy + rowOfs[1] ).r; + depth[3] = TORQUE_TEX2D( depthSampler, pixel.tcDepth3.xy + rowOfs[1] ).r; + viewCoc = saturate( dofEqWeapon.x * -depth + dofEqWeapon.y ); + sceneCoc = saturate( dofEqWorld.x * depth + dofEqWorld.y ); + curCoc = min( viewCoc, sceneCoc ); + coc = max( coc, curCoc ); + + depth[0] = TORQUE_TEX2D( depthSampler, pixel.tcDepth0.xy + rowOfs[2] ).r; + depth[1] = TORQUE_TEX2D( depthSampler, pixel.tcDepth1.xy + rowOfs[2] ).r; + depth[2] = TORQUE_TEX2D( depthSampler, pixel.tcDepth2.xy + rowOfs[2] ).r; + depth[3] = TORQUE_TEX2D( depthSampler, pixel.tcDepth3.xy + rowOfs[2] ).r; + viewCoc = saturate( dofEqWeapon.x * -depth + dofEqWeapon.y ); + sceneCoc = saturate( dofEqWorld.x * depth + dofEqWorld.y ); + curCoc = min( viewCoc, sceneCoc ); + coc = max( coc, curCoc ); + + depth[0] = TORQUE_TEX2D( depthSampler, pixel.tcDepth0.xy + rowOfs[3] ).r; + depth[1] = TORQUE_TEX2D( depthSampler, pixel.tcDepth1.xy + rowOfs[3] ).r; + depth[2] = TORQUE_TEX2D( depthSampler, pixel.tcDepth2.xy + rowOfs[3] ).r; + depth[3] = TORQUE_TEX2D( depthSampler, pixel.tcDepth3.xy + rowOfs[3] ).r; + viewCoc = saturate( dofEqWeapon.x * -depth + dofEqWeapon.y ); + sceneCoc = saturate( dofEqWorld.x * depth + dofEqWorld.y ); + curCoc = min( viewCoc, sceneCoc ); + coc = max( coc, curCoc ); + */ + + maxCoc = max( max( coc[0], coc[1] ), max( coc[2], coc[3] ) ); + + //return half4( 1.0, 0.0, 1.0, 1.0 ); + return half4( color, maxCoc ); + //return half4( color, 1.0f ); + //return half4( maxCoc.rrr, 1.0 ); +} \ No newline at end of file diff --git a/Templates/BaseGame/game/core/rendering/shaders/postFX/dof/DOF_DownSample_V.hlsl b/Templates/BaseGame/game/core/rendering/shaders/postFX/dof/DOF_DownSample_V.hlsl new file mode 100644 index 000000000..0b3ec01e2 --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/postFX/dof/DOF_DownSample_V.hlsl @@ -0,0 +1,61 @@ +//----------------------------------------------------------------------------- +// 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 "./../postFx.hlsl" +#include "./../../torque.hlsl" + +struct Vert +{ + float3 pos : POSITION; + float2 tc : TEXCOORD0; + float3 wsEyeRay : TEXCOORD1; +}; + +struct Pixel +{ + float4 position : TORQUE_POSITION; + float2 tcColor0 : TEXCOORD0; + float2 tcColor1 : TEXCOORD1; + float2 tcDepth0 : TEXCOORD2; + float2 tcDepth1 : TEXCOORD3; + float2 tcDepth2 : TEXCOORD4; + float2 tcDepth3 : TEXCOORD5; +}; + +uniform float4 rtParams0; +uniform float2 oneOverTargetSize; + +Pixel main( Vert IN ) +{ + Pixel OUT; + OUT.position = float4(IN.pos,1.0); + + float2 uv = viewportCoordToRenderTarget( IN.tc, rtParams0 ); + //OUT.position = mul( IN.pos, modelView ); + OUT.tcColor1 = uv + float2( +1.0, -0.0 ) * oneOverTargetSize; + OUT.tcColor0 = uv + float2( -1.0, -0.0 ) * oneOverTargetSize; + OUT.tcDepth0 = uv + float2( -0.5, -0.0 ) * oneOverTargetSize; + OUT.tcDepth1 = uv + float2( -1.5, -0.0 ) * oneOverTargetSize; + OUT.tcDepth2 = uv + float2( +1.5, -0.0 ) * oneOverTargetSize; + OUT.tcDepth3 = uv + float2( +2.5, -0.0 ) * oneOverTargetSize; + return OUT; +} \ No newline at end of file diff --git a/Templates/BaseGame/game/core/rendering/shaders/postFX/dof/DOF_Final_P.hlsl b/Templates/BaseGame/game/core/rendering/shaders/postFX/dof/DOF_Final_P.hlsl new file mode 100644 index 000000000..9a7cb3d5e --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/postFX/dof/DOF_Final_P.hlsl @@ -0,0 +1,145 @@ +//----------------------------------------------------------------------------- +// 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 "../../shaderModelAutoGen.hlsl" +#include "./../postFx.hlsl" + +TORQUE_UNIFORM_SAMPLER2D(colorSampler,0); // Original source image +TORQUE_UNIFORM_SAMPLER2D(smallBlurSampler,1); // Output of SmallBlurPS() +TORQUE_UNIFORM_SAMPLER2D(largeBlurSampler,2); // Blurred output of DofDownsample() +TORQUE_UNIFORM_SAMPLER2D(depthSampler,3); + +uniform float2 oneOverTargetSize; +uniform float4 dofLerpScale; +uniform float4 dofLerpBias; +uniform float3 dofEqFar; +uniform float maxFarCoC; + +//static float d0 = 0.1; +//static float d1 = 0.1; +//static float d2 = 0.8; +//static float4 dofLerpScale = float4( -1.0 / d0, -1.0 / d1, -1.0 / d2, 1.0 / d2 ); +//static float4 dofLerpBias = float4( 1.0, (1.0 - d2) / d1, 1.0 / d2, (d2 - 1.0) / d2 ); +//static float3 dofEqFar = float3( 2.0, 0.0, 1.0 ); + +float4 tex2Doffset(TORQUE_SAMPLER2D(s), float2 tc, float2 offset) +{ + return TORQUE_TEX2D( s, tc + offset * oneOverTargetSize ); +} + +half3 GetSmallBlurSample( float2 tc ) +{ + half3 sum; + const half weight = 4.0 / 17; + sum = 0; // Unblurred sample done by alpha blending + //sum += weight * tex2Doffset( colorSampler, tc, float2( 0, 0 ) ).rgb; + sum += weight * half3(tex2Doffset(TORQUE_SAMPLER2D_MAKEARG(colorSampler), tc, float2(+0.5, -1.5)).rgb); + sum += weight * half3(tex2Doffset(TORQUE_SAMPLER2D_MAKEARG(colorSampler), tc, float2(-1.5, -0.5)).rgb); + sum += weight * half3(tex2Doffset(TORQUE_SAMPLER2D_MAKEARG(colorSampler), tc, float2(-0.5, +1.5)).rgb); + sum += weight * half3(tex2Doffset(TORQUE_SAMPLER2D_MAKEARG(colorSampler), tc, float2(+1.5, +0.5)).rgb); + return sum; +} + +half4 InterpolateDof( half3 small, half3 med, half3 large, half t ) +{ + //t = 2; + half4 weights; + half3 color; + half alpha; + + // Efficiently calculate the cross-blend weights for each sample. + // Let the unblurred sample to small blur fade happen over distance + // d0, the small to medium blur over distance d1, and the medium to + // large blur over distance d2, where d0 + d1 + d2 = 1. + //float4 dofLerpScale = float4( -1 / d0, -1 / d1, -1 / d2, 1 / d2 ); + //float4 dofLerpBias = float4( 1, (1 � d2) / d1, 1 / d2, (d2 � 1) / d2 ); + + weights = half4(saturate( t * dofLerpScale + dofLerpBias )); + weights.yz = min( weights.yz, 1 - weights.xy ); + + // Unblurred sample with weight "weights.x" done by alpha blending + color = weights.y * small + weights.z * med + weights.w * large; + //color = med; + alpha = dot( weights.yzw, half3( 16.0 / 17, 1.0, 1.0 ) ); + //alpha = 0.0; + + return half4( color, alpha ); +} + +half4 main( PFXVertToPix IN ) : TORQUE_TARGET0 +{ + //return half4( 1,0,1,1 ); + //return half4( TORQUE_TEX2D( colorSampler, IN.uv0 ).rgb, 1.0 ); + //return half4( TORQUE_TEX2D( colorSampler, texCoords ).rgb, 0 ); + half3 small; + half4 med; + half3 large; + half depth; + half nearCoc; + half farCoc; + half coc; + + small = GetSmallBlurSample( IN.uv0 ); + //small = half3( 1,0,0 ); + //return half4( small, 1.0 ); + med = half4(TORQUE_TEX2D( smallBlurSampler, IN.uv1 )); + //med.rgb = half3( 0,1,0 ); + //return half4(med.rgb, 0.0); + large = half3(TORQUE_TEX2D(largeBlurSampler, IN.uv2).rgb); + //large = half3( 0,0,1 ); + //return large; + //return half4(large.rgb,1.0); + nearCoc = med.a; + + // Since the med blur texture is screwed up currently + // replace it with the large, but this needs to be fixed. + //med.rgb = large; + + //nearCoc = 0; + depth = half(TORQUE_DEFERRED_UNCONDITION( depthSampler, IN.uv3 ).w); + //return half4(depth.rrr,1); + //return half4(nearCoc.rrr,1.0); + + if (depth > 0.999 ) + { + coc = nearCoc; // We don't want to blur the sky. + //coc = 0; + } + else + { + // dofEqFar.x and dofEqFar.y specify the linear ramp to convert + // to depth for the distant out-of-focus region. + // dofEqFar.z is the ratio of the far to the near blur radius. + farCoc = half(clamp( dofEqFar.x * depth + dofEqFar.y, 0.0, maxFarCoC )); + coc = half(max( nearCoc, farCoc * dofEqFar.z )); + //coc = nearCoc; + } + + //coc = nearCoc; + //coc = farCoc; + //return half4(coc.rrr,0.5); + //return half4(farCoc.rrr,1); + //return half4(nearCoc.rrr,1); + + //return half4( 1,0,1,0 ); + return InterpolateDof( small, med.rgb, large, coc ); +} \ No newline at end of file diff --git a/Templates/BaseGame/game/core/rendering/shaders/postFX/dof/DOF_Final_V.hlsl b/Templates/BaseGame/game/core/rendering/shaders/postFX/dof/DOF_Final_V.hlsl new file mode 100644 index 000000000..86c93701a --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/postFX/dof/DOF_Final_V.hlsl @@ -0,0 +1,72 @@ +//----------------------------------------------------------------------------- +// 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 "./../postFx.hlsl" +#include "./../../torque.hlsl" + +uniform float4 rtParams0; +uniform float4 rtParams1; +uniform float4 rtParams2; +uniform float4 rtParams3; +uniform float2 oneOverTargetSize; + +PFXVertToPix main( PFXVert IN ) +{ + PFXVertToPix OUT; + + /* + OUT.hpos = IN.pos; + OUT.uv0 = IN.uv; + OUT.uv1 = IN.uv; + OUT.uv2 = IN.uv; + OUT.uv3 = IN.uv; + */ + + /* + OUT.hpos = IN.pos; + OUT.uv0 = IN.uv + rtParams0.xy; + OUT.uv1 = IN.uv + rtParams1.xy; + OUT.uv2 = IN.uv + rtParams2.xy; + OUT.uv3 = IN.uv + rtParams3.xy; + */ + + + /* + OUT.hpos = IN.pos; + OUT.uv0 = IN.uv * rtParams0.zw; + OUT.uv1 = IN.uv * rtParams1.zw; + OUT.uv2 = IN.uv * rtParams2.zw; + OUT.uv3 = IN.uv * rtParams3.zw; + */ + + + OUT.hpos = float4(IN.pos,1.0); + OUT.uv0 = viewportCoordToRenderTarget( IN.uv, rtParams0 ); + OUT.uv1 = viewportCoordToRenderTarget( IN.uv, rtParams1 ); // + float2( -5, 1 ) * oneOverTargetSize; + OUT.uv2 = viewportCoordToRenderTarget( IN.uv, rtParams2 ); + OUT.uv3 = viewportCoordToRenderTarget( IN.uv, rtParams3 ); + + + OUT.wsEyeRay = IN.wsEyeRay; + + return OUT; +} diff --git a/Templates/BaseGame/game/core/rendering/shaders/postFX/dof/DOF_Gausian_P.hlsl b/Templates/BaseGame/game/core/rendering/shaders/postFX/dof/DOF_Gausian_P.hlsl new file mode 100644 index 000000000..f4d29f3e1 --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/postFX/dof/DOF_Gausian_P.hlsl @@ -0,0 +1,63 @@ +//----------------------------------------------------------------------------- +// 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 "./../postFx.hlsl" + +TORQUE_UNIFORM_SAMPLER2D(diffuseMap, 0); + +struct VertToPix +{ + float4 hpos : TORQUE_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 ) : TORQUE_TARGET0 +{ + float4 kernel = float4( 0.175, 0.275, 0.375, 0.475 ) * 0.5 / 1.3; //25f; + + float4 OUT = 0; + OUT += TORQUE_TEX2D( diffuseMap, IN.uv0 ) * kernel.x; + OUT += TORQUE_TEX2D( diffuseMap, IN.uv1 ) * kernel.y; + OUT += TORQUE_TEX2D( diffuseMap, IN.uv2 ) * kernel.z; + OUT += TORQUE_TEX2D( diffuseMap, IN.uv3 ) * kernel.w; + + OUT += TORQUE_TEX2D( diffuseMap, IN.uv4 ) * kernel.x; + OUT += TORQUE_TEX2D( diffuseMap, IN.uv5 ) * kernel.y; + OUT += TORQUE_TEX2D( diffuseMap, IN.uv6 ) * kernel.z; + OUT += TORQUE_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/BaseGame/game/core/rendering/shaders/postFX/dof/DOF_Gausian_V.hlsl b/Templates/BaseGame/game/core/rendering/shaders/postFX/dof/DOF_Gausian_V.hlsl new file mode 100644 index 000000000..b2d4582e0 --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/postFX/dof/DOF_Gausian_V.hlsl @@ -0,0 +1,80 @@ +//----------------------------------------------------------------------------- +// 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 "./../postFx.hlsl" +#include "./../../torque.hlsl" + + +uniform float4 rtParams0; +uniform float2 texSize0; +uniform float2 oneOverTargetSize; + +struct VertToPix +{ + float4 hpos : TORQUE_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; +}; + +VertToPix main( PFXVert IN ) +{ + VertToPix OUT; + + OUT.hpos = float4(IN.pos,1.0); + + IN.uv = viewportCoordToRenderTarget( IN.uv, rtParams0 ); + + // I don't know why this offset is necessary, but it is. + //IN.uv = IN.uv * oneOverTargetSize; + + OUT.uv0 = IN.uv + ( ( BLUR_DIR * 3.5f ) / texSize0 ); + OUT.uv1 = IN.uv + ( ( BLUR_DIR * 2.5f ) / texSize0 ); + OUT.uv2 = IN.uv + ( ( BLUR_DIR * 1.5f ) / texSize0 ); + OUT.uv3 = IN.uv + ( ( BLUR_DIR * 0.5f ) / texSize0 ); + + OUT.uv4 = IN.uv - ( ( BLUR_DIR * 3.5f ) / texSize0 ); + OUT.uv5 = IN.uv - ( ( BLUR_DIR * 2.5f ) / texSize0 ); + OUT.uv6 = IN.uv - ( ( BLUR_DIR * 1.5f ) / texSize0 ); + OUT.uv7 = IN.uv - ( ( BLUR_DIR * 0.5f ) / texSize0 ); + + /* + OUT.uv0 = viewportCoordToRenderTarget( OUT.uv0, rtParams0 ); + OUT.uv1 = viewportCoordToRenderTarget( OUT.uv1, rtParams0 ); + OUT.uv2 = viewportCoordToRenderTarget( OUT.uv2, rtParams0 ); + OUT.uv3 = viewportCoordToRenderTarget( OUT.uv3, rtParams0 ); + + OUT.uv4 = viewportCoordToRenderTarget( OUT.uv4, rtParams0 ); + OUT.uv5 = viewportCoordToRenderTarget( OUT.uv5, rtParams0 ); + OUT.uv6 = viewportCoordToRenderTarget( OUT.uv6, rtParams0 ); + OUT.uv7 = viewportCoordToRenderTarget( OUT.uv7, rtParams0 ); + */ + + return OUT; +} diff --git a/Templates/BaseGame/game/core/rendering/shaders/postFX/dof/DOF_Passthrough_V.hlsl b/Templates/BaseGame/game/core/rendering/shaders/postFX/dof/DOF_Passthrough_V.hlsl new file mode 100644 index 000000000..8131e45cd --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/postFX/dof/DOF_Passthrough_V.hlsl @@ -0,0 +1,70 @@ +//----------------------------------------------------------------------------- +// 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 "./../postFx.hlsl" +#include "./../../torque.hlsl" + +uniform float4 rtParams0; +uniform float4 rtParams1; +uniform float4 rtParams2; +uniform float4 rtParams3; + +PFXVertToPix main( PFXVert IN ) +{ + PFXVertToPix OUT; + + /* + OUT.hpos = IN.pos; + OUT.uv0 = IN.uv; + OUT.uv1 = IN.uv; + OUT.uv2 = IN.uv; + OUT.uv3 = IN.uv; + */ + + /* + OUT.hpos = IN.pos; + OUT.uv0 = IN.uv + rtParams0.xy; + OUT.uv1 = IN.uv + rtParams1.xy; + OUT.uv2 = IN.uv + rtParams2.xy; + OUT.uv3 = IN.uv + rtParams3.xy; + */ + + /* + OUT.hpos = IN.pos; + OUT.uv0 = IN.uv * rtParams0.zw; + OUT.uv1 = IN.uv * rtParams1.zw; + OUT.uv2 = IN.uv * rtParams2.zw; + OUT.uv3 = IN.uv * rtParams3.zw; + */ + + + OUT.hpos = float4(IN.pos,1.0); + OUT.uv0 = viewportCoordToRenderTarget( IN.uv, rtParams0 ); + OUT.uv1 = viewportCoordToRenderTarget( IN.uv, rtParams1 ); + OUT.uv2 = viewportCoordToRenderTarget( IN.uv, rtParams2 ); + OUT.uv3 = viewportCoordToRenderTarget( IN.uv, rtParams3 ); + + + OUT.wsEyeRay = IN.wsEyeRay; + + return OUT; +} diff --git a/Templates/BaseGame/game/core/rendering/shaders/postFX/dof/DOF_SmallBlur_P.hlsl b/Templates/BaseGame/game/core/rendering/shaders/postFX/dof/DOF_SmallBlur_P.hlsl new file mode 100644 index 000000000..175525a91 --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/postFX/dof/DOF_SmallBlur_P.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. +//----------------------------------------------------------------------------- + +// This vertex and pixel shader applies a 3 x 3 blur to the image in +// colorMapSampler, which is the same size as the render target. +// The sample weights are 1/16 in the corners, 2/16 on the edges, +// and 4/16 in the center. +#include "../../shaderModel.hlsl" + +TORQUE_UNIFORM_SAMPLER2D(colorSampler, 0); // Output of DofNearCoc() + +struct Pixel +{ + float4 position : TORQUE_POSITION; + float4 texCoords : TEXCOORD0; +}; + +float4 main( Pixel IN ) : TORQUE_TARGET0 +{ + float4 color; + color = 0.0; + color += TORQUE_TEX2D( colorSampler, IN.texCoords.xz ); + color += TORQUE_TEX2D( colorSampler, IN.texCoords.yz ); + color += TORQUE_TEX2D( colorSampler, IN.texCoords.xw ); + color += TORQUE_TEX2D( colorSampler, IN.texCoords.yw ); + return color / 4.0; +} \ No newline at end of file diff --git a/Templates/BaseGame/game/core/rendering/shaders/postFX/dof/DOF_SmallBlur_V.hlsl b/Templates/BaseGame/game/core/rendering/shaders/postFX/dof/DOF_SmallBlur_V.hlsl new file mode 100644 index 000000000..3edb1ec2a --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/postFX/dof/DOF_SmallBlur_V.hlsl @@ -0,0 +1,56 @@ +//----------------------------------------------------------------------------- +// 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. +//----------------------------------------------------------------------------- + +// This vertex and pixel shader applies a 3 x 3 blur to the image in +// colorMapSampler, which is the same size as the render target. +// The sample weights are 1/16 in the corners, 2/16 on the edges, +// and 4/16 in the center. + +#include "./../postFx.hlsl" +#include "./../../torque.hlsl" + +struct Vert +{ + float3 position : POSITION; + float2 texCoords : TEXCOORD0; +}; + +struct Pixel +{ + float4 position : TORQUE_POSITION; + float4 texCoords : TEXCOORD0; +}; + +uniform float2 oneOverTargetSize; +uniform float4 rtParams0; + +Pixel main( Vert IN ) +{ + Pixel OUT; + const float4 halfPixel = { -0.5, 0.5, -0.5, 0.5 }; + OUT.position = float4(IN.position,1.0); //Transform_ObjectToClip( IN.position ); + + //float2 uv = IN.texCoords + rtParams0.xy; + float2 uv = viewportCoordToRenderTarget( IN.texCoords, rtParams0 ); + OUT.texCoords = uv.xxyy + halfPixel * oneOverTargetSize.xxyy; + return OUT; +} \ No newline at end of file diff --git a/Templates/BaseGame/game/core/rendering/shaders/postFX/dof/gl/DOF_CalcCoC_P.glsl b/Templates/BaseGame/game/core/rendering/shaders/postFX/dof/gl/DOF_CalcCoC_P.glsl new file mode 100644 index 000000000..38cb099c4 --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/postFX/dof/gl/DOF_CalcCoC_P.glsl @@ -0,0 +1,55 @@ +//----------------------------------------------------------------------------- +// 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 "../../gl/postFX.glsl" + +// These are set by the game engine. +uniform sampler2D shrunkSampler; // Output of DofDownsample() +uniform sampler2D blurredSampler; // Blurred version of the shrunk sampler + +out vec4 OUT_col; + +// This is the pixel shader function that calculates the actual +// value used for the near circle of confusion. +// "texCoords" are 0 at the bottom left pixel and 1 at the top right. +void main() +{ + vec3 color; + float coc; + half4 blurred; + half4 shrunk; + + shrunk = texture( shrunkSampler, IN_uv0 ); + blurred = texture( blurredSampler, IN_uv1 ); + color = shrunk.rgb; + //coc = shrunk.a; + //coc = blurred.a; + //coc = max( blurred.a, shrunk.a ); + coc = 2 * max( blurred.a, shrunk.a ) - shrunk.a; + + + //OUT_col = vec4( coc.rrr, 1.0 ); + //OUT_col = vec4( color, 1.0 ); + OUT_col = vec4( color, coc ); + //OUT_col = vec4( 1.0, 0.0, 1.0, 1.0 ); +} \ No newline at end of file diff --git a/Templates/BaseGame/game/core/rendering/shaders/postFX/dof/gl/DOF_CalcCoC_V.glsl b/Templates/BaseGame/game/core/rendering/shaders/postFX/dof/gl/DOF_CalcCoC_V.glsl new file mode 100644 index 000000000..d02ce6551 --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/postFX/dof/gl/DOF_CalcCoC_V.glsl @@ -0,0 +1,69 @@ +//----------------------------------------------------------------------------- +// 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 "../../../gl/torque.glsl" +#include "../../gl/postFX.glsl" + +uniform vec4 rtParams0; +uniform vec4 rtParams1; +uniform vec4 rtParams2; +uniform vec4 rtParams3; + +void main() +{ + /* + OUT_hpos = IN.pos; + OUT_uv0 = IN_uv; + OUT_uv1 = IN_uv; + OUT_uv2 = IN_uv; + OUT_uv3 = IN_uv; + */ + + /* + OUT_hpos = IN_pos; + OUT_uv0 = IN_uv + rtParams0.xy; + OUT_uv1 = IN_uv + rtParams1.xy; + OUT_uv2 = IN_uv + rtParams2.xy; + OUT_uv3 = IN_uv + rtParams3.xy; + */ + + /* + OUT_hpos = IN_pos; + OUT_uv0 = IN_uv * rtParams0.zw; + OUT_uv1 = IN_uv * rtParams1.zw; + OUT_uv2 = IN_uv * rtParams2.zw; + OUT_uv3 = IN_uv * rtParams3.zw; + */ + + + OUT_hpos = IN_pos; + OUT_uv0 = viewportCoordToRenderTarget( IN_uv, rtParams0 ); + OUT_uv1 = viewportCoordToRenderTarget( IN_uv, rtParams1 ); + OUT_uv2 = viewportCoordToRenderTarget( IN_uv, rtParams2 ); + OUT_uv3 = viewportCoordToRenderTarget( IN_uv, rtParams3 ); + + + OUT_wsEyeRay = IN_wsEyeRay; + + correctSSP(gl_Position);; +} diff --git a/Templates/BaseGame/game/core/rendering/shaders/postFX/dof/gl/DOF_DownSample_P.glsl b/Templates/BaseGame/game/core/rendering/shaders/postFX/dof/gl/DOF_DownSample_P.glsl new file mode 100644 index 000000000..f3c093f31 --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/postFX/dof/gl/DOF_DownSample_P.glsl @@ -0,0 +1,143 @@ +//----------------------------------------------------------------------------- +// 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" + +// These are set by the game engine. +// The render target size is one-quarter the scene rendering size. +uniform sampler2D colorSampler; +uniform sampler2D depthSampler; +uniform vec2 dofEqWorld; +uniform float depthOffset; +uniform vec2 targetSize; +uniform float maxWorldCoC; +//uniform vec2 dofEqWeapon; +//uniform vec2 dofRowDelta; // vec2( 0, 0.25 / renderTargetHeight ) + +in vec2 tcColor0; +#define IN_tcColor0 tcColor0 +in vec2 tcColor1; +#define IN_tcColor1 tcColor1 +in vec2 tcDepth0; +#define IN_tcDepth0 tcDepth0 +in vec2 tcDepth1; +#define IN_tcDepth1 tcDepth1 +in vec2 tcDepth2; +#define IN_tcDepth2 tcDepth2 +in vec2 tcDepth3; +#define IN_tcDepth3 tcDepth3 + +out vec4 OUT_col; + +void main() +{ + //return vec4( 1.0, 0.0, 1.0, 1.0 ); + + vec2 dofRowDelta = vec2( 0, 0.25 / targetSize.y ); + + //vec2 dofEqWorld = vec2( -60, 1.0 ); + + half3 color; + half maxCoc; + vec4 depth; + half4 viewCoc; + half4 sceneCoc; + half4 curCoc; + half4 coc; + vec2 rowOfs[4]; + + // "rowOfs" reduces how many moves PS2.0 uses to emulate swizzling. + rowOfs[0] = vec2(0); + rowOfs[1] = dofRowDelta.xy; + rowOfs[2] = dofRowDelta.xy * 2; + rowOfs[3] = dofRowDelta.xy * 3; + + // Use bilinear filtering to average 4 color samples for free. + color = half3(0); + color += texture( colorSampler, IN_tcColor0.xy + rowOfs[0] ).rgb; + color += texture( colorSampler, IN_tcColor1.xy + rowOfs[0] ).rgb; + color += texture( colorSampler, IN_tcColor0.xy + rowOfs[2] ).rgb; + color += texture( colorSampler, IN_tcColor1.xy + rowOfs[2] ).rgb; + color /= 4; + + // Process 4 samples at a time to use vector hardware efficiently. + // The CoC will be 1 if the depth is negative, so use "min" to pick + // between "sceneCoc" and "viewCoc". + + coc = half4(0); + for ( int i = 0; i < 4; i++ ) + { + depth[0] = deferredUncondition( depthSampler, ( IN_tcDepth0.xy + rowOfs[i] ) ).w; + depth[1] = deferredUncondition( depthSampler, ( IN_tcDepth1.xy + rowOfs[i] ) ).w; + depth[2] = deferredUncondition( depthSampler, ( IN_tcDepth2.xy + rowOfs[i] ) ).w; + depth[3] = deferredUncondition( depthSampler, ( IN_tcDepth3.xy + rowOfs[i] ) ).w; + + // @todo OPENGL INTEL need review + coc = max( coc, clamp( half4(dofEqWorld.x) * depth + half4(dofEqWorld.y), half4(0.0), half4(maxWorldCoC) ) ); + } + + /* + depth[0] = texture( depthSampler, pixel.tcDepth0.xy + rowOfs[0] ).r; + depth[1] = texture( depthSampler, pixel.tcDepth1.xy + rowOfs[0] ).r; + depth[2] = texture( depthSampler, pixel.tcDepth2.xy + rowOfs[0] ).r; + depth[3] = texture( depthSampler, pixel.tcDepth3.xy + rowOfs[0] ).r; + viewCoc = saturate( dofEqWeapon.x * -depth + dofEqWeapon.y ); + sceneCoc = saturate( dofEqWorld.x * depth + dofEqWorld.y ); + curCoc = min( viewCoc, sceneCoc ); + coc = curCoc; + + depth[0] = texture( depthSampler, pixel.tcDepth0.xy + rowOfs[1] ).r; + depth[1] = texture( depthSampler, pixel.tcDepth1.xy + rowOfs[1] ).r; + depth[2] = texture( depthSampler, pixel.tcDepth2.xy + rowOfs[1] ).r; + depth[3] = texture( depthSampler, pixel.tcDepth3.xy + rowOfs[1] ).r; + viewCoc = saturate( dofEqWeapon.x * -depth + dofEqWeapon.y ); + sceneCoc = saturate( dofEqWorld.x * depth + dofEqWorld.y ); + curCoc = min( viewCoc, sceneCoc ); + coc = max( coc, curCoc ); + + depth[0] = texture( depthSampler, pixel.tcDepth0.xy + rowOfs[2] ).r; + depth[1] = texture( depthSampler, pixel.tcDepth1.xy + rowOfs[2] ).r; + depth[2] = texture( depthSampler, pixel.tcDepth2.xy + rowOfs[2] ).r; + depth[3] = texture( depthSampler, pixel.tcDepth3.xy + rowOfs[2] ).r; + viewCoc = saturate( dofEqWeapon.x * -depth + dofEqWeapon.y ); + sceneCoc = saturate( dofEqWorld.x * depth + dofEqWorld.y ); + curCoc = min( viewCoc, sceneCoc ); + coc = max( coc, curCoc ); + + depth[0] = texture( depthSampler, pixel.tcDepth0.xy + rowOfs[3] ).r; + depth[1] = texture( depthSampler, pixel.tcDepth1.xy + rowOfs[3] ).r; + depth[2] = texture( depthSampler, pixel.tcDepth2.xy + rowOfs[3] ).r; + depth[3] = texture( depthSampler, pixel.tcDepth3.xy + rowOfs[3] ).r; + viewCoc = saturate( dofEqWeapon.x * -depth + dofEqWeapon.y ); + sceneCoc = saturate( dofEqWorld.x * depth + dofEqWorld.y ); + curCoc = min( viewCoc, sceneCoc ); + coc = max( coc, curCoc ); + */ + + maxCoc = max( max( coc[0], coc[1] ), max( coc[2], coc[3] ) ); + + //OUT_col = half4( 1.0, 0.0, 1.0, 1.0 ); + OUT_col = half4( color, maxCoc ); + //OUT_col = half4( color, 1.0f ); + //OUT_col = half4( maxCoc.rrr, 1.0 ); +} \ No newline at end of file diff --git a/Templates/BaseGame/game/core/rendering/shaders/postFX/dof/gl/DOF_DownSample_V.glsl b/Templates/BaseGame/game/core/rendering/shaders/postFX/dof/gl/DOF_DownSample_V.glsl new file mode 100644 index 000000000..b8e840c9e --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/postFX/dof/gl/DOF_DownSample_V.glsl @@ -0,0 +1,67 @@ +//----------------------------------------------------------------------------- +// 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 "../../../gl/torque.glsl" + +in vec4 vPosition; +in vec2 vTexCoord0; +in vec3 vTexCoord1; + +#define IN_pos vPosition +#define IN_tc vTexCoord0 +#define IN_wsEyeRay vTexCoord1 + +#define OUT_position gl_Position + +out vec2 tcColor0; +#define OUT_tcColor0 tcColor0 +out vec2 tcColor1; +#define OUT_tcColor1 tcColor1 +out vec2 tcDepth0; +#define OUT_tcDepth0 tcDepth0 +out vec2 tcDepth1; +#define OUT_tcDepth1 tcDepth1 +out vec2 tcDepth2; +#define OUT_tcDepth2 tcDepth2 +out vec2 tcDepth3; +#define OUT_tcDepth3 tcDepth3 + + +uniform vec4 rtParams0; +uniform vec2 oneOverTargetSize; + +void main() +{ + OUT_position = IN_pos; + + vec2 uv = viewportCoordToRenderTarget( IN_tc, rtParams0 ); + //OUT_position = tMul( IN_pos, modelView ); + OUT_tcColor1 = uv + vec2( +1.0, -0.0 ) * oneOverTargetSize; + OUT_tcColor0 = uv + vec2( -1.0, -0.0 ) * oneOverTargetSize; + OUT_tcDepth0 = uv + vec2( -0.5, -0.0 ) * oneOverTargetSize; + OUT_tcDepth1 = uv + vec2( -1.5, -0.0 ) * oneOverTargetSize; + OUT_tcDepth2 = uv + vec2( +1.5, -0.0 ) * oneOverTargetSize; + OUT_tcDepth3 = uv + vec2( +2.5, -0.0 ) * oneOverTargetSize; + + correctSSP(gl_Position); +} \ No newline at end of file diff --git a/Templates/BaseGame/game/core/rendering/shaders/postFX/dof/gl/DOF_Final_P.glsl b/Templates/BaseGame/game/core/rendering/shaders/postFX/dof/gl/DOF_Final_P.glsl new file mode 100644 index 000000000..9b976ba1e --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/postFX/dof/gl/DOF_Final_P.glsl @@ -0,0 +1,147 @@ +//----------------------------------------------------------------------------- +// 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/postFX.glsl" + +uniform sampler2D colorSampler; // Original source image +uniform sampler2D smallBlurSampler; // Output of SmallBlurPS() +uniform sampler2D largeBlurSampler; // Blurred output of DofDownsample() +uniform sampler2D depthSampler; // +uniform vec2 oneOverTargetSize; +uniform vec4 dofLerpScale; +uniform vec4 dofLerpBias; +uniform vec3 dofEqFar; +uniform float maxFarCoC; + +//static float d0 = 0.1; +//static float d1 = 0.1; +//static float d2 = 0.8; +//static vec4 dofLerpScale = vec4( -1.0 / d0, -1.0 / d1, -1.0 / d2, 1.0 / d2 ); +//static vec4 dofLerpBias = vec4( 1.0, (1.0 - d2) / d1, 1.0 / d2, (d2 - 1.0) / d2 ); +//static vec3 dofEqFar = vec3( 2.0, 0.0, 1.0 ); + +out vec4 OUT_col; + +vec4 tex2Doffset( sampler2D s, vec2 tc, vec2 offset ) +{ + return texture( s, tc + offset * oneOverTargetSize ); +} + +half3 GetSmallBlurSample( vec2 tc ) +{ + half3 sum; + const half weight = 4.0 / 17; + sum = half3(0); // Unblurred sample done by alpha blending + //sum += weight * tex2Doffset( colorSampler, tc, vec2( 0, 0 ) ).rgb; + sum += weight * tex2Doffset( colorSampler, tc, vec2( +0.5, -1.5 ) ).rgb; + sum += weight * tex2Doffset( colorSampler, tc, vec2( -1.5, -0.5 ) ).rgb; + sum += weight * tex2Doffset( colorSampler, tc, vec2( -0.5, +1.5 ) ).rgb; + sum += weight * tex2Doffset( colorSampler, tc, vec2( +1.5, +0.5 ) ).rgb; + return sum; +} + +half4 InterpolateDof( half3 small, half3 med, half3 large, half t ) +{ + //t = 2; + half4 weights; + half3 color; + half alpha; + + // Efficiently calculate the cross-blend weights for each sample. + // Let the unblurred sample to small blur fade happen over distance + // d0, the small to medium blur over distance d1, and the medium to + // large blur over distance d2, where d0 + d1 + d2 = 1. + //vec4 dofLerpScale = vec4( -1 / d0, -1 / d1, -1 / d2, 1 / d2 ); + //vec4 dofLerpBias = vec4( 1, (1 – d2) / d1, 1 / d2, (d2 – 1) / d2 ); + + weights = saturate( t * dofLerpScale + dofLerpBias ); + weights.yz = min( weights.yz, 1 - weights.xy ); + + // Unblurred sample with weight "weights.x" done by alpha blending + color = weights.y * small + weights.z * med + weights.w * large; + //color = med; + alpha = dot( weights.yzw, half3( 16.0 / 17, 1.0, 1.0 ) ); + //alpha = 0.0; + + return half4( color, alpha ); +} + +void main() +{ + //return half4( 1,0,1,1 ); + //return half4( texture( colorSampler, IN_uv0 ).rgb, 1.0 ); + //return half4( texture( colorSampler, texCoords ).rgb, 0 ); + half3 small; + half4 med; + half3 large; + half depth; + half nearCoc; + half farCoc; + half coc; + + small = GetSmallBlurSample( IN_uv0 ); + //small = half3( 1,0,0 ); + //return half4( small, 1.0 ); + med = texture( smallBlurSampler, IN_uv1 ); + //med.rgb = half3( 0,1,0 ); + //return half4(med.rgb, 0.0); + large = texture( largeBlurSampler, IN_uv2 ).rgb; + //large = half3( 0,0,1 ); + //return large; + //return half4(large.rgb,1.0); + nearCoc = med.a; + + // Since the med blur texture is screwed up currently + // replace it with the large, but this needs to be fixed. + //med.rgb = large; + + //nearCoc = 0; + depth = deferredUncondition( depthSampler, IN_uv3 ).w; + //return half4(depth.rrr,1); + //return half4(nearCoc.rrr,1.0); + + if (depth > 0.999 ) + { + coc = nearCoc; // We don't want to blur the sky. + //coc = 0; + } + else + { + // dofEqFar.x and dofEqFar.y specify the linear ramp to convert + // to depth for the distant out-of-focus region. + // dofEqFar.z is the ratio of the far to the near blur radius. + farCoc = clamp( dofEqFar.x * depth + dofEqFar.y, 0.0, maxFarCoC ); + coc = max( nearCoc, farCoc * dofEqFar.z ); + //coc = nearCoc; + } + + //coc = nearCoc; + //coc = farCoc; + //return half4(coc.rrr,0.5); + //return half4(farCoc.rrr,1); + //return half4(nearCoc.rrr,1); + + //return half4( 1,0,1,0 ); + OUT_col = InterpolateDof( small, med.rgb, large, coc ); +} \ No newline at end of file diff --git a/Templates/BaseGame/game/core/rendering/shaders/postFX/dof/gl/DOF_Final_V.glsl b/Templates/BaseGame/game/core/rendering/shaders/postFX/dof/gl/DOF_Final_V.glsl new file mode 100644 index 000000000..abc91246e --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/postFX/dof/gl/DOF_Final_V.glsl @@ -0,0 +1,71 @@ +//----------------------------------------------------------------------------- +// 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 "../../../gl/torque.glsl" +#include "../../gl/postFX.glsl" + +uniform vec4 rtParams0; +uniform vec4 rtParams1; +uniform vec4 rtParams2; +uniform vec4 rtParams3; +uniform vec2 oneOverTargetSize; + +void main() +{ + /* + OUT.hpos = IN_pos; + OUT_uv0 = IN_uv; + OUT_uv1 = IN_uv; + OUT_uv2 = IN_uv; + OUT_uv3 = IN_uv; + */ + + /* + OUT_hpos = IN_pos; + OUT_uv0 = IN_uv + rtParams0.xy; + OUT_uv1 = IN_uv + rtParams1.xy; + OUT_uv2 = IN_uv + rtParams2.xy; + OUT_uv3 = IN_uv + rtParams3.xy; + */ + + + /* + OUT_hpos = IN_pos; + OUT_uv0 = IN_uv * rtParams0.zw; + OUT_uv1 = IN_uv * rtParams1.zw; + OUT_uv2 = IN_uv * rtParams2.zw; + OUT_uv3 = IN_uv * rtParams3.zw; + */ + + + OUT_hpos = IN_pos; + OUT_uv0 = viewportCoordToRenderTarget( IN_uv, rtParams0 ); + OUT_uv1 = viewportCoordToRenderTarget( IN_uv, rtParams1 ); // + vec2( -5, 1 ) * oneOverTargetSize; + OUT_uv2 = viewportCoordToRenderTarget( IN_uv, rtParams2 ); + OUT_uv3 = viewportCoordToRenderTarget( IN_uv, rtParams3 ); + + + OUT_wsEyeRay = IN_wsEyeRay; + + correctSSP(gl_Position); +} diff --git a/Templates/BaseGame/game/core/rendering/shaders/postFX/dof/gl/DOF_Gausian_P.glsl b/Templates/BaseGame/game/core/rendering/shaders/postFX/dof/gl/DOF_Gausian_P.glsl new file mode 100644 index 000000000..61e7697af --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/postFX/dof/gl/DOF_Gausian_P.glsl @@ -0,0 +1,68 @@ +//----------------------------------------------------------------------------- +// 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" + +in vec3 wsEyeRay; +#define IN_wsEyeRay wsEyeRay +in vec2 uv0; +#define IN_uv0 uv0 +in vec2 uv1; +#define IN_uv1 uv1 +in vec2 uv2; +#define IN_uv2 uv2 +in vec2 uv3; +#define IN_uv3 uv3 +in vec2 uv4; +#define IN_uv4 uv4 +in vec2 uv5; +#define IN_uv5 uv5 +in vec2 uv6; +#define IN_uv6 uv6 +in vec2 uv7; +#define IN_uv7 uv7 + +out vec4 OUT_col; + +uniform sampler2D diffuseMap; + +void main() +{ + vec4 kernel = vec4( 0.175, 0.275, 0.375, 0.475 ) * 0.5 / 1.3; //25f; + + OUT_col = vec4(0); + OUT_col += texture( diffuseMap, IN_uv0 ) * kernel.x; + OUT_col += texture( diffuseMap, IN_uv1 ) * kernel.y; + OUT_col += texture( diffuseMap, IN_uv2 ) * kernel.z; + OUT_col += texture( diffuseMap, IN_uv3 ) * kernel.w; + + OUT_col += texture( diffuseMap, IN_uv4 ) * kernel.x; + OUT_col += texture( diffuseMap, IN_uv5 ) * kernel.y; + OUT_col += texture( diffuseMap, IN_uv6 ) * kernel.z; + OUT_col += texture( diffuseMap, IN_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/BaseGame/game/core/rendering/shaders/postFX/dof/gl/DOF_Gausian_V.glsl b/Templates/BaseGame/game/core/rendering/shaders/postFX/dof/gl/DOF_Gausian_V.glsl new file mode 100644 index 000000000..c77e23c53 --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/postFX/dof/gl/DOF_Gausian_V.glsl @@ -0,0 +1,91 @@ +//----------------------------------------------------------------------------- +// 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 "../../../gl/torque.glsl" + +in vec4 vPosition; +in vec2 vTexCoord0; +in vec3 vTexCoord1; + +#define IN_pos vPosition +#define _IN_uv vTexCoord0 +#define IN_wsEyeRay vTexCoord1 + +#define OUT_hpos gl_Position +out vec3 wsEyeRay; +#define OUT_wsEyeRay wsEyeRay +out vec2 uv0; +#define OUT_uv0 uv0 +out vec2 uv1; +#define OUT_uv1 uv1 +out vec2 uv2; +#define OUT_uv2 uv2 +out vec2 uv3; +#define OUT_uv3 uv3 +out vec2 uv4; +#define OUT_uv4 uv4 +out vec2 uv5; +#define OUT_uv5 uv5 +out vec2 uv6; +#define OUT_uv6 uv6 +out vec2 uv7; +#define OUT_uv7 uv7 + +uniform vec2 texSize0; +uniform vec4 rtParams0; +uniform vec2 oneOverTargetSize; + + +void main() +{ + OUT_hpos = IN_pos; + + vec2 IN_uv = viewportCoordToRenderTarget( _IN_uv, rtParams0 ); + + // I don't know why this offset is necessary, but it is. + //IN_uv = IN_uv * oneOverTargetSize; + + OUT_uv0 = IN_uv + ( ( BLUR_DIR * 3.5f ) / texSize0 ); + OUT_uv1 = IN_uv + ( ( BLUR_DIR * 2.5f ) / texSize0 ); + OUT_uv2 = IN_uv + ( ( BLUR_DIR * 1.5f ) / texSize0 ); + OUT_uv3 = IN_uv + ( ( BLUR_DIR * 0.5f ) / texSize0 ); + + OUT_uv4 = IN_uv - ( ( BLUR_DIR * 3.5f ) / texSize0 ); + OUT_uv5 = IN_uv - ( ( BLUR_DIR * 2.5f ) / texSize0 ); + OUT_uv6 = IN_uv - ( ( BLUR_DIR * 1.5f ) / texSize0 ); + OUT_uv7 = IN_uv - ( ( BLUR_DIR * 0.5f ) / texSize0 ); + + /* + OUT_uv0 = viewportCoordToRenderTarget( OUT_uv0, rtParams0 ); + OUT_uv1 = viewportCoordToRenderTarget( OUT_uv1, rtParams0 ); + OUT_uv2 = viewportCoordToRenderTarget( OUT_uv2, rtParams0 ); + OUT_uv3 = viewportCoordToRenderTarget( OUT_uv3, rtParams0 ); + + OUT_uv4 = viewportCoordToRenderTarget( OUT_uv4, rtParams0 ); + OUT_uv5 = viewportCoordToRenderTarget( OUT_uv5, rtParams0 ); + OUT_uv6 = viewportCoordToRenderTarget( OUT_uv6, rtParams0 ); + OUT_uv7 = viewportCoordToRenderTarget( OUT_uv7, rtParams0 ); + */ + + correctSSP(gl_Position); +} diff --git a/Templates/BaseGame/game/core/rendering/shaders/postFX/dof/gl/DOF_Passthrough_V.glsl b/Templates/BaseGame/game/core/rendering/shaders/postFX/dof/gl/DOF_Passthrough_V.glsl new file mode 100644 index 000000000..bd02fb7d4 --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/postFX/dof/gl/DOF_Passthrough_V.glsl @@ -0,0 +1,69 @@ +//----------------------------------------------------------------------------- +// 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 "../../../gl/torque.glsl" +#include "../../gl/postFX.glsl" + +uniform vec4 rtParams0; +uniform vec4 rtParams1; +uniform vec4 rtParams2; +uniform vec4 rtParams3; + +void main() +{ + /* + OUT.hpos = IN_pos; + OUT_uv0 = IN_uv; + OUT_uv1 = IN_uv; + OUT_uv2 = IN_uv; + OUT_uv3 = IN_uv; + */ + + /* + OUT_hpos = IN_pos; + OUT_uv0 = IN_uv + rtParams0.xy; + OUT_uv1 = IN_uv + rtParams1.xy; + OUT_uv2 = IN_uv + rtParams2.xy; + OUT_uv3 = IN_uv + rtParams3.xy; + */ + + /* + OUT_hpos = IN_pos; + OUT_uv0 = IN_uv * rtParams0.zw; + OUT_uv1 = IN_uv * rtParams1.zw; + OUT_uv2 = IN_uv * rtParams2.zw; + OUT_uv3 = IN_uv * rtParams3.zw; + */ + + + OUT_hpos = IN_pos; + OUT_uv0 = viewportCoordToRenderTarget( IN_uv, rtParams0 ); + OUT_uv1 = viewportCoordToRenderTarget( IN_uv, rtParams1 ); + OUT_uv2 = viewportCoordToRenderTarget( IN_uv, rtParams2 ); + OUT_uv3 = viewportCoordToRenderTarget( IN_uv, rtParams3 ); + + + OUT_wsEyeRay = IN_wsEyeRay; + + correctSSP(gl_Position); +} diff --git a/Templates/BaseGame/game/core/rendering/shaders/postFX/dof/gl/DOF_SmallBlur_P.glsl b/Templates/BaseGame/game/core/rendering/shaders/postFX/dof/gl/DOF_SmallBlur_P.glsl new file mode 100644 index 000000000..ae94edd78 --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/postFX/dof/gl/DOF_SmallBlur_P.glsl @@ -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. +//----------------------------------------------------------------------------- + +// This vertex and pixel shader applies a 3 x 3 blur to the image in +// colorMapSampler, which is the same size as the render target. +// The sample weights are 1/16 in the corners, 2/16 on the edges, +// and 4/16 in the center. + +#include "../../../gl/hlslCompat.glsl" + +uniform sampler2D colorSampler; // Output of DofNearCoc() + +in vec4 texCoords; +#define IN_texCoords texCoords + +out vec4 OUT_col; + +void main() +{ + vec4 color; + color = vec4(0.0); + color += texture( colorSampler, IN_texCoords.xz ); + color += texture( colorSampler, IN_texCoords.yz ); + color += texture( colorSampler, IN_texCoords.xw ); + color += texture( colorSampler, IN_texCoords.yw ); + OUT_col = color / 4.0; +} \ No newline at end of file diff --git a/Templates/BaseGame/game/core/rendering/shaders/postFX/dof/gl/DOF_SmallBlur_V.glsl b/Templates/BaseGame/game/core/rendering/shaders/postFX/dof/gl/DOF_SmallBlur_V.glsl new file mode 100644 index 000000000..413abd352 --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/postFX/dof/gl/DOF_SmallBlur_V.glsl @@ -0,0 +1,54 @@ +//----------------------------------------------------------------------------- +// 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. +//----------------------------------------------------------------------------- + +// This vertex and pixel shader applies a 3 x 3 blur to the image in +// colorMapSampler, which is the same size as the render target. +// The sample weights are 1/16 in the corners, 2/16 on the edges, +// and 4/16 in the center. + +#include "../../../gl/hlslCompat.glsl" +#include "../../../gl/torque.glsl" + +in vec4 vPosition; +in vec2 vTexCoord0; + +#define IN_position vPosition +#define IN_texCoords vTexCoord0 + +#define OUT_position gl_Position +out vec4 texCoords; +#define OUT_texCoords texCoords + +uniform vec2 oneOverTargetSize; +uniform vec4 rtParams0; + +void main() +{ + const vec4 halfPixel = vec4( -0.5, 0.5, -0.5, 0.5 ); + OUT_position = IN_position; //Transform_ObjectToClip( IN_position ); + + //vec2 uv = IN_texCoords + rtParams0.xy; + vec2 uv = viewportCoordToRenderTarget( IN_texCoords, rtParams0 ); + OUT_texCoords = uv.xxyy + halfPixel * oneOverTargetSize.xxyy; + + correctSSP(gl_Position); +} \ No newline at end of file diff --git a/Templates/BaseGame/game/core/rendering/shaders/postFX/edgeaa/dbgEdgeDisplayP.hlsl b/Templates/BaseGame/game/core/rendering/shaders/postFX/edgeaa/dbgEdgeDisplayP.hlsl new file mode 100644 index 000000000..fbd529031 --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/postFX/edgeaa/dbgEdgeDisplayP.hlsl @@ -0,0 +1,30 @@ +//----------------------------------------------------------------------------- +// 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 "../postFx.hlsl" + +TORQUE_UNIFORM_SAMPLER2D(edgeBuffer); + +float4 main( PFXVertToPix IN ) : TORQUE_TARGET0 +{ + return float4( TORQUE_TEX2D( edgeBuffer, IN.uv0 ).rrr, 1.0 ); +} \ No newline at end of file diff --git a/Templates/BaseGame/game/core/rendering/shaders/postFX/edgeaa/edgeAAP.hlsl b/Templates/BaseGame/game/core/rendering/shaders/postFX/edgeaa/edgeAAP.hlsl new file mode 100644 index 000000000..f5a71687d --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/postFX/edgeaa/edgeAAP.hlsl @@ -0,0 +1,66 @@ +//----------------------------------------------------------------------------- +// 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 "../postFx.hlsl" + +TORQUE_UNIFORM_SAMPLER2D(edgeBuffer,0); +TORQUE_UNIFORM_SAMPLER2D(backBuffer, 1); +uniform float2 targetSize; + +float4 main( PFXVertToPix IN ) : TORQUE_TARGET0 +{ + float2 pixelSize = 1.0 / targetSize; + + // Sample edge buffer, bail if not on an edge + float edgeSample = TORQUE_TEX2D(edgeBuffer, IN.uv0).r; + clip(edgeSample - 1e-6); + + // Ok we're on an edge, so multi-tap sample, average, and return + float2 offsets[9] = { + float2( 0.0, 0.0), + float2(-1.0, -1.0), + float2( 0.0, -1.0), + float2( 1.0, -1.0), + float2( 1.0, 0.0), + float2( 1.0, 1.0), + float2( 0.0, 1.0), + float2(-1.0, 1.0), + float2(-1.0, 0.0), + }; + + float4 accumColor = 0; + for(int i = 0; i < 9; i++) + { + // Multiply the intensity of the edge, by the UV, so that things which maybe + // aren't quite full edges get sub-pixel sampling to reduce artifacts + + // Scaling offsets by 0.5 to reduce the range bluriness from extending to + // far outward from the edge. + + float2 offsetUV = IN.uv1 + edgeSample * ( offsets[i] * 0.5 ) * pixelSize;//rtWidthHeightInvWidthNegHeight.zw; + //offsetUV *= 0.999; + accumColor += TORQUE_TEX2D(backBuffer, offsetUV); + } + accumColor /= 9.0; + + return accumColor; +} diff --git a/Templates/BaseGame/game/core/rendering/shaders/postFX/edgeaa/edgeAAV.hlsl b/Templates/BaseGame/game/core/rendering/shaders/postFX/edgeaa/edgeAAV.hlsl new file mode 100644 index 000000000..4718b40f5 --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/postFX/edgeaa/edgeAAV.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. +//----------------------------------------------------------------------------- + +#include "./../postFx.hlsl" +#include "./../../torque.hlsl" + + +uniform float4 rtParams0; +uniform float4 rtParams1; +uniform float4 rtParams2; +uniform float4 rtParams3; + +PFXVertToPix main( PFXVert IN ) +{ + PFXVertToPix OUT; + + OUT.hpos = IN.pos; + OUT.uv0 = viewportCoordToRenderTarget( IN.uv, rtParams0 ); + OUT.uv1 = viewportCoordToRenderTarget( IN.uv, rtParams1 ); + OUT.uv2 = viewportCoordToRenderTarget( IN.uv, rtParams2 ); + OUT.uv3 = viewportCoordToRenderTarget( IN.uv, rtParams3 ); + + OUT.wsEyeRay = IN.wsEyeRay; + + return OUT; +} diff --git a/Templates/BaseGame/game/core/rendering/shaders/postFX/edgeaa/edgeDetectP.hlsl b/Templates/BaseGame/game/core/rendering/shaders/postFX/edgeaa/edgeDetectP.hlsl new file mode 100644 index 000000000..c8bfb2153 --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/postFX/edgeaa/edgeDetectP.hlsl @@ -0,0 +1,93 @@ +//----------------------------------------------------------------------------- +// 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 "../postFx.hlsl" +#include "../../shaderModelAutoGen.hlsl" + +TORQUE_UNIFORM_SAMPLER2D(deferredBuffer,0); + +// GPU Gems 3, pg 443-444 +float GetEdgeWeight(float2 uv0, in float2 targetSize) +{ + float2 offsets[9] = { + float2( 0.0, 0.0), + float2(-1.0, -1.0), + float2( 0.0, -1.0), + float2( 1.0, -1.0), + float2( 1.0, 0.0), + float2( 1.0, 1.0), + float2( 0.0, 1.0), + float2(-1.0, 1.0), + float2(-1.0, 0.0), + }; + + + float2 PixelSize = 1.0 / targetSize; + + float Depth[9]; + float3 Normal[9]; + + [unroll] //no getting around this, may as well save the annoying warning message + for(int i = 0; i < 9; i++) + { + float2 uv = uv0 + offsets[i] * PixelSize; + float4 gbSample = TORQUE_DEFERRED_UNCONDITION( deferredBuffer, uv ); + Depth[i] = gbSample.a; + Normal[i] = gbSample.rgb; + } + + float4 Deltas1 = float4(Depth[1], Depth[2], Depth[3], Depth[4]); + float4 Deltas2 = float4(Depth[5], Depth[6], Depth[7], Depth[8]); + + Deltas1 = abs(Deltas1 - Depth[0]); + Deltas2 = abs(Depth[0] - Deltas2); + + float4 maxDeltas = max(Deltas1, Deltas2); + float4 minDeltas = max(min(Deltas1, Deltas2), 0.00001); + + float4 depthResults = step(minDeltas * 25.0, maxDeltas); + + Deltas1.x = dot(Normal[1], Normal[0]); + Deltas1.y = dot(Normal[2], Normal[0]); + Deltas1.z = dot(Normal[3], Normal[0]); + Deltas1.w = dot(Normal[4], Normal[0]); + + Deltas2.x = dot(Normal[5], Normal[0]); + Deltas2.y = dot(Normal[6], Normal[0]); + Deltas2.z = dot(Normal[7], Normal[0]); + Deltas2.w = dot(Normal[8], Normal[0]); + + Deltas1 = abs(Deltas1 - Deltas2); + + float4 normalResults = step(0.4, Deltas1); + + normalResults = max(normalResults, depthResults); + + return dot(normalResults, float4(1.0, 1.0, 1.0, 1.0)) * 0.25; +} + +uniform float2 targetSize; + +float4 main( PFXVertToPix IN ) : TORQUE_TARGET0 +{ + return GetEdgeWeight(IN.uv0, targetSize);//rtWidthHeightInvWidthNegHeight.zw); +} diff --git a/Templates/BaseGame/game/core/rendering/shaders/postFX/edgeaa/gl/dbgEdgeDisplayP.glsl b/Templates/BaseGame/game/core/rendering/shaders/postFX/edgeaa/gl/dbgEdgeDisplayP.glsl new file mode 100644 index 000000000..ccc3b8ba5 --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/postFX/edgeaa/gl/dbgEdgeDisplayP.glsl @@ -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. +//----------------------------------------------------------------------------- + +#include "../../../gl/hlslCompat.glsl" +#include "shadergen:/autogenConditioners.h" + +in vec2 uv0; +#define IN_uv0 uv0 + +uniform sampler2D edgeBuffer; + +out vec4 OUT_col; + +void main() +{ + OUT_col = vec4( texture( edgeBuffer, IN_uv0 ).rrr, 1.0 ); +} \ No newline at end of file diff --git a/Templates/BaseGame/game/core/rendering/shaders/postFX/edgeaa/gl/edgeAAP.glsl b/Templates/BaseGame/game/core/rendering/shaders/postFX/edgeaa/gl/edgeAAP.glsl new file mode 100644 index 000000000..216dc8725 --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/postFX/edgeaa/gl/edgeAAP.glsl @@ -0,0 +1,70 @@ +//----------------------------------------------------------------------------- +// 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/postFX.glsl" + +uniform sampler2D edgeBuffer; +uniform sampler2D backBuffer; +uniform vec2 targetSize; + +out vec4 OUT_col; + +void main() +{ + vec2 pixelSize = 1.0 / targetSize; + + // Sample edge buffer, bail if not on an edge + float edgeSample = texture(edgeBuffer, IN_uv0).r; + clip(edgeSample - 1e-6); + + // Ok we're on an edge, so multi-tap sample, average, and return + vec2 offsets[9] = vec2[]( + vec2( 0.0, 0.0), + vec2(-1.0, -1.0), + vec2( 0.0, -1.0), + vec2( 1.0, -1.0), + vec2( 1.0, 0.0), + vec2( 1.0, 1.0), + vec2( 0.0, 1.0), + vec2(-1.0, 1.0), + vec2(-1.0, 0.0) + ); + + vec4 accumColor = vec4(0.0); + for(int i = 0; i < 9; i++) + { + // Multiply the intensity of the edge, by the UV, so that things which maybe + // aren't quite full edges get sub-pixel sampling to reduce artifacts + + // Scaling offsets by 0.5 to reduce the range bluriness from extending to + // far outward from the edge. + + vec2 offsetUV = IN_uv1 + edgeSample * ( offsets[i] * 0.5 ) * pixelSize;//rtWidthHeightInvWidthNegHeight.zw; + //offsetUV *= 0.999; + accumColor+= texture(backBuffer, offsetUV); + } + accumColor /= 9.0; + + OUT_col = accumColor; +} diff --git a/Templates/BaseGame/game/core/rendering/shaders/postFX/edgeaa/gl/edgeAAV.glsl b/Templates/BaseGame/game/core/rendering/shaders/postFX/edgeaa/gl/edgeAAV.glsl new file mode 100644 index 000000000..975532272 --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/postFX/edgeaa/gl/edgeAAV.glsl @@ -0,0 +1,43 @@ +//----------------------------------------------------------------------------- +// 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 "../../../gl/torque.glsl" +#include "../../gl/postFX.glsl" + +uniform vec4 rtParams0; +uniform vec4 rtParams1; +uniform vec4 rtParams2; +uniform vec4 rtParams3; + +void main() +{ + OUT_hpos = IN_pos; + OUT_uv0 = viewportCoordToRenderTarget( IN_uv, rtParams0 ); + OUT_uv1 = viewportCoordToRenderTarget( IN_uv, rtParams1 ); + OUT_uv2 = viewportCoordToRenderTarget( IN_uv, rtParams2 ); + OUT_uv3 = viewportCoordToRenderTarget( IN_uv, rtParams3 ); + + OUT_wsEyeRay = IN_wsEyeRay; + + correctSSP(gl_Position); +} diff --git a/Templates/BaseGame/game/core/rendering/shaders/postFX/edgeaa/gl/edgeDetectP.glsl b/Templates/BaseGame/game/core/rendering/shaders/postFX/edgeaa/gl/edgeDetectP.glsl new file mode 100644 index 000000000..02507eee8 --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/postFX/edgeaa/gl/edgeDetectP.glsl @@ -0,0 +1,96 @@ +//----------------------------------------------------------------------------- +// 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" + +// GPU Gems 3, pg 443-444 +float GetEdgeWeight(vec2 uv0, in sampler2D deferredBuffer, in vec2 targetSize) +{ + vec2 offsets[9] = vec2[]( + vec2( 0.0, 0.0), + vec2(-1.0, -1.0), + vec2( 0.0, -1.0), + vec2( 1.0, -1.0), + vec2( 1.0, 0.0), + vec2( 1.0, 1.0), + vec2( 0.0, 1.0), + vec2(-1.0, 1.0), + vec2(-1.0, 0.0) + ); + + + vec2 PixelSize = 1.0 / targetSize; + + float Depth[9]; + vec3 Normal[9]; + + for(int i = 0; i < 9; i++) + { + vec2 uv = uv0 + offsets[i] * PixelSize; + vec4 gbSample = deferredUncondition( deferredBuffer, uv ); + Depth[i] = gbSample.a; + Normal[i] = gbSample.rgb; + } + + vec4 Deltas1 = vec4(Depth[1], Depth[2], Depth[3], Depth[4]); + vec4 Deltas2 = vec4(Depth[5], Depth[6], Depth[7], Depth[8]); + + Deltas1 = abs(Deltas1 - Depth[0]); + Deltas2 = abs(Depth[0] - Deltas2); + + vec4 maxDeltas = max(Deltas1, Deltas2); + vec4 minDeltas = max(min(Deltas1, Deltas2), 0.00001); + + vec4 depthResults = step(minDeltas * 25.0, maxDeltas); + + Deltas1.x = dot(Normal[1], Normal[0]); + Deltas1.y = dot(Normal[2], Normal[0]); + Deltas1.z = dot(Normal[3], Normal[0]); + Deltas1.w = dot(Normal[4], Normal[0]); + + Deltas2.x = dot(Normal[5], Normal[0]); + Deltas2.y = dot(Normal[6], Normal[0]); + Deltas2.z = dot(Normal[7], Normal[0]); + Deltas2.w = dot(Normal[8], Normal[0]); + + Deltas1 = abs(Deltas1 - Deltas2); + + vec4 normalResults = step(0.4, Deltas1); + + normalResults = max(normalResults, depthResults); + + return dot(normalResults, vec4(1.0, 1.0, 1.0, 1.0)) * 0.25; +} + +in vec2 uv0; +#define IN_uv0 uv0 + +uniform sampler2D deferredBuffer; +uniform vec2 targetSize; + +out vec4 OUT_col; + +void main() +{ + OUT_col = vec4( GetEdgeWeight(IN_uv0, deferredBuffer, targetSize ) );//rtWidthHeightInvWidthNegHeight.zw); +} diff --git a/Templates/BaseGame/game/core/rendering/shaders/postFX/flashP.hlsl b/Templates/BaseGame/game/core/rendering/shaders/postFX/flashP.hlsl new file mode 100644 index 000000000..93daf3c26 --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/postFX/flashP.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. +//----------------------------------------------------------------------------- + +#include "./postFx.hlsl" +#include "../torque.hlsl" + +uniform float damageFlash; +uniform float whiteOut; +TORQUE_UNIFORM_SAMPLER2D(backBuffer, 0); + +float4 main(PFXVertToPix IN) : TORQUE_TARGET0 +{ + float4 color1 = TORQUE_TEX2D(backBuffer, IN.uv0); + float4 color2 = color1 * MUL_COLOR; + float4 damage = lerp(color1,color2,damageFlash); + return lerp(damage,WHITE_COLOR,whiteOut); +} diff --git a/Templates/BaseGame/game/core/rendering/shaders/postFX/fogP.hlsl b/Templates/BaseGame/game/core/rendering/shaders/postFX/fogP.hlsl new file mode 100644 index 000000000..9f3500f67 --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/postFX/fogP.hlsl @@ -0,0 +1,47 @@ +//----------------------------------------------------------------------------- +// 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 "./postFx.hlsl" +#include "./../torque.hlsl" +#include "./../shaderModelAutoGen.hlsl" + +TORQUE_UNIFORM_SAMPLER2D(deferredTex, 0); +uniform float3 eyePosWorld; +uniform float4 fogColor; +uniform float3 fogData; +uniform float4 rtParams0; + +float4 main( PFXVertToPix IN ) : TORQUE_TARGET0 +{ + //float2 deferredCoord = ( IN.uv0.xy * rtParams0.zw ) + rtParams0.xy; + float depth = TORQUE_DEFERRED_UNCONDITION( deferredTex, IN.uv0 ).w; + //return float4( depth, 0, 0, 0.7 ); + + float factor = computeSceneFog( eyePosWorld, + eyePosWorld + ( IN.wsEyeRay * depth ), + fogData.x, + fogData.y, + fogData.z ); + + return hdrEncode( float4( fogColor.rgb, 1.0 - saturate( factor ) ) ); +} \ No newline at end of file diff --git a/Templates/BaseGame/game/core/rendering/shaders/postFX/fxaa/Fxaa3_11.h b/Templates/BaseGame/game/core/rendering/shaders/postFX/fxaa/Fxaa3_11.h new file mode 100644 index 000000000..9ca7627d4 --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/postFX/fxaa/Fxaa3_11.h @@ -0,0 +1,2047 @@ +/*============================================================================ + + + NVIDIA FXAA 3.11 by TIMOTHY LOTTES + + +------------------------------------------------------------------------------ +COPYRIGHT (C) 2010, 2011 NVIDIA CORPORATION. ALL RIGHTS RESERVED. +------------------------------------------------------------------------------ +TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, THIS SOFTWARE IS PROVIDED +*AS IS* AND NVIDIA AND ITS SUPPLIERS DISCLAIM ALL WARRANTIES, EITHER EXPRESS +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL NVIDIA +OR ITS SUPPLIERS BE LIABLE FOR ANY SPECIAL, INCIDENTAL, INDIRECT, OR +CONSEQUENTIAL DAMAGES WHATSOEVER (INCLUDING, WITHOUT LIMITATION, DAMAGES FOR +LOSS OF BUSINESS PROFITS, BUSINESS INTERRUPTION, LOSS OF BUSINESS INFORMATION, +OR ANY OTHER PECUNIARY LOSS) ARISING OUT OF THE USE OF OR INABILITY TO USE +THIS SOFTWARE, EVEN IF NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + +------------------------------------------------------------------------------ + INTEGRATION CHECKLIST +------------------------------------------------------------------------------ +(1.) +In the shader source, setup defines for the desired configuration. +When providing multiple shaders (for different presets), +simply setup the defines differently in multiple files. +Example, + + #define FXAA_PC 1 + #define FXAA_HLSL_5 1 + #define FXAA_QUALITY__PRESET 12 + +Or, + + #define FXAA_360 1 + +Or, + + #define FXAA_PS3 1 + +Etc. + +(2.) +Then include this file, + + include "Fxaa3_11.h" + +(3.) +Then call the FXAA pixel shader from within your desired shader. +Look at the FXAA Quality FxaaPixelShader() for docs on inputs. +As for FXAA 3.11 all inputs for all shaders are the same +to enable easy porting between platforms. + + return FxaaPixelShader(...); + +(4.) +Insure pass prior to FXAA outputs RGBL (see next section). +Or use, + + #define FXAA_GREEN_AS_LUMA 1 + +(5.) +Setup engine to provide the following constants +which are used in the FxaaPixelShader() inputs, + + FxaaFloat2 fxaaQualityRcpFrame, + FxaaFloat4 fxaaConsoleRcpFrameOpt, + FxaaFloat4 fxaaConsoleRcpFrameOpt2, + FxaaFloat4 fxaaConsole360RcpFrameOpt2, + FxaaFloat fxaaQualitySubpix, + FxaaFloat fxaaQualityEdgeThreshold, + FxaaFloat fxaaQualityEdgeThresholdMin, + FxaaFloat fxaaConsoleEdgeSharpness, + FxaaFloat fxaaConsoleEdgeThreshold, + FxaaFloat fxaaConsoleEdgeThresholdMin, + FxaaFloat4 fxaaConsole360ConstDir + +Look at the FXAA Quality FxaaPixelShader() for docs on inputs. + +(6.) +Have FXAA vertex shader run as a full screen triangle, +and output "pos" and "fxaaConsolePosPos" +such that inputs in the pixel shader provide, + + // {xy} = center of pixel + FxaaFloat2 pos, + + // {xy__} = upper left of pixel + // {__zw} = lower right of pixel + FxaaFloat4 fxaaConsolePosPos, + +(7.) +Insure the texture sampler(s) used by FXAA are set to bilinear filtering. + + +------------------------------------------------------------------------------ + INTEGRATION - RGBL AND COLORSPACE +------------------------------------------------------------------------------ +FXAA3 requires RGBL as input unless the following is set, + + #define FXAA_GREEN_AS_LUMA 1 + +In which case the engine uses green in place of luma, +and requires RGB input is in a non-linear colorspace. + +RGB should be LDR (low dynamic range). +Specifically do FXAA after tonemapping. + +RGB data as returned by a texture fetch can be non-linear, +or linear when FXAA_GREEN_AS_LUMA is not set. +Note an "sRGB format" texture counts as linear, +because the result of a texture fetch is linear data. +Regular "RGBA8" textures in the sRGB colorspace are non-linear. + +If FXAA_GREEN_AS_LUMA is not set, +luma must be stored in the alpha channel prior to running FXAA. +This luma should be in a perceptual space (could be gamma 2.0). +Example pass before FXAA where output is gamma 2.0 encoded, + + color.rgb = ToneMap(color.rgb); // linear color output + color.rgb = sqrt(color.rgb); // gamma 2.0 color output + return color; + +To use FXAA, + + color.rgb = ToneMap(color.rgb); // linear color output + color.rgb = sqrt(color.rgb); // gamma 2.0 color output + color.a = dot(color.rgb, FxaaFloat3(0.299, 0.587, 0.114)); // compute luma + return color; + +Another example where output is linear encoded, +say for instance writing to an sRGB formated render target, +where the render target does the conversion back to sRGB after blending, + + color.rgb = ToneMap(color.rgb); // linear color output + return color; + +To use FXAA, + + color.rgb = ToneMap(color.rgb); // linear color output + color.a = sqrt(dot(color.rgb, FxaaFloat3(0.299, 0.587, 0.114))); // compute luma + return color; + +Getting luma correct is required for the algorithm to work correctly. + + +------------------------------------------------------------------------------ + BEING LINEARLY CORRECT? +------------------------------------------------------------------------------ +Applying FXAA to a framebuffer with linear RGB color will look worse. +This is very counter intuitive, but happends to be true in this case. +The reason is because dithering artifacts will be more visiable +in a linear colorspace. + + +------------------------------------------------------------------------------ + COMPLEX INTEGRATION +------------------------------------------------------------------------------ +Q. What if the engine is blending into RGB before wanting to run FXAA? + +A. In the last opaque pass prior to FXAA, + have the pass write out luma into alpha. + Then blend into RGB only. + FXAA should be able to run ok + assuming the blending pass did not any add aliasing. + This should be the common case for particles and common blending passes. + +A. Or use FXAA_GREEN_AS_LUMA. + +============================================================================*/ + +/*============================================================================ + + INTEGRATION KNOBS + +============================================================================*/ +// +// FXAA_PS3 and FXAA_360 choose the console algorithm (FXAA3 CONSOLE). +// FXAA_360_OPT is a prototype for the new optimized 360 version. +// +// 1 = Use API. +// 0 = Don't use API. +// +/*--------------------------------------------------------------------------*/ +#ifndef FXAA_PS3 + #define FXAA_PS3 0 +#endif +/*--------------------------------------------------------------------------*/ +#ifndef FXAA_360 + #define FXAA_360 0 +#endif +/*--------------------------------------------------------------------------*/ +#ifndef FXAA_360_OPT + #define FXAA_360_OPT 0 +#endif +/*==========================================================================*/ +#ifndef FXAA_PC + // + // FXAA Quality + // The high quality PC algorithm. + // + #define FXAA_PC 0 +#endif +/*--------------------------------------------------------------------------*/ +#ifndef FXAA_PC_CONSOLE + // + // The console algorithm for PC is included + // for developers targeting really low spec machines. + // Likely better to just run FXAA_PC, and use a really low preset. + // + #define FXAA_PC_CONSOLE 0 +#endif +/*--------------------------------------------------------------------------*/ +#ifndef FXAA_GLSL_120 + #define FXAA_GLSL_120 0 +#endif +/*--------------------------------------------------------------------------*/ +#ifndef FXAA_GLSL_130 + #define FXAA_GLSL_130 0 +#endif +/*--------------------------------------------------------------------------*/ +#ifndef FXAA_HLSL_3 + #define FXAA_HLSL_3 0 +#endif +/*--------------------------------------------------------------------------*/ +#ifndef FXAA_HLSL_4 + #define FXAA_HLSL_4 0 +#endif +/*--------------------------------------------------------------------------*/ +#ifndef FXAA_HLSL_5 + #define FXAA_HLSL_5 0 +#endif +/*==========================================================================*/ +#ifndef FXAA_GREEN_AS_LUMA + // + // For those using non-linear color, + // and either not able to get luma in alpha, or not wanting to, + // this enables FXAA to run using green as a proxy for luma. + // So with this enabled, no need to pack luma in alpha. + // + // This will turn off AA on anything which lacks some amount of green. + // Pure red and blue or combination of only R and B, will get no AA. + // + // Might want to lower the settings for both, + // fxaaConsoleEdgeThresholdMin + // fxaaQualityEdgeThresholdMin + // In order to insure AA does not get turned off on colors + // which contain a minor amount of green. + // + // 1 = On. + // 0 = Off. + // + #define FXAA_GREEN_AS_LUMA 0 +#endif +/*--------------------------------------------------------------------------*/ +#ifndef FXAA_EARLY_EXIT + // + // Controls algorithm's early exit path. + // On PS3 turning this ON adds 2 cycles to the shader. + // On 360 turning this OFF adds 10ths of a millisecond to the shader. + // Turning this off on console will result in a more blurry image. + // So this defaults to on. + // + // 1 = On. + // 0 = Off. + // + #define FXAA_EARLY_EXIT 1 +#endif +/*--------------------------------------------------------------------------*/ +#ifndef FXAA_DISCARD + // + // Only valid for PC OpenGL currently. + // Probably will not work when FXAA_GREEN_AS_LUMA = 1. + // + // 1 = Use discard on pixels which don't need AA. + // For APIs which enable concurrent TEX+ROP from same surface. + // 0 = Return unchanged color on pixels which don't need AA. + // + #define FXAA_DISCARD 0 +#endif +/*--------------------------------------------------------------------------*/ +#ifndef FXAA_FAST_PIXEL_OFFSET + // + // Used for GLSL 120 only. + // + // 1 = GL API supports fast pixel offsets + // 0 = do not use fast pixel offsets + // + #ifdef GL_EXT_gpu_shader4 + #define FXAA_FAST_PIXEL_OFFSET 1 + #endif + #ifdef GL_NV_gpu_shader5 + #define FXAA_FAST_PIXEL_OFFSET 1 + #endif + #ifdef GL_ARB_gpu_shader5 + #define FXAA_FAST_PIXEL_OFFSET 1 + #endif + #ifndef FXAA_FAST_PIXEL_OFFSET + #define FXAA_FAST_PIXEL_OFFSET 0 + #endif +#endif +/*--------------------------------------------------------------------------*/ +#ifndef FXAA_GATHER4_ALPHA + // + // 1 = API supports gather4 on alpha channel. + // 0 = API does not support gather4 on alpha channel. + // + #if (FXAA_HLSL_5 == 1) + #define FXAA_GATHER4_ALPHA 1 + #endif + #ifdef GL_ARB_gpu_shader5 + #define FXAA_GATHER4_ALPHA 1 + #endif + #ifdef GL_NV_gpu_shader5 + #define FXAA_GATHER4_ALPHA 1 + #endif + #ifndef FXAA_GATHER4_ALPHA + #define FXAA_GATHER4_ALPHA 0 + #endif +#endif + +/*============================================================================ + FXAA CONSOLE PS3 - TUNING KNOBS +============================================================================*/ +#ifndef FXAA_CONSOLE__PS3_EDGE_SHARPNESS + // + // Consoles the sharpness of edges on PS3 only. + // Non-PS3 tuning is done with shader input. + // + // Due to the PS3 being ALU bound, + // there are only two safe values here: 4 and 8. + // These options use the shaders ability to a free *|/ by 2|4|8. + // + // 8.0 is sharper + // 4.0 is softer + // 2.0 is really soft (good for vector graphics inputs) + // + #if 1 + #define FXAA_CONSOLE__PS3_EDGE_SHARPNESS 8.0 + #endif + #if 0 + #define FXAA_CONSOLE__PS3_EDGE_SHARPNESS 4.0 + #endif + #if 0 + #define FXAA_CONSOLE__PS3_EDGE_SHARPNESS 2.0 + #endif +#endif +/*--------------------------------------------------------------------------*/ +#ifndef FXAA_CONSOLE__PS3_EDGE_THRESHOLD + // + // Only effects PS3. + // Non-PS3 tuning is done with shader input. + // + // The minimum amount of local contrast required to apply algorithm. + // The console setting has a different mapping than the quality setting. + // + // This only applies when FXAA_EARLY_EXIT is 1. + // + // Due to the PS3 being ALU bound, + // there are only two safe values here: 0.25 and 0.125. + // These options use the shaders ability to a free *|/ by 2|4|8. + // + // 0.125 leaves less aliasing, but is softer + // 0.25 leaves more aliasing, and is sharper + // + #if 1 + #define FXAA_CONSOLE__PS3_EDGE_THRESHOLD 0.125 + #else + #define FXAA_CONSOLE__PS3_EDGE_THRESHOLD 0.25 + #endif +#endif + +/*============================================================================ + FXAA QUALITY - TUNING KNOBS +------------------------------------------------------------------------------ +NOTE the other tuning knobs are now in the shader function inputs! +============================================================================*/ +#ifndef FXAA_QUALITY__PRESET + // + // Choose the quality preset. + // This needs to be compiled into the shader as it effects code. + // Best option to include multiple presets is to + // in each shader define the preset, then include this file. + // + // OPTIONS + // ----------------------------------------------------------------------- + // 10 to 15 - default medium dither (10=fastest, 15=highest quality) + // 20 to 29 - less dither, more expensive (20=fastest, 29=highest quality) + // 39 - no dither, very expensive + // + // NOTES + // ----------------------------------------------------------------------- + // 12 = slightly faster then FXAA 3.9 and higher edge quality (default) + // 13 = about same speed as FXAA 3.9 and better than 12 + // 23 = closest to FXAA 3.9 visually and performance wise + // _ = the lowest digit is directly related to performance + // _ = the highest digit is directly related to style + // + #define FXAA_QUALITY__PRESET 12 +#endif + + +/*============================================================================ + + FXAA QUALITY - PRESETS + +============================================================================*/ + +/*============================================================================ + FXAA QUALITY - MEDIUM DITHER PRESETS +============================================================================*/ +#if (FXAA_QUALITY__PRESET == 10) + #define FXAA_QUALITY__PS 3 + #define FXAA_QUALITY__P0 1.5 + #define FXAA_QUALITY__P1 3.0 + #define FXAA_QUALITY__P2 12.0 +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY__PRESET == 11) + #define FXAA_QUALITY__PS 4 + #define FXAA_QUALITY__P0 1.0 + #define FXAA_QUALITY__P1 1.5 + #define FXAA_QUALITY__P2 3.0 + #define FXAA_QUALITY__P3 12.0 +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY__PRESET == 12) + #define FXAA_QUALITY__PS 5 + #define FXAA_QUALITY__P0 1.0 + #define FXAA_QUALITY__P1 1.5 + #define FXAA_QUALITY__P2 2.0 + #define FXAA_QUALITY__P3 4.0 + #define FXAA_QUALITY__P4 12.0 +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY__PRESET == 13) + #define FXAA_QUALITY__PS 6 + #define FXAA_QUALITY__P0 1.0 + #define FXAA_QUALITY__P1 1.5 + #define FXAA_QUALITY__P2 2.0 + #define FXAA_QUALITY__P3 2.0 + #define FXAA_QUALITY__P4 4.0 + #define FXAA_QUALITY__P5 12.0 +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY__PRESET == 14) + #define FXAA_QUALITY__PS 7 + #define FXAA_QUALITY__P0 1.0 + #define FXAA_QUALITY__P1 1.5 + #define FXAA_QUALITY__P2 2.0 + #define FXAA_QUALITY__P3 2.0 + #define FXAA_QUALITY__P4 2.0 + #define FXAA_QUALITY__P5 4.0 + #define FXAA_QUALITY__P6 12.0 +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY__PRESET == 15) + #define FXAA_QUALITY__PS 8 + #define FXAA_QUALITY__P0 1.0 + #define FXAA_QUALITY__P1 1.5 + #define FXAA_QUALITY__P2 2.0 + #define FXAA_QUALITY__P3 2.0 + #define FXAA_QUALITY__P4 2.0 + #define FXAA_QUALITY__P5 2.0 + #define FXAA_QUALITY__P6 4.0 + #define FXAA_QUALITY__P7 12.0 +#endif + +/*============================================================================ + FXAA QUALITY - LOW DITHER PRESETS +============================================================================*/ +#if (FXAA_QUALITY__PRESET == 20) + #define FXAA_QUALITY__PS 3 + #define FXAA_QUALITY__P0 1.5 + #define FXAA_QUALITY__P1 2.0 + #define FXAA_QUALITY__P2 8.0 +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY__PRESET == 21) + #define FXAA_QUALITY__PS 4 + #define FXAA_QUALITY__P0 1.0 + #define FXAA_QUALITY__P1 1.5 + #define FXAA_QUALITY__P2 2.0 + #define FXAA_QUALITY__P3 8.0 +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY__PRESET == 22) + #define FXAA_QUALITY__PS 5 + #define FXAA_QUALITY__P0 1.0 + #define FXAA_QUALITY__P1 1.5 + #define FXAA_QUALITY__P2 2.0 + #define FXAA_QUALITY__P3 2.0 + #define FXAA_QUALITY__P4 8.0 +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY__PRESET == 23) + #define FXAA_QUALITY__PS 6 + #define FXAA_QUALITY__P0 1.0 + #define FXAA_QUALITY__P1 1.5 + #define FXAA_QUALITY__P2 2.0 + #define FXAA_QUALITY__P3 2.0 + #define FXAA_QUALITY__P4 2.0 + #define FXAA_QUALITY__P5 8.0 +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY__PRESET == 24) + #define FXAA_QUALITY__PS 7 + #define FXAA_QUALITY__P0 1.0 + #define FXAA_QUALITY__P1 1.5 + #define FXAA_QUALITY__P2 2.0 + #define FXAA_QUALITY__P3 2.0 + #define FXAA_QUALITY__P4 2.0 + #define FXAA_QUALITY__P5 3.0 + #define FXAA_QUALITY__P6 8.0 +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY__PRESET == 25) + #define FXAA_QUALITY__PS 8 + #define FXAA_QUALITY__P0 1.0 + #define FXAA_QUALITY__P1 1.5 + #define FXAA_QUALITY__P2 2.0 + #define FXAA_QUALITY__P3 2.0 + #define FXAA_QUALITY__P4 2.0 + #define FXAA_QUALITY__P5 2.0 + #define FXAA_QUALITY__P6 4.0 + #define FXAA_QUALITY__P7 8.0 +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY__PRESET == 26) + #define FXAA_QUALITY__PS 9 + #define FXAA_QUALITY__P0 1.0 + #define FXAA_QUALITY__P1 1.5 + #define FXAA_QUALITY__P2 2.0 + #define FXAA_QUALITY__P3 2.0 + #define FXAA_QUALITY__P4 2.0 + #define FXAA_QUALITY__P5 2.0 + #define FXAA_QUALITY__P6 2.0 + #define FXAA_QUALITY__P7 4.0 + #define FXAA_QUALITY__P8 8.0 +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY__PRESET == 27) + #define FXAA_QUALITY__PS 10 + #define FXAA_QUALITY__P0 1.0 + #define FXAA_QUALITY__P1 1.5 + #define FXAA_QUALITY__P2 2.0 + #define FXAA_QUALITY__P3 2.0 + #define FXAA_QUALITY__P4 2.0 + #define FXAA_QUALITY__P5 2.0 + #define FXAA_QUALITY__P6 2.0 + #define FXAA_QUALITY__P7 2.0 + #define FXAA_QUALITY__P8 4.0 + #define FXAA_QUALITY__P9 8.0 +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY__PRESET == 28) + #define FXAA_QUALITY__PS 11 + #define FXAA_QUALITY__P0 1.0 + #define FXAA_QUALITY__P1 1.5 + #define FXAA_QUALITY__P2 2.0 + #define FXAA_QUALITY__P3 2.0 + #define FXAA_QUALITY__P4 2.0 + #define FXAA_QUALITY__P5 2.0 + #define FXAA_QUALITY__P6 2.0 + #define FXAA_QUALITY__P7 2.0 + #define FXAA_QUALITY__P8 2.0 + #define FXAA_QUALITY__P9 4.0 + #define FXAA_QUALITY__P10 8.0 +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY__PRESET == 29) + #define FXAA_QUALITY__PS 12 + #define FXAA_QUALITY__P0 1.0 + #define FXAA_QUALITY__P1 1.5 + #define FXAA_QUALITY__P2 2.0 + #define FXAA_QUALITY__P3 2.0 + #define FXAA_QUALITY__P4 2.0 + #define FXAA_QUALITY__P5 2.0 + #define FXAA_QUALITY__P6 2.0 + #define FXAA_QUALITY__P7 2.0 + #define FXAA_QUALITY__P8 2.0 + #define FXAA_QUALITY__P9 2.0 + #define FXAA_QUALITY__P10 4.0 + #define FXAA_QUALITY__P11 8.0 +#endif + +/*============================================================================ + FXAA QUALITY - EXTREME QUALITY +============================================================================*/ +#if (FXAA_QUALITY__PRESET == 39) + #define FXAA_QUALITY__PS 12 + #define FXAA_QUALITY__P0 1.0 + #define FXAA_QUALITY__P1 1.0 + #define FXAA_QUALITY__P2 1.0 + #define FXAA_QUALITY__P3 1.0 + #define FXAA_QUALITY__P4 1.0 + #define FXAA_QUALITY__P5 1.5 + #define FXAA_QUALITY__P6 2.0 + #define FXAA_QUALITY__P7 2.0 + #define FXAA_QUALITY__P8 2.0 + #define FXAA_QUALITY__P9 2.0 + #define FXAA_QUALITY__P10 4.0 + #define FXAA_QUALITY__P11 8.0 +#endif + + + +/*============================================================================ + + API PORTING + +============================================================================*/ +#if (FXAA_GLSL_120 == 1) || (FXAA_GLSL_130 == 1) + #define FxaaBool bool + #define FxaaDiscard discard + #define FxaaFloat float + #define FxaaFloat2 vec2 + #define FxaaFloat3 vec3 + #define FxaaFloat4 vec4 + #define FxaaHalf float + #define FxaaHalf2 vec2 + #define FxaaHalf3 vec3 + #define FxaaHalf4 vec4 + #define FxaaInt2 ivec2 + #define FxaaSat(x) clamp(x, 0.0, 1.0) + #define FxaaTex sampler2D +#else + #define FxaaBool bool + #define FxaaDiscard clip(-1) + #define FxaaFloat float + #define FxaaFloat2 float2 + #define FxaaFloat3 float3 + #define FxaaFloat4 float4 + #define FxaaHalf half + #define FxaaHalf2 half2 + #define FxaaHalf3 half3 + #define FxaaHalf4 half4 + #define FxaaSat(x) saturate(x) +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_GLSL_120 == 1) + // Requires, + // #version 120 + // And at least, + // #extension GL_EXT_gpu_shader4 : enable + // (or set FXAA_FAST_PIXEL_OFFSET 1 to work like DX9) + #define FxaaTexTop(t, p) texture2DLod(t, p, 0.0) + #if (FXAA_FAST_PIXEL_OFFSET == 1) + #define FxaaTexOff(t, p, o, r) texture2DLodOffset(t, p, 0.0, o) + #else + #define FxaaTexOff(t, p, o, r) texture2DLod(t, p + (o * r), 0.0) + #endif + #if (FXAA_GATHER4_ALPHA == 1) + // use #extension GL_ARB_gpu_shader5 : enable + #define FxaaTexAlpha4(t, p) textureGather(t, p, 3) + #define FxaaTexOffAlpha4(t, p, o) textureGatherOffset(t, p, o, 3) + #define FxaaTexGreen4(t, p) textureGather(t, p, 1) + #define FxaaTexOffGreen4(t, p, o) textureGatherOffset(t, p, o, 1) + #endif +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_GLSL_130 == 1) + // Requires "#version 130" or better + #define FxaaTexTop(t, p) textureLod(t, p, 0.0) + #define FxaaTexOff(t, p, o, r) textureLodOffset(t, p, 0.0, o) + #if (FXAA_GATHER4_ALPHA == 1) + // use #extension GL_ARB_gpu_shader5 : enable + #define FxaaTexAlpha4(t, p) textureGather(t, p, 3) + #define FxaaTexOffAlpha4(t, p, o) textureGatherOffset(t, p, o, 3) + #define FxaaTexGreen4(t, p) textureGather(t, p, 1) + #define FxaaTexOffGreen4(t, p, o) textureGatherOffset(t, p, o, 1) + #endif +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_HLSL_3 == 1) || (FXAA_360 == 1) || (FXAA_PS3 == 1) + #define FxaaInt2 float2 + #define FxaaTex sampler2D + #define FxaaTexTop(t, p) tex2Dlod(t, float4(p, 0.0, 0.0)) + #define FxaaTexOff(t, p, o, r) tex2Dlod(t, float4(p + (o * r), 0, 0)) +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_HLSL_4 == 1) + #define FxaaInt2 int2 + struct FxaaTex { SamplerState smpl; Texture2D tex; }; + #define FxaaTexTop(t, p) t.tex.SampleLevel(t.smpl, p, 0.0) + #define FxaaTexOff(t, p, o, r) t.tex.SampleLevel(t.smpl, p, 0.0, o) +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_HLSL_5 == 1) + #define FxaaInt2 int2 + struct FxaaTex { SamplerState smpl; Texture2D tex; }; + #define FxaaTexTop(t, p) t.tex.SampleLevel(t.smpl, p, 0.0) + #define FxaaTexOff(t, p, o, r) t.tex.SampleLevel(t.smpl, p, 0.0, o) + #define FxaaTexAlpha4(t, p) t.tex.GatherAlpha(t.smpl, p) + #define FxaaTexOffAlpha4(t, p, o) t.tex.GatherAlpha(t.smpl, p, o) + #define FxaaTexGreen4(t, p) t.tex.GatherGreen(t.smpl, p) + #define FxaaTexOffGreen4(t, p, o) t.tex.GatherGreen(t.smpl, p, o) +#endif + + +/*============================================================================ + GREEN AS LUMA OPTION SUPPORT FUNCTION +============================================================================*/ +#if (FXAA_GREEN_AS_LUMA == 0) + FxaaFloat FxaaLuma(FxaaFloat4 rgba) { return rgba.w; } +#else + FxaaFloat FxaaLuma(FxaaFloat4 rgba) { return rgba.y; } +#endif + + + + +/*============================================================================ + + FXAA3 QUALITY - PC + +============================================================================*/ +#if (FXAA_PC == 1) +/*--------------------------------------------------------------------------*/ +FxaaFloat4 FxaaPixelShader( + // + // Use noperspective interpolation here (turn off perspective interpolation). + // {xy} = center of pixel + FxaaFloat2 pos, + // + // Used only for FXAA Console, and not used on the 360 version. + // Use noperspective interpolation here (turn off perspective interpolation). + // {xy__} = upper left of pixel + // {__zw} = lower right of pixel + FxaaFloat4 fxaaConsolePosPos, + // + // Input color texture. + // {rgb_} = color in linear or perceptual color space + // if (FXAA_GREEN_AS_LUMA == 0) + // {___a} = luma in perceptual color space (not linear) + FxaaTex tex, + // + // Only used on the optimized 360 version of FXAA Console. + // For everything but 360, just use the same input here as for "tex". + // For 360, same texture, just alias with a 2nd sampler. + // This sampler needs to have an exponent bias of -1. + FxaaTex fxaaConsole360TexExpBiasNegOne, + // + // Only used on the optimized 360 version of FXAA Console. + // For everything but 360, just use the same input here as for "tex". + // For 360, same texture, just alias with a 3nd sampler. + // This sampler needs to have an exponent bias of -2. + FxaaTex fxaaConsole360TexExpBiasNegTwo, + // + // Only used on FXAA Quality. + // This must be from a constant/uniform. + // {x_} = 1.0/screenWidthInPixels + // {_y} = 1.0/screenHeightInPixels + FxaaFloat2 fxaaQualityRcpFrame, + // + // Only used on FXAA Console. + // This must be from a constant/uniform. + // This effects sub-pixel AA quality and inversely sharpness. + // Where N ranges between, + // N = 0.50 (default) + // N = 0.33 (sharper) + // {x___} = -N/screenWidthInPixels + // {_y__} = -N/screenHeightInPixels + // {__z_} = N/screenWidthInPixels + // {___w} = N/screenHeightInPixels + FxaaFloat4 fxaaConsoleRcpFrameOpt, + // + // Only used on FXAA Console. + // Not used on 360, but used on PS3 and PC. + // This must be from a constant/uniform. + // {x___} = -2.0/screenWidthInPixels + // {_y__} = -2.0/screenHeightInPixels + // {__z_} = 2.0/screenWidthInPixels + // {___w} = 2.0/screenHeightInPixels + FxaaFloat4 fxaaConsoleRcpFrameOpt2, + // + // Only used on FXAA Console. + // Only used on 360 in place of fxaaConsoleRcpFrameOpt2. + // This must be from a constant/uniform. + // {x___} = 8.0/screenWidthInPixels + // {_y__} = 8.0/screenHeightInPixels + // {__z_} = -4.0/screenWidthInPixels + // {___w} = -4.0/screenHeightInPixels + FxaaFloat4 fxaaConsole360RcpFrameOpt2, + // + // Only used on FXAA Quality. + // This used to be the FXAA_QUALITY__SUBPIX define. + // It is here now to allow easier tuning. + // Choose the amount of sub-pixel aliasing removal. + // This can effect sharpness. + // 1.00 - upper limit (softer) + // 0.75 - default amount of filtering + // 0.50 - lower limit (sharper, less sub-pixel aliasing removal) + // 0.25 - almost off + // 0.00 - completely off + FxaaFloat fxaaQualitySubpix, + // + // Only used on FXAA Quality. + // This used to be the FXAA_QUALITY__EDGE_THRESHOLD define. + // It is here now to allow easier tuning. + // The minimum amount of local contrast required to apply algorithm. + // 0.333 - too little (faster) + // 0.250 - low quality + // 0.166 - default + // 0.125 - high quality + // 0.063 - overkill (slower) + FxaaFloat fxaaQualityEdgeThreshold, + // + // Only used on FXAA Quality. + // This used to be the FXAA_QUALITY__EDGE_THRESHOLD_MIN define. + // It is here now to allow easier tuning. + // Trims the algorithm from processing darks. + // 0.0833 - upper limit (default, the start of visible unfiltered edges) + // 0.0625 - high quality (faster) + // 0.0312 - visible limit (slower) + // Special notes when using FXAA_GREEN_AS_LUMA, + // Likely want to set this to zero. + // As colors that are mostly not-green + // will appear very dark in the green channel! + // Tune by looking at mostly non-green content, + // then start at zero and increase until aliasing is a problem. + FxaaFloat fxaaQualityEdgeThresholdMin, + // + // Only used on FXAA Console. + // This used to be the FXAA_CONSOLE__EDGE_SHARPNESS define. + // It is here now to allow easier tuning. + // This does not effect PS3, as this needs to be compiled in. + // Use FXAA_CONSOLE__PS3_EDGE_SHARPNESS for PS3. + // Due to the PS3 being ALU bound, + // there are only three safe values here: 2 and 4 and 8. + // These options use the shaders ability to a free *|/ by 2|4|8. + // For all other platforms can be a non-power of two. + // 8.0 is sharper (default!!!) + // 4.0 is softer + // 2.0 is really soft (good only for vector graphics inputs) + FxaaFloat fxaaConsoleEdgeSharpness, + // + // Only used on FXAA Console. + // This used to be the FXAA_CONSOLE__EDGE_THRESHOLD define. + // It is here now to allow easier tuning. + // This does not effect PS3, as this needs to be compiled in. + // Use FXAA_CONSOLE__PS3_EDGE_THRESHOLD for PS3. + // Due to the PS3 being ALU bound, + // there are only two safe values here: 1/4 and 1/8. + // These options use the shaders ability to a free *|/ by 2|4|8. + // The console setting has a different mapping than the quality setting. + // Other platforms can use other values. + // 0.125 leaves less aliasing, but is softer (default!!!) + // 0.25 leaves more aliasing, and is sharper + FxaaFloat fxaaConsoleEdgeThreshold, + // + // Only used on FXAA Console. + // This used to be the FXAA_CONSOLE__EDGE_THRESHOLD_MIN define. + // It is here now to allow easier tuning. + // Trims the algorithm from processing darks. + // The console setting has a different mapping than the quality setting. + // This only applies when FXAA_EARLY_EXIT is 1. + // This does not apply to PS3, + // PS3 was simplified to avoid more shader instructions. + // 0.06 - faster but more aliasing in darks + // 0.05 - default + // 0.04 - slower and less aliasing in darks + // Special notes when using FXAA_GREEN_AS_LUMA, + // Likely want to set this to zero. + // As colors that are mostly not-green + // will appear very dark in the green channel! + // Tune by looking at mostly non-green content, + // then start at zero and increase until aliasing is a problem. + FxaaFloat fxaaConsoleEdgeThresholdMin, + // + // Extra constants for 360 FXAA Console only. + // Use zeros or anything else for other platforms. + // These must be in physical constant registers and NOT immedates. + // Immedates will result in compiler un-optimizing. + // {xyzw} = float4(1.0, -1.0, 0.25, -0.25) + FxaaFloat4 fxaaConsole360ConstDir +) { +/*--------------------------------------------------------------------------*/ + FxaaFloat2 posM; + posM.x = pos.x; + posM.y = pos.y; + #if (FXAA_GATHER4_ALPHA == 1) + #if (FXAA_DISCARD == 0) + FxaaFloat4 rgbyM = FxaaTexTop(tex, posM); + #if (FXAA_GREEN_AS_LUMA == 0) + #define lumaM rgbyM.w + #else + #define lumaM rgbyM.y + #endif + #endif + #if (FXAA_GREEN_AS_LUMA == 0) + FxaaFloat4 luma4A = FxaaTexAlpha4(tex, posM); + FxaaFloat4 luma4B = FxaaTexOffAlpha4(tex, posM, FxaaInt2(-1, -1)); + #else + FxaaFloat4 luma4A = FxaaTexGreen4(tex, posM); + FxaaFloat4 luma4B = FxaaTexOffGreen4(tex, posM, FxaaInt2(-1, -1)); + #endif + #if (FXAA_DISCARD == 1) + #define lumaM luma4A.w + #endif + #define lumaE luma4A.z + #define lumaS luma4A.x + #define lumaSE luma4A.y + #define lumaNW luma4B.w + #define lumaN luma4B.z + #define lumaW luma4B.x + #else + FxaaFloat4 rgbyM = FxaaTexTop(tex, posM); + #if (FXAA_GREEN_AS_LUMA == 0) + #define lumaM rgbyM.w + #else + #define lumaM rgbyM.y + #endif + FxaaFloat lumaS = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2( 0, 1), fxaaQualityRcpFrame.xy)); + FxaaFloat lumaE = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2( 1, 0), fxaaQualityRcpFrame.xy)); + FxaaFloat lumaN = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2( 0,-1), fxaaQualityRcpFrame.xy)); + FxaaFloat lumaW = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2(-1, 0), fxaaQualityRcpFrame.xy)); + #endif +/*--------------------------------------------------------------------------*/ + FxaaFloat maxSM = max(lumaS, lumaM); + FxaaFloat minSM = min(lumaS, lumaM); + FxaaFloat maxESM = max(lumaE, maxSM); + FxaaFloat minESM = min(lumaE, minSM); + FxaaFloat maxWN = max(lumaN, lumaW); + FxaaFloat minWN = min(lumaN, lumaW); + FxaaFloat rangeMax = max(maxWN, maxESM); + FxaaFloat rangeMin = min(minWN, minESM); + FxaaFloat rangeMaxScaled = rangeMax * fxaaQualityEdgeThreshold; + FxaaFloat range = rangeMax - rangeMin; + FxaaFloat rangeMaxClamped = max(fxaaQualityEdgeThresholdMin, rangeMaxScaled); + FxaaBool earlyExit = range < rangeMaxClamped; +/*--------------------------------------------------------------------------*/ + if(earlyExit) + #if (FXAA_DISCARD == 1) + FxaaDiscard; + #else + return rgbyM; + #endif +/*--------------------------------------------------------------------------*/ + #if (FXAA_GATHER4_ALPHA == 0) + FxaaFloat lumaNW = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2(-1,-1), fxaaQualityRcpFrame.xy)); + FxaaFloat lumaSE = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2( 1, 1), fxaaQualityRcpFrame.xy)); + FxaaFloat lumaNE = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2( 1,-1), fxaaQualityRcpFrame.xy)); + FxaaFloat lumaSW = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2(-1, 1), fxaaQualityRcpFrame.xy)); + #else + FxaaFloat lumaNE = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2(1, -1), fxaaQualityRcpFrame.xy)); + FxaaFloat lumaSW = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2(-1, 1), fxaaQualityRcpFrame.xy)); + #endif +/*--------------------------------------------------------------------------*/ + FxaaFloat lumaNS = lumaN + lumaS; + FxaaFloat lumaWE = lumaW + lumaE; + FxaaFloat subpixRcpRange = 1.0/range; + FxaaFloat subpixNSWE = lumaNS + lumaWE; + FxaaFloat edgeHorz1 = (-2.0 * lumaM) + lumaNS; + FxaaFloat edgeVert1 = (-2.0 * lumaM) + lumaWE; +/*--------------------------------------------------------------------------*/ + FxaaFloat lumaNESE = lumaNE + lumaSE; + FxaaFloat lumaNWNE = lumaNW + lumaNE; + FxaaFloat edgeHorz2 = (-2.0 * lumaE) + lumaNESE; + FxaaFloat edgeVert2 = (-2.0 * lumaN) + lumaNWNE; +/*--------------------------------------------------------------------------*/ + FxaaFloat lumaNWSW = lumaNW + lumaSW; + FxaaFloat lumaSWSE = lumaSW + lumaSE; + FxaaFloat edgeHorz4 = (abs(edgeHorz1) * 2.0) + abs(edgeHorz2); + FxaaFloat edgeVert4 = (abs(edgeVert1) * 2.0) + abs(edgeVert2); + FxaaFloat edgeHorz3 = (-2.0 * lumaW) + lumaNWSW; + FxaaFloat edgeVert3 = (-2.0 * lumaS) + lumaSWSE; + FxaaFloat edgeHorz = abs(edgeHorz3) + edgeHorz4; + FxaaFloat edgeVert = abs(edgeVert3) + edgeVert4; +/*--------------------------------------------------------------------------*/ + FxaaFloat subpixNWSWNESE = lumaNWSW + lumaNESE; + FxaaFloat lengthSign = fxaaQualityRcpFrame.x; + FxaaBool horzSpan = edgeHorz >= edgeVert; + FxaaFloat subpixA = subpixNSWE * 2.0 + subpixNWSWNESE; +/*--------------------------------------------------------------------------*/ + if(!horzSpan) lumaN = lumaW; + if(!horzSpan) lumaS = lumaE; + if(horzSpan) lengthSign = fxaaQualityRcpFrame.y; + FxaaFloat subpixB = (subpixA * (1.0/12.0)) - lumaM; +/*--------------------------------------------------------------------------*/ + FxaaFloat gradientN = lumaN - lumaM; + FxaaFloat gradientS = lumaS - lumaM; + FxaaFloat lumaNN = lumaN + lumaM; + FxaaFloat lumaSS = lumaS + lumaM; + FxaaBool pairN = abs(gradientN) >= abs(gradientS); + FxaaFloat gradient = max(abs(gradientN), abs(gradientS)); + if(pairN) lengthSign = -lengthSign; + FxaaFloat subpixC = FxaaSat(abs(subpixB) * subpixRcpRange); +/*--------------------------------------------------------------------------*/ + FxaaFloat2 posB; + posB.x = posM.x; + posB.y = posM.y; + FxaaFloat2 offNP; + offNP.x = (!horzSpan) ? 0.0 : fxaaQualityRcpFrame.x; + offNP.y = ( horzSpan) ? 0.0 : fxaaQualityRcpFrame.y; + if(!horzSpan) posB.x += lengthSign * 0.5; + if( horzSpan) posB.y += lengthSign * 0.5; +/*--------------------------------------------------------------------------*/ + FxaaFloat2 posN; + posN.x = posB.x - offNP.x * FXAA_QUALITY__P0; + posN.y = posB.y - offNP.y * FXAA_QUALITY__P0; + FxaaFloat2 posP; + posP.x = posB.x + offNP.x * FXAA_QUALITY__P0; + posP.y = posB.y + offNP.y * FXAA_QUALITY__P0; + FxaaFloat subpixD = ((-2.0)*subpixC) + 3.0; + FxaaFloat lumaEndN = FxaaLuma(FxaaTexTop(tex, posN)); + FxaaFloat subpixE = subpixC * subpixC; + FxaaFloat lumaEndP = FxaaLuma(FxaaTexTop(tex, posP)); +/*--------------------------------------------------------------------------*/ + if(!pairN) lumaNN = lumaSS; + FxaaFloat gradientScaled = gradient * 1.0/4.0; + FxaaFloat lumaMM = lumaM - lumaNN * 0.5; + FxaaFloat subpixF = subpixD * subpixE; + FxaaBool lumaMLTZero = lumaMM < 0.0; +/*--------------------------------------------------------------------------*/ + lumaEndN -= lumaNN * 0.5; + lumaEndP -= lumaNN * 0.5; + FxaaBool doneN = abs(lumaEndN) >= gradientScaled; + FxaaBool doneP = abs(lumaEndP) >= gradientScaled; + if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P1; + if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P1; + FxaaBool doneNP = (!doneN) || (!doneP); + if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P1; + if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P1; +/*--------------------------------------------------------------------------*/ + if(doneNP) { + if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); + if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); + if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; + if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; + doneN = abs(lumaEndN) >= gradientScaled; + doneP = abs(lumaEndP) >= gradientScaled; + if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P2; + if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P2; + doneNP = (!doneN) || (!doneP); + if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P2; + if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P2; +/*--------------------------------------------------------------------------*/ + #if (FXAA_QUALITY__PS > 3) + if(doneNP) { + if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); + if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); + if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; + if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; + doneN = abs(lumaEndN) >= gradientScaled; + doneP = abs(lumaEndP) >= gradientScaled; + if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P3; + if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P3; + doneNP = (!doneN) || (!doneP); + if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P3; + if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P3; +/*--------------------------------------------------------------------------*/ + #if (FXAA_QUALITY__PS > 4) + if(doneNP) { + if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); + if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); + if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; + if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; + doneN = abs(lumaEndN) >= gradientScaled; + doneP = abs(lumaEndP) >= gradientScaled; + if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P4; + if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P4; + doneNP = (!doneN) || (!doneP); + if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P4; + if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P4; +/*--------------------------------------------------------------------------*/ + #if (FXAA_QUALITY__PS > 5) + if(doneNP) { + if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); + if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); + if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; + if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; + doneN = abs(lumaEndN) >= gradientScaled; + doneP = abs(lumaEndP) >= gradientScaled; + if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P5; + if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P5; + doneNP = (!doneN) || (!doneP); + if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P5; + if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P5; +/*--------------------------------------------------------------------------*/ + #if (FXAA_QUALITY__PS > 6) + if(doneNP) { + if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); + if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); + if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; + if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; + doneN = abs(lumaEndN) >= gradientScaled; + doneP = abs(lumaEndP) >= gradientScaled; + if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P6; + if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P6; + doneNP = (!doneN) || (!doneP); + if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P6; + if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P6; +/*--------------------------------------------------------------------------*/ + #if (FXAA_QUALITY__PS > 7) + if(doneNP) { + if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); + if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); + if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; + if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; + doneN = abs(lumaEndN) >= gradientScaled; + doneP = abs(lumaEndP) >= gradientScaled; + if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P7; + if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P7; + doneNP = (!doneN) || (!doneP); + if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P7; + if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P7; +/*--------------------------------------------------------------------------*/ + #if (FXAA_QUALITY__PS > 8) + if(doneNP) { + if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); + if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); + if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; + if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; + doneN = abs(lumaEndN) >= gradientScaled; + doneP = abs(lumaEndP) >= gradientScaled; + if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P8; + if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P8; + doneNP = (!doneN) || (!doneP); + if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P8; + if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P8; +/*--------------------------------------------------------------------------*/ + #if (FXAA_QUALITY__PS > 9) + if(doneNP) { + if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); + if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); + if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; + if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; + doneN = abs(lumaEndN) >= gradientScaled; + doneP = abs(lumaEndP) >= gradientScaled; + if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P9; + if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P9; + doneNP = (!doneN) || (!doneP); + if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P9; + if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P9; +/*--------------------------------------------------------------------------*/ + #if (FXAA_QUALITY__PS > 10) + if(doneNP) { + if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); + if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); + if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; + if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; + doneN = abs(lumaEndN) >= gradientScaled; + doneP = abs(lumaEndP) >= gradientScaled; + if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P10; + if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P10; + doneNP = (!doneN) || (!doneP); + if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P10; + if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P10; +/*--------------------------------------------------------------------------*/ + #if (FXAA_QUALITY__PS > 11) + if(doneNP) { + if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); + if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); + if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; + if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; + doneN = abs(lumaEndN) >= gradientScaled; + doneP = abs(lumaEndP) >= gradientScaled; + if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P11; + if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P11; + doneNP = (!doneN) || (!doneP); + if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P11; + if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P11; +/*--------------------------------------------------------------------------*/ + #if (FXAA_QUALITY__PS > 12) + if(doneNP) { + if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); + if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); + if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; + if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; + doneN = abs(lumaEndN) >= gradientScaled; + doneP = abs(lumaEndP) >= gradientScaled; + if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P12; + if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P12; + doneNP = (!doneN) || (!doneP); + if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P12; + if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P12; +/*--------------------------------------------------------------------------*/ + } + #endif +/*--------------------------------------------------------------------------*/ + } + #endif +/*--------------------------------------------------------------------------*/ + } + #endif +/*--------------------------------------------------------------------------*/ + } + #endif +/*--------------------------------------------------------------------------*/ + } + #endif +/*--------------------------------------------------------------------------*/ + } + #endif +/*--------------------------------------------------------------------------*/ + } + #endif +/*--------------------------------------------------------------------------*/ + } + #endif +/*--------------------------------------------------------------------------*/ + } + #endif +/*--------------------------------------------------------------------------*/ + } + #endif +/*--------------------------------------------------------------------------*/ + } +/*--------------------------------------------------------------------------*/ + FxaaFloat dstN = posM.x - posN.x; + FxaaFloat dstP = posP.x - posM.x; + if(!horzSpan) dstN = posM.y - posN.y; + if(!horzSpan) dstP = posP.y - posM.y; +/*--------------------------------------------------------------------------*/ + FxaaBool goodSpanN = (lumaEndN < 0.0) != lumaMLTZero; + FxaaFloat spanLength = (dstP + dstN); + FxaaBool goodSpanP = (lumaEndP < 0.0) != lumaMLTZero; + FxaaFloat spanLengthRcp = 1.0/spanLength; +/*--------------------------------------------------------------------------*/ + FxaaBool directionN = dstN < dstP; + FxaaFloat dst = min(dstN, dstP); + FxaaBool goodSpan = directionN ? goodSpanN : goodSpanP; + FxaaFloat subpixG = subpixF * subpixF; + FxaaFloat pixelOffset = (dst * (-spanLengthRcp)) + 0.5; + FxaaFloat subpixH = subpixG * fxaaQualitySubpix; +/*--------------------------------------------------------------------------*/ + FxaaFloat pixelOffsetGood = goodSpan ? pixelOffset : 0.0; + FxaaFloat pixelOffsetSubpix = max(pixelOffsetGood, subpixH); + if(!horzSpan) posM.x += pixelOffsetSubpix * lengthSign; + if( horzSpan) posM.y += pixelOffsetSubpix * lengthSign; + #if (FXAA_DISCARD == 1) + return FxaaTexTop(tex, posM); + #else + return FxaaFloat4(FxaaTexTop(tex, posM).xyz, lumaM); + #endif +} +/*==========================================================================*/ +#endif + + + + +/*============================================================================ + + FXAA3 CONSOLE - PC VERSION + +------------------------------------------------------------------------------ +Instead of using this on PC, I'd suggest just using FXAA Quality with + #define FXAA_QUALITY__PRESET 10 +Or + #define FXAA_QUALITY__PRESET 20 +Either are higher qualilty and almost as fast as this on modern PC GPUs. +============================================================================*/ +#if (FXAA_PC_CONSOLE == 1) +/*--------------------------------------------------------------------------*/ +FxaaFloat4 FxaaPixelShader( + // See FXAA Quality FxaaPixelShader() source for docs on Inputs! + FxaaFloat2 pos, + FxaaFloat4 fxaaConsolePosPos, + FxaaTex tex, + FxaaTex fxaaConsole360TexExpBiasNegOne, + FxaaTex fxaaConsole360TexExpBiasNegTwo, + FxaaFloat2 fxaaQualityRcpFrame, + FxaaFloat4 fxaaConsoleRcpFrameOpt, + FxaaFloat4 fxaaConsoleRcpFrameOpt2, + FxaaFloat4 fxaaConsole360RcpFrameOpt2, + FxaaFloat fxaaQualitySubpix, + FxaaFloat fxaaQualityEdgeThreshold, + FxaaFloat fxaaQualityEdgeThresholdMin, + FxaaFloat fxaaConsoleEdgeSharpness, + FxaaFloat fxaaConsoleEdgeThreshold, + FxaaFloat fxaaConsoleEdgeThresholdMin, + FxaaFloat4 fxaaConsole360ConstDir +) { +/*--------------------------------------------------------------------------*/ + FxaaFloat lumaNw = FxaaLuma(FxaaTexTop(tex, fxaaConsolePosPos.xy)); + FxaaFloat lumaSw = FxaaLuma(FxaaTexTop(tex, fxaaConsolePosPos.xw)); + FxaaFloat lumaNe = FxaaLuma(FxaaTexTop(tex, fxaaConsolePosPos.zy)); + FxaaFloat lumaSe = FxaaLuma(FxaaTexTop(tex, fxaaConsolePosPos.zw)); +/*--------------------------------------------------------------------------*/ + FxaaFloat4 rgbyM = FxaaTexTop(tex, pos.xy); + #if (FXAA_GREEN_AS_LUMA == 0) + FxaaFloat lumaM = rgbyM.w; + #else + FxaaFloat lumaM = rgbyM.y; + #endif +/*--------------------------------------------------------------------------*/ + FxaaFloat lumaMaxNwSw = max(lumaNw, lumaSw); + lumaNe += 1.0/384.0; + FxaaFloat lumaMinNwSw = min(lumaNw, lumaSw); +/*--------------------------------------------------------------------------*/ + FxaaFloat lumaMaxNeSe = max(lumaNe, lumaSe); + FxaaFloat lumaMinNeSe = min(lumaNe, lumaSe); +/*--------------------------------------------------------------------------*/ + FxaaFloat lumaMax = max(lumaMaxNeSe, lumaMaxNwSw); + FxaaFloat lumaMin = min(lumaMinNeSe, lumaMinNwSw); +/*--------------------------------------------------------------------------*/ + FxaaFloat lumaMaxScaled = lumaMax * fxaaConsoleEdgeThreshold; +/*--------------------------------------------------------------------------*/ + FxaaFloat lumaMinM = min(lumaMin, lumaM); + FxaaFloat lumaMaxScaledClamped = max(fxaaConsoleEdgeThresholdMin, lumaMaxScaled); + FxaaFloat lumaMaxM = max(lumaMax, lumaM); + FxaaFloat dirSwMinusNe = lumaSw - lumaNe; + FxaaFloat lumaMaxSubMinM = lumaMaxM - lumaMinM; + FxaaFloat dirSeMinusNw = lumaSe - lumaNw; + if(lumaMaxSubMinM < lumaMaxScaledClamped) return rgbyM; +/*--------------------------------------------------------------------------*/ + FxaaFloat2 dir; + dir.x = dirSwMinusNe + dirSeMinusNw; + dir.y = dirSwMinusNe - dirSeMinusNw; +/*--------------------------------------------------------------------------*/ + FxaaFloat2 dir1 = normalize(dir.xy); + FxaaFloat4 rgbyN1 = FxaaTexTop(tex, pos.xy - dir1 * fxaaConsoleRcpFrameOpt.zw); + FxaaFloat4 rgbyP1 = FxaaTexTop(tex, pos.xy + dir1 * fxaaConsoleRcpFrameOpt.zw); +/*--------------------------------------------------------------------------*/ + FxaaFloat dirAbsMinTimesC = min(abs(dir1.x), abs(dir1.y)) * fxaaConsoleEdgeSharpness; + FxaaFloat2 dir2 = clamp(dir1.xy / dirAbsMinTimesC, -2.0, 2.0); +/*--------------------------------------------------------------------------*/ + FxaaFloat4 rgbyN2 = FxaaTexTop(tex, pos.xy - dir2 * fxaaConsoleRcpFrameOpt2.zw); + FxaaFloat4 rgbyP2 = FxaaTexTop(tex, pos.xy + dir2 * fxaaConsoleRcpFrameOpt2.zw); +/*--------------------------------------------------------------------------*/ + FxaaFloat4 rgbyA = rgbyN1 + rgbyP1; + FxaaFloat4 rgbyB = ((rgbyN2 + rgbyP2) * 0.25) + (rgbyA * 0.25); +/*--------------------------------------------------------------------------*/ + #if (FXAA_GREEN_AS_LUMA == 0) + FxaaBool twoTap = (rgbyB.w < lumaMin) || (rgbyB.w > lumaMax); + #else + FxaaBool twoTap = (rgbyB.y < lumaMin) || (rgbyB.y > lumaMax); + #endif + if(twoTap) rgbyB.xyz = rgbyA.xyz * 0.5; + return rgbyB; } +/*==========================================================================*/ +#endif + + + +/*============================================================================ + + FXAA3 CONSOLE - 360 PIXEL SHADER + +------------------------------------------------------------------------------ +This optimized version thanks to suggestions from Andy Luedke. +Should be fully tex bound in all cases. +As of the FXAA 3.11 release, I have still not tested this code, +however I fixed a bug which was in both FXAA 3.9 and FXAA 3.10. +And note this is replacing the old unoptimized version. +If it does not work, please let me know so I can fix it. +============================================================================*/ +#if (FXAA_360 == 1) +/*--------------------------------------------------------------------------*/ +[reduceTempRegUsage(4)] +float4 FxaaPixelShader( + // See FXAA Quality FxaaPixelShader() source for docs on Inputs! + FxaaFloat2 pos, + FxaaFloat4 fxaaConsolePosPos, + FxaaTex tex, + FxaaTex fxaaConsole360TexExpBiasNegOne, + FxaaTex fxaaConsole360TexExpBiasNegTwo, + FxaaFloat2 fxaaQualityRcpFrame, + FxaaFloat4 fxaaConsoleRcpFrameOpt, + FxaaFloat4 fxaaConsoleRcpFrameOpt2, + FxaaFloat4 fxaaConsole360RcpFrameOpt2, + FxaaFloat fxaaQualitySubpix, + FxaaFloat fxaaQualityEdgeThreshold, + FxaaFloat fxaaQualityEdgeThresholdMin, + FxaaFloat fxaaConsoleEdgeSharpness, + FxaaFloat fxaaConsoleEdgeThreshold, + FxaaFloat fxaaConsoleEdgeThresholdMin, + FxaaFloat4 fxaaConsole360ConstDir +) { +/*--------------------------------------------------------------------------*/ + float4 lumaNwNeSwSe; + #if (FXAA_GREEN_AS_LUMA == 0) + asm { + tfetch2D lumaNwNeSwSe.w___, tex, pos.xy, OffsetX = -0.5, OffsetY = -0.5, UseComputedLOD=false + tfetch2D lumaNwNeSwSe._w__, tex, pos.xy, OffsetX = 0.5, OffsetY = -0.5, UseComputedLOD=false + tfetch2D lumaNwNeSwSe.__w_, tex, pos.xy, OffsetX = -0.5, OffsetY = 0.5, UseComputedLOD=false + tfetch2D lumaNwNeSwSe.___w, tex, pos.xy, OffsetX = 0.5, OffsetY = 0.5, UseComputedLOD=false + }; + #else + asm { + tfetch2D lumaNwNeSwSe.y___, tex, pos.xy, OffsetX = -0.5, OffsetY = -0.5, UseComputedLOD=false + tfetch2D lumaNwNeSwSe._y__, tex, pos.xy, OffsetX = 0.5, OffsetY = -0.5, UseComputedLOD=false + tfetch2D lumaNwNeSwSe.__y_, tex, pos.xy, OffsetX = -0.5, OffsetY = 0.5, UseComputedLOD=false + tfetch2D lumaNwNeSwSe.___y, tex, pos.xy, OffsetX = 0.5, OffsetY = 0.5, UseComputedLOD=false + }; + #endif +/*--------------------------------------------------------------------------*/ + lumaNwNeSwSe.y += 1.0/384.0; + float2 lumaMinTemp = min(lumaNwNeSwSe.xy, lumaNwNeSwSe.zw); + float2 lumaMaxTemp = max(lumaNwNeSwSe.xy, lumaNwNeSwSe.zw); + float lumaMin = min(lumaMinTemp.x, lumaMinTemp.y); + float lumaMax = max(lumaMaxTemp.x, lumaMaxTemp.y); +/*--------------------------------------------------------------------------*/ + float4 rgbyM = tex2Dlod(tex, float4(pos.xy, 0.0, 0.0)); + #if (FXAA_GREEN_AS_LUMA == 0) + float lumaMinM = min(lumaMin, rgbyM.w); + float lumaMaxM = max(lumaMax, rgbyM.w); + #else + float lumaMinM = min(lumaMin, rgbyM.y); + float lumaMaxM = max(lumaMax, rgbyM.y); + #endif + if((lumaMaxM - lumaMinM) < max(fxaaConsoleEdgeThresholdMin, lumaMax * fxaaConsoleEdgeThreshold)) return rgbyM; +/*--------------------------------------------------------------------------*/ + float2 dir; + dir.x = dot(lumaNwNeSwSe, fxaaConsole360ConstDir.yyxx); + dir.y = dot(lumaNwNeSwSe, fxaaConsole360ConstDir.xyxy); + dir = normalize(dir); +/*--------------------------------------------------------------------------*/ + float4 dir1 = dir.xyxy * fxaaConsoleRcpFrameOpt.xyzw; +/*--------------------------------------------------------------------------*/ + float4 dir2; + float dirAbsMinTimesC = min(abs(dir.x), abs(dir.y)) * fxaaConsoleEdgeSharpness; + dir2 = saturate(fxaaConsole360ConstDir.zzww * dir.xyxy / dirAbsMinTimesC + 0.5); + dir2 = dir2 * fxaaConsole360RcpFrameOpt2.xyxy + fxaaConsole360RcpFrameOpt2.zwzw; +/*--------------------------------------------------------------------------*/ + float4 rgbyN1 = tex2Dlod(fxaaConsole360TexExpBiasNegOne, float4(pos.xy + dir1.xy, 0.0, 0.0)); + float4 rgbyP1 = tex2Dlod(fxaaConsole360TexExpBiasNegOne, float4(pos.xy + dir1.zw, 0.0, 0.0)); + float4 rgbyN2 = tex2Dlod(fxaaConsole360TexExpBiasNegTwo, float4(pos.xy + dir2.xy, 0.0, 0.0)); + float4 rgbyP2 = tex2Dlod(fxaaConsole360TexExpBiasNegTwo, float4(pos.xy + dir2.zw, 0.0, 0.0)); +/*--------------------------------------------------------------------------*/ + float4 rgbyA = rgbyN1 + rgbyP1; + float4 rgbyB = rgbyN2 + rgbyP2 + rgbyA * 0.5; +/*--------------------------------------------------------------------------*/ + float4 rgbyR = ((FxaaLuma(rgbyB) - lumaMax) > 0.0) ? rgbyA : rgbyB; + rgbyR = ((FxaaLuma(rgbyB) - lumaMin) > 0.0) ? rgbyR : rgbyA; + return rgbyR; } +/*==========================================================================*/ +#endif + + + +/*============================================================================ + + FXAA3 CONSOLE - OPTIMIZED PS3 PIXEL SHADER (NO EARLY EXIT) + +============================================================================== +The code below does not exactly match the assembly. +I have a feeling that 12 cycles is possible, but was not able to get there. +Might have to increase register count to get full performance. +Note this shader does not use perspective interpolation. + +Use the following cgc options, + + --fenable-bx2 --fastmath --fastprecision --nofloatbindings + +------------------------------------------------------------------------------ + NVSHADERPERF OUTPUT +------------------------------------------------------------------------------ +For reference and to aid in debug, output of NVShaderPerf should match this, + +Shader to schedule: + 0: texpkb h0.w(TRUE), v5.zyxx, #0 + 2: addh h2.z(TRUE), h0.w, constant(0.001953, 0.000000, 0.000000, 0.000000).x + 4: texpkb h0.w(TRUE), v5.xwxx, #0 + 6: addh h0.z(TRUE), -h2, h0.w + 7: texpkb h1.w(TRUE), v5, #0 + 9: addh h0.x(TRUE), h0.z, -h1.w + 10: addh h3.w(TRUE), h0.z, h1 + 11: texpkb h2.w(TRUE), v5.zwzz, #0 + 13: addh h0.z(TRUE), h3.w, -h2.w + 14: addh h0.x(TRUE), h2.w, h0 + 15: nrmh h1.xz(TRUE), h0_n + 16: minh_m8 h0.x(TRUE), |h1|, |h1.z| + 17: maxh h4.w(TRUE), h0, h1 + 18: divx h2.xy(TRUE), h1_n.xzzw, h0_n + 19: movr r1.zw(TRUE), v4.xxxy + 20: madr r2.xz(TRUE), -h1, constant(cConst5.x, cConst5.y, cConst5.z, cConst5.w).zzww, r1.zzww + 22: minh h5.w(TRUE), h0, h1 + 23: texpkb h0(TRUE), r2.xzxx, #0 + 25: madr r0.zw(TRUE), h1.xzxz, constant(cConst5.x, cConst5.y, cConst5.z, cConst5.w), r1 + 27: maxh h4.x(TRUE), h2.z, h2.w + 28: texpkb h1(TRUE), r0.zwzz, #0 + 30: addh_d2 h1(TRUE), h0, h1 + 31: madr r0.xy(TRUE), -h2, constant(cConst5.x, cConst5.y, cConst5.z, cConst5.w).xyxx, r1.zwzz + 33: texpkb h0(TRUE), r0, #0 + 35: minh h4.z(TRUE), h2, h2.w + 36: fenct TRUE + 37: madr r1.xy(TRUE), h2, constant(cConst5.x, cConst5.y, cConst5.z, cConst5.w).xyxx, r1.zwzz + 39: texpkb h2(TRUE), r1, #0 + 41: addh_d2 h0(TRUE), h0, h2 + 42: maxh h2.w(TRUE), h4, h4.x + 43: minh h2.x(TRUE), h5.w, h4.z + 44: addh_d2 h0(TRUE), h0, h1 + 45: slth h2.x(TRUE), h0.w, h2 + 46: sgth h2.w(TRUE), h0, h2 + 47: movh h0(TRUE), h0 + 48: addx.c0 rc(TRUE), h2, h2.w + 49: movh h0(c0.NE.x), h1 + +IPU0 ------ Simplified schedule: -------- +Pass | Unit | uOp | PC: Op +-----+--------+------+------------------------- + 1 | SCT0/1 | mov | 0: TXLr h0.w, g[TEX1].zyxx, const.xxxx, TEX0; + | TEX | txl | 0: TXLr h0.w, g[TEX1].zyxx, const.xxxx, TEX0; + | SCB1 | add | 2: ADDh h2.z, h0.--w-, const.--x-; + | | | + 2 | SCT0/1 | mov | 4: TXLr h0.w, g[TEX1].xwxx, const.xxxx, TEX0; + | TEX | txl | 4: TXLr h0.w, g[TEX1].xwxx, const.xxxx, TEX0; + | SCB1 | add | 6: ADDh h0.z,-h2, h0.--w-; + | | | + 3 | SCT0/1 | mov | 7: TXLr h1.w, g[TEX1], const.xxxx, TEX0; + | TEX | txl | 7: TXLr h1.w, g[TEX1], const.xxxx, TEX0; + | SCB0 | add | 9: ADDh h0.x, h0.z---,-h1.w---; + | SCB1 | add | 10: ADDh h3.w, h0.---z, h1; + | | | + 4 | SCT0/1 | mov | 11: TXLr h2.w, g[TEX1].zwzz, const.xxxx, TEX0; + | TEX | txl | 11: TXLr h2.w, g[TEX1].zwzz, const.xxxx, TEX0; + | SCB0 | add | 14: ADDh h0.x, h2.w---, h0; + | SCB1 | add | 13: ADDh h0.z, h3.--w-,-h2.--w-; + | | | + 5 | SCT1 | mov | 15: NRMh h1.xz, h0; + | SRB | nrm | 15: NRMh h1.xz, h0; + | SCB0 | min | 16: MINh*8 h0.x, |h1|, |h1.z---|; + | SCB1 | max | 17: MAXh h4.w, h0, h1; + | | | + 6 | SCT0 | div | 18: DIVx h2.xy, h1.xz--, h0; + | SCT1 | mov | 19: MOVr r1.zw, g[TEX0].--xy; + | SCB0 | mad | 20: MADr r2.xz,-h1, const.z-w-, r1.z-w-; + | SCB1 | min | 22: MINh h5.w, h0, h1; + | | | + 7 | SCT0/1 | mov | 23: TXLr h0, r2.xzxx, const.xxxx, TEX0; + | TEX | txl | 23: TXLr h0, r2.xzxx, const.xxxx, TEX0; + | SCB0 | max | 27: MAXh h4.x, h2.z---, h2.w---; + | SCB1 | mad | 25: MADr r0.zw, h1.--xz, const, r1; + | | | + 8 | SCT0/1 | mov | 28: TXLr h1, r0.zwzz, const.xxxx, TEX0; + | TEX | txl | 28: TXLr h1, r0.zwzz, const.xxxx, TEX0; + | SCB0/1 | add | 30: ADDh/2 h1, h0, h1; + | | | + 9 | SCT0 | mad | 31: MADr r0.xy,-h2, const.xy--, r1.zw--; + | SCT1 | mov | 33: TXLr h0, r0, const.zzzz, TEX0; + | TEX | txl | 33: TXLr h0, r0, const.zzzz, TEX0; + | SCB1 | min | 35: MINh h4.z, h2, h2.--w-; + | | | + 10 | SCT0 | mad | 37: MADr r1.xy, h2, const.xy--, r1.zw--; + | SCT1 | mov | 39: TXLr h2, r1, const.zzzz, TEX0; + | TEX | txl | 39: TXLr h2, r1, const.zzzz, TEX0; + | SCB0/1 | add | 41: ADDh/2 h0, h0, h2; + | | | + 11 | SCT0 | min | 43: MINh h2.x, h5.w---, h4.z---; + | SCT1 | max | 42: MAXh h2.w, h4, h4.---x; + | SCB0/1 | add | 44: ADDh/2 h0, h0, h1; + | | | + 12 | SCT0 | set | 45: SLTh h2.x, h0.w---, h2; + | SCT1 | set | 46: SGTh h2.w, h0, h2; + | SCB0/1 | mul | 47: MOVh h0, h0; + | | | + 13 | SCT0 | mad | 48: ADDxc0_s rc, h2, h2.w---; + | SCB0/1 | mul | 49: MOVh h0(NE0.xxxx), h1; + +Pass SCT TEX SCB + 1: 0% 100% 25% + 2: 0% 100% 25% + 3: 0% 100% 50% + 4: 0% 100% 50% + 5: 0% 0% 50% + 6: 100% 0% 75% + 7: 0% 100% 75% + 8: 0% 100% 100% + 9: 0% 100% 25% + 10: 0% 100% 100% + 11: 50% 0% 100% + 12: 50% 0% 100% + 13: 25% 0% 100% + +MEAN: 17% 61% 67% + +Pass SCT0 SCT1 TEX SCB0 SCB1 + 1: 0% 0% 100% 0% 100% + 2: 0% 0% 100% 0% 100% + 3: 0% 0% 100% 100% 100% + 4: 0% 0% 100% 100% 100% + 5: 0% 0% 0% 100% 100% + 6: 100% 100% 0% 100% 100% + 7: 0% 0% 100% 100% 100% + 8: 0% 0% 100% 100% 100% + 9: 0% 0% 100% 0% 100% + 10: 0% 0% 100% 100% 100% + 11: 100% 100% 0% 100% 100% + 12: 100% 100% 0% 100% 100% + 13: 100% 0% 0% 100% 100% + +MEAN: 30% 23% 61% 76% 100% +Fragment Performance Setup: Driver RSX Compiler, GPU RSX, Flags 0x5 +Results 13 cycles, 3 r regs, 923,076,923 pixels/s +============================================================================*/ +#if (FXAA_PS3 == 1) && (FXAA_EARLY_EXIT == 0) +/*--------------------------------------------------------------------------*/ +#pragma regcount 7 +#pragma disablepc all +#pragma option O3 +#pragma option OutColorPrec=fp16 +#pragma texformat default RGBA8 +/*==========================================================================*/ +half4 FxaaPixelShader( + // See FXAA Quality FxaaPixelShader() source for docs on Inputs! + FxaaFloat2 pos, + FxaaFloat4 fxaaConsolePosPos, + FxaaTex tex, + FxaaTex fxaaConsole360TexExpBiasNegOne, + FxaaTex fxaaConsole360TexExpBiasNegTwo, + FxaaFloat2 fxaaQualityRcpFrame, + FxaaFloat4 fxaaConsoleRcpFrameOpt, + FxaaFloat4 fxaaConsoleRcpFrameOpt2, + FxaaFloat4 fxaaConsole360RcpFrameOpt2, + FxaaFloat fxaaQualitySubpix, + FxaaFloat fxaaQualityEdgeThreshold, + FxaaFloat fxaaQualityEdgeThresholdMin, + FxaaFloat fxaaConsoleEdgeSharpness, + FxaaFloat fxaaConsoleEdgeThreshold, + FxaaFloat fxaaConsoleEdgeThresholdMin, + FxaaFloat4 fxaaConsole360ConstDir +) { +/*--------------------------------------------------------------------------*/ +// (1) + half4 dir; + half4 lumaNe = h4tex2Dlod(tex, half4(fxaaConsolePosPos.zy, 0, 0)); + #if (FXAA_GREEN_AS_LUMA == 0) + lumaNe.w += half(1.0/512.0); + dir.x = -lumaNe.w; + dir.z = -lumaNe.w; + #else + lumaNe.y += half(1.0/512.0); + dir.x = -lumaNe.y; + dir.z = -lumaNe.y; + #endif +/*--------------------------------------------------------------------------*/ +// (2) + half4 lumaSw = h4tex2Dlod(tex, half4(fxaaConsolePosPos.xw, 0, 0)); + #if (FXAA_GREEN_AS_LUMA == 0) + dir.x += lumaSw.w; + dir.z += lumaSw.w; + #else + dir.x += lumaSw.y; + dir.z += lumaSw.y; + #endif +/*--------------------------------------------------------------------------*/ +// (3) + half4 lumaNw = h4tex2Dlod(tex, half4(fxaaConsolePosPos.xy, 0, 0)); + #if (FXAA_GREEN_AS_LUMA == 0) + dir.x -= lumaNw.w; + dir.z += lumaNw.w; + #else + dir.x -= lumaNw.y; + dir.z += lumaNw.y; + #endif +/*--------------------------------------------------------------------------*/ +// (4) + half4 lumaSe = h4tex2Dlod(tex, half4(fxaaConsolePosPos.zw, 0, 0)); + #if (FXAA_GREEN_AS_LUMA == 0) + dir.x += lumaSe.w; + dir.z -= lumaSe.w; + #else + dir.x += lumaSe.y; + dir.z -= lumaSe.y; + #endif +/*--------------------------------------------------------------------------*/ +// (5) + half4 dir1_pos; + dir1_pos.xy = normalize(dir.xyz).xz; + half dirAbsMinTimesC = min(abs(dir1_pos.x), abs(dir1_pos.y)) * half(FXAA_CONSOLE__PS3_EDGE_SHARPNESS); +/*--------------------------------------------------------------------------*/ +// (6) + half4 dir2_pos; + dir2_pos.xy = clamp(dir1_pos.xy / dirAbsMinTimesC, half(-2.0), half(2.0)); + dir1_pos.zw = pos.xy; + dir2_pos.zw = pos.xy; + half4 temp1N; + temp1N.xy = dir1_pos.zw - dir1_pos.xy * fxaaConsoleRcpFrameOpt.zw; +/*--------------------------------------------------------------------------*/ +// (7) + temp1N = h4tex2Dlod(tex, half4(temp1N.xy, 0.0, 0.0)); + half4 rgby1; + rgby1.xy = dir1_pos.zw + dir1_pos.xy * fxaaConsoleRcpFrameOpt.zw; +/*--------------------------------------------------------------------------*/ +// (8) + rgby1 = h4tex2Dlod(tex, half4(rgby1.xy, 0.0, 0.0)); + rgby1 = (temp1N + rgby1) * 0.5; +/*--------------------------------------------------------------------------*/ +// (9) + half4 temp2N; + temp2N.xy = dir2_pos.zw - dir2_pos.xy * fxaaConsoleRcpFrameOpt2.zw; + temp2N = h4tex2Dlod(tex, half4(temp2N.xy, 0.0, 0.0)); +/*--------------------------------------------------------------------------*/ +// (10) + half4 rgby2; + rgby2.xy = dir2_pos.zw + dir2_pos.xy * fxaaConsoleRcpFrameOpt2.zw; + rgby2 = h4tex2Dlod(tex, half4(rgby2.xy, 0.0, 0.0)); + rgby2 = (temp2N + rgby2) * 0.5; +/*--------------------------------------------------------------------------*/ +// (11) + // compilier moves these scalar ops up to other cycles + #if (FXAA_GREEN_AS_LUMA == 0) + half lumaMin = min(min(lumaNw.w, lumaSw.w), min(lumaNe.w, lumaSe.w)); + half lumaMax = max(max(lumaNw.w, lumaSw.w), max(lumaNe.w, lumaSe.w)); + #else + half lumaMin = min(min(lumaNw.y, lumaSw.y), min(lumaNe.y, lumaSe.y)); + half lumaMax = max(max(lumaNw.y, lumaSw.y), max(lumaNe.y, lumaSe.y)); + #endif + rgby2 = (rgby2 + rgby1) * 0.5; +/*--------------------------------------------------------------------------*/ +// (12) + #if (FXAA_GREEN_AS_LUMA == 0) + bool twoTapLt = rgby2.w < lumaMin; + bool twoTapGt = rgby2.w > lumaMax; + #else + bool twoTapLt = rgby2.y < lumaMin; + bool twoTapGt = rgby2.y > lumaMax; + #endif +/*--------------------------------------------------------------------------*/ +// (13) + if(twoTapLt || twoTapGt) rgby2 = rgby1; +/*--------------------------------------------------------------------------*/ + return rgby2; } +/*==========================================================================*/ +#endif + + + +/*============================================================================ + + FXAA3 CONSOLE - OPTIMIZED PS3 PIXEL SHADER (WITH EARLY EXIT) + +============================================================================== +The code mostly matches the assembly. +I have a feeling that 14 cycles is possible, but was not able to get there. +Might have to increase register count to get full performance. +Note this shader does not use perspective interpolation. + +Use the following cgc options, + + --fenable-bx2 --fastmath --fastprecision --nofloatbindings + +Use of FXAA_GREEN_AS_LUMA currently adds a cycle (16 clks). +Will look at fixing this for FXAA 3.12. +------------------------------------------------------------------------------ + NVSHADERPERF OUTPUT +------------------------------------------------------------------------------ +For reference and to aid in debug, output of NVShaderPerf should match this, + +Shader to schedule: + 0: texpkb h0.w(TRUE), v5.zyxx, #0 + 2: addh h2.y(TRUE), h0.w, constant(0.001953, 0.000000, 0.000000, 0.000000).x + 4: texpkb h1.w(TRUE), v5.xwxx, #0 + 6: addh h0.x(TRUE), h1.w, -h2.y + 7: texpkb h2.w(TRUE), v5.zwzz, #0 + 9: minh h4.w(TRUE), h2.y, h2 + 10: maxh h5.x(TRUE), h2.y, h2.w + 11: texpkb h0.w(TRUE), v5, #0 + 13: addh h3.w(TRUE), -h0, h0.x + 14: addh h0.x(TRUE), h0.w, h0 + 15: addh h0.z(TRUE), -h2.w, h0.x + 16: addh h0.x(TRUE), h2.w, h3.w + 17: minh h5.y(TRUE), h0.w, h1.w + 18: nrmh h2.xz(TRUE), h0_n + 19: minh_m8 h2.w(TRUE), |h2.x|, |h2.z| + 20: divx h4.xy(TRUE), h2_n.xzzw, h2_n.w + 21: movr r1.zw(TRUE), v4.xxxy + 22: maxh h2.w(TRUE), h0, h1 + 23: fenct TRUE + 24: madr r0.xy(TRUE), -h2.xzzw, constant(cConst5.x, cConst5.y, cConst5.z, cConst5.w).zwzz, r1.zwzz + 26: texpkb h0(TRUE), r0, #0 + 28: maxh h5.x(TRUE), h2.w, h5 + 29: minh h5.w(TRUE), h5.y, h4 + 30: madr r1.xy(TRUE), h2.xzzw, constant(cConst5.x, cConst5.y, cConst5.z, cConst5.w).zwzz, r1.zwzz + 32: texpkb h2(TRUE), r1, #0 + 34: addh_d2 h2(TRUE), h0, h2 + 35: texpkb h1(TRUE), v4, #0 + 37: maxh h5.y(TRUE), h5.x, h1.w + 38: minh h4.w(TRUE), h1, h5 + 39: madr r0.xy(TRUE), -h4, constant(cConst5.x, cConst5.y, cConst5.z, cConst5.w).xyxx, r1.zwzz + 41: texpkb h0(TRUE), r0, #0 + 43: addh_m8 h5.z(TRUE), h5.y, -h4.w + 44: madr r2.xy(TRUE), h4, constant(cConst5.x, cConst5.y, cConst5.z, cConst5.w).xyxx, r1.zwzz + 46: texpkb h3(TRUE), r2, #0 + 48: addh_d2 h0(TRUE), h0, h3 + 49: addh_d2 h3(TRUE), h0, h2 + 50: movh h0(TRUE), h3 + 51: slth h3.x(TRUE), h3.w, h5.w + 52: sgth h3.w(TRUE), h3, h5.x + 53: addx.c0 rc(TRUE), h3.x, h3 + 54: slth.c0 rc(TRUE), h5.z, h5 + 55: movh h0(c0.NE.w), h2 + 56: movh h0(c0.NE.x), h1 + +IPU0 ------ Simplified schedule: -------- +Pass | Unit | uOp | PC: Op +-----+--------+------+------------------------- + 1 | SCT0/1 | mov | 0: TXLr h0.w, g[TEX1].zyxx, const.xxxx, TEX0; + | TEX | txl | 0: TXLr h0.w, g[TEX1].zyxx, const.xxxx, TEX0; + | SCB0 | add | 2: ADDh h2.y, h0.-w--, const.-x--; + | | | + 2 | SCT0/1 | mov | 4: TXLr h1.w, g[TEX1].xwxx, const.xxxx, TEX0; + | TEX | txl | 4: TXLr h1.w, g[TEX1].xwxx, const.xxxx, TEX0; + | SCB0 | add | 6: ADDh h0.x, h1.w---,-h2.y---; + | | | + 3 | SCT0/1 | mov | 7: TXLr h2.w, g[TEX1].zwzz, const.xxxx, TEX0; + | TEX | txl | 7: TXLr h2.w, g[TEX1].zwzz, const.xxxx, TEX0; + | SCB0 | max | 10: MAXh h5.x, h2.y---, h2.w---; + | SCB1 | min | 9: MINh h4.w, h2.---y, h2; + | | | + 4 | SCT0/1 | mov | 11: TXLr h0.w, g[TEX1], const.xxxx, TEX0; + | TEX | txl | 11: TXLr h0.w, g[TEX1], const.xxxx, TEX0; + | SCB0 | add | 14: ADDh h0.x, h0.w---, h0; + | SCB1 | add | 13: ADDh h3.w,-h0, h0.---x; + | | | + 5 | SCT0 | mad | 16: ADDh h0.x, h2.w---, h3.w---; + | SCT1 | mad | 15: ADDh h0.z,-h2.--w-, h0.--x-; + | SCB0 | min | 17: MINh h5.y, h0.-w--, h1.-w--; + | | | + 6 | SCT1 | mov | 18: NRMh h2.xz, h0; + | SRB | nrm | 18: NRMh h2.xz, h0; + | SCB1 | min | 19: MINh*8 h2.w, |h2.---x|, |h2.---z|; + | | | + 7 | SCT0 | div | 20: DIVx h4.xy, h2.xz--, h2.ww--; + | SCT1 | mov | 21: MOVr r1.zw, g[TEX0].--xy; + | SCB1 | max | 22: MAXh h2.w, h0, h1; + | | | + 8 | SCT0 | mad | 24: MADr r0.xy,-h2.xz--, const.zw--, r1.zw--; + | SCT1 | mov | 26: TXLr h0, r0, const.xxxx, TEX0; + | TEX | txl | 26: TXLr h0, r0, const.xxxx, TEX0; + | SCB0 | max | 28: MAXh h5.x, h2.w---, h5; + | SCB1 | min | 29: MINh h5.w, h5.---y, h4; + | | | + 9 | SCT0 | mad | 30: MADr r1.xy, h2.xz--, const.zw--, r1.zw--; + | SCT1 | mov | 32: TXLr h2, r1, const.xxxx, TEX0; + | TEX | txl | 32: TXLr h2, r1, const.xxxx, TEX0; + | SCB0/1 | add | 34: ADDh/2 h2, h0, h2; + | | | + 10 | SCT0/1 | mov | 35: TXLr h1, g[TEX0], const.xxxx, TEX0; + | TEX | txl | 35: TXLr h1, g[TEX0], const.xxxx, TEX0; + | SCB0 | max | 37: MAXh h5.y, h5.-x--, h1.-w--; + | SCB1 | min | 38: MINh h4.w, h1, h5; + | | | + 11 | SCT0 | mad | 39: MADr r0.xy,-h4, const.xy--, r1.zw--; + | SCT1 | mov | 41: TXLr h0, r0, const.zzzz, TEX0; + | TEX | txl | 41: TXLr h0, r0, const.zzzz, TEX0; + | SCB0 | mad | 44: MADr r2.xy, h4, const.xy--, r1.zw--; + | SCB1 | add | 43: ADDh*8 h5.z, h5.--y-,-h4.--w-; + | | | + 12 | SCT0/1 | mov | 46: TXLr h3, r2, const.xxxx, TEX0; + | TEX | txl | 46: TXLr h3, r2, const.xxxx, TEX0; + | SCB0/1 | add | 48: ADDh/2 h0, h0, h3; + | | | + 13 | SCT0/1 | mad | 49: ADDh/2 h3, h0, h2; + | SCB0/1 | mul | 50: MOVh h0, h3; + | | | + 14 | SCT0 | set | 51: SLTh h3.x, h3.w---, h5.w---; + | SCT1 | set | 52: SGTh h3.w, h3, h5.---x; + | SCB0 | set | 54: SLThc0 rc, h5.z---, h5; + | SCB1 | add | 53: ADDxc0_s rc, h3.---x, h3; + | | | + 15 | SCT0/1 | mul | 55: MOVh h0(NE0.wwww), h2; + | SCB0/1 | mul | 56: MOVh h0(NE0.xxxx), h1; + +Pass SCT TEX SCB + 1: 0% 100% 25% + 2: 0% 100% 25% + 3: 0% 100% 50% + 4: 0% 100% 50% + 5: 50% 0% 25% + 6: 0% 0% 25% + 7: 100% 0% 25% + 8: 0% 100% 50% + 9: 0% 100% 100% + 10: 0% 100% 50% + 11: 0% 100% 75% + 12: 0% 100% 100% + 13: 100% 0% 100% + 14: 50% 0% 50% + 15: 100% 0% 100% + +MEAN: 26% 60% 56% + +Pass SCT0 SCT1 TEX SCB0 SCB1 + 1: 0% 0% 100% 100% 0% + 2: 0% 0% 100% 100% 0% + 3: 0% 0% 100% 100% 100% + 4: 0% 0% 100% 100% 100% + 5: 100% 100% 0% 100% 0% + 6: 0% 0% 0% 0% 100% + 7: 100% 100% 0% 0% 100% + 8: 0% 0% 100% 100% 100% + 9: 0% 0% 100% 100% 100% + 10: 0% 0% 100% 100% 100% + 11: 0% 0% 100% 100% 100% + 12: 0% 0% 100% 100% 100% + 13: 100% 100% 0% 100% 100% + 14: 100% 100% 0% 100% 100% + 15: 100% 100% 0% 100% 100% + +MEAN: 33% 33% 60% 86% 80% +Fragment Performance Setup: Driver RSX Compiler, GPU RSX, Flags 0x5 +Results 15 cycles, 3 r regs, 800,000,000 pixels/s +============================================================================*/ +#if (FXAA_PS3 == 1) && (FXAA_EARLY_EXIT == 1) +/*--------------------------------------------------------------------------*/ +#pragma regcount 7 +#pragma disablepc all +#pragma option O2 +#pragma option OutColorPrec=fp16 +#pragma texformat default RGBA8 +/*==========================================================================*/ +half4 FxaaPixelShader( + // See FXAA Quality FxaaPixelShader() source for docs on Inputs! + FxaaFloat2 pos, + FxaaFloat4 fxaaConsolePosPos, + FxaaTex tex, + FxaaTex fxaaConsole360TexExpBiasNegOne, + FxaaTex fxaaConsole360TexExpBiasNegTwo, + FxaaFloat2 fxaaQualityRcpFrame, + FxaaFloat4 fxaaConsoleRcpFrameOpt, + FxaaFloat4 fxaaConsoleRcpFrameOpt2, + FxaaFloat4 fxaaConsole360RcpFrameOpt2, + FxaaFloat fxaaQualitySubpix, + FxaaFloat fxaaQualityEdgeThreshold, + FxaaFloat fxaaQualityEdgeThresholdMin, + FxaaFloat fxaaConsoleEdgeSharpness, + FxaaFloat fxaaConsoleEdgeThreshold, + FxaaFloat fxaaConsoleEdgeThresholdMin, + FxaaFloat4 fxaaConsole360ConstDir +) { +/*--------------------------------------------------------------------------*/ +// (1) + half4 rgbyNe = h4tex2Dlod(tex, half4(fxaaConsolePosPos.zy, 0, 0)); + #if (FXAA_GREEN_AS_LUMA == 0) + half lumaNe = rgbyNe.w + half(1.0/512.0); + #else + half lumaNe = rgbyNe.y + half(1.0/512.0); + #endif +/*--------------------------------------------------------------------------*/ +// (2) + half4 lumaSw = h4tex2Dlod(tex, half4(fxaaConsolePosPos.xw, 0, 0)); + #if (FXAA_GREEN_AS_LUMA == 0) + half lumaSwNegNe = lumaSw.w - lumaNe; + #else + half lumaSwNegNe = lumaSw.y - lumaNe; + #endif +/*--------------------------------------------------------------------------*/ +// (3) + half4 lumaNw = h4tex2Dlod(tex, half4(fxaaConsolePosPos.xy, 0, 0)); + #if (FXAA_GREEN_AS_LUMA == 0) + half lumaMaxNwSw = max(lumaNw.w, lumaSw.w); + half lumaMinNwSw = min(lumaNw.w, lumaSw.w); + #else + half lumaMaxNwSw = max(lumaNw.y, lumaSw.y); + half lumaMinNwSw = min(lumaNw.y, lumaSw.y); + #endif +/*--------------------------------------------------------------------------*/ +// (4) + half4 lumaSe = h4tex2Dlod(tex, half4(fxaaConsolePosPos.zw, 0, 0)); + #if (FXAA_GREEN_AS_LUMA == 0) + half dirZ = lumaNw.w + lumaSwNegNe; + half dirX = -lumaNw.w + lumaSwNegNe; + #else + half dirZ = lumaNw.y + lumaSwNegNe; + half dirX = -lumaNw.y + lumaSwNegNe; + #endif +/*--------------------------------------------------------------------------*/ +// (5) + half3 dir; + dir.y = 0.0; + #if (FXAA_GREEN_AS_LUMA == 0) + dir.x = lumaSe.w + dirX; + dir.z = -lumaSe.w + dirZ; + half lumaMinNeSe = min(lumaNe, lumaSe.w); + #else + dir.x = lumaSe.y + dirX; + dir.z = -lumaSe.y + dirZ; + half lumaMinNeSe = min(lumaNe, lumaSe.y); + #endif +/*--------------------------------------------------------------------------*/ +// (6) + half4 dir1_pos; + dir1_pos.xy = normalize(dir).xz; + half dirAbsMinTimes8 = min(abs(dir1_pos.x), abs(dir1_pos.y)) * half(FXAA_CONSOLE__PS3_EDGE_SHARPNESS); +/*--------------------------------------------------------------------------*/ +// (7) + half4 dir2_pos; + dir2_pos.xy = clamp(dir1_pos.xy / dirAbsMinTimes8, half(-2.0), half(2.0)); + dir1_pos.zw = pos.xy; + dir2_pos.zw = pos.xy; + #if (FXAA_GREEN_AS_LUMA == 0) + half lumaMaxNeSe = max(lumaNe, lumaSe.w); + #else + half lumaMaxNeSe = max(lumaNe, lumaSe.y); + #endif +/*--------------------------------------------------------------------------*/ +// (8) + half4 temp1N; + temp1N.xy = dir1_pos.zw - dir1_pos.xy * fxaaConsoleRcpFrameOpt.zw; + temp1N = h4tex2Dlod(tex, half4(temp1N.xy, 0.0, 0.0)); + half lumaMax = max(lumaMaxNwSw, lumaMaxNeSe); + half lumaMin = min(lumaMinNwSw, lumaMinNeSe); +/*--------------------------------------------------------------------------*/ +// (9) + half4 rgby1; + rgby1.xy = dir1_pos.zw + dir1_pos.xy * fxaaConsoleRcpFrameOpt.zw; + rgby1 = h4tex2Dlod(tex, half4(rgby1.xy, 0.0, 0.0)); + rgby1 = (temp1N + rgby1) * 0.5; +/*--------------------------------------------------------------------------*/ +// (10) + half4 rgbyM = h4tex2Dlod(tex, half4(pos.xy, 0.0, 0.0)); + #if (FXAA_GREEN_AS_LUMA == 0) + half lumaMaxM = max(lumaMax, rgbyM.w); + half lumaMinM = min(lumaMin, rgbyM.w); + #else + half lumaMaxM = max(lumaMax, rgbyM.y); + half lumaMinM = min(lumaMin, rgbyM.y); + #endif +/*--------------------------------------------------------------------------*/ +// (11) + half4 temp2N; + temp2N.xy = dir2_pos.zw - dir2_pos.xy * fxaaConsoleRcpFrameOpt2.zw; + temp2N = h4tex2Dlod(tex, half4(temp2N.xy, 0.0, 0.0)); + half4 rgby2; + rgby2.xy = dir2_pos.zw + dir2_pos.xy * fxaaConsoleRcpFrameOpt2.zw; + half lumaRangeM = (lumaMaxM - lumaMinM) / FXAA_CONSOLE__PS3_EDGE_THRESHOLD; +/*--------------------------------------------------------------------------*/ +// (12) + rgby2 = h4tex2Dlod(tex, half4(rgby2.xy, 0.0, 0.0)); + rgby2 = (temp2N + rgby2) * 0.5; +/*--------------------------------------------------------------------------*/ +// (13) + rgby2 = (rgby2 + rgby1) * 0.5; +/*--------------------------------------------------------------------------*/ +// (14) + #if (FXAA_GREEN_AS_LUMA == 0) + bool twoTapLt = rgby2.w < lumaMin; + bool twoTapGt = rgby2.w > lumaMax; + #else + bool twoTapLt = rgby2.y < lumaMin; + bool twoTapGt = rgby2.y > lumaMax; + #endif + bool earlyExit = lumaRangeM < lumaMax; + bool twoTap = twoTapLt || twoTapGt; +/*--------------------------------------------------------------------------*/ +// (15) + if(twoTap) rgby2 = rgby1; + if(earlyExit) rgby2 = rgbyM; +/*--------------------------------------------------------------------------*/ + return rgby2; } +/*==========================================================================*/ +#endif diff --git a/Templates/BaseGame/game/core/rendering/shaders/postFX/fxaa/fxaaP.hlsl b/Templates/BaseGame/game/core/rendering/shaders/postFX/fxaa/fxaaP.hlsl new file mode 100644 index 000000000..269bfea67 --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/postFX/fxaa/fxaaP.hlsl @@ -0,0 +1,143 @@ +//----------------------------------------------------------------------------- +// 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 "../../shaderModel.hlsl" + +#define FXAA_PC 1 +#if (TORQUE_SM <= 30) +#define FXAA_HLSL_3 1 +#elif TORQUE_SM < 49 +#define FXAA_HLSL_4 1 +#elif TORQUE_SM >=50 +#define FXAA_HLSL_5 1 +#endif +#define FXAA_QUALITY__PRESET 12 +#define FXAA_GREEN_AS_LUMA 1 + +#include "Fxaa3_11.h" + +struct VertToPix +{ + float4 hpos : TORQUE_POSITION; + float2 uv0 : TEXCOORD0; +}; + +TORQUE_UNIFORM_SAMPLER2D(colorTex, 0); + +uniform float2 oneOverTargetSize; + + +float4 main( VertToPix IN ) : TORQUE_TARGET0 +{ +#if (TORQUE_SM >= 10 && TORQUE_SM <=30) + FxaaTex tex = colorTex; +#elif TORQUE_SM >=40 + FxaaTex tex; + tex.smpl = colorTex; + tex.tex = texture_colorTex; +#endif + + return FxaaPixelShader( + + IN.uv0, // vertex position + + 0, // Unused... console stuff + + tex, // The color back buffer + + tex, // Used for 360 optimization + + tex, // Used for 360 optimization + + oneOverTargetSize, + + 0, // Unused... console stuff + + 0, // Unused... console stuff + + 0, // Unused... console stuff + + // + // Only used on FXAA Quality. + // This used to be the FXAA_QUALITY__SUBPIX define. + // It is here now to allow easier tuning. + // Choose the amount of sub-pixel aliasing removal. + // This can effect sharpness. + // 1.00 - upper limit (softer) + // 0.75 - default amount of filtering + // 0.50 - lower limit (sharper, less sub-pixel aliasing removal) + // 0.25 - almost off + // 0.00 - completely off + 0.75, + + // + // Only used on FXAA Quality. + // This used to be the FXAA_QUALITY__EDGE_THRESHOLD define. + // It is here now to allow easier tuning. + // The minimum amount of local contrast required to apply algorithm. + // 0.333 - too little (faster) + // 0.250 - low quality + // 0.166 - default + // 0.125 - high quality + // 0.063 - overkill (slower) + 0.166, + + // + // Only used on FXAA Quality. + // This used to be the FXAA_QUALITY__EDGE_THRESHOLD_MIN define. + // It is here now to allow easier tuning. + // Trims the algorithm from processing darks. + // 0.0833 - upper limit (default, the start of visible unfiltered edges) + // 0.0625 - high quality (faster) + // 0.0312 - visible limit (slower) + // Special notes when using FXAA_GREEN_AS_LUMA, + // Likely want to set this to zero. + // As colors that are mostly not-green + // will appear very dark in the green channel! + // Tune by looking at mostly non-green content, + // then start at zero and increase until aliasing is a problem. + 0, + + // + // Only used on FXAA Console. + // This used to be the FXAA_CONSOLE__EDGE_SHARPNESS define. + // It is here now to allow easier tuning. + // This does not effect PS3, as this needs to be compiled in. + // Use FXAA_CONSOLE__PS3_EDGE_SHARPNESS for PS3. + // Due to the PS3 being ALU bound, + // there are only three safe values here: 2 and 4 and 8. + // These options use the shaders ability to a free *|/ by 2|4|8. + // For all other platforms can be a non-power of two. + // 8.0 is sharper (default!!!) + // 4.0 is softer + // 2.0 is really soft (good only for vector graphics inputs) + 8, + + 0, // Unused... console stuff + + 0, // Unused... console stuff + + 0 // Unused... console stuff + + ); +} + diff --git a/Templates/BaseGame/game/core/rendering/shaders/postFX/fxaa/fxaaV.hlsl b/Templates/BaseGame/game/core/rendering/shaders/postFX/fxaa/fxaaV.hlsl new file mode 100644 index 000000000..f2974c587 --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/postFX/fxaa/fxaaV.hlsl @@ -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 "./../../torque.hlsl" +#include "./../postFx.hlsl" + +struct VertToPix +{ + float4 hpos : TORQUE_POSITION; + float2 uv0 : TEXCOORD0; +}; + +uniform float4 rtParams0; + +VertToPix main( PFXVert IN ) +{ + VertToPix OUT; + + OUT.hpos = float4(IN.pos,1); + OUT.uv0 = viewportCoordToRenderTarget( IN.uv, rtParams0 ); + + return OUT; +} diff --git a/Templates/BaseGame/game/core/rendering/shaders/postFX/fxaa/gl/fxaaP.glsl b/Templates/BaseGame/game/core/rendering/shaders/postFX/fxaa/gl/fxaaP.glsl new file mode 100644 index 000000000..19d76ef42 --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/postFX/fxaa/gl/fxaaP.glsl @@ -0,0 +1,125 @@ +//----------------------------------------------------------------------------- +// 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. +//----------------------------------------------------------------------------- + +#define FXAA_PC 1 +#define FXAA_GLSL_130 1 +#define FXAA_QUALITY__PRESET 12 +#define FXAA_GREEN_AS_LUMA 1 + +#include "../Fxaa3_11.h" +#include "../../../gl/hlslCompat.glsl" + +uniform sampler2D colorTex ; +uniform vec2 oneOverTargetSize; + +in vec4 hpos; +in vec2 uv0; + +out vec4 OUT_col; + +void main() +{ + OUT_col = FxaaPixelShader( + + uv0, // vertex position + + vec4(0), // Unused... console stuff + + colorTex, // The color back buffer + + colorTex, // Used for 360 optimization + + colorTex, // Used for 360 optimization + + oneOverTargetSize, + + vec4(0), // Unused... console stuff + + vec4(0), // Unused... console stuff + + vec4(0), // Unused... console stuff + + // + // Only used on FXAA Quality. + // This used to be the FXAA_QUALITY__SUBPIX define. + // It is here now to allow easier tuning. + // Choose the amount of sub-pixel aliasing removal. + // This can effect sharpness. + // 1.00 - upper limit (softer) + // 0.75 - default amount of filtering + // 0.50 - lower limit (sharper, less sub-pixel aliasing removal) + // 0.25 - almost off + // 0.00 - completely off + 0.75, + + // + // Only used on FXAA Quality. + // This used to be the FXAA_QUALITY__EDGE_THRESHOLD define. + // It is here now to allow easier tuning. + // The minimum amount of local contrast required to apply algorithm. + // 0.333 - too little (faster) + // 0.250 - low quality + // 0.166 - default + // 0.125 - high quality + // 0.063 - overkill (slower) + 0.166, + + // + // Only used on FXAA Quality. + // This used to be the FXAA_QUALITY__EDGE_THRESHOLD_MIN define. + // It is here now to allow easier tuning. + // Trims the algorithm from processing darks. + // 0.0833 - upper limit (default, the start of visible unfiltered edges) + // 0.0625 - high quality (faster) + // 0.0312 - visible limit (slower) + // Special notes when using FXAA_GREEN_AS_LUMA, + // Likely want to set this to zero. + // As colors that are mostly not-green + // will appear very dark in the green channel! + // Tune by looking at mostly non-green content, + // then start at zero and increase until aliasing is a problem. + 0, + + // + // Only used on FXAA Console. + // This used to be the FXAA_CONSOLE__EDGE_SHARPNESS define. + // It is here now to allow easier tuning. + // This does not effect PS3, as this needs to be compiled in. + // Use FXAA_CONSOLE__PS3_EDGE_SHARPNESS for PS3. + // Due to the PS3 being ALU bound, + // there are only three safe values here: 2 and 4 and 8. + // These options use the shaders ability to a free *|/ by 2|4|8. + // For all other platforms can be a non-power of two. + // 8.0 is sharper (default!!!) + // 4.0 is softer + // 2.0 is really soft (good only for vector graphics inputs) + 8, + + 0, // Unused... console stuff + + 0, // Unused... console stuff + + vec4(0) // Unused... console stuff + + ); +} + diff --git a/Templates/BaseGame/game/core/rendering/shaders/postFX/fxaa/gl/fxaaV.glsl b/Templates/BaseGame/game/core/rendering/shaders/postFX/fxaa/gl/fxaaV.glsl new file mode 100644 index 000000000..55d445d91 --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/postFX/fxaa/gl/fxaaV.glsl @@ -0,0 +1,40 @@ +//----------------------------------------------------------------------------- +// 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 "../../../gl/torque.glsl" + +in vec4 vPosition; +in vec2 vTexCoord0; + +uniform vec4 rtParams0; + +out vec4 hpos; +out vec2 uv0; + +void main() +{ + gl_Position = vPosition; + hpos = gl_Position; + uv0 = viewportCoordToRenderTarget( vTexCoord0, rtParams0 ); + + correctSSP(gl_Position); +} diff --git a/Templates/BaseGame/game/core/rendering/shaders/postFX/gammaP.hlsl b/Templates/BaseGame/game/core/rendering/shaders/postFX/gammaP.hlsl new file mode 100644 index 000000000..1e13d068b --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/postFX/gammaP.hlsl @@ -0,0 +1,50 @@ +//----------------------------------------------------------------------------- +// 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 "shadergen:/autogenConditioners.h" +#include "./postFx.hlsl" +#include "../torque.hlsl" + +TORQUE_UNIFORM_SAMPLER2D(backBuffer, 0); +TORQUE_UNIFORM_SAMPLER1D(colorCorrectionTex, 1); + +uniform float OneOverGamma; +uniform float Brightness; +uniform float Contrast; + +float4 main( PFXVertToPix IN ) : TORQUE_TARGET0 +{ + float4 color = TORQUE_TEX2D(backBuffer, IN.uv0.xy); + + // Apply the color correction. + color.r = TORQUE_TEX1D( colorCorrectionTex, color.r ).r; + color.g = TORQUE_TEX1D( colorCorrectionTex, color.g ).g; + color.b = TORQUE_TEX1D( colorCorrectionTex, color.b ).b; + + // 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/BaseGame/game/core/rendering/shaders/postFX/gl/VolFogGlowP.glsl b/Templates/BaseGame/game/core/rendering/shaders/postFX/gl/VolFogGlowP.glsl new file mode 100644 index 000000000..01b072dd9 --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/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/BaseGame/game/core/rendering/shaders/postFX/gl/chromaticLens.glsl b/Templates/BaseGame/game/core/rendering/shaders/postFX/gl/chromaticLens.glsl new file mode 100644 index 000000000..fdb85ba00 --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/postFX/gl/chromaticLens.glsl @@ -0,0 +1,62 @@ +//----------------------------------------------------------------------------- +// 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. +//----------------------------------------------------------------------------- + +// Based on 'Cubic Lens Distortion HLSL Shader' by François Tarlier +// www.francois-tarlier.com/blog/index.php/2009/11/cubic-lens-distortion-shader + +#include "./postFX.glsl" +#include "../../gl/torque.glsl" +#include "../../gl/hlslCompat.glsl" + +uniform sampler2D backBuffer; +uniform float distCoeff; +uniform float cubeDistort; +uniform vec3 colorDistort; + +out vec4 OUT_col; + +void main() +{ + vec2 tex = IN_uv0; + + float f = 0; + float r2 = (tex.x - 0.5) * (tex.x - 0.5) + (tex.y - 0.5) * (tex.y - 0.5); + + // Only compute the cubic distortion if necessary. + if ( cubeDistort == 0.0 ) + f = 1 + r2 * distCoeff; + else + f = 1 + r2 * (distCoeff + cubeDistort * sqrt(r2)); + + // Distort each color channel seperately to get a chromatic distortion effect. + vec3 outColor; + vec3 distort = vec3(f) + colorDistort; + + for ( int i=0; i < 3; i++ ) + { + float x = distort[i] * ( tex.x - 0.5 ) + 0.5; + float y = distort[i] * ( tex.y - 0.5 ) + 0.5; + outColor[i] = tex2Dlod( backBuffer, vec4(x,y,0,0) )[i]; + } + + OUT_col = vec4( outColor.rgb, 1 ); +} diff --git a/Templates/BaseGame/game/core/rendering/shaders/postFX/gl/flashP.glsl b/Templates/BaseGame/game/core/rendering/shaders/postFX/gl/flashP.glsl new file mode 100644 index 000000000..fc5072e6d --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/postFX/gl/flashP.glsl @@ -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. +//----------------------------------------------------------------------------- + +#include "./postFX.glsl" +#include "../../gl/torque.glsl" +#include "../../gl/hlslCompat.glsl" + +uniform float damageFlash; +uniform float whiteOut; +uniform sampler2D backBuffer; + +out vec4 OUT_col; + +void main() +{ + vec4 color1 = texture(backBuffer, IN_uv0); + vec4 color2 = color1 * MUL_COLOR; + vec4 damage = mix(color1,color2,damageFlash); + OUT_col = mix(damage,WHITE_COLOR,whiteOut); +} diff --git a/Templates/BaseGame/game/core/rendering/shaders/postFX/gl/fogP.glsl b/Templates/BaseGame/game/core/rendering/shaders/postFX/gl/fogP.glsl new file mode 100644 index 000000000..c2fe32fe4 --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/postFX/gl/fogP.glsl @@ -0,0 +1,52 @@ +//----------------------------------------------------------------------------- +// 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 deferredTex ; +uniform vec3 eyePosWorld; +uniform vec4 fogColor; +uniform vec3 fogData; +uniform vec4 rtParams0; + +in vec2 uv0; +in vec3 wsEyeRay; + +out vec4 OUT_col; + +void main() +{ + //vec2 deferredCoord = ( uv0.xy * rtParams0.zw ) + rtParams0.xy; + float depth = deferredUncondition( deferredTex, uv0 ).w; + //return vec4( depth, 0, 0, 0.7 ); + + float factor = computeSceneFog( eyePosWorld, + eyePosWorld + ( wsEyeRay * depth ), + fogData.x, + fogData.y, + fogData.z ); + + OUT_col = hdrEncode( vec4( fogColor.rgb, 1.0 - saturate( factor ) ) ); +} \ No newline at end of file diff --git a/Templates/BaseGame/game/core/rendering/shaders/postFX/gl/gammaP.glsl b/Templates/BaseGame/game/core/rendering/shaders/postFX/gl/gammaP.glsl new file mode 100644 index 000000000..04533e494 --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/postFX/gl/gammaP.glsl @@ -0,0 +1,54 @@ +//----------------------------------------------------------------------------- +// 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 "../../gl/torque.glsl" +#include "shadergen:/autogenConditioners.h" + +uniform sampler2D backBuffer; +uniform sampler1D colorCorrectionTex; + +uniform float OneOverGamma; +uniform float Brightness; +uniform float Contrast; + +in vec2 uv0; + +out vec4 OUT_col; + +void main() +{ + vec4 color = texture(backBuffer, uv0.xy); + + // Apply the color correction. + color.r = texture( colorCorrectionTex, color.r ).r; + color.g = texture( colorCorrectionTex, color.g ).g; + color.b = texture( colorCorrectionTex, color.b ).b; + + // 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/BaseGame/game/core/rendering/shaders/postFX/gl/glowBlurP.glsl b/Templates/BaseGame/game/core/rendering/shaders/postFX/gl/glowBlurP.glsl new file mode 100644 index 000000000..9ebca32fa --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/postFX/gl/glowBlurP.glsl @@ -0,0 +1,59 @@ +//----------------------------------------------------------------------------- +// 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 sampler2D diffuseMap ; + +in vec4 hpos; //POSITION; +in vec2 uv0; //TEXCOORD0; +in vec2 uv1; //TEXCOORD1; +in vec2 uv2; //TEXCOORD2; +in vec2 uv3; //TEXCOORD3; +in vec2 uv4; //TEXCOORD4; +in vec2 uv5; //TEXCOORD5; +in vec2 uv6; //TEXCOORD6; +in vec2 uv7; //TEXCOORD7; + +out vec4 OUT_col; + +void main() +{ + vec4 kernel = vec4( 0.175, 0.275, 0.375, 0.475 ) * 0.5f; + + 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/BaseGame/game/core/rendering/shaders/postFX/gl/glowBlurV.glsl b/Templates/BaseGame/game/core/rendering/shaders/postFX/gl/glowBlurV.glsl new file mode 100644 index 000000000..70445d7fe --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/postFX/gl/glowBlurV.glsl @@ -0,0 +1,59 @@ +//----------------------------------------------------------------------------- +// 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 "../../gl/torque.glsl" + +in vec4 vPosition; +in vec2 vTexCoord0; + +uniform vec2 texSize0; + +out vec4 hpos; //POSITION; +out vec2 uv0; //TEXCOORD0; +out vec2 uv1; //TEXCOORD1; +out vec2 uv2; //TEXCOORD2; +out vec2 uv3; //TEXCOORD3; +out vec2 uv4; //TEXCOORD4; +out vec2 uv5; //TEXCOORD5; +out vec2 uv6; //TEXCOORD6; +out vec2 uv7; //TEXCOORD7; + +void main() +{ + gl_Position = vPosition; + hpos = gl_Position; + + vec2 uv = vTexCoord0 + (0.5f / texSize0); + + uv0 = uv + ( ( BLUR_DIR * 3.5f ) / texSize0 ); + uv1 = uv + ( ( BLUR_DIR * 2.5f ) / texSize0 ); + uv2 = uv + ( ( BLUR_DIR * 1.5f ) / texSize0 ); + uv3 = uv + ( ( BLUR_DIR * 0.5f ) / texSize0 ); + + uv4 = uv - ( ( BLUR_DIR * 3.5f ) / texSize0 ); + uv5 = uv - ( ( BLUR_DIR * 2.5f ) / texSize0 ); + uv6 = uv - ( ( BLUR_DIR * 1.5f ) / texSize0 ); + uv7 = uv - ( ( BLUR_DIR * 0.5f ) / texSize0 ); + + correctSSP(gl_Position); +} diff --git a/Templates/BaseGame/game/core/rendering/shaders/postFX/gl/motionBlurP.glsl b/Templates/BaseGame/game/core/rendering/shaders/postFX/gl/motionBlurP.glsl new file mode 100644 index 000000000..8077d4124 --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/postFX/gl/motionBlurP.glsl @@ -0,0 +1,78 @@ +//----------------------------------------------------------------------------- +// 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 "../../gl/torque.glsl" +#include "shadergen:/autogenConditioners.h" +#include "postFX.glsl" + +#undef IN_uv0 +#define _IN_uv0 uv0 + +uniform mat4 matPrevScreenToWorld; +uniform mat4 matWorldToScreen; + +// Passed in from setShaderConsts() +uniform float velocityMultiplier; + +uniform sampler2D backBuffer; +uniform sampler2D deferredTex; + +out vec4 OUT_col; + +void main() +{ + vec2 IN_uv0 = _IN_uv0; + float samples = 5; + + // First get the deferred texture for uv channel 0 + vec4 deferred = deferredUncondition( deferredTex, IN_uv0 ); + + // Next extract the depth + float depth = deferred.a; + + // Create the screen position + vec4 screenPos = vec4(IN_uv0.x*2-1, IN_uv0.y*2-1, depth*2-1, 1); + + // Calculate the world position + vec4 D = tMul(screenPos, matWorldToScreen); + vec4 worldPos = D / D.w; + + // Now calculate the previous screen position + vec4 previousPos = tMul( worldPos, matPrevScreenToWorld ); + previousPos /= previousPos.w; + + // Calculate the XY velocity + vec2 velocity = ((screenPos - previousPos) / velocityMultiplier).xy; + + // Generate the motion blur + vec4 color = texture(backBuffer, IN_uv0); + IN_uv0 += velocity; + + for(int i = 1; i 0 ) + { + rayStart.z -= ( startSide ); + //return vec4( 1, 0, 0, 1 ); + } + + vec3 hitPos; + vec3 ray = rayEnd - rayStart; + float rayLen = length( ray ); + vec3 rayDir = normalize( ray ); + + float endSide = dot( plane.xyz, rayEnd ) + plane.w; + float planeDist; + + if ( endSide < -0.005 ) + { + //return vec4( 0, 0, 1, 1 ); + hitPos = rayEnd; + planeDist = endSide; + } + else + { + //return vec4( 0, 0, 0, 0 ); + float den = dot( ray, plane.xyz ); + + // Parallal to the plane, return the endPnt. + //if ( den == 0.0f ) + // return endPnt; + + float dist = -( dot( plane.xyz, rayStart ) + plane.w ) / den; + if ( dist < 0.0 ) + dist = 0.0; + //return vec4( 1, 0, 0, 1 ); + //return vec4( ( dist ).rrr, 1 ); + + + hitPos = mix( rayStart, rayEnd, dist ); + + planeDist = dist; + } + + float delta = length( hitPos - rayStart ); + + float fogAmt = 1.0 - saturate( exp( -FOG_DENSITY * ( delta - FOG_DENSITY_OFFSET ) ) ); + //return vec4( fogAmt.rrr, 1 ); + + // Calculate the water "base" color based on depth. + vec4 fogColor = waterColor * texture( waterDepthGradMap, saturate( delta / waterDepthGradMax ) ); + // Modulate baseColor by the ambientColor. + fogColor *= vec4( ambientColor.rgb, 1 ); + + vec3 inColor = hdrDecode( texture( backbuffer, IN_uv0 ).rgb ); + inColor.rgb *= 1.0 - saturate( abs( planeDist ) / WET_DEPTH ) * WET_DARKENING; + //return vec4( inColor, 1 ); + + vec3 outColor = mix( inColor, fogColor.rgb, fogAmt ); + + OUT_col = vec4( hdrEncode( outColor ), 1 ); +} \ No newline at end of file diff --git a/Templates/BaseGame/game/core/rendering/shaders/postFX/glowBlurP.hlsl b/Templates/BaseGame/game/core/rendering/shaders/postFX/glowBlurP.hlsl new file mode 100644 index 000000000..80f8ed02d --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/postFX/glowBlurP.hlsl @@ -0,0 +1,63 @@ +//----------------------------------------------------------------------------- +// 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 "./postFx.hlsl" + +TORQUE_UNIFORM_SAMPLER2D(diffuseMap, 0); + +struct VertToPix +{ + float4 hpos : TORQUE_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 ) : TORQUE_TARGET0 +{ + float4 kernel = float4( 0.175, 0.275, 0.375, 0.475 ) * 0.5f; + + float4 OUT = 0; + OUT += TORQUE_TEX2D( diffuseMap, IN.uv0 ) * kernel.x; + OUT += TORQUE_TEX2D( diffuseMap, IN.uv1 ) * kernel.y; + OUT += TORQUE_TEX2D( diffuseMap, IN.uv2 ) * kernel.z; + OUT += TORQUE_TEX2D( diffuseMap, IN.uv3 ) * kernel.w; + + OUT += TORQUE_TEX2D( diffuseMap, IN.uv4 ) * kernel.x; + OUT += TORQUE_TEX2D( diffuseMap, IN.uv5 ) * kernel.y; + OUT += TORQUE_TEX2D( diffuseMap, IN.uv6 ) * kernel.z; + OUT += TORQUE_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/BaseGame/game/core/rendering/shaders/postFX/glowBlurV.hlsl b/Templates/BaseGame/game/core/rendering/shaders/postFX/glowBlurV.hlsl new file mode 100644 index 000000000..b8f5cf9c2 --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/postFX/glowBlurV.hlsl @@ -0,0 +1,63 @@ +//----------------------------------------------------------------------------- +// 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 "./postFx.hlsl" +#include "./../torque.hlsl" + + +uniform float2 texSize0; + +struct VertToPix +{ + float4 hpos : TORQUE_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; +}; + +VertToPix main( PFXVert IN ) +{ + VertToPix OUT; + + OUT.hpos = float4(IN.pos,1.0); + + float2 uv = IN.uv + (0.5f / texSize0); + + OUT.uv0 = uv + ( ( BLUR_DIR * 3.5f ) / texSize0 ); + OUT.uv1 = uv + ( ( BLUR_DIR * 2.5f ) / texSize0 ); + OUT.uv2 = uv + ( ( BLUR_DIR * 1.5f ) / texSize0 ); + OUT.uv3 = uv + ( ( BLUR_DIR * 0.5f ) / texSize0 ); + + OUT.uv4 = uv - ( ( BLUR_DIR * 3.5f ) / texSize0 ); + OUT.uv5 = uv - ( ( BLUR_DIR * 2.5f ) / texSize0 ); + OUT.uv6 = uv - ( ( BLUR_DIR * 1.5f ) / texSize0 ); + OUT.uv7 = uv - ( ( BLUR_DIR * 0.5f ) / texSize0 ); + + return OUT; +} diff --git a/Templates/BaseGame/game/core/rendering/shaders/postFX/hdr/bloomGaussBlurHP.hlsl b/Templates/BaseGame/game/core/rendering/shaders/postFX/hdr/bloomGaussBlurHP.hlsl new file mode 100644 index 000000000..77f4b9915 --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/postFX/hdr/bloomGaussBlurHP.hlsl @@ -0,0 +1,68 @@ +//----------------------------------------------------------------------------- +// 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 "../postFx.hlsl" + +TORQUE_UNIFORM_SAMPLER2D(inputTex, 0); +uniform float2 oneOverTargetSize; +uniform float gaussMultiplier; +uniform float gaussMean; +uniform float gaussStdDev; + +#define PI 3.141592654 + +float computeGaussianValue( float x, float mean, float std_deviation ) +{ + // The gaussian equation is defined as such: + /* + -(x - mean)^2 + ------------- + 1.0 2*std_dev^2 + f(x,mean,std_dev) = -------------------- * e^ + sqrt(2*pi*std_dev^2) + + */ + + float tmp = ( 1.0f / sqrt( 2.0f * PI * std_deviation * std_deviation ) ); + float tmp2 = exp( ( -( ( x - mean ) * ( x - mean ) ) ) / ( 2.0f * std_deviation * std_deviation ) ); + return tmp * tmp2; +} + +float4 main( PFXVertToPix IN ) : TORQUE_TARGET0 +{ + float4 color = { 0.0f, 0.0f, 0.0f, 0.0f }; + float offset = 0; + float weight = 0; + float x = 0; + float fI = 0; + + for( int i = 0; i < 9; i++ ) + { + fI = (float)i; + offset = (i - 4.0) * oneOverTargetSize.x; + x = (i - 4.0) / 4.0; + weight = gaussMultiplier * computeGaussianValue( x, gaussMean, gaussStdDev ); + color += (TORQUE_TEX2D( inputTex, IN.uv0 + float2( offset, 0.0f ) ) * weight ); + } + + return float4( color.rgb, 1.0f ); +} \ No newline at end of file diff --git a/Templates/BaseGame/game/core/rendering/shaders/postFX/hdr/bloomGaussBlurVP.hlsl b/Templates/BaseGame/game/core/rendering/shaders/postFX/hdr/bloomGaussBlurVP.hlsl new file mode 100644 index 000000000..8381f6a5d --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/postFX/hdr/bloomGaussBlurVP.hlsl @@ -0,0 +1,67 @@ +//----------------------------------------------------------------------------- +// 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 "../postFx.hlsl" + +TORQUE_UNIFORM_SAMPLER2D(inputTex, 0); +uniform float2 oneOverTargetSize; +uniform float gaussMultiplier; +uniform float gaussMean; +uniform float gaussStdDev; + +#define D3DX_PI 3.141592654 + +float computeGaussianValue( float x, float mean, float std_deviation ) +{ + // The gaussian equation is defined as such: + /* + -(x - mean)^2 + ------------- + 1.0 2*std_dev^2 + f(x,mean,std_dev) = -------------------- * e^ + sqrt(2*pi*std_dev^2) + + */ + float tmp = ( 1.0f / sqrt( 2.0f * D3DX_PI * std_deviation * std_deviation ) ); + float tmp2 = exp( ( -( ( x - mean ) * ( x - mean ) ) ) / ( 2.0f * std_deviation * std_deviation ) ); + return tmp * tmp2; +} + +float4 main( PFXVertToPix IN ) : TORQUE_TARGET0 +{ + float4 color = { 0.0f, 0.0f, 0.0f, 0.0f }; + float offset = 0; + float weight = 0; + float x = 0; + float fI = 0; + + for( int i = 0; i < 9; i++ ) + { + fI = (float)i; + offset = (fI - 4.0) * oneOverTargetSize.y; + x = (fI - 4.0) / 4.0; + weight = gaussMultiplier * computeGaussianValue( x, gaussMean, gaussStdDev ); + color += (TORQUE_TEX2D( inputTex, IN.uv0 + float2( 0.0f, offset ) ) * weight ); + } + + return float4( color.rgb, 1.0f ); +} \ No newline at end of file diff --git a/Templates/BaseGame/game/core/rendering/shaders/postFX/hdr/brightPassFilterP.hlsl b/Templates/BaseGame/game/core/rendering/shaders/postFX/hdr/brightPassFilterP.hlsl new file mode 100644 index 000000000..9a8a93e97 --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/postFX/hdr/brightPassFilterP.hlsl @@ -0,0 +1,62 @@ +//----------------------------------------------------------------------------- +// 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 "../postFx.hlsl" +#include "../../torque.hlsl" + + +TORQUE_UNIFORM_SAMPLER2D(inputTex, 0); +TORQUE_UNIFORM_SAMPLER2D(luminanceTex, 1); +uniform float2 oneOverTargetSize; +uniform float brightPassThreshold; +uniform float g_fMiddleGray; + +static const float3 LUMINANCE_VECTOR = float3(0.3125f, 0.6154f, 0.0721f); + + +static float2 gTapOffsets[4] = +{ + { -0.5, 0.5 }, { 0.5, -0.5 }, + { -0.5, -0.5 }, { 0.5, 0.5 } +}; + +float4 main( PFXVertToPix IN ) : TORQUE_TARGET0 +{ + float4 average = { 0.0f, 0.0f, 0.0f, 0.0f }; + + // Combine and average 4 samples from the source HDR texture. + for( int i = 0; i < 4; i++ ) + average += hdrDecode( TORQUE_TEX2D( inputTex, IN.uv0 + ( gTapOffsets[i] * oneOverTargetSize ) ) ); + average *= 0.25f; + + // Determine the brightness of this particular pixel. + float adaptedLum = TORQUE_TEX2D( luminanceTex, float2( 0.5f, 0.5f ) ).r; + float lum = (g_fMiddleGray / (adaptedLum + 0.0001)) * hdrLuminance( average.rgb ); + //float lum = hdrLuminance( average.rgb ); + + // Determine whether this pixel passes the test... + if ( lum < brightPassThreshold ) + average = float4( 0.0f, 0.0f, 0.0f, 1.0f ); + + // Write the colour to the bright-pass render target + return hdrEncode( average ); +} diff --git a/Templates/BaseGame/game/core/rendering/shaders/postFX/hdr/calculateAdaptedLumP.hlsl b/Templates/BaseGame/game/core/rendering/shaders/postFX/hdr/calculateAdaptedLumP.hlsl new file mode 100644 index 000000000..0f895070a --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/postFX/hdr/calculateAdaptedLumP.hlsl @@ -0,0 +1,44 @@ +//----------------------------------------------------------------------------- +// 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 "../postFx.hlsl" + +TORQUE_UNIFORM_SAMPLER2D(currLum, 0); +TORQUE_UNIFORM_SAMPLER2D(lastAdaptedLum, 1); + +uniform float adaptRate; +uniform float deltaTime; + +float4 main( PFXVertToPix IN ) : TORQUE_TARGET0 +{ + float fAdaptedLum = TORQUE_TEX2D( lastAdaptedLum, float2(0.5f, 0.5f) ).r; + float fCurrentLum = TORQUE_TEX2D( currLum, float2(0.5f, 0.5f) ).r; + + // The user's adapted luminance level is simulated by closing the gap between + // adapted luminance and current luminance by 2% every frame, based on a + // 30 fps rate. This is not an accurate model of human adaptation, which can + // take longer than half an hour. + float diff = fCurrentLum - fAdaptedLum; + float fNewAdaptation = fAdaptedLum + ( diff * ( 1.0 - exp( -deltaTime * adaptRate ) ) ); + + return float4( fNewAdaptation, 0.0, 0.0, 1.0f ); +} diff --git a/Templates/BaseGame/game/core/rendering/shaders/postFX/hdr/downScale4x4P.hlsl b/Templates/BaseGame/game/core/rendering/shaders/postFX/hdr/downScale4x4P.hlsl new file mode 100644 index 000000000..01998af0b --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/postFX/hdr/downScale4x4P.hlsl @@ -0,0 +1,53 @@ +//----------------------------------------------------------------------------- +// 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. +//----------------------------------------------------------------------------- + +#define IN_HLSL +#include "../../shdrConsts.h" +#include "../postFx.hlsl" + +//----------------------------------------------------------------------------- +// Data +//----------------------------------------------------------------------------- +struct VertIn +{ + float4 hpos : TORQUE_POSITION; + float4 texCoords[8] : TEXCOORD0; +}; + +TORQUE_UNIFORM_SAMPLER2D(inputTex, 0); + +//----------------------------------------------------------------------------- +// Main +//----------------------------------------------------------------------------- +float4 main( VertIn IN) : TORQUE_TARGET0 +{ + // We calculate the texture coords + // in the vertex shader as an optimization. + float4 sample = 0.0f; + for ( int i = 0; i < 8; i++ ) + { + sample += TORQUE_TEX2D( inputTex, IN.texCoords[i].xy ); + sample += TORQUE_TEX2D( inputTex, IN.texCoords[i].zw ); + } + + return sample / 16; +} \ No newline at end of file diff --git a/Templates/BaseGame/game/core/rendering/shaders/postFX/hdr/downScale4x4V.hlsl b/Templates/BaseGame/game/core/rendering/shaders/postFX/hdr/downScale4x4V.hlsl new file mode 100644 index 000000000..c9a34b7f4 --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/postFX/hdr/downScale4x4V.hlsl @@ -0,0 +1,138 @@ +//----------------------------------------------------------------------------- +// 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. +//----------------------------------------------------------------------------- + +#define IN_HLSL +#include "../../shdrConsts.h" +#include "../postFx.hlsl" +//----------------------------------------------------------------------------- +// Constants +//----------------------------------------------------------------------------- + +struct Conn +{ + float4 hpos : TORQUE_POSITION; + float4 texCoords[8] : TEXCOORD0; +}; + +uniform float2 targetSize; + +//----------------------------------------------------------------------------- +// Main +//----------------------------------------------------------------------------- +Conn main( PFXVert In ) +{ + Conn Out; + + Out.hpos = float4(In.pos,1.0); + + // Sample from the 16 surrounding points. Since the center point will be in + // the exact center of 16 texels, a 0.5f offset is needed to specify a texel + // center. + float2 texSize = float2( 1.0 / (targetSize.x - 1.0), 1.0 / (targetSize.y - 1.0) ); + + float4 uv; + uv.xy = In.uv.xy; + uv.zw = In.uv.xy; + + Out.texCoords[0] = uv; + Out.texCoords[0].x += texSize.x; + Out.texCoords[0].y += texSize.y; + Out.texCoords[0].z += texSize.x; + Out.texCoords[0].w += texSize.y; + Out.texCoords[0].x += ( 0 - 1.5 ) * texSize.x; + Out.texCoords[0].y += ( 0 - 1.5 ) * texSize.y; + Out.texCoords[0].z += ( 1 - 1.5 ) * texSize.x; + Out.texCoords[0].w += ( 0 - 1.5 ) * texSize.y; + + Out.texCoords[1] = uv; + Out.texCoords[1].x += texSize.x; + Out.texCoords[1].y += texSize.y; + Out.texCoords[1].z += texSize.x; + Out.texCoords[1].w += texSize.y; + Out.texCoords[1].x += ( 2 - 1.5 ) * texSize.x; + Out.texCoords[1].y += ( 0 - 1.5 ) * texSize.y; + Out.texCoords[1].z += ( 3 - 1.5 ) * texSize.x; + Out.texCoords[1].w += ( 0 - 1.5 ) * texSize.y; + + Out.texCoords[2] = uv; + Out.texCoords[2].x += texSize.x; + Out.texCoords[2].y += texSize.y; + Out.texCoords[2].z += texSize.x; + Out.texCoords[2].w += texSize.y; + Out.texCoords[2].x += ( 0 - 1.5 ) * texSize.x; + Out.texCoords[2].y += ( 1 - 1.5 ) * texSize.y; + Out.texCoords[2].z += ( 1 - 1.5 ) * texSize.x; + Out.texCoords[2].w += ( 1 - 1.5 ) * texSize.y; + + Out.texCoords[3] = uv; + Out.texCoords[3].x += texSize.x; + Out.texCoords[3].y += texSize.y; + Out.texCoords[3].z += texSize.x; + Out.texCoords[3].w += texSize.y; + Out.texCoords[3].x += ( 2 - 1.5 ) * texSize.x; + Out.texCoords[3].y += ( 1 - 1.5 ) * texSize.y; + Out.texCoords[3].z += ( 3 - 1.5 ) * texSize.x; + Out.texCoords[3].w += ( 1 - 1.5 ) * texSize.y; + + Out.texCoords[4] = uv; + Out.texCoords[4].x += texSize.x; + Out.texCoords[4].y += texSize.y; + Out.texCoords[4].z += texSize.x; + Out.texCoords[4].w += texSize.y; + Out.texCoords[4].x += ( 0 - 1.5 ) * texSize.x; + Out.texCoords[4].y += ( 2 - 1.5 ) * texSize.y; + Out.texCoords[4].z += ( 1 - 1.5 ) * texSize.x; + Out.texCoords[4].w += ( 2 - 1.5 ) * texSize.y; + + Out.texCoords[5] = uv; + Out.texCoords[5].x += texSize.x; + Out.texCoords[5].y += texSize.y; + Out.texCoords[5].z += texSize.x; + Out.texCoords[5].w += texSize.y; + Out.texCoords[5].x += ( 2 - 1.5 ) * texSize.x; + Out.texCoords[5].y += ( 2 - 1.5 ) * texSize.y; + Out.texCoords[5].z += ( 3 - 1.5 ) * texSize.x; + Out.texCoords[5].w += ( 2 - 1.5 ) * texSize.y; + + Out.texCoords[6] = uv; + Out.texCoords[6].x += texSize.x; + Out.texCoords[6].y += texSize.y; + Out.texCoords[6].z += texSize.x; + Out.texCoords[6].w += texSize.y; + Out.texCoords[6].x += ( 0 - 1.5 ) * texSize.x; + Out.texCoords[6].y += ( 3 - 1.5 ) * texSize.y; + Out.texCoords[6].z += ( 1 - 1.5 ) * texSize.x; + Out.texCoords[6].w += ( 3 - 1.5 ) * texSize.y; + + Out.texCoords[7] = uv; + Out.texCoords[7].x += texSize.x; + Out.texCoords[7].y += texSize.y; + Out.texCoords[7].z += texSize.x; + Out.texCoords[7].w += texSize.y; + Out.texCoords[7].x += ( 2 - 1.5 ) * texSize.x; + Out.texCoords[7].y += ( 3 - 1.5 ) * texSize.y; + Out.texCoords[7].z += ( 3 - 1.5 ) * texSize.x; + Out.texCoords[7].w += ( 3 - 1.5 ) * texSize.y; + + return Out; +} + diff --git a/Templates/BaseGame/game/core/rendering/shaders/postFX/hdr/finalPassCombineP.hlsl b/Templates/BaseGame/game/core/rendering/shaders/postFX/hdr/finalPassCombineP.hlsl new file mode 100644 index 000000000..07f7276c3 --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/postFX/hdr/finalPassCombineP.hlsl @@ -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. +//----------------------------------------------------------------------------- + +#include "../../torque.hlsl" +#include "../postFx.hlsl" +#include "../../shaderModelAutoGen.hlsl" + +TORQUE_UNIFORM_SAMPLER2D(sceneTex, 0); +TORQUE_UNIFORM_SAMPLER2D(luminanceTex, 1); +TORQUE_UNIFORM_SAMPLER2D(bloomTex, 2); +TORQUE_UNIFORM_SAMPLER1D(colorCorrectionTex, 3); + +uniform float2 texSize0; +uniform float2 texSize2; + +uniform float g_fEnableToneMapping; +uniform float g_fMiddleGray; +uniform float g_fWhiteCutoff; +uniform float g_fEnableBlueShift; + +uniform float3 g_fBlueShiftColor; +uniform float g_fBloomScale; +uniform float g_fOneOverGamma; +uniform float Brightness; +uniform float Contrast; + +float4 main( PFXVertToPix IN ) : TORQUE_TARGET0 +{ + float4 sample = hdrDecode( TORQUE_TEX2D( sceneTex, IN.uv0 ) ); + float adaptedLum = TORQUE_TEX2D( luminanceTex, float2( 0.5f, 0.5f ) ).r; + float4 bloom = TORQUE_TEX2D( bloomTex, IN.uv0 ); + + // For very low light conditions, the rods will dominate the perception + // of light, and therefore color will be desaturated and shifted + // towards blue. + if ( g_fEnableBlueShift > 0.0f ) + { + const float3 LUMINANCE_VECTOR = float3(0.2125f, 0.7154f, 0.0721f); + + // Define a linear blending from -1.5 to 2.6 (log scale) which + // determines the lerp amount for blue shift + float coef = 1.0f - ( adaptedLum + 1.5 ) / 4.1; + coef = saturate( coef * g_fEnableBlueShift ); + + // Lerp between current color and blue, desaturated copy + float3 rodColor = dot( sample.rgb, LUMINANCE_VECTOR ) * g_fBlueShiftColor; + sample.rgb = lerp( sample.rgb, rodColor, coef ); + + rodColor = dot( bloom.rgb, LUMINANCE_VECTOR ) * g_fBlueShiftColor; + bloom.rgb = lerp( bloom.rgb, rodColor, coef ); + } + + // Add the bloom effect. + sample += g_fBloomScale * bloom; + + // Map the high range of color values into a range appropriate for + // display, taking into account the user's adaptation level, + // white point, and selected value for for middle gray. + if ( g_fEnableToneMapping > 0.0f ) + { + float Lp = (g_fMiddleGray / (adaptedLum + 0.0001)) * hdrLuminance( sample.rgb ); + //float toneScalar = ( Lp * ( 1.0 + ( Lp / ( g_fWhiteCutoff ) ) ) ) / ( 1.0 + Lp ); + float toneScalar = Lp; + sample.rgb = lerp( sample.rgb, sample.rgb * toneScalar, g_fEnableToneMapping ); + } + + // Apply the color correction. + sample.r = TORQUE_TEX1D( colorCorrectionTex, sample.r ).r; + sample.g = TORQUE_TEX1D( colorCorrectionTex, sample.g ).g; + sample.b = TORQUE_TEX1D( colorCorrectionTex, sample.b ).b; + + return sample; +} diff --git a/Templates/BaseGame/game/core/rendering/shaders/postFX/hdr/gl/bloomGaussBlurHP.glsl b/Templates/BaseGame/game/core/rendering/shaders/postFX/hdr/gl/bloomGaussBlurHP.glsl new file mode 100644 index 000000000..1d9a2df3e --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/postFX/hdr/gl/bloomGaussBlurHP.glsl @@ -0,0 +1,72 @@ +//----------------------------------------------------------------------------- +// 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/postFX.glsl" + +uniform sampler2D inputTex ; +uniform vec2 oneOverTargetSize; +uniform float gaussMultiplier; +uniform float gaussMean; +uniform float gaussStdDev; + +out vec4 OUT_col; + +#define PI 3.141592654 + +float computeGaussianValue( float x, float mean, float std_deviation ) +{ + // The gaussian equation is defined as such: + /* + -(x - mean)^2 + ------------- + 1.0 2*std_dev^2 + f(x,mean,std_dev) = -------------------- * e^ + sqrt(2*pi*std_dev^2) + + */ + + float tmp = ( 1.0f / sqrt( 2.0f * PI * std_deviation * std_deviation ) ); + float tmp2 = exp( ( -( ( x - mean ) * ( x - mean ) ) ) / ( 2.0f * std_deviation * std_deviation ) ); + return tmp * tmp2; +} + +void main() +{ + vec4 color = vec4( 0.0f, 0.0f, 0.0f, 0.0f ); + float offset = 0; + float weight = 0; + float x = 0; + float fI = 0; + + for( int i = 0; i < 9; i++ ) + { + fI = float(i); + offset = (i - 4.0) * oneOverTargetSize.x; + x = (i - 4.0) / 4.0; + weight = gaussMultiplier * computeGaussianValue( x, gaussMean, gaussStdDev ); + color += (texture( inputTex, IN_uv0 + vec2( offset, 0.0f ) ) * weight ); + } + + OUT_col = vec4( color.rgb, 1.0f ); +} \ No newline at end of file diff --git a/Templates/BaseGame/game/core/rendering/shaders/postFX/hdr/gl/bloomGaussBlurVP.glsl b/Templates/BaseGame/game/core/rendering/shaders/postFX/hdr/gl/bloomGaussBlurVP.glsl new file mode 100644 index 000000000..68f34b164 --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/postFX/hdr/gl/bloomGaussBlurVP.glsl @@ -0,0 +1,71 @@ +//----------------------------------------------------------------------------- +// 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/postFX.glsl" + +uniform sampler2D inputTex ; +uniform vec2 oneOverTargetSize; +uniform float gaussMultiplier; +uniform float gaussMean; +uniform float gaussStdDev; + +out vec4 OUT_col; + +#define D3DX_PI 3.141592654 + +float computeGaussianValue( float x, float mean, float std_deviation ) +{ + // The gaussian equation is defined as such: + /* + -(x - mean)^2 + ------------- + 1.0 2*std_dev^2 + f(x,mean,std_dev) = -------------------- * e^ + sqrt(2*pi*std_dev^2) + + */ + float tmp = ( 1.0f / sqrt( 2.0f * D3DX_PI * std_deviation * std_deviation ) ); + float tmp2 = exp( ( -( ( x - mean ) * ( x - mean ) ) ) / ( 2.0f * std_deviation * std_deviation ) ); + return tmp * tmp2; +} + +void main() +{ + vec4 color = vec4( 0.0f, 0.0f, 0.0f, 0.0f ); + float offset = 0; + float weight = 0; + float x = 0; + float fI = 0; + + for( int i = 0; i < 9; i++ ) + { + fI = float(i); + offset = (fI - 4.0) * oneOverTargetSize.y; + x = (fI - 4.0) / 4.0; + weight = gaussMultiplier * computeGaussianValue( x, gaussMean, gaussStdDev ); + color += (texture( inputTex, IN_uv0 + vec2( 0.0f, offset ) ) * weight ); + } + + OUT_col = vec4( color.rgb, 1.0f ); +} \ No newline at end of file diff --git a/Templates/BaseGame/game/core/rendering/shaders/postFX/hdr/gl/brightPassFilterP.glsl b/Templates/BaseGame/game/core/rendering/shaders/postFX/hdr/gl/brightPassFilterP.glsl new file mode 100644 index 000000000..f220ca1e7 --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/postFX/hdr/gl/brightPassFilterP.glsl @@ -0,0 +1,65 @@ +//----------------------------------------------------------------------------- +// 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/torque.glsl" +#include "../../../gl/hlslCompat.glsl" +#include "shadergen:/autogenConditioners.h" +#include "../../gl/postFX.glsl" + +uniform sampler2D inputTex ; +uniform sampler2D luminanceTex ; +uniform vec2 oneOverTargetSize; +uniform float brightPassThreshold; +uniform float g_fMiddleGray; + +const vec3 LUMINANCE_VECTOR = vec3(0.3125f, 0.6154f, 0.0721f); + +out vec4 OUT_col; + + +const vec2 gTapOffsets[4] = vec2[] +( + vec2( -0.5, 0.5 ), vec2( 0.5, -0.5 ), + vec2( -0.5, -0.5 ), vec2( 0.5, 0.5 ) +); + +void main() +{ + vec4 average = vec4( 0.0f, 0.0f, 0.0f, 0.0f ); + + // Combine and average 4 samples from the source HDR texture. + for( int i = 0; i < 4; i++ ) + average += hdrDecode( texture( inputTex, IN_uv0 + ( gTapOffsets[i] * oneOverTargetSize ) ) ); + average *= 0.25f; + + // Determine the brightness of this particular pixel. + float adaptedLum = texture( luminanceTex, vec2( 0.5f, 0.5f ) ).r; + float lum = (g_fMiddleGray / (adaptedLum + 0.0001)) * hdrLuminance( average.rgb ); + //float lum = hdrLuminance( average.rgb ); + + // Determine whether this pixel passes the test... + if ( lum < brightPassThreshold ) + average = vec4( 0.0f, 0.0f, 0.0f, 1.0f ); + + // Write the colour to the bright-pass render target + OUT_col = hdrEncode( average ); +} diff --git a/Templates/BaseGame/game/core/rendering/shaders/postFX/hdr/gl/calculateAdaptedLumP.glsl b/Templates/BaseGame/game/core/rendering/shaders/postFX/hdr/gl/calculateAdaptedLumP.glsl new file mode 100644 index 000000000..96ee9d6df --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/postFX/hdr/gl/calculateAdaptedLumP.glsl @@ -0,0 +1,48 @@ +//----------------------------------------------------------------------------- +// 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/postFX.glsl" + +uniform sampler2D currLum; +uniform sampler2D lastAdaptedLum; + +uniform float adaptRate; +uniform float deltaTime; + +out vec4 OUT_col; + +void main() +{ + float fAdaptedLum = texture( lastAdaptedLum, vec2(0.5f, 0.5f) ).r; + float fCurrentLum = texture( currLum, vec2(0.5f, 0.5f) ).r; + + // The user's adapted luminance level is simulated by closing the gap between + // adapted luminance and current luminance by 2% every frame, based on a + // 30 fps rate. This is not an accurate model of human adaptation, which can + // take longer than half an hour. + float diff = fCurrentLum - fAdaptedLum; + float fNewAdaptation = fAdaptedLum + ( diff * ( 1.0 - exp( -deltaTime * adaptRate ) ) ); + + OUT_col = vec4( fNewAdaptation, 0.0, 0.0, 1.0f ); +} diff --git a/Templates/BaseGame/game/core/rendering/shaders/postFX/hdr/gl/downScale4x4P.glsl b/Templates/BaseGame/game/core/rendering/shaders/postFX/hdr/gl/downScale4x4P.glsl new file mode 100644 index 000000000..131671760 --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/postFX/hdr/gl/downScale4x4P.glsl @@ -0,0 +1,50 @@ +//----------------------------------------------------------------------------- +// 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. +//----------------------------------------------------------------------------- + +#define IN_GLSL +#include "../../../shdrConsts.h" +#include "../../../gl/hlslCompat.glsl" +#include "shadergen:/autogenConditioners.h" + +in vec4 texCoords[8]; +#define IN_texCoords texCoords + +uniform sampler2D inputTex; + +out vec4 OUT_col; + +//----------------------------------------------------------------------------- +// Main +//----------------------------------------------------------------------------- +void main() +{ + // We calculate the texture coords + // in the vertex shader as an optimization. + vec4 _sample = vec4(0.0f); + for ( int i = 0; i < 8; i++ ) + { + _sample += texture( inputTex, IN_texCoords[i].xy ); + _sample += texture( inputTex, IN_texCoords[i].zw ); + } + + OUT_col = _sample / 16; +} \ No newline at end of file diff --git a/Templates/BaseGame/game/core/rendering/shaders/postFX/hdr/gl/downScale4x4V.glsl b/Templates/BaseGame/game/core/rendering/shaders/postFX/hdr/gl/downScale4x4V.glsl new file mode 100644 index 000000000..51f1da896 --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/postFX/hdr/gl/downScale4x4V.glsl @@ -0,0 +1,141 @@ +//----------------------------------------------------------------------------- +// 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. +//----------------------------------------------------------------------------- + +#define IN_GLSL +#include "../../../shdrConsts.h" +#include "../../../gl/hlslCompat.glsl" + +in vec4 vPosition; +in vec2 vTexCoord0; + +#define In_pos vPosition +#define In_uv vTexCoord0 + +//----------------------------------------------------------------------------- +// Constants +//----------------------------------------------------------------------------- +out vec4 texCoords[8]; +#define Out_texCoords texCoords + +#define Out_hpos gl_Position + +uniform vec2 targetSize; + +//----------------------------------------------------------------------------- +// Main +//----------------------------------------------------------------------------- +void main() +{ + Out_hpos = In_pos; + + // Sample from the 16 surrounding points. Since the center point will be in + // the exact center of 16 texels, a 0.5f offset is needed to specify a texel + // center. + vec2 texSize = vec2( 1.0 / (targetSize.x - 1.0), 1.0 / (targetSize.y - 1.0) ); + + vec4 uv; + uv.xy = In_uv.xy; + uv.zw = In_uv.xy; + + Out_texCoords[0] = uv; + Out_texCoords[0].x += texSize.x; + Out_texCoords[0].y += texSize.y; + Out_texCoords[0].z += texSize.x; + Out_texCoords[0].w += texSize.y; + Out_texCoords[0].x += ( 0 - 1.5 ) * texSize.x; + Out_texCoords[0].y += ( 0 - 1.5 ) * texSize.y; + Out_texCoords[0].z += ( 1 - 1.5 ) * texSize.x; + Out_texCoords[0].w += ( 0 - 1.5 ) * texSize.y; + + Out_texCoords[1] = uv; + Out_texCoords[1].x += texSize.x; + Out_texCoords[1].y += texSize.y; + Out_texCoords[1].z += texSize.x; + Out_texCoords[1].w += texSize.y; + Out_texCoords[1].x += ( 2 - 1.5 ) * texSize.x; + Out_texCoords[1].y += ( 0 - 1.5 ) * texSize.y; + Out_texCoords[1].z += ( 3 - 1.5 ) * texSize.x; + Out_texCoords[1].w += ( 0 - 1.5 ) * texSize.y; + + Out_texCoords[2] = uv; + Out_texCoords[2].x += texSize.x; + Out_texCoords[2].y += texSize.y; + Out_texCoords[2].z += texSize.x; + Out_texCoords[2].w += texSize.y; + Out_texCoords[2].x += ( 0 - 1.5 ) * texSize.x; + Out_texCoords[2].y += ( 1 - 1.5 ) * texSize.y; + Out_texCoords[2].z += ( 1 - 1.5 ) * texSize.x; + Out_texCoords[2].w += ( 1 - 1.5 ) * texSize.y; + + Out_texCoords[3] = uv; + Out_texCoords[3].x += texSize.x; + Out_texCoords[3].y += texSize.y; + Out_texCoords[3].z += texSize.x; + Out_texCoords[3].w += texSize.y; + Out_texCoords[3].x += ( 2 - 1.5 ) * texSize.x; + Out_texCoords[3].y += ( 1 - 1.5 ) * texSize.y; + Out_texCoords[3].z += ( 3 - 1.5 ) * texSize.x; + Out_texCoords[3].w += ( 1 - 1.5 ) * texSize.y; + + Out_texCoords[4] = uv; + Out_texCoords[4].x += texSize.x; + Out_texCoords[4].y += texSize.y; + Out_texCoords[4].z += texSize.x; + Out_texCoords[4].w += texSize.y; + Out_texCoords[4].x += ( 0 - 1.5 ) * texSize.x; + Out_texCoords[4].y += ( 2 - 1.5 ) * texSize.y; + Out_texCoords[4].z += ( 1 - 1.5 ) * texSize.x; + Out_texCoords[4].w += ( 2 - 1.5 ) * texSize.y; + + Out_texCoords[5] = uv; + Out_texCoords[5].x += texSize.x; + Out_texCoords[5].y += texSize.y; + Out_texCoords[5].z += texSize.x; + Out_texCoords[5].w += texSize.y; + Out_texCoords[5].x += ( 2 - 1.5 ) * texSize.x; + Out_texCoords[5].y += ( 2 - 1.5 ) * texSize.y; + Out_texCoords[5].z += ( 3 - 1.5 ) * texSize.x; + Out_texCoords[5].w += ( 2 - 1.5 ) * texSize.y; + + Out_texCoords[6] = uv; + Out_texCoords[6].x += texSize.x; + Out_texCoords[6].y += texSize.y; + Out_texCoords[6].z += texSize.x; + Out_texCoords[6].w += texSize.y; + Out_texCoords[6].x += ( 0 - 1.5 ) * texSize.x; + Out_texCoords[6].y += ( 3 - 1.5 ) * texSize.y; + Out_texCoords[6].z += ( 1 - 1.5 ) * texSize.x; + Out_texCoords[6].w += ( 3 - 1.5 ) * texSize.y; + + Out_texCoords[7] = uv; + Out_texCoords[7].x += texSize.x; + Out_texCoords[7].y += texSize.y; + Out_texCoords[7].z += texSize.x; + Out_texCoords[7].w += texSize.y; + Out_texCoords[7].x += ( 2 - 1.5 ) * texSize.x; + Out_texCoords[7].y += ( 3 - 1.5 ) * texSize.y; + Out_texCoords[7].z += ( 3 - 1.5 ) * texSize.x; + Out_texCoords[7].w += ( 3 - 1.5 ) * texSize.y; + + correctSSP(gl_Position); +} + diff --git a/Templates/BaseGame/game/core/rendering/shaders/postFX/hdr/gl/finalPassCombineP.glsl b/Templates/BaseGame/game/core/rendering/shaders/postFX/hdr/gl/finalPassCombineP.glsl new file mode 100644 index 000000000..4b173d4d3 --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/postFX/hdr/gl/finalPassCombineP.glsl @@ -0,0 +1,97 @@ +//----------------------------------------------------------------------------- +// 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/torque.glsl" +#include "../../../gl/hlslCompat.glsl" +#include "../../gl/postFX.glsl" +#include "shadergen:/autogenConditioners.h" + +uniform sampler2D sceneTex; +uniform sampler2D luminanceTex; +uniform sampler2D bloomTex; +uniform sampler1D colorCorrectionTex; + +uniform vec2 texSize0; +uniform vec2 texSize2; + +uniform float g_fEnableToneMapping; +uniform float g_fMiddleGray; +uniform float g_fWhiteCutoff; + +uniform float g_fEnableBlueShift; +uniform vec3 g_fBlueShiftColor; + +uniform float g_fBloomScale; + +uniform float g_fOneOverGamma; +uniform float Brightness; +uniform float Contrast; + +out vec4 OUT_col; + +void main() +{ + vec4 _sample = hdrDecode( texture( sceneTex, IN_uv0 ) ); + float adaptedLum = texture( luminanceTex, vec2( 0.5f, 0.5f ) ).r; + vec4 bloom = texture( bloomTex, IN_uv0 ); + + // For very low light conditions, the rods will dominate the perception + // of light, and therefore color will be desaturated and shifted + // towards blue. + if ( g_fEnableBlueShift > 0.0f ) + { + const vec3 LUMINANCE_VECTOR = vec3(0.2125f, 0.7154f, 0.0721f); + + // Define a linear blending from -1.5 to 2.6 (log scale) which + // determines the mix amount for blue shift + float coef = 1.0f - ( adaptedLum + 1.5 ) / 4.1; + coef = saturate( coef * g_fEnableBlueShift ); + + // Lerp between current color and blue, desaturated copy + vec3 rodColor = dot( _sample.rgb, LUMINANCE_VECTOR ) * g_fBlueShiftColor; + _sample.rgb = mix( _sample.rgb, rodColor, coef ); + + rodColor = dot( bloom.rgb, LUMINANCE_VECTOR ) * g_fBlueShiftColor; + bloom.rgb = mix( bloom.rgb, rodColor, coef ); + } + + // Add the bloom effect. + _sample += g_fBloomScale * bloom; + + // Map the high range of color values into a range appropriate for + // display, taking into account the user's adaptation level, + // white point, and selected value for for middle gray. + if ( g_fEnableToneMapping > 0.0f ) + { + float Lp = (g_fMiddleGray / (adaptedLum + 0.0001)) * hdrLuminance( _sample.rgb ); + //float toneScalar = ( Lp * ( 1.0 + ( Lp / ( g_fWhiteCutoff ) ) ) ) / ( 1.0 + Lp ); + float toneScalar = Lp; + _sample.rgb = mix( _sample.rgb, _sample.rgb * toneScalar, g_fEnableToneMapping ); + } + + // Apply the color correction. + _sample.r = texture( colorCorrectionTex, _sample.r ).r; + _sample.g = texture( colorCorrectionTex, _sample.g ).g; + _sample.b = texture( colorCorrectionTex, _sample.b ).b; + + OUT_col = _sample; +} diff --git a/Templates/BaseGame/game/core/rendering/shaders/postFX/hdr/gl/luminanceVisP.glsl b/Templates/BaseGame/game/core/rendering/shaders/postFX/hdr/gl/luminanceVisP.glsl new file mode 100644 index 000000000..ee9c28c87 --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/postFX/hdr/gl/luminanceVisP.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/torque.glsl" +#include "../../../gl/hlslCompat.glsl" +#include "shadergen:/autogenConditioners.h" +#include "../../gl/postFX.glsl" + +uniform sampler2D inputTex; +uniform float brightPassThreshold; + +out vec4 OUT_col; + +void main() +{ + vec4 _sample = hdrDecode( texture( inputTex, IN_uv0 ) ); + + // Determine the brightness of this particular pixel. + float lum = hdrLuminance( _sample.rgb ); + + // Write the colour to the bright-pass render target + OUT_col = ( vec4( lum.rrr, 1 ) ); +} diff --git a/Templates/BaseGame/game/core/rendering/shaders/postFX/hdr/gl/sampleLumInitialP.glsl b/Templates/BaseGame/game/core/rendering/shaders/postFX/hdr/gl/sampleLumInitialP.glsl new file mode 100644 index 000000000..8a2b9b318 --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/postFX/hdr/gl/sampleLumInitialP.glsl @@ -0,0 +1,62 @@ +//----------------------------------------------------------------------------- +// 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/torque.glsl" +#include "../../../gl/hlslCompat.glsl" +#include "../../gl/postFX.glsl" + +uniform sampler2D inputTex; +uniform vec2 texSize0; + +uniform float g_fMinLuminace; + +out vec4 OUT_col; + +const vec2 gTapOffsets[9] = vec2[] +( + vec2( -1.0, -1.0 ), vec2( 0.0, -1.0 ), vec2( 1.0, -1.0 ), + vec2( -1.0, 0.0 ), vec2( 0.0, 0.0 ), vec2( 1.0, 0.0 ), + vec2( -1.0, 1.0 ), vec2( 0.0, 1.0 ), vec2( 1.0, 1.0 ) +); + + +void main() +{ + vec2 tsize = 1.0 / texSize0; + + vec3 _sample; + float average = 0.0; + + for ( int i = 0; i < 9; i++ ) + { + // Decode the hdr value. + _sample = hdrDecode( texture( inputTex, IN_uv0 + ( gTapOffsets[i] * tsize ) ).rgb ); + + // Get the luminance and add it to the average. + float lum = max( hdrLuminance( _sample ), g_fMinLuminace ); + average += log( lum ); + } + + average = exp( average / 9.0 ); + + OUT_col = vec4( average, 0.0, 0.0, 1.0 ); +} diff --git a/Templates/BaseGame/game/core/rendering/shaders/postFX/hdr/gl/sampleLumIterativeP.glsl b/Templates/BaseGame/game/core/rendering/shaders/postFX/hdr/gl/sampleLumIterativeP.glsl new file mode 100644 index 000000000..2e800d612 --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/postFX/hdr/gl/sampleLumIterativeP.glsl @@ -0,0 +1,52 @@ +//----------------------------------------------------------------------------- +// 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 "../../gl/postFX.glsl" + +uniform sampler2D inputTex; +uniform vec2 oneOverTargetSize; + +out vec4 OUT_col; + +const vec2 gTapOffsets[16] = vec2[] +( + vec2( -1.5, -1.5 ), vec2( -0.5, -1.5 ), vec2( 0.5, -1.5 ), vec2( 1.5, -1.5 ), + vec2( -1.5, -0.5 ), vec2( -0.5, -0.5 ), vec2( 0.5, -0.5 ), vec2( 1.5, -0.5 ), + vec2( -1.5, 0.5 ), vec2( -0.5, 0.5 ), vec2( 0.5, 0.5 ), vec2( 1.5, 0.5 ), + vec2( -1.5, 1.5 ), vec2( -0.5, 1.5 ), vec2( 0.5, 1.5 ), vec2( 1.5, 1.5 ) +); + +void main() +{ + vec2 pixelSize = oneOverTargetSize; + + float average = 0.0; + + for ( int i = 0; i < 16; i++ ) + { + float lum = texture( inputTex, IN_uv0 + ( gTapOffsets[i] * pixelSize ) ).r; + average += lum; + } + + OUT_col = vec4( average / 16.0, 0.0, 0.0, 1.0 ); +} diff --git a/Templates/BaseGame/game/core/rendering/shaders/postFX/hdr/luminanceVisP.hlsl b/Templates/BaseGame/game/core/rendering/shaders/postFX/hdr/luminanceVisP.hlsl new file mode 100644 index 000000000..505d1b825 --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/postFX/hdr/luminanceVisP.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. +//----------------------------------------------------------------------------- + +#include "../postFx.hlsl" +#include "../../torque.hlsl" + + +TORQUE_UNIFORM_SAMPLER2D(inputTex, 0); +uniform float brightPassThreshold; + +float4 main( PFXVertToPix IN ) : TORQUE_TARGET0 +{ + float4 sample = hdrDecode( TORQUE_TEX2D( inputTex, IN.uv0 ) ); + + // Determine the brightness of this particular pixel. + float lum = hdrLuminance( sample.rgb ); + + // Write the colour to the bright-pass render target + return ( float4( lum.rrr, 1 ) ); +} diff --git a/Templates/BaseGame/game/core/rendering/shaders/postFX/hdr/sampleLumInitialP.hlsl b/Templates/BaseGame/game/core/rendering/shaders/postFX/hdr/sampleLumInitialP.hlsl new file mode 100644 index 000000000..2e23ece1f --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/postFX/hdr/sampleLumInitialP.hlsl @@ -0,0 +1,59 @@ +//----------------------------------------------------------------------------- +// 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 "../../torque.hlsl" +#include "../postFx.hlsl" + +TORQUE_UNIFORM_SAMPLER2D(inputTex, 0); +uniform float2 texSize0; + +uniform float g_fMinLuminace; + +static float2 gTapOffsets[9] = +{ + { -1.0, -1.0 }, { 0.0, -1.0 }, { 1.0, -1.0 }, + { -1.0, 0.0 }, { 0.0, 0.0 }, { 1.0, 0.0 }, + { -1.0, 1.0 }, { 0.0, 1.0 }, { 1.0, 1.0 } +}; + + +float4 main( PFXVertToPix IN ) : TORQUE_TARGET0 +{ + float2 tsize = 1.0 / texSize0; + + float3 sample; + float average = 0.0; + + for ( int i = 0; i < 9; i++ ) + { + // Decode the hdr value. + sample = hdrDecode( TORQUE_TEX2D( inputTex, IN.uv0 + ( gTapOffsets[i] * tsize ) ).rgb ); + + // Get the luminance and add it to the average. + float lum = max( hdrLuminance( sample ), g_fMinLuminace ); + average += log( lum ); + } + + average = exp( average / 9.0 ); + + return float4( average, 0.0, 0.0, 1.0 ); +} diff --git a/Templates/BaseGame/game/core/rendering/shaders/postFX/hdr/sampleLumIterativeP.hlsl b/Templates/BaseGame/game/core/rendering/shaders/postFX/hdr/sampleLumIterativeP.hlsl new file mode 100644 index 000000000..46ed6fc70 --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/postFX/hdr/sampleLumIterativeP.hlsl @@ -0,0 +1,50 @@ +//----------------------------------------------------------------------------- +// 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 "../postFx.hlsl" + +TORQUE_UNIFORM_SAMPLER2D(inputTex, 0); +uniform float2 oneOverTargetSize; + + +static float2 gTapOffsets[16] = +{ + { -1.5, -1.5 }, { -0.5, -1.5 }, { 0.5, -1.5 }, { 1.5, -1.5 }, + { -1.5, -0.5 }, { -0.5, -0.5 }, { 0.5, -0.5 }, { 1.5, -0.5 }, + { -1.5, 0.5 }, { -0.5, 0.5 }, { 0.5, 0.5 }, { 1.5, 0.5 }, + { -1.5, 1.5 }, { -0.5, 1.5 }, { 0.5, 1.5 }, { 1.5, 1.5 } +}; + +float4 main( PFXVertToPix IN ) : TORQUE_TARGET0 +{ + float2 pixelSize = oneOverTargetSize; + + float average = 0.0; + + for ( int i = 0; i < 16; i++ ) + { + float lum = TORQUE_TEX2D( inputTex, IN.uv0 + ( gTapOffsets[i] * pixelSize ) ).r; + average += lum; + } + + return float4( average / 16.0, 0.0, 0.0, 1.0 ); +} diff --git a/Templates/BaseGame/game/core/rendering/shaders/postFX/lightRay/gl/lightRayOccludeP.glsl b/Templates/BaseGame/game/core/rendering/shaders/postFX/lightRay/gl/lightRayOccludeP.glsl new file mode 100644 index 000000000..59f5f4bbf --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/postFX/lightRay/gl/lightRayOccludeP.glsl @@ -0,0 +1,55 @@ +//----------------------------------------------------------------------------- +// 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/postFX.glsl" + +uniform sampler2D backBuffer; // The original backbuffer. +uniform sampler2D deferredTex; // The pre-pass depth and normals. + +uniform float brightScalar; + +const vec3 LUMINANCE_VECTOR = vec3(0.3125f, 0.6154f, 0.0721f); + +out vec4 OUT_col; + +void main() +{ + vec4 col = vec4( 0, 0, 0, 1 ); + + // Get the depth at this pixel. + float depth = deferredUncondition( deferredTex, IN_uv0 ).w; + + // If the depth is equal to 1.0, read from the backbuffer + // and perform the exposure calculation on the result. + if ( depth >= 0.999 ) + { + col = texture( backBuffer, IN_uv0 ); + + //col = 1 - exp(-120000 * col); + col += dot( vec3(col), LUMINANCE_VECTOR ) + 0.0001f; + col *= brightScalar; + } + + OUT_col = col; +} diff --git a/Templates/BaseGame/game/core/rendering/shaders/postFX/lightRay/gl/lightRayP.glsl b/Templates/BaseGame/game/core/rendering/shaders/postFX/lightRay/gl/lightRayP.glsl new file mode 100644 index 000000000..6d78f4eae --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/postFX/lightRay/gl/lightRayP.glsl @@ -0,0 +1,94 @@ +//----------------------------------------------------------------------------- +// 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 "../../gl/postFX.glsl" + +uniform sampler2D frameSampler; +uniform sampler2D backBuffer; + +uniform vec3 camForward; +uniform vec3 lightDirection; +uniform vec2 screenSunPos; +uniform vec2 oneOverTargetSize; +uniform int numSamples; +uniform float density; +uniform float weight; +uniform float decay; +uniform float exposure; + +out vec4 OUT_col; + +void main() +{ + vec4 texCoord = vec4( IN_uv0.xy, 0, 0 ); + + // Store initial sample. + half3 color = half3(texture( frameSampler, texCoord.xy ).rgb); + + // Store original bb color. + vec4 bbCol = texture( backBuffer, IN_uv1 ); + + // Set up illumination decay factor. + half illuminationDecay = 1.0; + + float amount = saturate( dot( -lightDirection, camForward ) ); + + int samples = int(numSamples * amount); + + if ( samples <= 0 ) + { + OUT_col = bbCol; + return; + } + + // Calculate vector from pixel to light source in screen space. + half2 deltaTexCoord = half2( texCoord.xy - screenSunPos ); + + // Divide by number of samples and scale by control factor. + deltaTexCoord *= 1.0 / half(samples * density); + + // Evaluate summation from Equation 3 NUM_SAMPLES iterations. + for ( int i = 0; i < samples; i++ ) + { + // Step sample location along ray. + texCoord.xy -= deltaTexCoord; + + // Retrieve sample at new location. + half3 sample_ = half3(tex2Dlod( frameSampler, texCoord )); + + // Apply sample attenuation scale/decay factors. + sample_ *= illuminationDecay * weight; + + // Accumulate combined color. + color += sample_; + + // Update exponential decay factor. + illuminationDecay *= decay; + } + + //return saturate( amount ) * color * Exposure; + //return bbCol * decay; + + // Output final color with a further scale control factor. + OUT_col = saturate( amount ) * vec4( color * exposure, 1 ) + bbCol; +} diff --git a/Templates/BaseGame/game/core/rendering/shaders/postFX/lightRay/lightRayOccludeP.hlsl b/Templates/BaseGame/game/core/rendering/shaders/postFX/lightRay/lightRayOccludeP.hlsl new file mode 100644 index 000000000..5db6ecb5b --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/postFX/lightRay/lightRayOccludeP.hlsl @@ -0,0 +1,53 @@ +//----------------------------------------------------------------------------- +// 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 "../../shaderModelAutoGen.hlsl" +#include "../postFx.hlsl" + +TORQUE_UNIFORM_SAMPLER2D(backBuffer, 0); +TORQUE_UNIFORM_SAMPLER2D(deferredTex, 1); + +uniform float brightScalar; + +static const float3 LUMINANCE_VECTOR = float3(0.3125f, 0.6154f, 0.0721f); + + +float4 main( PFXVertToPix IN ) : TORQUE_TARGET0 +{ + float4 col = float4( 0, 0, 0, 1 ); + + // Get the depth at this pixel. + float depth = TORQUE_DEFERRED_UNCONDITION( deferredTex, IN.uv0 ).w; + + // If the depth is equal to 1.0, read from the backbuffer + // and perform the exposure calculation on the result. + if ( depth >= 0.999 ) + { + col = TORQUE_TEX2D( backBuffer, IN.uv0 ); + + //col = 1 - exp(-120000 * col); + col += dot( col.rgb, LUMINANCE_VECTOR ) + 0.0001f; + col *= brightScalar; + } + + return col; +} diff --git a/Templates/BaseGame/game/core/rendering/shaders/postFX/lightRay/lightRayP.hlsl b/Templates/BaseGame/game/core/rendering/shaders/postFX/lightRay/lightRayP.hlsl new file mode 100644 index 000000000..032894710 --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/postFX/lightRay/lightRayP.hlsl @@ -0,0 +1,89 @@ +//----------------------------------------------------------------------------- +// 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 "../postFx.hlsl" + +TORQUE_UNIFORM_SAMPLER2D(frameSampler, 0); +TORQUE_UNIFORM_SAMPLER2D(backBuffer, 1); + + +uniform float3 camForward; +uniform int numSamples; +uniform float3 lightDirection; +uniform float density; +uniform float2 screenSunPos; +uniform float2 oneOverTargetSize; +uniform float weight; +uniform float decay; +uniform float exposure; + +float4 main( PFXVertToPix IN ) : TORQUE_TARGET0 +{ + float4 texCoord = float4( IN.uv0.xy, 0, 0 ); + + // Store initial sample. + half3 color = (half3)TORQUE_TEX2D( frameSampler, texCoord.xy ).rgb; + + // Store original bb color. + float4 bbCol = TORQUE_TEX2D( backBuffer, IN.uv1 ); + + // Set up illumination decay factor. + half illuminationDecay = 1.0; + + float amount = saturate( dot( -lightDirection, camForward ) ); + + int samples = numSamples * amount; + + if ( samples <= 0 ) + return bbCol; + + // Calculate vector from pixel to light source in screen space. + half2 deltaTexCoord = (half2)( texCoord.xy - screenSunPos ); + + // Divide by number of samples and scale by control factor. + deltaTexCoord *= (half)(1.0 / samples * density); + + // Evaluate summation from Equation 3 NUM_SAMPLES iterations. + for ( int i = 0; i < samples; i++ ) + { + // Step sample location along ray. + texCoord.xy -= deltaTexCoord; + + // Retrieve sample at new location. + half3 sample = (half3)TORQUE_TEX2DLOD( frameSampler, texCoord ); + + // Apply sample attenuation scale/decay factors. + sample *= half(illuminationDecay * weight); + + // Accumulate combined color. + color += sample; + + // Update exponential decay factor. + illuminationDecay *= half(decay); + } + + //return saturate( amount ) * color * Exposure; + //return bbCol * decay; + + // Output final color with a further scale control factor. + return saturate( amount ) * float4( color * exposure, 1 ) + bbCol; +} diff --git a/Templates/BaseGame/game/core/rendering/shaders/postFX/mlaa/blendWeightCalculationP.hlsl b/Templates/BaseGame/game/core/rendering/shaders/postFX/mlaa/blendWeightCalculationP.hlsl new file mode 100644 index 000000000..2c4777c36 --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/postFX/mlaa/blendWeightCalculationP.hlsl @@ -0,0 +1,78 @@ +//----------------------------------------------------------------------------- +// 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. +//----------------------------------------------------------------------------- + +// An implementation of "Practical Morphological Anti-Aliasing" from +// GPU Pro 2 by Jorge Jimenez, Belen Masia, Jose I. Echevarria, +// Fernando Navarro, and Diego Gutierrez. +// +// http://www.iryoku.com/mlaa/ + + +uniform sampler2D edgesMap : register(S0); +uniform sampler2D edgesMapL : register(S1); +uniform sampler2D areaMap : register(S2); + +#include "./functions.hlsl" + + +float4 main(float2 texcoord : TEXCOORD0) : COLOR0 +{ + float4 areas = 0.0; + + float2 e = tex2D(edgesMap, texcoord).rg; + + [branch] + if (e.g) // Edge at north + { + // Search distances to the left and to the right: + float2 d = float2(SearchXLeft(texcoord), SearchXRight(texcoord)); + + // Now fetch the crossing edges. Instead of sampling between edgels, we + // sample at -0.25, to be able to discern what value has each edgel: + float4 coords = mad(float4(d.x, -0.25, d.y + 1.0, -0.25), + PIXEL_SIZE.xyxy, texcoord.xyxy); + float e1 = tex2Dlevel0(edgesMapL, coords.xy).r; + float e2 = tex2Dlevel0(edgesMapL, coords.zw).r; + + // Ok, we know how this pattern looks like, now it is time for getting + // the actual area: + areas.rg = Area(abs(d), e1, e2); + } + + [branch] + if (e.r) // Edge at west + { + // Search distances to the top and to the bottom: + float2 d = float2(SearchYUp(texcoord), SearchYDown(texcoord)); + + // Now fetch the crossing edges (yet again): + float4 coords = mad(float4(-0.25, d.x, -0.25, d.y + 1.0), + PIXEL_SIZE.xyxy, texcoord.xyxy); + float e1 = tex2Dlevel0(edgesMapL, coords.xy).g; + float e2 = tex2Dlevel0(edgesMapL, coords.zw).g; + + // Get the area for this direction: + areas.ba = Area(abs(d), e1, e2); + } + + return areas; +} \ No newline at end of file diff --git a/Templates/BaseGame/game/core/rendering/shaders/postFX/mlaa/edgeDetectionP.hlsl b/Templates/BaseGame/game/core/rendering/shaders/postFX/mlaa/edgeDetectionP.hlsl new file mode 100644 index 000000000..7d5c7f057 --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/postFX/mlaa/edgeDetectionP.hlsl @@ -0,0 +1,72 @@ +//----------------------------------------------------------------------------- +// 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. +//----------------------------------------------------------------------------- + +// An implementation of "Practical Morphological Anti-Aliasing" from +// GPU Pro 2 by Jorge Jimenez, Belen Masia, Jose I. Echevarria, +// Fernando Navarro, and Diego Gutierrez. +// +// http://www.iryoku.com/mlaa/ + +#include "shadergen:/autogenConditioners.h" + +uniform sampler2D colorMapG : register(S0); +uniform sampler2D deferredMap : register(S1); + +uniform float3 lumaCoefficients; +uniform float threshold; +uniform float depthThreshold; + + +float4 main( float2 texcoord : TEXCOORD0, + float4 offset[2]: TEXCOORD1) : COLOR0 +{ + // Luma calculation requires gamma-corrected colors (texture 'colorMapG'). + // + // Note that there is a lot of overlapped luma calculations; performance + // can be improved if this luma calculation is performed in the main pass, + // which may give you an edge if used in conjunction with a z deferred. + + float L = dot(tex2D(colorMapG, texcoord).rgb, lumaCoefficients); + + float Lleft = dot(tex2D(colorMapG, offset[0].xy).rgb, lumaCoefficients); + float Ltop = dot(tex2D(colorMapG, offset[0].zw).rgb, lumaCoefficients); + float Lright = dot(tex2D(colorMapG, offset[1].xy).rgb, lumaCoefficients); + float Lbottom = dot(tex2D(colorMapG, offset[1].zw).rgb, lumaCoefficients); + + float4 delta = abs(L.xxxx - float4(Lleft, Ltop, Lright, Lbottom)); + float4 edges = step(threshold, delta); + + // Add depth edges to color edges + float D = deferredUncondition(deferredMap, texcoord).w; + float Dleft = deferredUncondition(deferredMap, offset[0].xy).w; + float Dtop = deferredUncondition(deferredMap, offset[0].zw).w; + float Dright = deferredUncondition(deferredMap, offset[1].xy).w; + float Dbottom = deferredUncondition(deferredMap, offset[1].zw).w; + + delta = abs(D.xxxx - float4(Dleft, Dtop, Dright, Dbottom)); + edges += step(depthThreshold, delta); + + if (dot(edges, 1.0) == 0.0) + discard; + + return edges; +} \ No newline at end of file diff --git a/Templates/BaseGame/game/core/rendering/shaders/postFX/mlaa/functions.hlsl b/Templates/BaseGame/game/core/rendering/shaders/postFX/mlaa/functions.hlsl new file mode 100644 index 000000000..9935a5e30 --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/postFX/mlaa/functions.hlsl @@ -0,0 +1,145 @@ +//----------------------------------------------------------------------------- +// 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. +//----------------------------------------------------------------------------- + +// An implementation of "Practical Morphological Anti-Aliasing" from +// GPU Pro 2 by Jorge Jimenez, Belen Masia, Jose I. Echevarria, +// Fernando Navarro, and Diego Gutierrez. +// +// http://www.iryoku.com/mlaa/ + + +uniform float2 texSize0; + +#if !defined(PIXEL_SIZE) +#define PIXEL_SIZE (1.0 / texSize0) +#define MAX_SEARCH_STEPS 8 +#define MAX_DISTANCE 33 +#endif + +// Typical Multiply-Add operation to ease translation to assembly code. + +float4 mad(float4 m, float4 a, float4 b) +{ + #if defined(XBOX) + float4 result; + asm { + mad result, m, a, b + }; + return result; + #else + return m * a + b; + #endif +} + + +// This one just returns the first level of a mip map chain, which allow us to +// avoid the nasty ddx/ddy warnings, even improving the performance a little +// bit. +float4 tex2Dlevel0(sampler2D map, float2 texcoord) +{ + return tex2Dlod(map, float4(texcoord, 0.0, 0.0)); +} + + +// Same as above, this eases translation to assembly code; +float4 tex2Doffset(sampler2D map, float2 texcoord, float2 offset) +{ + #if defined(XBOX) && MAX_SEARCH_STEPS < 6 + float4 result; + float x = offset.x; + float y = offset.y; + asm { + tfetch2D result, texcoord, map, OffsetX = x, OffsetY = y + }; + return result; + #else + return tex2Dlevel0(map, texcoord + PIXEL_SIZE * offset); + #endif +} + + +// Ok, we have the distance and both crossing edges, can you please return +// the float2 blending weights? +float2 Area(float2 distance, float e1, float e2) +{ + // * By dividing by areaSize - 1.0 below we are implicitely offsetting to + // always fall inside of a pixel + // * Rounding prevents bilinear access precision problems + float areaSize = MAX_DISTANCE * 5.0; + float2 pixcoord = MAX_DISTANCE * round(4.0 * float2(e1, e2)) + distance; + float2 texcoord = pixcoord / (areaSize - 1.0); + return tex2Dlevel0(areaMap, texcoord).rg; +} + + +// Search functions for the 2nd pass. +float SearchXLeft(float2 texcoord) +{ + // We compare with 0.9 to prevent bilinear access precision problems. + float i; + float e = 0.0; + for (i = -1.5; i > -2.0 * MAX_SEARCH_STEPS; i -= 2.0) + { + e = tex2Doffset(edgesMapL, texcoord, float2(i, 0.0)).g; + [flatten] if (e < 0.9) break; + } + return max(i + 1.5 - 2.0 * e, -2.0 * MAX_SEARCH_STEPS); +} + +// Search functions for the 2nd pass. +float SearchXRight(float2 texcoord) +{ + float i; + float e = 0.0; + for (i = 1.5; i < 2.0 * MAX_SEARCH_STEPS; i += 2.0) + { + e = tex2Doffset(edgesMapL, texcoord, float2(i, 0.0)).g; + [flatten] if (e < 0.9) break; + } + return min(i - 1.5 + 2.0 * e, 2.0 * MAX_SEARCH_STEPS); +} + +// Search functions for the 2nd pass. +float SearchYUp(float2 texcoord) +{ + float i; + float e = 0.0; + for (i = -1.5; i > -2.0 * MAX_SEARCH_STEPS; i -= 2.0) + { + e = tex2Doffset(edgesMapL, texcoord, float2(i, 0.0).yx).r; + [flatten] if (e < 0.9) break; + } + return max(i + 1.5 - 2.0 * e, -2.0 * MAX_SEARCH_STEPS); +} + +// Search functions for the 2nd pass. +float SearchYDown(float2 texcoord) +{ + float i; + float e = 0.0; + for (i = 1.5; i < 2.0 * MAX_SEARCH_STEPS; i += 2.0) + { + e = tex2Doffset(edgesMapL, texcoord, float2(i, 0.0).yx).r; + [flatten] if (e < 0.9) break; + } + return min(i - 1.5 + 2.0 * e, 2.0 * MAX_SEARCH_STEPS); +} diff --git a/Templates/BaseGame/game/core/rendering/shaders/postFX/mlaa/gl/blendWeightCalculationP.glsl b/Templates/BaseGame/game/core/rendering/shaders/postFX/mlaa/gl/blendWeightCalculationP.glsl new file mode 100644 index 000000000..af01ce6f9 --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/postFX/mlaa/gl/blendWeightCalculationP.glsl @@ -0,0 +1,83 @@ +//----------------------------------------------------------------------------- +// 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. +//----------------------------------------------------------------------------- + +// An implementation of "Practical Morphological Anti-Aliasing" from +// GPU Pro 2 by Jorge Jimenez, Belen Masia, Jose I. Echevarria, +// Fernando Navarro, and Diego Gutierrez. +// +// http://www.iryoku.com/mlaa/ + +#include "../../../gl/hlslCompat.glsl" + +in vec2 texcoord; + +uniform sampler2D edgesMap; +uniform sampler2D edgesMapL; +uniform sampler2D areaMap; + +out vec4 OUT_col; + +#include "./functions.glsl" + + +void main() +{ + vec4 areas = vec4(0.0); + + vec2 e = texture(edgesMap, texcoord).rg; + + //[branch] + if (bool(e.g)) // Edge at north + { + // Search distances to the left and to the right: + vec2 d = vec2(SearchXLeft(texcoord), SearchXRight(texcoord)); + + // Now fetch the crossing edges. Instead of sampling between edgels, we + // sample at -0.25, to be able to discern what value has each edgel: + vec4 coords = mad(vec4(d.x, -0.25, d.y + 1.0, -0.25), + PIXEL_SIZE.xyxy, texcoord.xyxy); + float e1 = tex2Dlevel0(edgesMapL, coords.xy).r; + float e2 = tex2Dlevel0(edgesMapL, coords.zw).r; + + // Ok, we know how this pattern looks like, now it is time for getting + // the actual area: + areas.rg = Area(abs(d), e1, e2); + } + + //[branch] + if (bool(e.r)) // Edge at west + { + // Search distances to the top and to the bottom: + vec2 d = vec2(SearchYUp(texcoord), SearchYDown(texcoord)); + + // Now fetch the crossing edges (yet again): + vec4 coords = mad(vec4(-0.25, d.x, -0.25, d.y + 1.0), + PIXEL_SIZE.xyxy, texcoord.xyxy); + float e1 = tex2Dlevel0(edgesMapL, coords.xy).g; + float e2 = tex2Dlevel0(edgesMapL, coords.zw).g; + + // Get the area for this direction: + areas.ba = Area(abs(d), e1, e2); + } + + OUT_col = areas; +} \ No newline at end of file diff --git a/Templates/BaseGame/game/core/rendering/shaders/postFX/mlaa/gl/edgeDetectionP.glsl b/Templates/BaseGame/game/core/rendering/shaders/postFX/mlaa/gl/edgeDetectionP.glsl new file mode 100644 index 000000000..d964a28a4 --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/postFX/mlaa/gl/edgeDetectionP.glsl @@ -0,0 +1,76 @@ +//----------------------------------------------------------------------------- +// 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. +//----------------------------------------------------------------------------- + +// An implementation of "Practical Morphological Anti-Aliasing" from +// GPU Pro 2 by Jorge Jimenez, Belen Masia, Jose I. Echevarria, +// Fernando Navarro, and Diego Gutierrez. +// +// http://www.iryoku.com/mlaa/ + +#include "../../../gl/hlslCompat.glsl" +#include "shadergen:/autogenConditioners.h" + +uniform sampler2D colorMapG; +uniform sampler2D deferredMap; + +uniform vec3 lumaCoefficients; +uniform float threshold; +uniform float depthThreshold; + +in vec2 texcoord; +in vec4 offset[2]; + +out vec4 OUT_col; + +void main() +{ + // Luma calculation requires gamma-corrected colors (texture 'colorMapG'). + // + // Note that there is a lot of overlapped luma calculations; performance + // can be improved if this luma calculation is performed in the main pass, + // which may give you an edge if used in conjunction with a z deferred. + + float L = dot(texture(colorMapG, texcoord).rgb, lumaCoefficients); + + float Lleft = dot(texture(colorMapG, offset[0].xy).rgb, lumaCoefficients); + float Ltop = dot(texture(colorMapG, offset[0].zw).rgb, lumaCoefficients); + float Lright = dot(texture(colorMapG, offset[1].xy).rgb, lumaCoefficients); + float Lbottom = dot(texture(colorMapG, offset[1].zw).rgb, lumaCoefficients); + + vec4 delta = abs(vec4(L) - vec4(Lleft, Ltop, Lright, Lbottom)); + vec4 edges = step(threshold, delta); + + // Add depth edges to color edges + float D = deferredUncondition(deferredMap, texcoord).w; + float Dleft = deferredUncondition(deferredMap, offset[0].xy).w; + float Dtop = deferredUncondition(deferredMap, offset[0].zw).w; + float Dright = deferredUncondition(deferredMap, offset[1].xy).w; + float Dbottom = deferredUncondition(deferredMap, offset[1].zw).w; + + delta = abs(vec4(D) - vec4(Dleft, Dtop, Dright, Dbottom)); + edges += step(depthThreshold, delta); + + if (dot(edges, vec4(1.0)) == 0.0) + discard; + + OUT_col = edges; +} \ No newline at end of file diff --git a/Templates/BaseGame/game/core/rendering/shaders/postFX/mlaa/gl/functions.glsl b/Templates/BaseGame/game/core/rendering/shaders/postFX/mlaa/gl/functions.glsl new file mode 100644 index 000000000..3ff56fb1a --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/postFX/mlaa/gl/functions.glsl @@ -0,0 +1,145 @@ +//----------------------------------------------------------------------------- +// 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. +//----------------------------------------------------------------------------- + +// An implementation of "Practical Morphological Anti-Aliasing" from +// GPU Pro 2 by Jorge Jimenez, Belen Masia, Jose I. Echevarria, +// Fernando Navarro, and Diego Gutierrez. +// +// http://www.iryoku.com/mlaa/ + + +uniform vec2 texSize0; + +#if !defined(PIXEL_SIZE) +#define PIXEL_SIZE (1.0 / texSize0) +#define MAX_SEARCH_STEPS 8 +#define MAX_DISTANCE 33 +#endif + +// Typical Multiply-Add operation to ease translation to assembly code. + +vec4 mad(vec4 m, vec4 a, vec4 b) +{ + #if defined(XBOX) + vec4 result; + asm { + mad result, m, a, b + }; + return result; + #else + return m * a + b; + #endif +} + + +// This one just returns the first level of a mip map chain, which allow us to +// avoid the nasty ddx/ddy warnings, even improving the performance a little +// bit. +vec4 tex2Dlevel0(sampler2D map, vec2 texcoord) +{ + return tex2Dlod(map, vec4(texcoord, 0.0, 0.0)); +} + + +// Same as above, this eases translation to assembly code; +vec4 tex2Doffset(sampler2D map, vec2 texcoord, vec2 offset) +{ + #if defined(XBOX) && MAX_SEARCH_STEPS < 6 + vec4 result; + float x = offset.x; + float y = offset.y; + asm { + tfetch2D result, texcoord, map, OffsetX = x, OffsetY = y + }; + return result; + #else + return tex2Dlevel0(map, texcoord + PIXEL_SIZE * offset); + #endif +} + + +// Ok, we have the distance and both crossing edges, can you please return +// the vec2 blending weights? +vec2 Area(vec2 distance, float e1, float e2) +{ + // * By dividing by areaSize - 1.0 below we are implicitely offsetting to + // always fall inside of a pixel + // * Rounding prevents bilinear access precision problems + float areaSize = MAX_DISTANCE * 5.0; + vec2 pixcoord = MAX_DISTANCE * round(4.0 * vec2(e1, e2)) + distance; + vec2 texcoord = pixcoord / (areaSize - 1.0); + return tex2Dlevel0(areaMap, texcoord).rg; +} + + +// Search functions for the 2nd pass. +float SearchXLeft(vec2 texcoord) +{ + // We compare with 0.9 to prevent bilinear access precision problems. + float i; + float e = 0.0; + for (i = -1.5; i > -2.0 * MAX_SEARCH_STEPS; i -= 2.0) + { + e = tex2Doffset(edgesMapL, texcoord, vec2(i, 0.0)).g; + /*[flatten]*/ if (e < 0.9) break; + } + return max(i + 1.5 - 2.0 * e, -2.0 * MAX_SEARCH_STEPS); +} + +// Search functions for the 2nd pass. +float SearchXRight(vec2 texcoord) +{ + float i; + float e = 0.0; + for (i = 1.5; i < 2.0 * MAX_SEARCH_STEPS; i += 2.0) + { + e = tex2Doffset(edgesMapL, texcoord, vec2(i, 0.0)).g; + /*[flatten]*/ if (e < 0.9) break; + } + return min(i - 1.5 + 2.0 * e, 2.0 * MAX_SEARCH_STEPS); +} + +// Search functions for the 2nd pass. +float SearchYUp(vec2 texcoord) +{ + float i; + float e = 0.0; + for (i = -1.5; i > -2.0 * MAX_SEARCH_STEPS; i -= 2.0) + { + e = tex2Doffset(edgesMapL, texcoord, vec2(i, 0.0).yx).r; + /*[flatten]*/ if (e < 0.9) break; + } + return max(i + 1.5 - 2.0 * e, -2.0 * MAX_SEARCH_STEPS); +} + +// Search functions for the 2nd pass. +float SearchYDown(vec2 texcoord) +{ + float i; + float e = 0.0; + for (i = 1.5; i < 2.0 * MAX_SEARCH_STEPS; i += 2.0) + { + e = tex2Doffset(edgesMapL, texcoord, vec2(i, 0.0).yx).r; + /*[flatten]*/ if (e < 0.9) break; + } + return min(i - 1.5 + 2.0 * e, 2.0 * MAX_SEARCH_STEPS); +} diff --git a/Templates/BaseGame/game/core/rendering/shaders/postFX/mlaa/gl/neighborhoodBlendingP.glsl b/Templates/BaseGame/game/core/rendering/shaders/postFX/mlaa/gl/neighborhoodBlendingP.glsl new file mode 100644 index 000000000..eddbcc47c --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/postFX/mlaa/gl/neighborhoodBlendingP.glsl @@ -0,0 +1,88 @@ +//----------------------------------------------------------------------------- +// 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. +//----------------------------------------------------------------------------- + +// An implementation of "Practical Morphological Anti-Aliasing" from +// GPU Pro 2 by Jorge Jimenez, Belen Masia, Jose I. Echevarria, +// Fernando Navarro, and Diego Gutierrez. +// +// http://www.iryoku.com/mlaa/ + +#include "../../../gl/hlslCompat.glsl" + +in vec2 texcoord; +in vec4 offset[2]; + +uniform sampler2D blendMap; +uniform sampler2D colorMapL; +uniform sampler2D colorMap; + +// Dummy sampers to please include. +uniform sampler2D areaMap; +uniform sampler2D edgesMapL; +#include "./functions.glsl" + +out vec4 OUT_col; + +void main() +{ + // Fetch the blending weights for current pixel: + vec4 topLeft = texture(blendMap, texcoord); + float bottom = texture(blendMap, offset[1].zw).g; + float right = texture(blendMap, offset[1].xy).a; + vec4 a = vec4(topLeft.r, bottom, topLeft.b, right); + + // Up to 4 lines can be crossing a pixel (one in each edge). So, we perform + // a weighted average, where the weight of each line is 'a' cubed, which + // favors blending and works well in practice. + vec4 w = a * a * a; + + // There is some blending weight with a value greater than 0.0? + float sum = dot(w, vec4(1.0)); + if (sum < 1e-5) + discard; + + vec4 color = vec4(0.0); + + // Add the contributions of the possible 4 lines that can cross this pixel: + #ifdef BILINEAR_FILTER_TRICK + vec4 coords = mad(vec4( 0.0, -a.r, 0.0, a.g), PIXEL_SIZE.yyyy, texcoord.xyxy); + color = mad(texture(colorMapL, coords.xy), vec4(w.r), color); + color = mad(texture(colorMapL, coords.zw), vec4(w.g), color); + + coords = mad(vec4(-a.b, 0.0, a.a, 0.0), PIXEL_SIZE.xxxx, texcoord.xyxy); + color = mad(texture(colorMapL, coords.xy), vec4(w.b), color); + color = mad(texture(colorMapL, coords.zw), vec4(w.a), color); + #else + vec4 C = texture(colorMap, texcoord); + vec4 Cleft = texture(colorMap, offset[0].xy); + vec4 Ctop = texture(colorMap, offset[0].zw); + vec4 Cright = texture(colorMap, offset[1].xy); + vec4 Cbottom = texture(colorMap, offset[1].zw); + color = mad(mix(C, Ctop, a.r), vec4(w.r), color); + color = mad(mix(C, Cbottom, a.g), vec4(w.g), color); + color = mad(mix(C, Cleft, a.b), vec4(w.b), color); + color = mad(mix(C, Cright, a.a), vec4(w.a), color); + #endif + + // Normalize the resulting color and we are finished! + OUT_col = color / sum; +} \ No newline at end of file diff --git a/Templates/BaseGame/game/core/rendering/shaders/postFX/mlaa/gl/offsetV.glsl b/Templates/BaseGame/game/core/rendering/shaders/postFX/mlaa/gl/offsetV.glsl new file mode 100644 index 000000000..53d927c29 --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/postFX/mlaa/gl/offsetV.glsl @@ -0,0 +1,57 @@ +//----------------------------------------------------------------------------- +// 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. +//----------------------------------------------------------------------------- + +// An implementation of "Practical Morphological Anti-Aliasing" from +// GPU Pro 2 by Jorge Jimenez, Belen Masia, Jose I. Echevarria, +// Fernando Navarro, and Diego Gutierrez. +// +// http://www.iryoku.com/mlaa/ + +#include "../../../gl/hlslCompat.glsl" + +in vec4 vPosition; +in vec2 vTexCoord0; + +#define IN_position vPosition +#define IN_texcoord vTexCoord0 + +#define OUT_position gl_Position +out vec2 texcoord; +#define OUT_texcoord texcoord +out vec4 offset[2]; +#define OUT_offset offset + +uniform vec2 texSize0; + +void main() +{ + OUT_position = IN_position; + vec2 PIXEL_SIZE = 1.0 / texSize0; + + OUT_texcoord = IN_texcoord; + OUT_texcoord.xy += PIXEL_SIZE * 0.5; + + OUT_offset[0] = OUT_texcoord.xyxy + PIXEL_SIZE.xyxy * vec4(-1.0, 0.0, 0.0, -1.0); + OUT_offset[1] = OUT_texcoord.xyxy + PIXEL_SIZE.xyxy * vec4( 1.0, 0.0, 0.0, 1.0); + + correctSSP(gl_Position); +} diff --git a/Templates/BaseGame/game/core/rendering/shaders/postFX/mlaa/gl/passthruV.glsl b/Templates/BaseGame/game/core/rendering/shaders/postFX/mlaa/gl/passthruV.glsl new file mode 100644 index 000000000..1aa64112c --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/postFX/mlaa/gl/passthruV.glsl @@ -0,0 +1,52 @@ +//----------------------------------------------------------------------------- +// 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. +//----------------------------------------------------------------------------- + +// An implementation of "Practical Morphological Anti-Aliasing" from +// GPU Pro 2 by Jorge Jimenez, Belen Masia, Jose I. Echevarria, +// Fernando Navarro, and Diego Gutierrez. +// +// http://www.iryoku.com/mlaa/ + +#include "../../../gl/hlslCompat.glsl" + +in vec4 vPosition; +in vec2 vTexCoord0; + +#define IN_position vPosition +#define IN_texcoord vTexCoord0 + +#define OUT_position gl_Position +out vec2 texcoord; +#define OUT_texcoord texcoord + +uniform vec2 texSize0; + +void main() +{ + OUT_position = IN_position; + vec2 PIXEL_SIZE = 1.0 / texSize0; + + OUT_texcoord = IN_texcoord; + texcoord.xy += PIXEL_SIZE * 0.5; + + correctSSP(gl_Position); +} diff --git a/Templates/BaseGame/game/core/rendering/shaders/postFX/mlaa/neighborhoodBlendingP.hlsl b/Templates/BaseGame/game/core/rendering/shaders/postFX/mlaa/neighborhoodBlendingP.hlsl new file mode 100644 index 000000000..aaaacafe2 --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/postFX/mlaa/neighborhoodBlendingP.hlsl @@ -0,0 +1,84 @@ +//----------------------------------------------------------------------------- +// 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. +//----------------------------------------------------------------------------- + +// An implementation of "Practical Morphological Anti-Aliasing" from +// GPU Pro 2 by Jorge Jimenez, Belen Masia, Jose I. Echevarria, +// Fernando Navarro, and Diego Gutierrez. +// +// http://www.iryoku.com/mlaa/ + + +uniform sampler2D blendMap : register(S0); +uniform sampler2D colorMapL : register(S1); +uniform sampler2D colorMap : register(S2); + +// Dummy sampers to please include. +sampler2D areaMap; +sampler2D edgesMapL; +#include "./functions.hlsl" + + +float4 main( float2 texcoord : TEXCOORD0, + float4 offset[2]: TEXCOORD1 ) : COLOR0 +{ + // Fetch the blending weights for current pixel: + float4 topLeft = tex2D(blendMap, texcoord); + float bottom = tex2D(blendMap, offset[1].zw).g; + float right = tex2D(blendMap, offset[1].xy).a; + float4 a = float4(topLeft.r, bottom, topLeft.b, right); + + // Up to 4 lines can be crossing a pixel (one in each edge). So, we perform + // a weighted average, where the weight of each line is 'a' cubed, which + // favors blending and works well in practice. + float4 w = a * a * a; + + // There is some blending weight with a value greater than 0.0? + float sum = dot(w, 1.0); + if (sum < 1e-5) + discard; + + float4 color = 0.0; + + // Add the contributions of the possible 4 lines that can cross this pixel: + #ifdef BILINEAR_FILTER_TRICK + float4 coords = mad(float4( 0.0, -a.r, 0.0, a.g), PIXEL_SIZE.yyyy, texcoord.xyxy); + color = mad(tex2D(colorMapL, coords.xy), w.r, color); + color = mad(tex2D(colorMapL, coords.zw), w.g, color); + + coords = mad(float4(-a.b, 0.0, a.a, 0.0), PIXEL_SIZE.xxxx, texcoord.xyxy); + color = mad(tex2D(colorMapL, coords.xy), w.b, color); + color = mad(tex2D(colorMapL, coords.zw), w.a, color); + #else + float4 C = tex2D(colorMap, texcoord); + float4 Cleft = tex2D(colorMap, offset[0].xy); + float4 Ctop = tex2D(colorMap, offset[0].zw); + float4 Cright = tex2D(colorMap, offset[1].xy); + float4 Cbottom = tex2D(colorMap, offset[1].zw); + color = mad(lerp(C, Ctop, a.r), w.r, color); + color = mad(lerp(C, Cbottom, a.g), w.g, color); + color = mad(lerp(C, Cleft, a.b), w.b, color); + color = mad(lerp(C, Cright, a.a), w.a, color); + #endif + + // Normalize the resulting color and we are finished! + return color / sum; +} \ No newline at end of file diff --git a/Templates/BaseGame/game/core/rendering/shaders/postFX/mlaa/offsetV.hlsl b/Templates/BaseGame/game/core/rendering/shaders/postFX/mlaa/offsetV.hlsl new file mode 100644 index 000000000..d9c922afd --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/postFX/mlaa/offsetV.hlsl @@ -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. +//----------------------------------------------------------------------------- + +// An implementation of "Practical Morphological Anti-Aliasing" from +// GPU Pro 2 by Jorge Jimenez, Belen Masia, Jose I. Echevarria, +// Fernando Navarro, and Diego Gutierrez. +// +// http://www.iryoku.com/mlaa/ + + +uniform float2 texSize0; + +void main( inout float4 position : POSITION0, + inout float2 texcoord : TEXCOORD0, + out float4 offset[2] : TEXCOORD1 ) +{ + float2 PIXEL_SIZE = 1.0 / texSize0; + + texcoord.xy += PIXEL_SIZE * 0.5; + + offset[0] = texcoord.xyxy + PIXEL_SIZE.xyxy * float4(-1.0, 0.0, 0.0, -1.0); + offset[1] = texcoord.xyxy + PIXEL_SIZE.xyxy * float4( 1.0, 0.0, 0.0, 1.0); +} diff --git a/Templates/BaseGame/game/core/rendering/shaders/postFX/mlaa/passthruV.hlsl b/Templates/BaseGame/game/core/rendering/shaders/postFX/mlaa/passthruV.hlsl new file mode 100644 index 000000000..24ef534fd --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/postFX/mlaa/passthruV.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. +//----------------------------------------------------------------------------- + +// An implementation of "Practical Morphological Anti-Aliasing" from +// GPU Pro 2 by Jorge Jimenez, Belen Masia, Jose I. Echevarria, +// Fernando Navarro, and Diego Gutierrez. +// +// http://www.iryoku.com/mlaa/ + + +uniform float2 texSize0; + +void main( inout float4 position : POSITION0, + inout float2 texcoord : TEXCOORD0) +{ + float2 PIXEL_SIZE = 1.0 / texSize0; + texcoord.xy += PIXEL_SIZE * 0.5; +} diff --git a/Templates/BaseGame/game/core/rendering/shaders/postFX/motionBlurP.hlsl b/Templates/BaseGame/game/core/rendering/shaders/postFX/motionBlurP.hlsl new file mode 100644 index 000000000..90b8f6f25 --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/postFX/motionBlurP.hlsl @@ -0,0 +1,70 @@ +//----------------------------------------------------------------------------- +// 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 "./postFx.hlsl" +#include "../torque.hlsl" +#include "../shaderModelAutoGen.hlsl" + +uniform float4x4 matPrevScreenToWorld; +uniform float4x4 matWorldToScreen; + +// Passed in from setShaderConsts() +uniform float velocityMultiplier; +TORQUE_UNIFORM_SAMPLER2D(backBuffer, 0); +TORQUE_UNIFORM_SAMPLER2D(deferredTex, 1); + +float4 main(PFXVertToPix IN) : TORQUE_TARGET0 +{ + float samples = 5; + + // First get the deferred texture for uv channel 0 + float4 deferred = TORQUE_DEFERRED_UNCONDITION( deferredTex, IN.uv0 ); + + // Next extract the depth + float depth = deferred.a; + + // Create the screen position + float4 screenPos = float4(IN.uv0.x*2-1, IN.uv0.y*2-1, depth*2-1, 1); + + // Calculate the world position + float4 D = mul(screenPos, matWorldToScreen); + float4 worldPos = D / D.w; + + // Now calculate the previous screen position + float4 previousPos = mul( worldPos, matPrevScreenToWorld ); + previousPos /= previousPos.w; + + // Calculate the XY velocity + float2 velocity = ((screenPos - previousPos) / velocityMultiplier).xy; + + // Generate the motion blur + float4 color = TORQUE_TEX2D(backBuffer, IN.uv0); + IN.uv0 += velocity; + + for(int i = 1; i blurNormalTol ) + { + usedCount++; + total += weight; + occlusion += TORQUE_TEX2D( occludeMap, uv ).r * weight; + } + } +} + +float4 main( VertToPix IN ) : TORQUE_TARGET0 +{ + //float4 centerTap; + float4 centerTap = TORQUE_DEFERRED_UNCONDITION( deferredMap, IN.uv0.zw ); + + //return centerTap; + + //float centerOcclude = TORQUE_TEX2D( occludeMap, IN.uv0.zw ).r; + //return float4( centerOcclude.rrr, 1 ); + + float4 kernel = float4( 0.175, 0.275, 0.375, 0.475 ); //25f; + + float occlusion = 0; + int usedCount = 0; + float total = 0.0; + + sample( IN.uv0.xy, kernel.x, centerTap, usedCount, occlusion, total ); + sample( IN.uv1, kernel.y, centerTap, usedCount, occlusion, total ); + sample( IN.uv2, kernel.z, centerTap, usedCount, occlusion, total ); + sample( IN.uv3, kernel.w, centerTap, usedCount, occlusion, total ); + + sample( IN.uv4, kernel.x, centerTap, usedCount, occlusion, total ); + sample( IN.uv5, kernel.y, centerTap, usedCount, occlusion, total ); + sample( IN.uv6, kernel.z, centerTap, usedCount, occlusion, total ); + sample( IN.uv7, kernel.w, centerTap, usedCount, occlusion, total ); + + occlusion += TORQUE_TEX2D( occludeMap, IN.uv0.zw ).r * 0.5; + total += 0.5; + //occlusion /= 3.0; + + //occlusion /= (float)usedCount / 8.0; + occlusion /= total; + + return float4( occlusion.rrr, 1 ); + + + //return float4( 0,0,0,occlusion ); + + //float3 color = TORQUE_TEX2D( colorMap, IN.uv0.zw ); + + //return float4( color, occlusion ); +} \ No newline at end of file diff --git a/Templates/BaseGame/game/core/rendering/shaders/postFX/ssao/SSAO_Blur_V.hlsl b/Templates/BaseGame/game/core/rendering/shaders/postFX/ssao/SSAO_Blur_V.hlsl new file mode 100644 index 000000000..6ab278900 --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/postFX/ssao/SSAO_Blur_V.hlsl @@ -0,0 +1,86 @@ +//----------------------------------------------------------------------------- +// 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 "./../postFx.hlsl" +#include "./../../torque.hlsl" + + +uniform float2 texSize0; +uniform float2 oneOverTargetSize; +uniform float4 rtParams0; + +struct VertToPix +{ + float4 hpos : TORQUE_POSITION; + + float4 uv0 : TEXCOORD0; + float2 uv1 : TEXCOORD1; + float2 uv2 : TEXCOORD2; + float2 uv3 : TEXCOORD3; + + float2 uv4 : TEXCOORD4; + float2 uv5 : TEXCOORD5; + float2 uv6 : TEXCOORD6; + float2 uv7 : TEXCOORD7; +}; + +VertToPix main( PFXVert IN ) +{ + VertToPix OUT; + + OUT.hpos = float4(IN.pos,1.0); + + IN.uv = viewportCoordToRenderTarget( IN.uv, rtParams0 ); + + //float4 step = float4( 3.5, 2.5, 1.5, 0.5 ); + //float4 step = float4( 4.0, 3.0, 2.0, 1.0 ); + float4 step = float4( 9.0, 5.0, 2.5, 0.5 ); + + // I don't know why this offset is necessary, but it is. + //IN.uv = IN.uv * oneOverTargetSize; + + OUT.uv0.xy = IN.uv + ( ( BLUR_DIR * step.x ) / texSize0 ); + OUT.uv1 = IN.uv + ( ( BLUR_DIR * step.y ) / texSize0 ); + OUT.uv2 = IN.uv + ( ( BLUR_DIR * step.z ) / texSize0 ); + OUT.uv3 = IN.uv + ( ( BLUR_DIR * step.w ) / texSize0 ); + + OUT.uv4 = IN.uv - ( ( BLUR_DIR * step.x ) / texSize0 ); + OUT.uv5 = IN.uv - ( ( BLUR_DIR * step.y ) / texSize0 ); + OUT.uv6 = IN.uv - ( ( BLUR_DIR * step.z ) / texSize0 ); + OUT.uv7 = IN.uv - ( ( BLUR_DIR * step.w ) / texSize0 ); + + OUT.uv0.zw = IN.uv; + + /* + OUT.uv0 = viewportCoordToRenderTarget( OUT.uv0, rtParams0 ); + OUT.uv1 = viewportCoordToRenderTarget( OUT.uv1, rtParams0 ); + OUT.uv2 = viewportCoordToRenderTarget( OUT.uv2, rtParams0 ); + OUT.uv3 = viewportCoordToRenderTarget( OUT.uv3, rtParams0 ); + + OUT.uv4 = viewportCoordToRenderTarget( OUT.uv4, rtParams0 ); + OUT.uv5 = viewportCoordToRenderTarget( OUT.uv5, rtParams0 ); + OUT.uv6 = viewportCoordToRenderTarget( OUT.uv6, rtParams0 ); + OUT.uv7 = viewportCoordToRenderTarget( OUT.uv7, rtParams0 ); + */ + + return OUT; +} diff --git a/Templates/BaseGame/game/core/rendering/shaders/postFX/ssao/SSAO_P.hlsl b/Templates/BaseGame/game/core/rendering/shaders/postFX/ssao/SSAO_P.hlsl new file mode 100644 index 000000000..ff31a4b8b --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/postFX/ssao/SSAO_P.hlsl @@ -0,0 +1,272 @@ +//----------------------------------------------------------------------------- +// 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 "../../shaderModelAutoGen.hlsl" +#include "./../postFx.hlsl" + +#define DOSMALL +#define DOLARGE + +TORQUE_UNIFORM_SAMPLER2D(deferredMap,0); +TORQUE_UNIFORM_SAMPLER2D(randNormalTex,1); +TORQUE_UNIFORM_SAMPLER1D(powTable,2); + +uniform float2 nearFar; +uniform float2 worldToScreenScale; +uniform float2 texSize0; +uniform float2 texSize1; +uniform float2 targetSize; + +// Script-set constants. + +uniform float overallStrength; + +uniform float sRadius; +uniform float sStrength; +uniform float sDepthMin; +uniform float sDepthMax; +uniform float sDepthPow; +uniform float sNormalTol; +uniform float sNormalPow; + +uniform float lRadius; +uniform float lStrength; +uniform float lDepthMin; +uniform float lDepthMax; +uniform float lDepthPow; +uniform float lNormalTol; +uniform float lNormalPow; + + +#ifndef QUALITY + #define QUALITY 2 +#endif + + +#if QUALITY == 0 + #define sSampleCount 4 + #define totalSampleCount 12 +#elif QUALITY == 1 + #define sSampleCount 6 + #define totalSampleCount 24 +#elif QUALITY == 2 + #define sSampleCount 8 + #define totalSampleCount 32 +#endif + + +float getOcclusion( float depthDiff, float depthMin, float depthMax, float depthPow, + float normalDiff, float dt, float normalTol, float normalPow ) +{ + if ( depthDiff < 0.0 ) + return 0.0; + + float delta = abs( depthDiff ); + + if ( delta < depthMin || delta > depthMax ) + return 0.0; + + delta = saturate( delta / depthMax ); + + if ( dt > 0.0 ) + normalDiff *= dt; + else + normalDiff = 1.0; + + + normalDiff *= 1.0 - ( dt * 0.5 + 0.5 ); + + return ( 1.0 - TORQUE_TEX1D( powTable, delta ).r ) * normalDiff; +} + + +float4 main( PFXVertToPix IN ) : TORQUE_TARGET0 +{ + float3 ptSphere[32] = + { + float3( 0.295184, 0.077723, 0.068429 ), + float3( -0.271976, -0.365221, -0.838363 ), + float3( 0.547713, 0.467576, 0.488515 ), + float3( 0.662808, -0.031733, -0.584758 ), + float3( -0.025717, 0.218955, -0.657094 ), + float3( -0.310153, -0.365223, -0.370701 ), + float3( -0.101407, -0.006313, -0.747665 ), + float3( -0.769138, 0.360399, -0.086847 ), + float3( -0.271988, -0.275140, -0.905353 ), + float3( 0.096740, -0.566901, 0.700151 ), + float3( 0.562872, -0.735136, -0.094647 ), + float3( 0.379877, 0.359278, 0.190061 ), + float3( 0.519064, -0.023055, 0.405068 ), + float3( -0.301036, 0.114696, -0.088885 ), + float3( -0.282922, 0.598305, 0.487214 ), + float3( -0.181859, 0.251670, -0.679702 ), + float3( -0.191463, -0.635818, -0.512919 ), + float3( -0.293655, 0.427423, 0.078921 ), + float3( -0.267983, 0.680534, -0.132880 ), + float3( 0.139611, 0.319637, 0.477439 ), + float3( -0.352086, 0.311040, 0.653913 ), + float3( 0.321032, 0.805279, 0.487345 ), + float3( 0.073516, 0.820734, -0.414183 ), + float3( -0.155324, 0.589983, -0.411460 ), + float3( 0.335976, 0.170782, -0.527627 ), + float3( 0.463460, -0.355658, -0.167689 ), + float3( 0.222654, 0.596550, -0.769406 ), + float3( 0.922138, -0.042070, 0.147555 ), + float3( -0.727050, -0.329192, 0.369826 ), + float3( -0.090731, 0.533820, 0.463767 ), + float3( -0.323457, -0.876559, -0.238524 ), + float3( -0.663277, -0.372384, -0.342856 ) + }; + + // Sample a random normal for reflecting the + // sphere vector later in our loop. + float4 noiseMapUV = float4( ( IN.uv1 * ( targetSize / texSize1 ) ).xy, 0, 0 ); + float3 reflectNormal = normalize( TORQUE_TEX2DLOD( randNormalTex, noiseMapUV ).xyz * 2.0 - 1.0 ); + //return float4( reflectNormal, 1 ); + + float4 deferred = TORQUE_DEFERRED_UNCONDITION( deferredMap, IN.uv0 ); + float3 normal = deferred.xyz; + float depth = deferred.a; + //return float4( ( depth ).xxx, 1 ); + + // Early out if too far away. + if ( depth > 0.99999999 ) + return float4( 0,0,0,0 ); + + // current fragment coords in screen space + float3 ep = float3( IN.uv0, depth ); + + float bl; + float3 baseRay, ray, se, occNorm, projRadius; + float normalDiff = 0; + float depthMin, depthMax, dt, depthDiff; + float4 occluderFragment; + int i; + float sOcclusion = 0.0; + float lOcclusion = 0.0; + + //------------------------------------------------------------ + // Small radius + //------------------------------------------------------------ + +#ifdef DOSMALL + + bl = 0.0; + + projRadius.xy = ( float2( sRadius.rr ) / ( depth * nearFar.y ) ) * ( worldToScreenScale / texSize0 ); + projRadius.z = sRadius / nearFar.y; + + depthMin = projRadius.z * sDepthMin; + depthMax = projRadius.z * sDepthMax; + + //float maxr = 1; + //radiusDepth = clamp( radiusDepth, 0.0001, maxr.rrr ); + //if ( radiusDepth.x < 1.0 / targetSize.x ) + // return color; + //radiusDepth.xyz = 0.0009; + [unroll] + for ( i = 0; i < sSampleCount; i++ ) + { + baseRay = reflect( ptSphere[i], reflectNormal ); + + dt = dot( baseRay.xyz, normal ); + + baseRay *= sign( dt ); + + ray = ( projRadius * baseRay.xzy ); + ray.y = -ray.y; + + se = ep + ray; + + occluderFragment = TORQUE_DEFERRED_UNCONDITION( deferredMap, se.xy ); + + depthDiff = se.z - occluderFragment.a; + + dt = dot( occluderFragment.xyz, baseRay.xyz ); + normalDiff = dot( occluderFragment.xyz, normal ); + + bl += getOcclusion( depthDiff, depthMin, depthMax, sDepthPow, normalDiff, dt, sNormalTol, sNormalPow ); + } + + sOcclusion = sStrength * ( bl / (float)sSampleCount ); + +#endif // DOSMALL + + + //------------------------------------------------------------ + // Large radius + //------------------------------------------------------------ + +#ifdef DOLARGE + + bl = 0.0; + + projRadius.xy = ( float2( lRadius.rr ) / ( depth * nearFar.y ) ) * ( worldToScreenScale / texSize0 ); + projRadius.z = lRadius / nearFar.y; + + depthMin = projRadius.z * lDepthMin; + depthMax = projRadius.z * lDepthMax; + + //projRadius.xy = clamp( projRadius.xy, 0.0, 0.01 ); + //float maxr = 1; + //radiusDepth = clamp( radiusDepth, 0.0001, maxr.rrr ); + //if ( radiusDepth.x < 1.0 / targetSize.x ) + // return color; + //radiusDepth.xyz = 0.0009; + [unroll] + for ( i = sSampleCount; i < totalSampleCount; i++ ) + { + baseRay = reflect( ptSphere[i], reflectNormal ); + + dt = dot( baseRay.xyz, normal ); + + baseRay *= sign( dt ); + + ray = ( projRadius * baseRay.xzy ); + ray.y = -ray.y; + + se = ep + ray; + + occluderFragment = TORQUE_DEFERRED_UNCONDITION( deferredMap, se.xy ); + + depthDiff = se.z - occluderFragment.a; + + normalDiff = dot( occluderFragment.xyz, normal ); + dt = dot( occluderFragment.xyz, baseRay.xyz ); + + bl += getOcclusion( depthDiff, depthMin, depthMax, lDepthPow, normalDiff, dt, lNormalTol, lNormalPow ); + } + + lOcclusion = lStrength * ( bl / (float)( totalSampleCount - sSampleCount ) ); + +#endif // DOLARGE + + float occlusion = saturate( max( sOcclusion, lOcclusion ) * overallStrength ); + + // Note black is unoccluded and white is fully occluded. This + // seems backwards, but it makes it simple to deal with the SSAO + // being disabled in the lighting shaders. + + return occlusion; +} + + diff --git a/Templates/BaseGame/game/core/rendering/shaders/postFX/ssao/SSAO_PowerTable_P.hlsl b/Templates/BaseGame/game/core/rendering/shaders/postFX/ssao/SSAO_PowerTable_P.hlsl new file mode 100644 index 000000000..696947d3e --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/postFX/ssao/SSAO_PowerTable_P.hlsl @@ -0,0 +1,29 @@ +//----------------------------------------------------------------------------- +// 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 "./../postFx.hlsl" + +float4 main( PFXVertToPix IN ) : TORQUE_TARGET0 +{ + float power = pow( max( IN.uv0.x, 0 ), 0.1 ); + return float4( power, 0, 0, 1 ); +} \ No newline at end of file diff --git a/Templates/BaseGame/game/core/rendering/shaders/postFX/ssao/SSAO_PowerTable_V.hlsl b/Templates/BaseGame/game/core/rendering/shaders/postFX/ssao/SSAO_PowerTable_V.hlsl new file mode 100644 index 000000000..76f67e711 --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/postFX/ssao/SSAO_PowerTable_V.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. +//----------------------------------------------------------------------------- + +#include "./../postFx.hlsl" +#include "./../../torque.hlsl" + + +uniform float4 rtParams0; +uniform float4 rtParams1; +uniform float4 rtParams2; +uniform float4 rtParams3; + +PFXVertToPix main( PFXVert IN ) +{ + PFXVertToPix OUT; + + OUT.hpos = float4(IN.pos,1.0); + OUT.uv0 = IN.uv; //viewportCoordToRenderTarget( IN.uv, rtParams0 ); + OUT.uv1 = IN.uv; //viewportCoordToRenderTarget( IN.uv, rtParams1 ); + OUT.uv2 = IN.uv; //viewportCoordToRenderTarget( IN.uv, rtParams2 ); + OUT.uv3 = IN.uv; //viewportCoordToRenderTarget( IN.uv, rtParams3 ); + + OUT.wsEyeRay = IN.wsEyeRay; + + return OUT; +} diff --git a/Templates/BaseGame/game/core/rendering/shaders/postFX/ssao/gl/SSAO_Blur_P.glsl b/Templates/BaseGame/game/core/rendering/shaders/postFX/ssao/gl/SSAO_Blur_P.glsl new file mode 100644 index 000000000..cae920af8 --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/postFX/ssao/gl/SSAO_Blur_P.glsl @@ -0,0 +1,108 @@ +//----------------------------------------------------------------------------- +// 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" + +in vec4 uv0; +#define IN_uv0 uv0 +in vec2 uv1; +#define IN_uv1 uv1 +in vec2 uv2; +#define IN_uv2 uv2 +in vec2 uv3; +#define IN_uv3 uv3 + +in vec2 uv4; +#define IN_uv4 uv4 +in vec2 uv5; +#define IN_uv5 uv5 +in vec2 uv6; +#define IN_uv6 uv6 +in vec2 uv7; +#define IN_uv7 uv7 + +uniform sampler2D occludeMap ; +uniform sampler2D deferredMap ; +uniform float blurDepthTol; +uniform float blurNormalTol; + +out vec4 OUT_col; + +void _sample( vec2 uv, float weight, vec4 centerTap, inout int usedCount, inout float occlusion, inout float total ) +{ + //return; + vec4 tap = deferredUncondition( deferredMap, uv ); + + if ( abs( tap.a - centerTap.a ) < blurDepthTol ) + { + if ( dot( tap.xyz, centerTap.xyz ) > blurNormalTol ) + { + usedCount++; + total += weight; + occlusion += texture( occludeMap, uv ).r * weight; + } + } +} + +void main() +{ + //vec4 centerTap; + vec4 centerTap = deferredUncondition( deferredMap, IN_uv0.zw ); + + //return centerTap; + + //float centerOcclude = texture( occludeMap, IN_uv0.zw ).r; + //return vec4( centerOcclude.rrr, 1 ); + + vec4 kernel = vec4( 0.175, 0.275, 0.375, 0.475 ); //25f; + + float occlusion = 0; + int usedCount = 0; + float total = 0.0; + + _sample( IN_uv0.xy, kernel.x, centerTap, usedCount, occlusion, total ); + _sample( IN_uv1, kernel.y, centerTap, usedCount, occlusion, total ); + _sample( IN_uv2, kernel.z, centerTap, usedCount, occlusion, total ); + _sample( IN_uv3, kernel.w, centerTap, usedCount, occlusion, total ); + + _sample( IN_uv4, kernel.x, centerTap, usedCount, occlusion, total ); + _sample( IN_uv5, kernel.y, centerTap, usedCount, occlusion, total ); + _sample( IN_uv6, kernel.z, centerTap, usedCount, occlusion, total ); + _sample( IN_uv7, kernel.w, centerTap, usedCount, occlusion, total ); + + occlusion += texture( occludeMap, IN_uv0.zw ).r * 0.5; + total += 0.5; + //occlusion /= 3.0; + + //occlusion /= (float)usedCount / 8.0; + occlusion /= total; + + OUT_col = vec4( vec3(occlusion), 1 ); + + + //return vec4( 0,0,0,occlusion ); + + //vec3 color = texture( colorMap, IN_uv0.zw ); + + //return vec4( color, occlusion ); +} \ No newline at end of file diff --git a/Templates/BaseGame/game/core/rendering/shaders/postFX/ssao/gl/SSAO_Blur_V.glsl b/Templates/BaseGame/game/core/rendering/shaders/postFX/ssao/gl/SSAO_Blur_V.glsl new file mode 100644 index 000000000..45a52e890 --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/postFX/ssao/gl/SSAO_Blur_V.glsl @@ -0,0 +1,96 @@ +//----------------------------------------------------------------------------- +// 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/torque.glsl" +#include "../../../gl/hlslCompat.glsl" + +in vec4 vPosition; +in vec2 vTexCoord0; + +#define IN_pos vPosition +#define _IN_uv vTexCoord0 + +uniform vec2 texSize0; +uniform vec4 rtParams0; +uniform vec2 oneOverTargetSize; + +#define OUT_hpos gl_Position + +out vec4 uv0; +#define OUT_uv0 uv0 +out vec2 uv1; +#define OUT_uv1 uv1 +out vec2 uv2; +#define OUT_uv2 uv2 +out vec2 uv3; +#define OUT_uv3 uv3 + +out vec2 uv4; +#define OUT_uv4 uv4 +out vec2 uv5; +#define OUT_uv5 uv5 +out vec2 uv6; +#define OUT_uv6 uv6 +out vec2 uv7; +#define OUT_uv7 uv7 + + +void main() +{ + OUT_hpos = IN_pos; + + vec2 IN_uv = viewportCoordToRenderTarget( _IN_uv, rtParams0 ); + + //vec4 step = vec4( 3.5, 2.5, 1.5, 0.5 ); + //vec4 step = vec4( 4.0, 3.0, 2.0, 1.0 ); + vec4 step = vec4( 9.0, 5.0, 2.5, 0.5 ); + + // I don't know why this offset is necessary, but it is. + //IN_uv = IN_uv * oneOverTargetSize; + + OUT_uv0.xy = IN_uv + ( ( BLUR_DIR * step.x ) / texSize0 ); + OUT_uv1 = IN_uv + ( ( BLUR_DIR * step.y ) / texSize0 ); + OUT_uv2 = IN_uv + ( ( BLUR_DIR * step.z ) / texSize0 ); + OUT_uv3 = IN_uv + ( ( BLUR_DIR * step.w ) / texSize0 ); + + OUT_uv4 = IN_uv - ( ( BLUR_DIR * step.x ) / texSize0 ); + OUT_uv5 = IN_uv - ( ( BLUR_DIR * step.y ) / texSize0 ); + OUT_uv6 = IN_uv - ( ( BLUR_DIR * step.z ) / texSize0 ); + OUT_uv7 = IN_uv - ( ( BLUR_DIR * step.w ) / texSize0 ); + + OUT_uv0.zw = IN_uv; + + /* + OUT_uv0 = viewportCoordToRenderTarget( OUT_uv0, rtParams0 ); + OUT_uv1 = viewportCoordToRenderTarget( OUT_uv1, rtParams0 ); + OUT_uv2 = viewportCoordToRenderTarget( OUT_uv2, rtParams0 ); + OUT_uv3 = viewportCoordToRenderTarget( OUT_uv3, rtParams0 ); + + OUT_uv4 = viewportCoordToRenderTarget( OUT_uv4, rtParams0 ); + OUT_uv5 = viewportCoordToRenderTarget( OUT_uv5, rtParams0 ); + OUT_uv6 = viewportCoordToRenderTarget( OUT_uv6, rtParams0 ); + OUT_uv7 = viewportCoordToRenderTarget( OUT_uv7, rtParams0 ); + */ + + correctSSP(gl_Position); +} diff --git a/Templates/BaseGame/game/core/rendering/shaders/postFX/ssao/gl/SSAO_P.glsl b/Templates/BaseGame/game/core/rendering/shaders/postFX/ssao/gl/SSAO_P.glsl new file mode 100644 index 000000000..cfff88381 --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/postFX/ssao/gl/SSAO_P.glsl @@ -0,0 +1,278 @@ +//----------------------------------------------------------------------------- +// 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/postFX.glsl" + +#define DOSMALL +#define DOLARGE + +uniform sampler2D deferredMap ; +uniform sampler2D randNormalTex ; +uniform sampler1D powTable ; + +uniform vec2 nearFar; +uniform vec2 worldToScreenScale; +uniform vec2 texSize0; +uniform vec2 texSize1; +uniform vec2 targetSize; + +// Script-set constants. + +uniform float overallStrength; + +uniform float sRadius; +uniform float sStrength; +uniform float sDepthMin; +uniform float sDepthMax; +uniform float sDepthPow; +uniform float sNormalTol; +uniform float sNormalPow; + +uniform float lRadius; +uniform float lStrength; +uniform float lDepthMin; +uniform float lDepthMax; +uniform float lDepthPow; +uniform float lNormalTol; +uniform float lNormalPow; + +out vec4 OUT_col; + + +#ifndef QUALITY + #define QUALITY 2 +#endif + + +#if QUALITY == 0 + #define sSampleCount 4 + #define totalSampleCount 12 +#elif QUALITY == 1 + #define sSampleCount 6 + #define totalSampleCount 24 +#elif QUALITY == 2 + #define sSampleCount 8 + #define totalSampleCount 32 +#endif + + +float getOcclusion( float depthDiff, float depthMin, float depthMax, float depthPow, + float normalDiff, float dt, float normalTol, float normalPow ) +{ + if ( depthDiff < 0.0 ) + return 0.0; + + float delta = abs( depthDiff ); + + if ( delta < depthMin || delta > depthMax ) + return 0.0; + + delta = saturate( delta / depthMax ); + + if ( dt > 0.0 ) + normalDiff *= dt; + else + normalDiff = 1.0; + + + normalDiff *= 1.0 - ( dt * 0.5 + 0.5 ); + + return ( 1.0 - texture( powTable, delta ).r ) * normalDiff; +} + + +void main() +{ + const vec3 ptSphere[32] = vec3[] + ( + vec3( 0.295184, 0.077723, 0.068429 ), + vec3( -0.271976, -0.365221, -0.838363 ), + vec3( 0.547713, 0.467576, 0.488515 ), + vec3( 0.662808, -0.031733, -0.584758 ), + vec3( -0.025717, 0.218955, -0.657094 ), + vec3( -0.310153, -0.365223, -0.370701 ), + vec3( -0.101407, -0.006313, -0.747665 ), + vec3( -0.769138, 0.360399, -0.086847 ), + vec3( -0.271988, -0.275140, -0.905353 ), + vec3( 0.096740, -0.566901, 0.700151 ), + vec3( 0.562872, -0.735136, -0.094647 ), + vec3( 0.379877, 0.359278, 0.190061 ), + vec3( 0.519064, -0.023055, 0.405068 ), + vec3( -0.301036, 0.114696, -0.088885 ), + vec3( -0.282922, 0.598305, 0.487214 ), + vec3( -0.181859, 0.251670, -0.679702 ), + vec3( -0.191463, -0.635818, -0.512919 ), + vec3( -0.293655, 0.427423, 0.078921 ), + vec3( -0.267983, 0.680534, -0.132880 ), + vec3( 0.139611, 0.319637, 0.477439 ), + vec3( -0.352086, 0.311040, 0.653913 ), + vec3( 0.321032, 0.805279, 0.487345 ), + vec3( 0.073516, 0.820734, -0.414183 ), + vec3( -0.155324, 0.589983, -0.411460 ), + vec3( 0.335976, 0.170782, -0.527627 ), + vec3( 0.463460, -0.355658, -0.167689 ), + vec3( 0.222654, 0.596550, -0.769406 ), + vec3( 0.922138, -0.042070, 0.147555 ), + vec3( -0.727050, -0.329192, 0.369826 ), + vec3( -0.090731, 0.533820, 0.463767 ), + vec3( -0.323457, -0.876559, -0.238524 ), + vec3( -0.663277, -0.372384, -0.342856 ) + ); + + // Sample a random normal for reflecting the + // sphere vector later in our loop. + vec4 noiseMapUV = vec4( ( IN_uv1 * ( targetSize / texSize1 ) ).xy, 0, 0 ); + vec3 reflectNormal = normalize( tex2Dlod( randNormalTex, noiseMapUV ).xyz * 2.0 - 1.0 ); + //return vec4( reflectNormal, 1 ); + + vec4 deferred = deferredUncondition( deferredMap, IN_uv0 ); + vec3 normal = deferred.xyz; + float depth = deferred.a; + //return vec4( ( depth ).xxx, 1 ); + + // Early out if too far away. + if ( depth > 0.99999999 ) + { + OUT_col = vec4( 0,0,0,0 ); + return; + } + + // current fragment coords in screen space + vec3 ep = vec3( IN_uv0, depth ); + + float bl; + vec3 baseRay, ray, se, occNorm, projRadius; + float normalDiff = 0; + float depthMin, depthMax, dt, depthDiff; + vec4 occluderFragment; + int i; + float sOcclusion = 0.0; + float lOcclusion = 0.0; + + //------------------------------------------------------------ + // Small radius + //------------------------------------------------------------ + +#ifdef DOSMALL + + bl = 0.0; + + projRadius.xy = ( vec2( sRadius ) / ( depth * nearFar.y ) ) * ( worldToScreenScale / texSize0 ); + projRadius.z = sRadius / nearFar.y; + + depthMin = projRadius.z * sDepthMin; + depthMax = projRadius.z * sDepthMax; + + //float maxr = 1; + //radiusDepth = clamp( radiusDepth, 0.0001, maxr.rrr ); + //if ( radiusDepth.x < 1.0 / targetSize.x ) + // return color; + //radiusDepth.xyz = 0.0009; + + for ( i = 0; i < sSampleCount; i++ ) + { + baseRay = reflect( ptSphere[i], reflectNormal ); + + dt = dot( baseRay.xyz, normal ); + + baseRay *= sign( dt ); + + ray = ( projRadius * baseRay.xzy ); + ray.y = -ray.y; + + se = ep + ray; + + occluderFragment = deferredUncondition( deferredMap, se.xy ); + + depthDiff = se.z - occluderFragment.a; + + dt = dot( occluderFragment.xyz, baseRay.xyz ); + normalDiff = dot( occluderFragment.xyz, normal ); + + bl += getOcclusion( depthDiff, depthMin, depthMax, sDepthPow, normalDiff, dt, sNormalTol, sNormalPow ); + } + + sOcclusion = sStrength * ( bl / float(sSampleCount) ); + +#endif // DOSMALL + + + //------------------------------------------------------------ + // Large radius + //------------------------------------------------------------ + +#ifdef DOLARGE + + bl = 0.0; + + projRadius.xy = ( vec2( lRadius ) / ( depth * nearFar.y ) ) * ( worldToScreenScale / texSize0 ); + projRadius.z = lRadius / nearFar.y; + + depthMin = projRadius.z * lDepthMin; + depthMax = projRadius.z * lDepthMax; + + //projRadius.xy = clamp( projRadius.xy, 0.0, 0.01 ); + //float maxr = 1; + //radiusDepth = clamp( radiusDepth, 0.0001, maxr.rrr ); + //if ( radiusDepth.x < 1.0 / targetSize.x ) + // return color; + //radiusDepth.xyz = 0.0009; + + for ( i = sSampleCount; i < totalSampleCount; i++ ) + { + baseRay = reflect( ptSphere[i], reflectNormal ); + + dt = dot( baseRay.xyz, normal ); + + baseRay *= sign( dt ); + + ray = ( projRadius * baseRay.xzy ); + ray.y = -ray.y; + + se = ep + ray; + + occluderFragment = deferredUncondition( deferredMap, se.xy ); + + depthDiff = se.z - occluderFragment.a; + + normalDiff = dot( occluderFragment.xyz, normal ); + dt = dot( occluderFragment.xyz, baseRay.xyz ); + + bl += getOcclusion( depthDiff, depthMin, depthMax, lDepthPow, normalDiff, dt, lNormalTol, lNormalPow ); + } + + lOcclusion = lStrength * ( bl / float( totalSampleCount - sSampleCount ) ); + +#endif // DOLARGE + + float occlusion = saturate( max( sOcclusion, lOcclusion ) * overallStrength ); + + // Note black is unoccluded and white is fully occluded. This + // seems backwards, but it makes it simple to deal with the SSAO + // being disabled in the lighting shaders. + + OUT_col = vec4(occlusion, vec3(0.0)); +} + + diff --git a/Templates/BaseGame/game/core/rendering/shaders/postFX/ssao/gl/SSAO_PowerTable_P.glsl b/Templates/BaseGame/game/core/rendering/shaders/postFX/ssao/gl/SSAO_PowerTable_P.glsl new file mode 100644 index 000000000..4f49479ba --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/postFX/ssao/gl/SSAO_PowerTable_P.glsl @@ -0,0 +1,34 @@ +//----------------------------------------------------------------------------- +// 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 vec2 uv0; +#define IN_uv0 uv0 + +out vec4 OUT_col; + +void main() +{ + float power = pow( max( IN_uv0.x, 0 ), 0.1 ); + OUT_col = vec4( power, 0, 0, 1 ); +} \ No newline at end of file diff --git a/Templates/BaseGame/game/core/rendering/shaders/postFX/ssao/gl/SSAO_PowerTable_V.glsl b/Templates/BaseGame/game/core/rendering/shaders/postFX/ssao/gl/SSAO_PowerTable_V.glsl new file mode 100644 index 000000000..a193f63ce --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/postFX/ssao/gl/SSAO_PowerTable_V.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/torque.glsl" +#include "../../../gl/hlslCompat.glsl" +#include "../../gl/postFX.glsl" + +void main() +{ + OUT_hpos = IN_pos; + OUT_uv0 = IN_uv; //viewportCoordToRenderTarget( IN_uv, rtParams0 ); + OUT_uv1 = IN_uv; //viewportCoordToRenderTarget( IN_uv, rtParams1 ); + OUT_uv2 = IN_uv; //viewportCoordToRenderTarget( IN_uv, rtParams2 ); + OUT_uv3 = IN_uv; //viewportCoordToRenderTarget( IN_uv, rtParams3 ); + + OUT_wsEyeRay = IN_wsEyeRay; + + correctSSP(gl_Position); +} diff --git a/Templates/BaseGame/game/core/rendering/shaders/postFX/turbulenceP.hlsl b/Templates/BaseGame/game/core/rendering/shaders/postFX/turbulenceP.hlsl new file mode 100644 index 000000000..c8c572ae7 --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/postFX/turbulenceP.hlsl @@ -0,0 +1,44 @@ +//----------------------------------------------------------------------------- +// 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 "./postFx.hlsl" + +uniform float accumTime; +uniform float2 projectionOffset; +uniform float4 targetViewport; +TORQUE_UNIFORM_SAMPLER2D(inputTex, 0); + + +float4 main( PFXVertToPix IN ) : TORQUE_TARGET0 +{ + float speed = 2.0; + float distortion = 6.0; + + float y = IN.uv0.y + (cos((IN.uv0.y+projectionOffset.y) * distortion + accumTime * speed) * 0.01); + float x = IN.uv0.x + (sin((IN.uv0.x+projectionOffset.x) * distortion + accumTime * speed) * 0.01); + + // Clamp the calculated uv values to be within the target's viewport + y = clamp(y, targetViewport.y, targetViewport.w); + x = clamp(x, targetViewport.x, targetViewport.z); + + return TORQUE_TEX2D(inputTex, float2(x, y)); +} diff --git a/Templates/BaseGame/game/core/rendering/shaders/postFX/underwaterFogP.hlsl b/Templates/BaseGame/game/core/rendering/shaders/postFX/underwaterFogP.hlsl new file mode 100644 index 000000000..aab43c45c --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/postFX/underwaterFogP.hlsl @@ -0,0 +1,138 @@ +//----------------------------------------------------------------------------- +// 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 "./postFx.hlsl" +#include "../torque.hlsl" +#include "../shaderModelAutoGen.hlsl" +//----------------------------------------------------------------------------- +// Defines +//----------------------------------------------------------------------------- + +// oceanFogData +#define FOG_DENSITY waterFogData[0] +#define FOG_DENSITY_OFFSET waterFogData[1] +#define WET_DEPTH waterFogData[2] +#define WET_DARKENING waterFogData[3] + +//----------------------------------------------------------------------------- +// Uniforms +//----------------------------------------------------------------------------- + +TORQUE_UNIFORM_SAMPLER2D(deferredTex, 0); +TORQUE_UNIFORM_SAMPLER2D(backbuffer, 1); +TORQUE_UNIFORM_SAMPLER1D(waterDepthGradMap, 2); + +uniform float3 eyePosWorld; +uniform float waterDepthGradMax; +uniform float3 ambientColor; +uniform float4 waterColor; +uniform float4 waterFogData; +uniform float4 waterFogPlane; +uniform float2 nearFar; +uniform float4 rtParams0; + + +float4 main( PFXVertToPix IN ) : TORQUE_TARGET0 +{ + //float2 deferredCoord = IN.uv0; + //IN.uv0 = ( IN.uv0.xy * rtParams0.zw ) + rtParams0.xy; + float depth = TORQUE_DEFERRED_UNCONDITION( deferredTex, IN.uv0 ).w; + //return float4( depth.rrr, 1 ); + + // Skip fogging the extreme far plane so that + // the canvas clear color always appears. + //clip( 0.9 - depth ); + + // We assume that the eye position is below water because + // otherwise this shader/posteffect should not be active. + + depth *= nearFar.y; + + float3 eyeRay = normalize( IN.wsEyeRay ); + + float3 rayStart = eyePosWorld; + float3 rayEnd = eyePosWorld + ( eyeRay * depth ); + //return float4( rayEnd, 1 ); + + float4 plane = waterFogPlane; //float4( 0, 0, 1, -waterHeight ); + //plane.w -= 0.15; + + float startSide = dot( plane.xyz, rayStart ) + plane.w; + if ( startSide > 0 ) + { + rayStart.z -= ( startSide ); + //return float4( 1, 0, 0, 1 ); + } + + float3 hitPos; + float3 ray = rayEnd - rayStart; + float rayLen = length( ray ); + float3 rayDir = normalize( ray ); + + float endSide = dot( plane.xyz, rayEnd ) + plane.w; + float planeDist; + + if ( endSide < -0.005 ) + { + //return float4( 0, 0, 1, 1 ); + hitPos = rayEnd; + planeDist = endSide; + } + else + { + //return float4( 0, 0, 0, 0 ); + float den = dot( ray, plane.xyz ); + + // Parallal to the plane, return the endPnt. + //if ( den == 0.0f ) + // return endPnt; + + float dist = -( dot( plane.xyz, rayStart ) + plane.w ) / den; + if ( dist < 0.0 ) + dist = 0.0; + //return float4( 1, 0, 0, 1 ); + //return float4( ( dist ).rrr, 1 ); + + + hitPos = lerp( rayStart, rayEnd, dist ); + + planeDist = dist; + } + + float delta = length( hitPos - rayStart ); + + float fogAmt = 1.0 - saturate( exp( -FOG_DENSITY * ( delta - FOG_DENSITY_OFFSET ) ) ); + //return float4( fogAmt.rrr, 1 ); + + // Calculate the water "base" color based on depth. + float4 fogColor = waterColor * TORQUE_TEX1D( waterDepthGradMap, saturate( delta / waterDepthGradMax ) ); + // Modulate baseColor by the ambientColor. + fogColor *= float4( ambientColor.rgb, 1 ); + + float3 inColor = hdrDecode( TORQUE_TEX2D( backbuffer, IN.uv0 ).rgb ); + inColor.rgb *= 1.0 - saturate( abs( planeDist ) / WET_DEPTH ) * WET_DARKENING; + //return float4( inColor, 1 ); + + float3 outColor = lerp( inColor, fogColor.rgb, fogAmt ); + + return float4( hdrEncode( outColor ), 1 ); +} \ No newline at end of file diff --git a/Templates/BaseGame/game/core/rendering/shaders/postFX/vignette/VignetteP.hlsl b/Templates/BaseGame/game/core/rendering/shaders/postFX/vignette/VignetteP.hlsl new file mode 100644 index 000000000..c518a2145 --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/postFX/vignette/VignetteP.hlsl @@ -0,0 +1,35 @@ +//----------------------------------------------------------------------------- +// 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 "../postFx.hlsl" + +TORQUE_UNIFORM_SAMPLER2D(backBuffer, 0); +uniform float Vmax; +uniform float Vmin; + +float4 main(PFXVertToPix IN) : TORQUE_TARGET0 +{ + float4 base = TORQUE_TEX2D(backBuffer, IN.uv0); + float dist = distance(IN.uv0, float2(0.5,0.5)); + base.rgb *= smoothstep(Vmax, Vmin, dist); + return base; +} \ No newline at end of file diff --git a/Templates/BaseGame/game/core/rendering/shaders/postFX/vignette/gl/VignetteP.glsl b/Templates/BaseGame/game/core/rendering/shaders/postFX/vignette/gl/VignetteP.glsl new file mode 100644 index 000000000..35de95c34 --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/postFX/vignette/gl/VignetteP.glsl @@ -0,0 +1,41 @@ +//----------------------------------------------------------------------------- +// 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" + +uniform sampler2D backBuffer; +uniform float Vmax; +uniform float Vmin; + +in vec2 uv0; +#define IN_uv0 uv0 + +out vec4 OUT_col; + +void main() +{ + vec4 base = texture(backBuffer, IN_uv0); + float dist = distance(IN_uv0, vec2(0.5,0.5)); + base.rgb *= smoothstep(Vmax, Vmin, dist); + OUT_col = base; +} \ No newline at end of file diff --git a/Templates/BaseGame/game/core/rendering/shaders/precipP.hlsl b/Templates/BaseGame/game/core/rendering/shaders/precipP.hlsl new file mode 100644 index 000000000..069ba4992 --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/precipP.hlsl @@ -0,0 +1,53 @@ +//----------------------------------------------------------------------------- +// 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. +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// Structures +//----------------------------------------------------------------------------- + +#include "shaderModel.hlsl" + +struct Conn +{ + float4 position : TORQUE_POSITION; + float2 texCoord : TEXCOORD0; + float4 color : COLOR0; +}; + +struct Frag +{ + float4 col : TORQUE_TARGET0; +}; + +TORQUE_UNIFORM_SAMPLER2D(diffuseMap, 0); + +//----------------------------------------------------------------------------- +// Main +//----------------------------------------------------------------------------- +Frag main( Conn In) +{ + Frag Out; + + Out.col = TORQUE_TEX2D(diffuseMap, In.texCoord) * In.color; + + return Out; +} diff --git a/Templates/BaseGame/game/core/rendering/shaders/precipV.hlsl b/Templates/BaseGame/game/core/rendering/shaders/precipV.hlsl new file mode 100644 index 000000000..3c40942c7 --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/precipV.hlsl @@ -0,0 +1,71 @@ +//----------------------------------------------------------------------------- +// 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. +//----------------------------------------------------------------------------- + +//***************************************************************************** +// Precipitation vertex shader +//***************************************************************************** +//----------------------------------------------------------------------------- +// Constants +//----------------------------------------------------------------------------- + +#include "shaderModel.hlsl" + +struct Vert +{ + float3 position : POSITION; + float2 texCoord : TEXCOORD0; + float4 color : COLOR0; +}; + +struct Conn +{ + float4 position : TORQUE_POSITION; + float2 texCoord : TEXCOORD0; + float4 color : COLOR0; +}; + +uniform float4x4 modelview : register(C0); +uniform float2 fadeStartEnd : register(C4); +uniform float3 cameraPos : register(C5); +uniform float3 ambient : register(C6); + +//----------------------------------------------------------------------------- +// Main +//----------------------------------------------------------------------------- +Conn main( Vert In ) +{ + Conn Out; + + Out.position = mul(modelview, float4(In.position,1.0)); + Out.texCoord = In.texCoord; + Out.color = float4( ambient.r, ambient.g, ambient.b, 1 ); + + // Do we need to do a distance fade? + if ( fadeStartEnd.x < fadeStartEnd.y ) { + + float distance = length( cameraPos - In.position ); + Out.color.a = abs( clamp( ( distance - fadeStartEnd.x ) / ( fadeStartEnd.y - fadeStartEnd.x ), 0, 1 ) - 1 ); + } + + return Out; +} + diff --git a/Templates/BaseGame/game/core/rendering/shaders/projectedShadowP.hlsl b/Templates/BaseGame/game/core/rendering/shaders/projectedShadowP.hlsl new file mode 100644 index 000000000..88713bd52 --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/projectedShadowP.hlsl @@ -0,0 +1,40 @@ +//----------------------------------------------------------------------------- +// 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 "shaderModel.hlsl" + +struct Conn +{ + float4 position : TORQUE_POSITION; + float4 color : COLOR0; + float2 texCoord : TEXCOORD0; + float fade : TEXCOORD1; +}; + +TORQUE_UNIFORM_SAMPLER2D(inputTex, 0); +uniform float4 ambient; + +float4 main( Conn IN ) : TORQUE_TARGET0 +{ + float shadow = TORQUE_TEX2D( inputTex, IN.texCoord ).a * IN.color.a; + return ( ambient * shadow ) + ( 1 - shadow ); +} diff --git a/Templates/BaseGame/game/core/rendering/shaders/projectedShadowV.hlsl b/Templates/BaseGame/game/core/rendering/shaders/projectedShadowV.hlsl new file mode 100644 index 000000000..38b1bd3e2 --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/projectedShadowV.hlsl @@ -0,0 +1,60 @@ +//----------------------------------------------------------------------------- +// 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 "shaderModel.hlsl" + +struct Vert +{ + float3 position : POSITION; + float3 normal : NORMAL; + float3 T : TANGENT; + float4 color : COLOR0; + float2 texCoord : TEXCOORD0; +}; + +struct Conn +{ + float4 position : TORQUE_POSITION; + float4 color : COLOR0; + float2 texCoord : TEXCOORD0; + float fade : TEXCOORD1; +}; + +uniform float4x4 modelview; +uniform float shadowLength; +uniform float3 shadowCasterPosition; + +Conn main( Vert In ) +{ + Conn Out; + + // Decals are in world space. + Out.position = mul( modelview, float4( In.position, 1.0 ) ); + + Out.color = In.color; + Out.texCoord = In.texCoord; + + float fromCasterDist = length( In.position - shadowCasterPosition ) - shadowLength; + Out.fade = 1.0 - saturate( fromCasterDist / shadowLength ); + + return Out; +} diff --git a/Templates/BaseGame/game/core/rendering/shaders/ribbons/basicRibbonShaderP.hlsl b/Templates/BaseGame/game/core/rendering/shaders/ribbons/basicRibbonShaderP.hlsl new file mode 100644 index 000000000..f4c6c7b04 --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/ribbons/basicRibbonShaderP.hlsl @@ -0,0 +1,19 @@ +#define IN_HLSL +#include "../shdrConsts.h" +#include "../shaderModel.hlsl" + +struct v2f +{ + float4 hpos : TORQUE_POSITION; + float4 color : COLOR0; + float2 texCoord : TEXCOORD0; + float2 shiftdata : TEXCOORD1; +}; + +float4 main(v2f IN) : TORQUE_TARGET0 +{ + float fade = 1.0 - abs(IN.shiftdata.y - 0.5) * 2.0; + IN.color.xyz = IN.color.xyz + pow(fade, 4) / 10; + IN.color.a = IN.color.a * fade; + return IN.color; +} \ No newline at end of file diff --git a/Templates/BaseGame/game/core/rendering/shaders/ribbons/basicRibbonShaderV.hlsl b/Templates/BaseGame/game/core/rendering/shaders/ribbons/basicRibbonShaderV.hlsl new file mode 100644 index 000000000..1a6bc85e4 --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/ribbons/basicRibbonShaderV.hlsl @@ -0,0 +1,35 @@ +#define IN_HLSL +#include "../shdrConsts.h" +#include "../shaderModel.hlsl" + +struct a2v +{ + float3 position : POSITION; + float3 normal : NORMAL; + float4 color : COLOR0; + float2 texCoord : TEXCOORD0; + float2 shiftdata : TEXCOORD1; +}; + +struct v2f +{ + float4 hpos : TORQUE_POSITION; + float4 color : COLOR0; + float2 texCoord : TEXCOORD0; + float2 shiftdata : TEXCOORD1; +}; + +uniform float4x4 modelview; +uniform float3 eyePos; + +v2f main(a2v IN) +{ + v2f OUT; + + OUT.hpos = mul(modelview, float4(IN.position, 1.0)); + OUT.color = IN.color; + OUT.texCoord = IN.texCoord; + OUT.shiftdata = IN.shiftdata; + + return OUT; +} \ No newline at end of file diff --git a/Templates/BaseGame/game/core/rendering/shaders/ribbons/gl/basicRibbonShaderP.glsl b/Templates/BaseGame/game/core/rendering/shaders/ribbons/gl/basicRibbonShaderP.glsl new file mode 100644 index 000000000..f3f83ce30 --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/ribbons/gl/basicRibbonShaderP.glsl @@ -0,0 +1,20 @@ +#include "../../gl/hlslCompat.glsl" + +in float4 _hpos; +in float2 _texCoord; +in float2 _shiftdata; +in float4 _color; + +#define IN_hpos _hpos +#define IN_texCoord _texCoord +#define IN_shiftdata _shiftdata +#define IN_color _color + +out float4 OUT_col; + +void main() +{ + float fade = 1.0 - abs(IN_shiftdata.y - 0.5) * 2.0; + OUT_col.xyz = IN_color.xyz + pow(fade, 4) / 10; + OUT_col.a = IN_color.a * fade; +} \ No newline at end of file diff --git a/Templates/BaseGame/game/core/rendering/shaders/ribbons/gl/basicRibbonShaderV.glsl b/Templates/BaseGame/game/core/rendering/shaders/ribbons/gl/basicRibbonShaderV.glsl new file mode 100644 index 000000000..9f6826d55 --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/ribbons/gl/basicRibbonShaderV.glsl @@ -0,0 +1,37 @@ +#include "../../gl/hlslCompat.glsl" + +in float2 vTexCoord0; +in float2 vTexCoord1; +in float3 vNormal; +in float4 vPosition; +in float4 vColor; + +#define IN_texCoord vTexCoord0 +#define IN_shiftdata vTexCoord1 +#define IN_normal vNormal +#define IN_position vPosition +#define IN_color vColor + +out float4 _hpos; +out float2 _texCoord; +out float2 _shiftdata; +out float4 _color; + +#define OUT_hpos _hpos +#define OUT_texCoord _texCoord +#define OUT_shiftdata _shiftdata +#define OUT_color _color + +uniform float4x4 modelview; +uniform float3 eyePos; + +void main() +{ + OUT_hpos = tMul(modelview, IN_position); + OUT_color = IN_color; + OUT_texCoord = IN_texCoord; + OUT_shiftdata = IN_shiftdata; + + gl_Position = OUT_hpos; + correctSSP(gl_Position); +} \ No newline at end of file diff --git a/Templates/BaseGame/game/core/rendering/shaders/ribbons/gl/texRibbonShaderP.glsl b/Templates/BaseGame/game/core/rendering/shaders/ribbons/gl/texRibbonShaderP.glsl new file mode 100644 index 000000000..cd3e72d43 --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/ribbons/gl/texRibbonShaderP.glsl @@ -0,0 +1,22 @@ +#include "../../gl/hlslCompat.glsl" +#include "../../gl/torque.glsl" + +in float4 _hpos; +in float2 _texCoord; +in float2 _shiftdata; +in float4 _color; + +#define IN_hpos _hpos +#define IN_texCoord _texCoord +#define IN_shiftdata _shiftdata +#define IN_color _color + +out float4 OUT_col; +uniform sampler2D ribTex; + +void main() +{ + float4 Tex = tex2D(ribTex,IN_texCoord); + Tex.a *= IN_color.a; + OUT_col = hdrEncode(Tex); +} \ No newline at end of file diff --git a/Templates/BaseGame/game/core/rendering/shaders/ribbons/gl/texRibbonShaderV.glsl b/Templates/BaseGame/game/core/rendering/shaders/ribbons/gl/texRibbonShaderV.glsl new file mode 100644 index 000000000..9f6826d55 --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/ribbons/gl/texRibbonShaderV.glsl @@ -0,0 +1,37 @@ +#include "../../gl/hlslCompat.glsl" + +in float2 vTexCoord0; +in float2 vTexCoord1; +in float3 vNormal; +in float4 vPosition; +in float4 vColor; + +#define IN_texCoord vTexCoord0 +#define IN_shiftdata vTexCoord1 +#define IN_normal vNormal +#define IN_position vPosition +#define IN_color vColor + +out float4 _hpos; +out float2 _texCoord; +out float2 _shiftdata; +out float4 _color; + +#define OUT_hpos _hpos +#define OUT_texCoord _texCoord +#define OUT_shiftdata _shiftdata +#define OUT_color _color + +uniform float4x4 modelview; +uniform float3 eyePos; + +void main() +{ + OUT_hpos = tMul(modelview, IN_position); + OUT_color = IN_color; + OUT_texCoord = IN_texCoord; + OUT_shiftdata = IN_shiftdata; + + gl_Position = OUT_hpos; + correctSSP(gl_Position); +} \ No newline at end of file diff --git a/Templates/BaseGame/game/core/rendering/shaders/ribbons/texRibbonShaderP.hlsl b/Templates/BaseGame/game/core/rendering/shaders/ribbons/texRibbonShaderP.hlsl new file mode 100644 index 000000000..55bae76fd --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/ribbons/texRibbonShaderP.hlsl @@ -0,0 +1,21 @@ +#define IN_HLSL +#include "../shdrConsts.h" +#include "../torque.hlsl" + + +TORQUE_UNIFORM_SAMPLER2D(ribTex, 0); + +struct v2f +{ + float4 hpos : TORQUE_POSITION; + float4 color : COLOR0; + float2 texCoord : TEXCOORD0; + float2 shiftdata : TEXCOORD1; +}; + +float4 main(v2f IN) : TORQUE_TARGET0 +{ + float4 Tex = TORQUE_TEX2D(ribTex,IN.texCoord); + Tex.a *= IN.color.a; + return hdrEncode(Tex); +} \ No newline at end of file diff --git a/Templates/BaseGame/game/core/rendering/shaders/ribbons/texRibbonShaderV.hlsl b/Templates/BaseGame/game/core/rendering/shaders/ribbons/texRibbonShaderV.hlsl new file mode 100644 index 000000000..2ce4f62fd --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/ribbons/texRibbonShaderV.hlsl @@ -0,0 +1,35 @@ +#define IN_HLSL +#include "../shdrConsts.h" +#include "../shaderModel.hlsl" + +struct a2v +{ + float3 position : POSITION; + float4 color : COLOR0; + float3 normal : NORMAL; + float2 texCoord : TEXCOORD0; + float2 shiftdata : TEXCOORD1; +}; + +struct v2f +{ + float4 hpos : TORQUE_POSITION; + float4 color : COLOR0; + float2 texCoord : TEXCOORD0; + float2 shiftdata : TEXCOORD1; +}; + +uniform float4x4 modelview; +uniform float3 eyePos; + +v2f main(a2v IN) +{ + v2f OUT; + + OUT.hpos = mul(modelview, float4(IN.position,1.0)); + OUT.color = IN.color; + OUT.texCoord = IN.texCoord; + OUT.shiftdata = IN.shiftdata; + + return OUT; +} \ No newline at end of file diff --git a/Templates/BaseGame/game/core/rendering/shaders/scatterSkyP.hlsl b/Templates/BaseGame/game/core/rendering/shaders/scatterSkyP.hlsl new file mode 100644 index 000000000..84e0854e0 --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/scatterSkyP.hlsl @@ -0,0 +1,69 @@ +//----------------------------------------------------------------------------- +// 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 "shaderModel.hlsl" +#include "torque.hlsl" + +struct Conn +{ + float4 hpos : TORQUE_POSITION; + float4 rayleighColor : TEXCOORD0; + float4 mieColor : TEXCOORD1; + float3 v3Direction : TEXCOORD2; + float3 pos : TEXCOORD3; +}; + +TORQUE_UNIFORM_SAMPLERCUBE(nightSky, 0); +uniform float4 nightColor; +uniform float2 nightInterpAndExposure; +uniform float useCubemap; +uniform float3 lightDir; +uniform float3 sunDir; + +float4 main( Conn In ) : TORQUE_TARGET0 +{ + + float fCos = dot( lightDir, In.v3Direction ) / length(In.v3Direction); + float fCos2 = fCos*fCos; + + float g = -0.991; + float g2 = -0.991 * -0.991; + + float fMiePhase = 1.5 * ((1.0 - g2) / (2.0 + g2)) * (1.0 + fCos2) / pow(abs(1.0 + g2 - 2.0*g*fCos), 1.5); + + float4 color = In.rayleighColor + fMiePhase * In.mieColor; + color.a = color.b; + + float4 Out; + + float4 nightSkyColor = TORQUE_TEXCUBE(nightSky, -In.v3Direction); + nightSkyColor = lerp( nightColor, nightSkyColor, useCubemap ); + + float fac = dot( normalize( In.pos ), sunDir ); + fac = max( nightInterpAndExposure.y, pow( saturate( fac ), 2 ) ); + Out = lerp( color, nightSkyColor, nightInterpAndExposure.y ); + + Out.a = 1; + Out = saturate(Out); + + return hdrEncode( Out ); +} diff --git a/Templates/BaseGame/game/core/rendering/shaders/scatterSkyV.hlsl b/Templates/BaseGame/game/core/rendering/shaders/scatterSkyV.hlsl new file mode 100644 index 000000000..2052448db --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/scatterSkyV.hlsl @@ -0,0 +1,157 @@ +//----------------------------------------------------------------------------- +// 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 "shaderModel.hlsl" + +// The scale equation calculated by Vernier's Graphical Analysis +float vernierScale(float fCos) +{ + float x = 1.0 - fCos; + float x5 = x * 5.25; + float x5p6 = (-6.80 + x5); + float xnew = (3.83 + x * x5p6); + float xfinal = (0.459 + x * xnew); + float xfinal2 = -0.00287 + x * xfinal; + float outx = exp( xfinal2 ); + return 0.25 * outx; +} + +// This is the shader input vertex structure. +struct Vert +{ + // .xyz = point + float3 position : POSITION; +}; + +// This is the shader output data. +struct Conn +{ + float4 position : TORQUE_POSITION; + float4 rayleighColor : TEXCOORD0; + float4 mieColor : TEXCOORD1; + float3 v3Direction : TEXCOORD2; + float3 pos : TEXCOORD3; +}; + +float3 desaturate(const float3 color, const float desaturation) +{ + const float3 gray_conv = float3 (0.30, 0.59, 0.11); + return lerp(color, dot(gray_conv , color), desaturation); +} + +uniform float4x4 modelView; +uniform float4 misc; +uniform float4 sphereRadii; +uniform float4 scatteringCoeffs; +uniform float4 colorize; +uniform float3 camPos; +uniform float3 lightDir; +uniform float4 invWaveLength; + +Conn main( Vert In ) +{ + // Pull some variables out: + float camHeight = misc.x; + float camHeightSqr = misc.y; + + float scale = misc.z; + float scaleOverScaleDepth = misc.w; + + float outerRadius = sphereRadii.x; + float outerRadiusSqr = sphereRadii.y; + + float innerRadius = sphereRadii.z; + float innerRadiusSqr = sphereRadii.w; + + float rayleighBrightness = scatteringCoeffs.x; // Kr * ESun + float rayleigh4PI = scatteringCoeffs.y; // Kr * 4 * PI + + float mieBrightness = scatteringCoeffs.z; // Km * ESun + float mie4PI = scatteringCoeffs.w; // Km * 4 * PI + + // Get the ray from the camera to the vertex, + // and its length (which is the far point of the ray + // passing through the atmosphere). + float4 v3Pos = float4(In.position,1.0) / 6378000.0; // outerRadius; + float3 newCamPos = float3( 0, 0, camHeight ); + v3Pos.z += innerRadius; + float3 v3Ray = v3Pos.xyz - newCamPos; + float fFar = length(v3Ray); + v3Ray /= fFar; + + // Calculate the ray's starting position, + // then calculate its scattering offset. + float3 v3Start = newCamPos; + float fHeight = length(v3Start); + float fDepth = exp(scaleOverScaleDepth * (innerRadius - camHeight)); + float fStartAngle = dot(v3Ray, v3Start) / fHeight; + + float fStartOffset = fDepth * vernierScale( fStartAngle ); + + // Initialize the scattering loop variables. + float fSampleLength = fFar / 2; + float fScaledLength = fSampleLength * scale; + float3 v3SampleRay = v3Ray * fSampleLength; + float3 v3SamplePoint = v3Start + v3SampleRay * 0.5; + + // Now loop through the sample rays + float3 v3FrontColor = float3(0.0, 0.0, 0.0); + for(int i=0; i<2; i++) + { + float fHeight = length(v3SamplePoint); + float fDepth = exp(scaleOverScaleDepth * (innerRadius - fHeight)); + float fLightAngle = dot(lightDir, v3SamplePoint) / fHeight; + float fCameraAngle = dot(v3Ray, v3SamplePoint) / fHeight; + + float vscale3 = vernierScale( fCameraAngle ); + float vscale2 = vernierScale( fLightAngle ); + + float fScatter = (fStartOffset + fDepth*(vscale2 - vscale3)); + float3 v3Attenuate = exp(-fScatter * (invWaveLength.xyz * rayleigh4PI + mie4PI)); + v3FrontColor += v3Attenuate * (fDepth * fScaledLength); + v3SamplePoint += v3SampleRay; + } + + Conn Out; + + // Finally, scale the Mie and Rayleigh colors + // and set up the varying variables for the pixel shader. + Out.position = mul( modelView, float4(In.position,1.0) ); + Out.mieColor.rgb = v3FrontColor * mieBrightness; + Out.mieColor.a = 1.0f; + Out.rayleighColor.rgb = v3FrontColor * (invWaveLength.xyz * rayleighBrightness); + Out.rayleighColor.a = 1.0f; + Out.v3Direction = newCamPos - v3Pos.xyz; + Out.pos = In.position; + +#ifdef USE_COLORIZE + + Out.rayleighColor.rgb = desaturate(Out.rayleighColor.rgb, 1) * colorize.a; + + Out.rayleighColor.r *= colorize.r; + Out.rayleighColor.g *= colorize.g; + Out.rayleighColor.b *= colorize.b; + +#endif + + return Out; +} \ No newline at end of file diff --git a/Templates/BaseGame/game/core/rendering/shaders/shaderModel.hlsl b/Templates/BaseGame/game/core/rendering/shaders/shaderModel.hlsl new file mode 100644 index 000000000..70ce3a02d --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/shaderModel.hlsl @@ -0,0 +1,97 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2015 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 _TORQUE_SHADERMODEL_ +#define _TORQUE_SHADERMODEL_ + +// Portability helpers for different shader models +//Shader model 1.0 - 3.0 +#if (TORQUE_SM >= 10 && TORQUE_SM <=30) + // Semantics + #define TORQUE_POSITION POSITION + #define TORQUE_DEPTH DEPTH + #define TORQUE_TARGET0 COLOR0 + #define TORQUE_TARGET1 COLOR1 + #define TORQUE_TARGET2 COLOR2 + #define TORQUE_TARGET3 COLOR3 + + // Sampler uniforms + #define TORQUE_UNIFORM_SAMPLER1D(tex,regist) uniform sampler1D tex : register(S##regist) + #define TORQUE_UNIFORM_SAMPLER2D(tex,regist) uniform sampler2D tex : register(S##regist) + #define TORQUE_UNIFORM_SAMPLER3D(tex,regist) uniform sampler3D tex : register(S##regist) + #define TORQUE_UNIFORM_SAMPLERCUBE(tex,regist) uniform samplerCUBE tex : register(S##regist) + // Sampling functions + #define TORQUE_TEX1D(tex,coords) tex1D(tex,coords) + #define TORQUE_TEX2D(tex,coords) tex2D(tex,coords) + #define TORQUE_TEX2DPROJ(tex,coords) tex2Dproj(tex,coords) //this really is sm 2 or later + #define TORQUE_TEX3D(tex,coords) tex3D(tex,coords) + #define TORQUE_TEXCUBE(tex,coords) texCUBE(tex,coords) + + //Shader model 3.0 only + #if TORQUE_SM == 30 + #define TORQUE_VPOS VPOS // This is a float2 + // The mipmap LOD is specified in coord.w + #define TORQUE_TEX2DLOD(tex,coords) tex2Dlod(tex,coords) + #endif + + //helper if you want to pass sampler/texture in a function + //2D + #define TORQUE_SAMPLER2D(tex) sampler2D tex + #define TORQUE_SAMPLER2D_MAKEARG(tex) tex + //Cube + #define TORQUE_SAMPLERCUBE(tex) samplerCUBE tex + #define TORQUE_SAMPLERCUBE_MAKEARG(tex) tex +// Shader model 4.0+ +#elif TORQUE_SM >= 40 + #define TORQUE_POSITION SV_Position + #define TORQUE_DEPTH SV_Depth + #define TORQUE_VPOS SV_Position //note float4 compared to SM 3 where it is a float2 + #define TORQUE_TARGET0 SV_Target0 + #define TORQUE_TARGET1 SV_Target1 + #define TORQUE_TARGET2 SV_Target2 + #define TORQUE_TARGET3 SV_Target3 + // Sampler uniforms + //1D is emulated to a 2D for now + #define TORQUE_UNIFORM_SAMPLER1D(tex,regist) uniform Texture2D texture_##tex : register(T##regist); uniform SamplerState tex : register(S##regist) + #define TORQUE_UNIFORM_SAMPLER2D(tex,regist) uniform Texture2D texture_##tex : register(T##regist); uniform SamplerState tex : register(S##regist) + #define TORQUE_UNIFORM_SAMPLER3D(tex,regist) uniform Texture3D texture_##tex : register(T##regist); uniform SamplerState tex : register(S##regist) + #define TORQUE_UNIFORM_SAMPLERCUBE(tex,regist) uniform TextureCube texture_##tex : register(T##regist); uniform SamplerState tex : register(S##regist) + // Sampling functions + #define TORQUE_TEX1D(tex,coords) texture_##tex.Sample(tex,coords) + #define TORQUE_TEX2D(tex,coords) texture_##tex.Sample(tex,coords) + #define TORQUE_TEX2DPROJ(tex,coords) texture_##tex.Sample(tex,coords.xy / coords.w) + #define TORQUE_TEX3D(tex,coords) texture_##tex.Sample(tex,coords) + #define TORQUE_TEXCUBE(tex,coords) texture_##tex.Sample(tex,coords) + // The mipmap LOD is specified in coord.w + #define TORQUE_TEX2DLOD(tex,coords) texture_##tex.SampleLevel(tex,coords.xy,coords.w) + + //helper if you want to pass sampler/texture in a function + //2D + #define TORQUE_SAMPLER2D(tex) Texture2D texture_##tex, SamplerState tex + #define TORQUE_SAMPLER2D_MAKEARG(tex) texture_##tex, tex + //Cube + #define TORQUE_SAMPLERCUBE(tex) TextureCube texture_##tex, SamplerState tex + #define TORQUE_SAMPLERCUBE_MAKEARG(tex) texture_##tex, tex +#endif + +#endif // _TORQUE_SHADERMODEL_ + diff --git a/Templates/BaseGame/game/core/rendering/shaders/shaderModelAutoGen.hlsl b/Templates/BaseGame/game/core/rendering/shaders/shaderModelAutoGen.hlsl new file mode 100644 index 000000000..d70847e46 --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/shaderModelAutoGen.hlsl @@ -0,0 +1,35 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2015 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 _TORQUE_SHADERMODEL_AUTOGEN_ +#define _TORQUE_SHADERMODEL_AUTOGEN_ + +#include "shadergen:/autogenConditioners.h" + +// Portability helpers for autogenConditioners +#if (TORQUE_SM >= 10 && TORQUE_SM <=30) + #define TORQUE_DEFERRED_UNCONDITION(tex, coords) deferredUncondition(tex, coords) +#elif TORQUE_SM >= 40 + #define TORQUE_DEFERRED_UNCONDITION(tex, coords) deferredUncondition(tex, texture_##tex, coords) +#endif + +#endif //_TORQUE_SHADERMODEL_AUTOGEN_ diff --git a/Templates/BaseGame/game/core/rendering/shaders/shdrConsts.h b/Templates/BaseGame/game/core/rendering/shaders/shdrConsts.h new file mode 100644 index 000000000..8c262b76a --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/shdrConsts.h @@ -0,0 +1,117 @@ +//----------------------------------------------------------------------------- +// 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. +//----------------------------------------------------------------------------- + +#ifdef IN_HLSL + +#define VC_WORLD_PROJ C0 + +#define VC_TEX_TRANS1 C4 +#define VC_LIGHT_TRANS C8 +#define VC_OBJ_TRANS C12 + +#define VC_CUBE_TRANS C16 +#define VC_CUBE_EYE_POS C19 // in cubemap space +#define VC_EYE_POS C20 // in object space +#define VC_MAT_SPECPOWER C21 + +#define VC_FOGDATA C22 + +#define VC_LIGHT_POS1 C23 +#define VC_LIGHT_DIR1 C24 +#define VC_LIGHT_DIFFUSE1 C25 +#define VC_LIGHT_SPEC1 C26 + +#define VC_LIGHT_POS2 C27 +//#define VC_LIGHT_DIR2 C28 +//#define VC_LIGHT_DIFFUSE2 C29 +//#define VC_LIGHT_SPEC2 C30 +#define VC_LIGHT_TRANS2 C31 + +//#define VC_LIGHT_POS4 C35 +//#define VC_LIGHT_DIR4 C36 +//#define VC_LIGHT_DIFFUSE4 C37 +//#define VC_LIGHT_SPEC4 C38 + +#define VC_DETAIL_SCALE C40 + + +#define PC_MAT_SPECCOLOR C0 +#define PC_MAT_SPECPOWER C1 +#define PC_DIFF_COLOR C2 +#define PC_AMBIENT_COLOR C3 +#define PC_ACCUM_TIME C4 +#define PC_DIFF_COLOR2 C5 +#define PC_VISIBILITY C6 +#define PC_COLORMULTIPLY C7 + +#define PC_USERDEF1 C8 + +// Mirror of above. Couldn't be cleaner because HLSL doesn't support function macros +#else + +#define VC_WORLD_PROJ 0 + +#define VC_TEX_TRANS1 4 +#define VC_LIGHT_TRANS 8 +#define VC_OBJ_TRANS 12 + +#define VC_CUBE_TRANS 16 +#define VC_CUBE_EYE_POS 19 // in cubemap space +#define VC_EYE_POS 20 // in object space +#define VC_MAT_SPECPOWER 21 + +#define VC_FOGDATA 22 + +#define VC_LIGHT_POS1 23 +#define VC_LIGHT_DIR1 24 +#define VC_LIGHT_DIFFUSE1 25 +#define VC_LIGHT_SPEC1 26 + +#define VC_LIGHT_POS2 27 +//#define VC_LIGHT_DIR2 28 +//#define VC_LIGHT_DIFFUSE2 29 +//#define VC_LIGHT_SPEC2 30 +#define VC_LIGHT_TRANS2 31 + +//#define VC_LIGHT_POS4 35 +//#define VC_LIGHT_DIR4 36 +//#define VC_LIGHT_DIFFUSE4 37 +//#define VC_LIGHT_SPEC4 38 + +#define VC_DETAIL_SCALE 40 + + + +#define PC_MAT_SPECCOLOR 0 +#define PC_MAT_SPECPOWER 1 +#define PC_DIFF_COLOR 2 +#define PC_AMBIENT_COLOR 3 +#define PC_ACCUM_TIME 4 +#define PC_DIFF_COLOR2 5 +#define PC_VISIBILITY 6 +#define PC_COLORMULTIPLY 7 + +#define PC_USERDEF1 8 + +#endif + + diff --git a/Templates/BaseGame/game/core/rendering/shaders/terrain/blendP.hlsl b/Templates/BaseGame/game/core/rendering/shaders/terrain/blendP.hlsl new file mode 100644 index 000000000..aeef9d6e3 --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/terrain/blendP.hlsl @@ -0,0 +1,48 @@ +//----------------------------------------------------------------------------- +// 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 "terrain.hlsl" +#include "../shaderModel.hlsl" + +struct ConnectData +{ + float4 hpos : TORQUE_POSITION; + float2 layerCoord : TEXCOORD0; + float2 texCoord : TEXCOORD1; +}; + +TORQUE_UNIFORM_SAMPLER2D(layerTex, 0); +TORQUE_UNIFORM_SAMPLER2D(textureMap, 1); + +uniform float texId; +uniform float layerSize; + +float4 main( ConnectData IN ) : TORQUE_TARGET0 +{ + float4 layerSample = round( TORQUE_TEX2D( layerTex, IN.layerCoord ) * 255.0f ); + + float blend = calcBlend( texId, IN.layerCoord, layerSize, layerSample ); + + clip( blend - 0.0001 ); + + return float4( TORQUE_TEX2D(textureMap, IN.texCoord).rgb, blend); +} diff --git a/Templates/BaseGame/game/core/rendering/shaders/terrain/blendV.hlsl b/Templates/BaseGame/game/core/rendering/shaders/terrain/blendV.hlsl new file mode 100644 index 000000000..9ccd33301 --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/terrain/blendV.hlsl @@ -0,0 +1,52 @@ +//----------------------------------------------------------------------------- +// 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. +//----------------------------------------------------------------------------- + +/// The vertex shader used in the generation and caching of the +/// base terrain texture. + +#include "../shaderModel.hlsl" + +struct VertData +{ + float3 position : POSITION; + float2 texCoord : TEXCOORD0; +}; + +struct ConnectData +{ + float4 hpos : TORQUE_POSITION; + float2 layerCoord : TEXCOORD0; + float2 texCoord : TEXCOORD1; +}; + +uniform float2 texScale; + +ConnectData main( VertData IN ) +{ + ConnectData OUT; + + OUT.hpos = float4( IN.position, 1 ); + OUT.layerCoord = IN.texCoord; + OUT.texCoord = IN.texCoord * texScale; + + return OUT; +} diff --git a/Templates/BaseGame/game/core/rendering/shaders/terrain/gl/blendP.glsl b/Templates/BaseGame/game/core/rendering/shaders/terrain/gl/blendP.glsl new file mode 100644 index 000000000..3189ea01d --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/terrain/gl/blendP.glsl @@ -0,0 +1,48 @@ +//----------------------------------------------------------------------------- +// 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 "../terrain.glsl" +#include "../../gl/hlslCompat.glsl" + +in vec2 layerCoord; +#define IN_layerCoord layerCoord +in vec2 texCoord; +#define IN_texCoord texCoord + +uniform sampler2D layerTex; +uniform sampler2D textureMap; +uniform float texId; +uniform float layerSize; + +out vec4 OUT_col; + +void main() +{ + vec4 layerSample = round(texture( layerTex, IN_layerCoord ) * 255.0); + + float blend = calcBlend( texId, IN_layerCoord, layerSize, layerSample ); + + if(blend - 0.0001 < 0.0) + discard; + + OUT_col = vec4( texture( textureMap, IN_texCoord ).rgb, blend ); +} diff --git a/Templates/BaseGame/game/core/rendering/shaders/terrain/gl/blendV.glsl b/Templates/BaseGame/game/core/rendering/shaders/terrain/gl/blendV.glsl new file mode 100644 index 000000000..dc7b7befa --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/terrain/gl/blendV.glsl @@ -0,0 +1,41 @@ +//----------------------------------------------------------------------------- +// 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. +//----------------------------------------------------------------------------- + +/// The vertex shader used in the generation and caching of the +/// base terrain texture. + +in vec4 vPosition; +in vec2 vTexCoord0; + +out vec2 layerCoord; +out vec2 texCoord; + +uniform vec2 texScale; + +void main() +{ + gl_Position = vec4(vPosition.xyz, 1.0); + layerCoord = vTexCoord0.st; + texCoord = vTexCoord0.st * texScale; + + gl_Position.y *= -1; +} diff --git a/Templates/BaseGame/game/core/rendering/shaders/terrain/terrain.glsl b/Templates/BaseGame/game/core/rendering/shaders/terrain/terrain.glsl new file mode 100644 index 000000000..756edd553 --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/terrain/terrain.glsl @@ -0,0 +1,52 @@ +//----------------------------------------------------------------------------- +// 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. +//----------------------------------------------------------------------------- + + +float calcBlend( float texId, vec2 layerCoord, float layerSize, vec4 layerSample ) +{ + // This is here to disable the blend if none of + // the neighbors equal the current id. + // + // We depend on the input layer samples being + // rounded to the correct integer ids. + // + vec4 diff = clamp( abs( layerSample - texId ), 0.0, 1.0 ); + float noBlend = float(any( bvec4(1 - diff) )); + + // Check if any of the layer samples + // match the current texture id. + vec4 factors = vec4(0); + for(int i = 0; i < 4; i++) + factors[i] = (layerSample[i] == texId) ? 1 : 0; // workaround for Intel + + // This is a custom bilinear filter. + + vec2 uv = layerCoord * layerSize; + vec2 xy = floor( uv ); + vec2 ratio = uv - xy; + vec2 opposite = 1 - ratio; + + float blend = ( factors.b * opposite.x + factors.g * ratio.x ) * opposite.y + + ( factors.r * opposite.x + factors.a * ratio.x ) * ratio.y; + + return noBlend * blend; +} diff --git a/Templates/BaseGame/game/core/rendering/shaders/terrain/terrain.hlsl b/Templates/BaseGame/game/core/rendering/shaders/terrain/terrain.hlsl new file mode 100644 index 000000000..b7c87e618 --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/terrain/terrain.hlsl @@ -0,0 +1,55 @@ +//----------------------------------------------------------------------------- +// 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. +//----------------------------------------------------------------------------- + + +float calcBlend( float texId, float2 layerCoord, float layerSize, float4 layerSample ) +{ + // This is here to disable the blend if none of + // the neighbors equal the current id. + // + // We depend on the input layer samples being + // rounded to the correct integer ids. + // + float4 diff = saturate( abs( layerSample - texId ) ); + float noBlend = any( 1 - diff ); + + // Check if any of the layer samples + // match the current texture id. + float4 factors = 0; + [unroll] + for(int i = 0; i < 4; i++) + if(layerSample[i] == texId) + factors[i] = 1; + + // This is a custom bilinear filter. + + float2 uv = layerCoord * layerSize; + float2 xy = floor( uv ); + float2 ratio = uv - xy; + float2 opposite = 1 - ratio; + + // NOTE: This will optimize down to two lerp operations. + float blend = ( factors.b * opposite.x + factors.g * ratio.x ) * opposite.y + + ( factors.r * opposite.x + factors.a * ratio.x ) * ratio.y; + + return noBlend * blend; +} diff --git a/Templates/BaseGame/game/core/rendering/shaders/torque.hlsl b/Templates/BaseGame/game/core/rendering/shaders/torque.hlsl new file mode 100644 index 000000000..7081c7153 --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/torque.hlsl @@ -0,0 +1,342 @@ +//----------------------------------------------------------------------------- +// 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 _TORQUE_HLSL_ +#define _TORQUE_HLSL_ + +#include "./shaderModel.hlsl" + +static float M_HALFPI_F = 1.57079632679489661923f; +static float M_PI_F = 3.14159265358979323846f; +static float M_2PI_F = 6.28318530717958647692f; + + +/// Calculate fog based on a start and end positions in worldSpace. +float computeSceneFog( float3 startPos, + float3 endPos, + float fogDensity, + float fogDensityOffset, + float fogHeightFalloff ) +{ + float f = length( startPos - endPos ) - fogDensityOffset; + float h = 1.0 - ( endPos.z * fogHeightFalloff ); + return exp( -fogDensity * f * h ); +} + + +/// Calculate fog based on a start and end position and a height. +/// Positions do not need to be in worldSpace but height does. +float computeSceneFog( float3 startPos, + float3 endPos, + float height, + float fogDensity, + float fogDensityOffset, + float fogHeightFalloff ) +{ + float f = length( startPos - endPos ) - fogDensityOffset; + float h = 1.0 - ( height * fogHeightFalloff ); + return exp( -fogDensity * f * h ); +} + + +/// Calculate fog based on a distance, height is not used. +float computeSceneFog( float dist, float fogDensity, float fogDensityOffset ) +{ + float f = dist - fogDensityOffset; + return exp( -fogDensity * f ); +} + + +/// Convert a float4 uv in viewport space to render target space. +float2 viewportCoordToRenderTarget( float4 inCoord, float4 rtParams ) +{ + float2 outCoord = inCoord.xy / inCoord.w; + outCoord = ( outCoord * rtParams.zw ) + rtParams.xy; + return outCoord; +} + + +/// Convert a float2 uv in viewport space to render target space. +float2 viewportCoordToRenderTarget( float2 inCoord, float4 rtParams ) +{ + float2 outCoord = ( inCoord * rtParams.zw ) + rtParams.xy; + return outCoord; +} + + +/// Convert a float4 quaternion into a 3x3 matrix. +float3x3 quatToMat( float4 quat ) +{ + float xs = quat.x * 2.0f; + float ys = quat.y * 2.0f; + float zs = quat.z * 2.0f; + + float wx = quat.w * xs; + float wy = quat.w * ys; + float wz = quat.w * zs; + + float xx = quat.x * xs; + float xy = quat.x * ys; + float xz = quat.x * zs; + + float yy = quat.y * ys; + float yz = quat.y * zs; + float zz = quat.z * zs; + + float3x3 mat; + + mat[0][0] = 1.0f - (yy + zz); + mat[0][1] = xy - wz; + mat[0][2] = xz + wy; + + mat[1][0] = xy + wz; + mat[1][1] = 1.0f - (xx + zz); + mat[1][2] = yz - wx; + + mat[2][0] = xz - wy; + mat[2][1] = yz + wx; + mat[2][2] = 1.0f - (xx + yy); + + return mat; +} + + +/// The number of additional substeps we take when refining +/// the results of the offset parallax mapping function below. +/// +/// You should turn down the number of steps if your needing +/// more performance out of your parallax surfaces. Increasing +/// the number doesn't yeild much better results and is rarely +/// worth the additional cost. +/// +#define PARALLAX_REFINE_STEPS 3 + +/// Performs fast parallax offset mapping using +/// multiple refinement steps. +/// +/// @param texMap The texture map whos alpha channel we sample the parallax depth. +/// @param texCoord The incoming texture coordinate for sampling the parallax depth. +/// @param negViewTS The negative view vector in tangent space. +/// @param depthScale The parallax factor used to scale the depth result. +/// +float2 parallaxOffset(TORQUE_SAMPLER2D(texMap), float2 texCoord, float3 negViewTS, float depthScale) +{ + float depth = TORQUE_TEX2D(texMap, texCoord).a/(PARALLAX_REFINE_STEPS*2); + float2 offset = negViewTS.xy * (depth * depthScale)/(PARALLAX_REFINE_STEPS); + + for (int i = 0; i < PARALLAX_REFINE_STEPS; i++) + { + depth = (depth + TORQUE_TEX2D(texMap, texCoord + offset).a)/(PARALLAX_REFINE_STEPS*2); + offset = negViewTS.xy * (depth * depthScale)/(PARALLAX_REFINE_STEPS); + } + + return offset; +} + +/// Same as parallaxOffset but for dxtnm where depth is stored in the red channel instead of the alpha +float2 parallaxOffsetDxtnm(TORQUE_SAMPLER2D(texMap), float2 texCoord, float3 negViewTS, float depthScale) +{ + float depth = TORQUE_TEX2D(texMap, texCoord).r/(PARALLAX_REFINE_STEPS*2); + float2 offset = negViewTS.xy * (depth * depthScale)/(PARALLAX_REFINE_STEPS*2); + + for (int i = 0; i < PARALLAX_REFINE_STEPS; i++) + { + depth = (depth + TORQUE_TEX2D(texMap, texCoord + offset).r)/(PARALLAX_REFINE_STEPS*2); + offset = negViewTS.xy * (depth * depthScale)/(PARALLAX_REFINE_STEPS*2); + } + + return offset; +} + + +/// The maximum value for 16bit per component integer HDR encoding. +static const float HDR_RGB16_MAX = 100.0; + +/// The maximum value for 10bit per component integer HDR encoding. +static const float HDR_RGB10_MAX = 4.0; + +/// Encodes an HDR color for storage into a target. +float3 hdrEncode( float3 sample ) +{ + #if defined( TORQUE_HDR_RGB16 ) + + return sample / HDR_RGB16_MAX; + + #elif defined( TORQUE_HDR_RGB10 ) + + return sample / HDR_RGB10_MAX; + + #else + + // No encoding. + return sample; + + #endif +} + +/// Encodes an HDR color for storage into a target. +float4 hdrEncode( float4 sample ) +{ + return float4( hdrEncode( sample.rgb ), sample.a ); +} + +/// Decodes an HDR color from a target. +float3 hdrDecode( float3 sample ) +{ + #if defined( TORQUE_HDR_RGB16 ) + + return sample * HDR_RGB16_MAX; + + #elif defined( TORQUE_HDR_RGB10 ) + + return sample * HDR_RGB10_MAX; + + #else + + // No encoding. + return sample; + + #endif +} + +/// Decodes an HDR color from a target. +float4 hdrDecode( float4 sample ) +{ + return float4( hdrDecode( sample.rgb ), sample.a ); +} + +/// Returns the luminance for an HDR pixel. +float hdrLuminance( float3 sample ) +{ + // There are quite a few different ways to + // calculate luminance from an rgb value. + // + // If you want to use a different technique + // then plug it in here. + // + + //////////////////////////////////////////////////////////////////////////// + // + // Max component luminance. + // + //float lum = max( sample.r, max( sample.g, sample.b ) ); + + //////////////////////////////////////////////////////////////////////////// + // The perceptual relative luminance. + // + // See http://en.wikipedia.org/wiki/Luminance_(relative) + // + const float3 RELATIVE_LUMINANCE = float3( 0.2126, 0.7152, 0.0722 ); + float lum = dot( sample, RELATIVE_LUMINANCE ); + + //////////////////////////////////////////////////////////////////////////// + // + // The average component luminance. + // + //const float3 AVERAGE_LUMINANCE = float3( 0.3333, 0.3333, 0.3333 ); + //float lum = dot( sample, AVERAGE_LUMINANCE ); + + return lum; +} + +/// Called from the visibility feature to do screen +/// door transparency for fading of objects. +void fizzle(float2 vpos, float visibility) +{ + // NOTE: The magic values below are what give us + // the nice even pattern during the fizzle. + // + // These values can be changed to get different + // patterns... some better than others. + // + // Horizontal Blinds - { vpos.x, 0.916, vpos.y, 0 } + // Vertical Lines - { vpos.x, 12.9898, vpos.y, 78.233 } + // + // I'm sure there are many more patterns here to + // discover for different effects. + + float2x2 m = { vpos.x, 0.916, vpos.y, 0.350 }; + 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 toGamma(float4 tex) +{ + return tex; +} +float3 toLinear(float3 tex) +{ + return tex; +} +// Encodes gamma. +float3 toGamma(float3 tex) +{ + return tex; +} +float3 toLinear(float3 tex) +{ + return tex; +} +// Encodes gamma. +float3 toLinear(float3 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); +} +// Sample in linear space. Decodes gamma. +float3 toLinear(float3 tex) +{ + return pow(abs(tex.rgb), 2.2); +} +// Encodes gamma. +float3 toGamma(float3 tex) +{ + return pow(abs(tex.rgb), 1.0/2.2); +} +#endif // + +#endif // _TORQUE_HLSL_ diff --git a/Templates/BaseGame/game/core/rendering/shaders/water/gl/waterBasicP.glsl b/Templates/BaseGame/game/core/rendering/shaders/water/gl/waterBasicP.glsl new file mode 100644 index 000000000..91bdb4137 --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/water/gl/waterBasicP.glsl @@ -0,0 +1,216 @@ +//----------------------------------------------------------------------------- +// 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/torque.glsl" +#include "../../gl/hlslCompat.glsl" + +//----------------------------------------------------------------------------- +// Defines +//----------------------------------------------------------------------------- + +// miscParams +#define FRESNEL_BIAS miscParams[0] +#define FRESNEL_POWER miscParams[1] +#define CLARITY miscParams[2] +#define ISRIVER miscParams[3] + +// reflectParams +#define REFLECT_PLANE_Z reflectParams[0] +#define REFLECT_MIN_DIST reflectParams[1] +#define REFLECT_MAX_DIST reflectParams[2] +#define NO_REFLECT reflectParams[3] + +// distortionParams +#define DISTORT_START_DIST distortionParams[0] +#define DISTORT_END_DIST distortionParams[1] +#define DISTORT_FULL_DEPTH distortionParams[2] + +// ConnectData.misc +#define LIGHT_VEC IN_misc.xyz +#define WORLD_Z IN_objPos.w + +// specularParams +#define SPEC_POWER specularParams[3] +#define SPEC_COLOR specularParams.xyz + +//----------------------------------------------------------------------------- +// Defines +//----------------------------------------------------------------------------- + +// TexCoord 0 and 1 (xy,zw) for ripple texture lookup +in vec4 rippleTexCoord01; +#define IN_rippleTexCoord01 rippleTexCoord01 + +// TexCoord 2 for ripple texture lookup +in vec2 rippleTexCoord2; +#define IN_rippleTexCoord2 rippleTexCoord2 + +// Screenspace vert position BEFORE wave transformation +in vec4 posPreWave; +#define IN_posPreWave posPreWave + +// Screenspace vert position AFTER wave transformation +in vec4 posPostWave; +#define IN_posPostWave posPostWave + +// Worldspace unit distance/depth of this vertex/pixel +in float pixelDist; +#define IN_pixelDist pixelDist + +in vec4 objPos; +#define IN_objPos objPos + +in vec3 misc; +#define IN_misc misc + +//----------------------------------------------------------------------------- +// approximate Fresnel function +//----------------------------------------------------------------------------- +float fresnel(float NdotV, float bias, float power) +{ + return bias + (1.0-bias)*pow(abs(1.0 - max(NdotV, 0)), power); +} + +//----------------------------------------------------------------------------- +// Uniforms +//----------------------------------------------------------------------------- +uniform sampler2D bumpMap; +//uniform sampler2D deferredTex; +uniform sampler2D reflectMap; +uniform sampler2D refractBuff; +uniform samplerCube skyMap; +//uniform sampler2D foamMap; +uniform vec4 baseColor; +uniform vec4 miscParams; +uniform vec4 reflectParams; +uniform vec3 ambientColor; +uniform vec3 eyePos; +uniform vec3 distortionParams; +uniform vec3 fogData; +uniform vec4 fogColor; +uniform vec4 rippleMagnitude; +uniform vec4 specularParams; +uniform mat4 modelMat; + +out vec4 OUT_col; + +//----------------------------------------------------------------------------- +// Main +//----------------------------------------------------------------------------- +void main() +{ + // Modulate baseColor by the ambientColor. + vec4 waterBaseColor = baseColor * vec4( ambientColor.rgb, 1 ); + + // Get the bumpNorm... + vec3 bumpNorm = ( texture( bumpMap, IN_rippleTexCoord01.xy ).rgb * 2.0 - 1.0 ) * rippleMagnitude.x; + bumpNorm += ( texture( bumpMap, IN_rippleTexCoord01.zw ).rgb * 2.0 - 1.0 ) * rippleMagnitude.y; + bumpNorm += ( texture( bumpMap, IN_rippleTexCoord2 ).rgb * 2.0 - 1.0 ) * rippleMagnitude.z; + + bumpNorm = normalize( bumpNorm ); + bumpNorm = mix( bumpNorm, vec3(0,0,1), 1.0 - rippleMagnitude.w ); + + // We subtract a little from it so that we don't + // distort where the water surface intersects the + // camera near plane. + float distortAmt = saturate( IN_pixelDist / 1.0 ) * 0.8; + + vec4 distortPos = IN_posPostWave; + distortPos.xy += bumpNorm.xy * distortAmt; + + #ifdef UNDERWATER + OUT_col = hdrEncode( textureProj( refractBuff, distortPos ) ); + #else + + vec3 eyeVec = IN_objPos.xyz - eyePos; + eyeVec = tMul( mat3(modelMat), eyeVec ); + vec3 reflectionVec = reflect( eyeVec, bumpNorm ); + + // Color that replaces the reflection color when we do not + // have one that is appropriate. + vec4 fakeColor = vec4(ambientColor,1); + + // Use fakeColor for ripple-normals that are angled towards the camera + eyeVec = -eyeVec; + eyeVec = normalize( eyeVec ); + float ang = saturate( dot( eyeVec, bumpNorm ) ); + float fakeColorAmt = ang; + + // Get reflection map color + vec4 refMapColor = hdrDecode( textureProj( reflectMap, distortPos ) ); + // If we do not have a reflection texture then we use the cubemap. + refMapColor = mix( refMapColor, texture( skyMap, reflectionVec ), NO_REFLECT ); + + // Combine reflection color and fakeColor. + vec4 reflectColor = mix( refMapColor, fakeColor, fakeColorAmt ); + //return refMapColor; + + // Get refract color + vec4 refractColor = hdrDecode( textureProj( refractBuff, distortPos ) ); + + // calc "diffuse" color by lerping from the water color + // to refraction image based on the water clarity. + vec4 diffuseColor = mix( refractColor, waterBaseColor, 1.0f - CLARITY ); + + // fresnel calculation + float fresnelTerm = fresnel( ang, FRESNEL_BIAS, FRESNEL_POWER ); + //return vec4( fresnelTerm.rrr, 1 ); + + // Also scale the frensel by our distance to the + // water surface. This removes the hard reflection + // when really close to the water surface. + fresnelTerm *= saturate( IN_pixelDist - 0.1 ); + + // Combine the diffuse color and reflection image via the + // fresnel term and set out output color. + vec4 OUT = mix( diffuseColor, reflectColor, fresnelTerm ); + + #ifdef WATER_SPEC + + // Get some specular reflection. + vec3 newbump = bumpNorm; + newbump.xy *= 3.5; + newbump = normalize( bumpNorm ); + half3 halfAng = normalize( eyeVec + -LIGHT_VEC ); + float specular = saturate( dot( newbump, halfAng ) ); + specular = pow( specular, SPEC_POWER ); + + OUT.rgb = OUT.rgb + ( SPEC_COLOR * specular.xxx ); + + #else // Disable fogging if spec is on because otherwise we run out of instructions. + + // Fog it. + float factor = computeSceneFog( eyePos, + IN_objPos.xyz, + WORLD_Z, + fogData.x, + fogData.y, + fogData.z ); + + //OUT.rgb = mix( OUT.rgb, fogColor.rgb, 1.0 - saturate( factor ) ); + + #endif + + OUT_col = hdrEncode( OUT ); + +#endif +} diff --git a/Templates/BaseGame/game/core/rendering/shaders/water/gl/waterBasicV.glsl b/Templates/BaseGame/game/core/rendering/shaders/water/gl/waterBasicV.glsl new file mode 100644 index 000000000..e92c948e9 --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/water/gl/waterBasicV.glsl @@ -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. +//----------------------------------------------------------------------------- + +#include "../../gl/hlslCompat.glsl" + +//----------------------------------------------------------------------------- +// Defines +//----------------------------------------------------------------------------- + +// TexCoord 0 and 1 (xy,zw) for ripple texture lookup +out vec4 rippleTexCoord01; +#define OUT_rippleTexCoord01 rippleTexCoord01 + +// TexCoord 2 for ripple texture lookup +out vec2 rippleTexCoord2; +#define OUT_rippleTexCoord2 rippleTexCoord2 + +// Screenspace vert position BEFORE wave transformation +out vec4 posPreWave; +#define OUT_posPreWave posPreWave + +// Screenspace vert position AFTER wave transformation +out vec4 posPostWave; +#define OUT_posPostWave posPostWave + +// Worldspace unit distance/depth of this vertex/pixel +out float pixelDist; +#define OUT_pixelDist pixelDist + +out vec4 objPos; +#define OUT_objPos objPos + +out vec3 misc; +#define OUT_misc misc + +//----------------------------------------------------------------------------- +// Uniforms +//----------------------------------------------------------------------------- +uniform mat4 modelMat; +uniform mat4 modelview; +uniform vec4 rippleMat[3]; +uniform vec3 eyePos; +uniform vec2 waveDir[3]; +uniform vec2 waveData[3]; +uniform vec2 rippleDir[3]; +uniform vec2 rippleTexScale[3]; +uniform vec3 rippleSpeed; +uniform vec3 inLightVec; +uniform vec3 reflectNormal; +uniform float gridElementSize; +uniform float elapsedTime; +uniform float undulateMaxDist; + +in vec4 vPosition; +in vec3 vNormal; +in vec2 vTexCoord0; +in vec4 vTexCoord1; + +//----------------------------------------------------------------------------- +// Main +//----------------------------------------------------------------------------- +void main() +{ + vec4 IN_position = vPosition; + vec3 IN_normal = vNormal; + vec2 IN_undulateData = vTexCoord0; + vec4 IN_horizonFactor = vTexCoord1; + vec4 OUT_hpos = vec4(0); + + // use projection matrix for reflection / refraction texture coords + mat4 texGen = mat4FromRow( 0.5, 0.0, 0.0, 0.5, + 0.0, -0.5, 0.0, 0.5, + 0.0, 0.0, 1.0, 0.0, + 0.0, 0.0, 0.0, 1.0 ); + + // Move the vertex based on the horizonFactor if specified to do so for this vert. + // if ( IN_horizonFactor.z > 0 ) + // { + // vec2 offsetXY = eyePos.xy - eyePos.xy % gridElementSize; + // IN_position.xy += offsetXY; + // IN_undulateData += offsetXY; + // } + + vec4 worldPos = tMul( modelMat, IN_position ); + + IN_position.z = mix( IN_position.z, eyePos.z, IN_horizonFactor.x ); + + //OUT_objPos = worldPos; + OUT_objPos.xyz = IN_position.xyz; + OUT_objPos.w = worldPos.z; + + // Send pre-undulation screenspace position + OUT_posPreWave = tMul( modelview, IN_position ); + OUT_posPreWave = tMul( texGen, OUT_posPreWave ); + + // Calculate the undulation amount for this vertex. + vec2 undulatePos = tMul( modelMat, vec4( IN_undulateData.xy, 0, 1 ) ).xy; + //if ( undulatePos.x < 0 ) + // undulatePos = IN_position.xy; + + float undulateAmt = 0.0; + + undulateAmt += waveData[0].y * sin( elapsedTime * waveData[0].x + + undulatePos.x * waveDir[0].x + + undulatePos.y * waveDir[0].y ); + undulateAmt += waveData[1].y * sin( elapsedTime * waveData[1].x + + undulatePos.x * waveDir[1].x + + undulatePos.y * waveDir[1].y ); + undulateAmt += waveData[2].y * sin( elapsedTime * waveData[2].x + + undulatePos.x * waveDir[2].x + + undulatePos.y * waveDir[2].y ); + + float undulateFade = 1; + + // Scale down wave magnitude amount based on distance from the camera. + float dist = distance( IN_position.xyz, eyePos ); + dist = clamp( dist, 1.0, undulateMaxDist ); + undulateFade *= ( 1 - dist / undulateMaxDist ); + + // Also scale down wave magnitude if the camera is very very close. + undulateFade *= saturate( ( distance( IN_position.xyz, eyePos ) - 0.5 ) / 10.0 ); + + undulateAmt *= undulateFade; + + //#endif + //undulateAmt = 0; + + // Apply wave undulation to the vertex. + OUT_posPostWave = IN_position; + OUT_posPostWave.xyz += IN_normal.xyz * undulateAmt; + + // Save worldSpace position of this pixel/vert + //OUT_worldPos = OUT_posPostWave.xyz; + //OUT_worldPos = tMul( modelMat, OUT_posPostWave.xyz ); + //OUT_worldPos.z += objTrans[2][2]; //91.16; + + // OUT_misc.w = tMul( modelMat, OUT_fogPos ).z; + // if ( IN_horizonFactor.x > 0 ) + // { + // vec3 awayVec = normalize( OUT_fogPos.xyz - eyePos ); + // OUT_fogPos.xy += awayVec.xy * 1000.0; + // } + + // Convert to screen + OUT_posPostWave = tMul( modelview, OUT_posPostWave ); // tMul( modelview, vec4( OUT_posPostWave.xyz, 1 ) ); + + // Setup the OUT position symantic variable + OUT_hpos = OUT_posPostWave; // tMul( modelview, vec4( IN_position.xyz, 1 ) ); //vec4( OUT_posPostWave.xyz, 1 ); + //OUT_hpos.z = mix( OUT_hpos.z, OUT_hpos.w, IN_horizonFactor.x ); + + // Save world space camera dist/depth of the outgoing pixel + OUT_pixelDist = OUT_hpos.z; + + // Convert to reflection texture space + OUT_posPostWave = tMul( texGen, OUT_posPostWave ); + + vec2 txPos = undulatePos; + if ( bool(IN_horizonFactor.x) ) + txPos = normalize( txPos ) * 50000.0; + + // set up tex coordinates for the 3 interacting normal maps + OUT_rippleTexCoord01.xy = txPos * rippleTexScale[0]; + OUT_rippleTexCoord01.xy += rippleDir[0] * elapsedTime * rippleSpeed.x; + + mat2 texMat; + texMat[0][0] = rippleMat[0].x; + texMat[1][0] = rippleMat[0].y; + texMat[0][1] = rippleMat[0].z; + texMat[1][1] = rippleMat[0].w; + OUT_rippleTexCoord01.xy = tMul( texMat, OUT_rippleTexCoord01.xy ); + + OUT_rippleTexCoord01.zw = txPos * rippleTexScale[1]; + OUT_rippleTexCoord01.zw += rippleDir[1] * elapsedTime * rippleSpeed.y; + + texMat[0][0] = rippleMat[1].x; + texMat[1][0] = rippleMat[1].y; + texMat[0][1] = rippleMat[1].z; + texMat[1][1] = rippleMat[1].w; + OUT_rippleTexCoord01.zw = tMul( texMat, OUT_rippleTexCoord01.zw ); + + OUT_rippleTexCoord2.xy = txPos * rippleTexScale[2]; + OUT_rippleTexCoord2.xy += rippleDir[2] * elapsedTime * rippleSpeed.z; + + texMat[0][0] = rippleMat[2].x; + texMat[1][0] = rippleMat[2].y; + texMat[0][1] = rippleMat[2].z; + texMat[1][1] = rippleMat[2].w; + OUT_rippleTexCoord2.xy = tMul( texMat, OUT_rippleTexCoord2.xy ); + +#ifdef WATER_SPEC + + vec3 binormal = vec3( 1, 0, 0 ); + vec3 tangent = vec3( 0, 1, 0 ); + vec3 normal; + for ( int i = 0; i < 3; i++ ) + { + binormal.z += undulateFade * waveDir[i].x * waveData[i].y * cos( waveDir[i].x * IN_undulateData.x + waveDir[i].y * IN_undulateData.y + elapsedTime * waveData[i].x ); + tangent.z += undulateFade * waveDir[i].y * waveData[i].y * cos( waveDir[i].x * IN_undulateData.x + waveDir[i].y * IN_undulateData.y + elapsedTime * waveData[i].x ); + } + + binormal = normalize( binormal ); + tangent = normalize( tangent ); + normal = cross( binormal, tangent ); + + mat3 worldToTangent; + worldToTangent[0] = binormal; + worldToTangent[1] = tangent; + worldToTangent[2] = normal; + + worldToTangent = transpose(worldToTangent); + + OUT_misc.xyz = tMul( inLightVec, modelMat ); + OUT_misc.xyz = tMul( worldToTangent, OUT_misc.xyz ); + +#else + + OUT_misc.xyz = inLightVec; + +#endif + + gl_Position = OUT_hpos; + correctSSP(gl_Position); +} + diff --git a/Templates/BaseGame/game/core/rendering/shaders/water/gl/waterP.glsl b/Templates/BaseGame/game/core/rendering/shaders/water/gl/waterP.glsl new file mode 100644 index 000000000..d4804245a --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/water/gl/waterP.glsl @@ -0,0 +1,396 @@ +//----------------------------------------------------------------------------- +// 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" + +//----------------------------------------------------------------------------- +// Defines +//----------------------------------------------------------------------------- + +#define PIXEL_DIST IN_rippleTexCoord2.z +// miscParams +#define FRESNEL_BIAS miscParams[0] +#define FRESNEL_POWER miscParams[1] +// miscParams[2] is unused +#define ISRIVER miscParams[3] + +// reflectParams +#define REFLECT_PLANE_Z reflectParams[0] +#define REFLECT_MIN_DIST reflectParams[1] +#define REFLECT_MAX_DIST reflectParams[2] +#define NO_REFLECT reflectParams[3] + +// fogParams +#define FOG_DENSITY fogParams[0] +#define FOG_DENSITY_OFFSET fogParams[1] + +// wetnessParams +#define WET_DEPTH wetnessParams[0] +#define WET_COLOR_FACTOR wetnessParams[1] + +// distortionParams +#define DISTORT_START_DIST distortionParams[0] +#define DISTORT_END_DIST distortionParams[1] +#define DISTORT_FULL_DEPTH distortionParams[2] + +// foamParams +#define FOAM_OPACITY foamParams[0] +#define FOAM_MAX_DEPTH foamParams[1] +#define FOAM_AMBIENT_LERP foamParams[2] +#define FOAM_RIPPLE_INFLUENCE foamParams[3] + +// specularParams +#define SPEC_POWER specularParams[3] +#define SPEC_COLOR specularParams.xyz + +//----------------------------------------------------------------------------- +// Structures +//----------------------------------------------------------------------------- + +//ConnectData IN + +in vec4 hpos; + +// TexCoord 0 and 1 (xy,zw) for ripple texture lookup +in vec4 rippleTexCoord01; + +// xy is TexCoord 2 for ripple texture lookup +// z is the Worldspace unit distance/depth of this vertex/pixel +// w is amount of the crestFoam ( more at crest of waves ). +in vec4 rippleTexCoord2; + +// Screenspace vert position BEFORE wave transformation +in vec4 posPreWave; + +// Screenspace vert position AFTER wave transformation +in vec4 posPostWave; + +// Objectspace vert position BEFORE wave transformation +// w coord is world space z position. +in vec4 objPos; + +in vec4 foamTexCoords; + +in mat3 tangentMat; + + +#define IN_hpos hpos +#define IN_rippleTexCoord01 rippleTexCoord01 +#define IN_rippleTexCoord2 rippleTexCoord2 +#define IN_posPreWave posPreWave +#define IN_posPostWave posPostWave +#define IN_objPos objPos +#define IN_foamTexCoords foamTexCoords +#define IN_tangentMat tangentMat + +//----------------------------------------------------------------------------- +// approximate Fresnel function +//----------------------------------------------------------------------------- +float fresnel(float NdotV, float bias, float power) +{ + return bias + (1.0-bias)*pow(abs(1.0 - max(NdotV, 0)), power); +} + +//----------------------------------------------------------------------------- +// Uniforms +//----------------------------------------------------------------------------- +uniform sampler2D bumpMap; +uniform sampler2D deferredTex; +uniform sampler2D reflectMap; +uniform sampler2D refractBuff; +uniform samplerCube skyMap; +uniform sampler2D foamMap; +uniform sampler1D depthGradMap; +uniform vec4 specularParams; +uniform vec4 baseColor; +uniform vec4 miscParams; +uniform vec2 fogParams; +uniform vec4 reflectParams; +uniform vec3 reflectNormal; +uniform vec2 wetnessParams; +uniform float farPlaneDist; +uniform vec3 distortionParams; +uniform vec4 foamParams; +uniform vec3 ambientColor; +uniform vec3 eyePos; // This is in object space! +uniform vec3 fogData; +uniform vec4 fogColor; +uniform vec4 rippleMagnitude; +uniform vec4 rtParams1; +uniform float depthGradMax; +uniform vec3 inLightVec; +uniform mat4 modelMat; +uniform vec4 sunColor; +uniform float sunBrightness; +uniform float reflectivity; + +out vec4 OUT_col; + +//----------------------------------------------------------------------------- +// Main +//----------------------------------------------------------------------------- +void main() +{ + // Get the bumpNorm... + vec3 bumpNorm = ( texture( bumpMap, IN_rippleTexCoord01.xy ).rgb * 2.0 - 1.0 ) * rippleMagnitude.x; + bumpNorm += ( texture( bumpMap, IN_rippleTexCoord01.zw ).rgb * 2.0 - 1.0 ) * rippleMagnitude.y; + bumpNorm += ( texture( bumpMap, IN_rippleTexCoord2.xy ).rgb * 2.0 - 1.0 ) * rippleMagnitude.z; + + bumpNorm = normalize( bumpNorm ); + bumpNorm = mix( bumpNorm, vec3(0,0,1), 1.0 - rippleMagnitude.w ); + bumpNorm = tMul( bumpNorm, IN_tangentMat ); + + // Get depth of the water surface (this pixel). + // Convert from WorldSpace to EyeSpace. + float pixelDepth = PIXEL_DIST / farPlaneDist; + + vec2 deferredCoord = viewportCoordToRenderTarget( IN_posPostWave, rtParams1 ); + + float startDepth = deferredUncondition( deferredTex, deferredCoord ).w; + + // The water depth in world units of the undistorted pixel. + float startDelta = ( startDepth - pixelDepth ); + startDelta = max( startDelta, 0.0 ); + startDelta *= farPlaneDist; + + // Calculate the distortion amount for the water surface. + // + // We subtract a little from it so that we don't + // distort where the water surface intersects the + // camera near plane. + float distortAmt = saturate( ( PIXEL_DIST - DISTORT_START_DIST ) / DISTORT_END_DIST ); + + // Scale down distortion in shallow water. + distortAmt *= saturate( startDelta / DISTORT_FULL_DEPTH ); + + // Do the intial distortion... we might remove it below. + vec2 distortDelta = bumpNorm.xy * distortAmt; + vec4 distortPos = IN_posPostWave; + distortPos.xy += distortDelta; + + deferredCoord = viewportCoordToRenderTarget( distortPos, rtParams1 ); + + // Get deferred depth at the position of this distorted pixel. + float deferredDepth = deferredUncondition( deferredTex, deferredCoord ).w; + if ( deferredDepth > 0.99 ) + deferredDepth = 5.0; + + float delta = ( deferredDepth - pixelDepth ) * farPlaneDist; + + if ( delta < 0.0 ) + { + // If we got a negative delta then the distorted + // sample is above the water surface. Mask it out + // by removing the distortion. + distortPos = IN_posPostWave; + delta = startDelta; + distortAmt = 0; + } + else + { + float diff = ( deferredDepth - startDepth ) * farPlaneDist; + + if ( diff < 0 ) + { + distortAmt = saturate( ( PIXEL_DIST - DISTORT_START_DIST ) / DISTORT_END_DIST ); + distortAmt *= saturate( delta / DISTORT_FULL_DEPTH ); + + distortDelta = bumpNorm.xy * distortAmt; + + distortPos = IN_posPostWave; + distortPos.xy += distortDelta; + + deferredCoord = viewportCoordToRenderTarget( distortPos, rtParams1 ); + + // Get deferred depth at the position of this distorted pixel. + deferredDepth = deferredUncondition( deferredTex, deferredCoord ).w; + if ( deferredDepth > 0.99 ) + deferredDepth = 5.0; + delta = ( deferredDepth - pixelDepth ) * farPlaneDist; + } + + if ( delta < 0.1 ) + { + // If we got a negative delta then the distorted + // sample is above the water surface. Mask it out + // by removing the distortion. + distortPos = IN_posPostWave; + delta = startDelta; + distortAmt = 0; + } + } + + vec4 temp = IN_posPreWave; + temp.xy += bumpNorm.xy * distortAmt; + vec2 reflectCoord = viewportCoordToRenderTarget( temp, rtParams1 ); + + vec2 refractCoord = viewportCoordToRenderTarget( distortPos, rtParams1 ); + + vec4 fakeColor = vec4(ambientColor,1); + vec3 eyeVec = IN_objPos.xyz - eyePos; + eyeVec = tMul( mat3(modelMat), eyeVec ); + eyeVec = tMul( IN_tangentMat, eyeVec ); + vec3 reflectionVec = reflect( eyeVec, bumpNorm ); + + // Use fakeColor for ripple-normals that are angled towards the camera + eyeVec = -eyeVec; + eyeVec = normalize( eyeVec ); + float ang = saturate( dot( eyeVec, bumpNorm ) ); + float fakeColorAmt = ang; + + // for verts far from the reflect plane z position + float rplaneDist = abs( REFLECT_PLANE_Z - IN_objPos.w ); + rplaneDist = saturate( ( rplaneDist - 1.0 ) / 2.0 ); + rplaneDist *= ISRIVER; + fakeColorAmt = max( fakeColorAmt, rplaneDist ); + +#ifndef UNDERWATER + + // Get foam color and amount + vec2 foamRippleOffset = bumpNorm.xy * FOAM_RIPPLE_INFLUENCE; + vec4 IN_foamTexCoords = IN_foamTexCoords; + IN_foamTexCoords.xy += foamRippleOffset; + IN_foamTexCoords.zw += foamRippleOffset; + + vec4 foamColor = texture( foamMap, IN_foamTexCoords.xy ); + foamColor += texture( foamMap, IN_foamTexCoords.zw ); + foamColor = saturate( foamColor ); + + // Modulate foam color by ambient color + // so we don't have glowing white foam at night. + foamColor.rgb = mix( foamColor.rgb, ambientColor.rgb, FOAM_AMBIENT_LERP ); + + float foamDelta = saturate( delta / FOAM_MAX_DEPTH ); + float foamAmt = 1 - pow( foamDelta, 2 ); + + // Fade out the foam in very very low depth, + // this improves the shoreline a lot. + float diff = 0.8 - foamAmt; + if ( diff < 0.0 ) + foamAmt -= foamAmt * abs( diff ) / 0.2; + + foamAmt *= FOAM_OPACITY * foamColor.a; + + foamColor.rgb *= FOAM_OPACITY * foamAmt * foamColor.a; + + // Get reflection map color. + vec4 refMapColor = texture( reflectMap, reflectCoord ); + + // If we do not have a reflection texture then we use the cubemap. + refMapColor = mix( refMapColor, texture( skyMap, reflectionVec ), NO_REFLECT ); + + fakeColor = ( texture( skyMap, reflectionVec ) ); + fakeColor.a = 1; + // Combine reflection color and fakeColor. + vec4 reflectColor = mix( refMapColor, fakeColor, fakeColorAmt ); + + // Get refract color + vec4 refractColor = hdrDecode( texture( refractBuff, refractCoord ) ); + + // We darken the refraction color a bit to make underwater + // elements look wet. We fade out this darkening near the + // surface in order to not have hard water edges. + // @param WET_DEPTH The depth in world units at which full darkening will be recieved. + // @param WET_COLOR_FACTOR The refract color is scaled down by this amount when at WET_DEPTH + refractColor.rgb *= 1.0f - ( saturate( delta / WET_DEPTH ) * WET_COLOR_FACTOR ); + + // Add Water fog/haze. + float fogDelta = delta - FOG_DENSITY_OFFSET; + + if ( fogDelta < 0.0 ) + fogDelta = 0.0; + float fogAmt = 1.0 - saturate( exp( -FOG_DENSITY * fogDelta ) ); + + // Calculate the water "base" color based on depth. + vec4 waterBaseColor = baseColor * texture( depthGradMap, saturate( delta / depthGradMax ) ); + + // Modulate baseColor by the ambientColor. + waterBaseColor *= vec4( ambientColor.rgb, 1 ); + + // calc "diffuse" color by lerping from the water color + // to refraction image based on the water clarity. + vec4 diffuseColor = mix( refractColor, waterBaseColor, fogAmt ); + + // fresnel calculation + float fresnelTerm = fresnel( ang, FRESNEL_BIAS, FRESNEL_POWER ); + + // Scale the frensel strength by fog amount + // so that parts that are very clear get very little reflection. + fresnelTerm *= fogAmt; + + // Also scale the frensel by our distance to the + // water surface. This removes the hard reflection + // when really close to the water surface. + fresnelTerm *= saturate( PIXEL_DIST - 0.1 ); + + fresnelTerm *= reflectivity; + + // Combine the diffuse color and reflection image via the + // fresnel term and set out output color. + vec4 OUT = mix( diffuseColor, reflectColor, fresnelTerm ); + + vec3 lightVec = inLightVec; + + // Get some specular reflection. + vec3 newbump = bumpNorm; + newbump.xy *= 3.5; + newbump = normalize( newbump ); + vec3 halfAng = normalize( eyeVec + -lightVec ); + float specular = saturate( dot( newbump, halfAng ) ); + specular = pow( specular, SPEC_POWER ); + + // Scale down specularity in very shallow water to improve the transparency of the shoreline. + specular *= saturate( delta / 2 ); + OUT.rgb = OUT.rgb + ( SPEC_COLOR * vec3(specular) ); + +#else + + vec4 refractColor = hdrDecode( texture( refractBuff, refractCoord ) ); + vec4 OUT = refractColor; + +#endif + +#ifndef UNDERWATER + + OUT.rgb = OUT.rgb + foamColor.rgb; + + float factor = computeSceneFog( eyePos, + IN_objPos.xyz, + IN_objPos.w, + fogData.x, + fogData.y, + fogData.z ); + + OUT.rgb = mix( OUT.rgb, fogColor.rgb, 1.0 - saturate( factor ) ); + + //OUT.rgb = fogColor.rgb; + +#endif + + OUT.a = 1.0; + + //return OUT; + + OUT_col = hdrEncode( OUT ); +} diff --git a/Templates/BaseGame/game/core/rendering/shaders/water/gl/waterV.glsl b/Templates/BaseGame/game/core/rendering/shaders/water/gl/waterV.glsl new file mode 100644 index 000000000..490af63a7 --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/water/gl/waterV.glsl @@ -0,0 +1,241 @@ +//----------------------------------------------------------------------------- +// 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" + +//----------------------------------------------------------------------------- +// Structures +//----------------------------------------------------------------------------- +struct VertData +{ + vec4 position ;// POSITION; + vec3 normal ;// NORMAL; + vec2 undulateData ;// TEXCOORD0; + vec4 horizonFactor ;// TEXCOORD1; +}; + +//----------------------------------------------------------------------------- +// Defines +//----------------------------------------------------------------------------- +//VertData IN +in vec4 vPosition; +in vec3 vNormal; +in vec2 vTexCoord0; +in vec4 vTexCoord1; + +#define IN_position_ vPosition +#define IN_normal vNormal +#define IN_undulateData vTexCoord0 +#define IN_horizonFactor vTexCoord1 + +//ConnectData OUT +// + out vec4 hpos ; + +// TexCoord 0 and 1 (xy,zw) for ripple texture lookup +out vec4 rippleTexCoord01; + + // xy is TexCoord 2 for ripple texture lookup + // z is the Worldspace unit distance/depth of this vertex/pixel + // w is amount of the crestFoam ( more at crest of waves ). + out vec4 rippleTexCoord2 ; + +// Screenspace vert position BEFORE wave transformation +out vec4 posPreWave; + +// Screenspace vert position AFTER wave transformation +out vec4 posPostWave; + + // Objectspace vert position BEFORE wave transformation + // w coord is world space z position. + out vec4 objPos ; + + out vec4 foamTexCoords ; + + out mat3 tangentMat ; +// + +#define OUT_hpos hpos +#define OUT_rippleTexCoord01 rippleTexCoord01 +#define OUT_rippleTexCoord2 rippleTexCoord2 +#define OUT_posPreWave posPreWave +#define OUT_posPostWave posPostWave +#define OUT_objPos objPos +#define OUT_foamTexCoords foamTexCoords +#define OUT_tangentMat tangentMat + +//----------------------------------------------------------------------------- +// Uniforms +//----------------------------------------------------------------------------- +uniform mat4 modelMat; +uniform mat4 modelview; +uniform vec4 rippleMat[3]; +uniform vec3 eyePos; +uniform vec2 waveDir[3]; +uniform vec2 waveData[3]; +uniform vec2 rippleDir[3]; +uniform vec2 rippleTexScale[3]; +uniform vec3 rippleSpeed; +uniform vec4 foamDir; +uniform vec4 foamTexScale; +uniform vec2 foamSpeed; +uniform vec3 inLightVec; +uniform float gridElementSize; +uniform float elapsedTime; +uniform float undulateMaxDist; + +//----------------------------------------------------------------------------- +// Main +//----------------------------------------------------------------------------- +void main() +{ + vec4 IN_position = IN_position_; + + // use projection matrix for reflection / refraction texture coords + mat4 texGen = mat4FromRow( 0.5, 0.0, 0.0, 0.5, + 0.0, -0.5, 0.0, 0.5, + 0.0, 0.0, 1.0, 0.0, + 0.0, 0.0, 0.0, 1.0 ); + + IN_position.z = mix( IN_position.z, eyePos.z, IN_horizonFactor.x ); + + OUT_objPos = IN_position; + OUT_objPos.w = tMul( modelMat, IN_position ).z; + + // Send pre-undulation screenspace position + OUT_posPreWave = tMul( modelview, IN_position ); + OUT_posPreWave = tMul( texGen, OUT_posPreWave ); + + // Calculate the undulation amount for this vertex. + vec2 undulatePos = tMul( modelMat, vec4 ( IN_undulateData.xy, 0, 1 ) ).xy; + float undulateAmt = 0.0; + + undulateAmt += waveData[0].y * sin( elapsedTime * waveData[0].x + + undulatePos.x * waveDir[0].x + + undulatePos.y * waveDir[0].y ); + undulateAmt += waveData[1].y * sin( elapsedTime * waveData[1].x + + undulatePos.x * waveDir[1].x + + undulatePos.y * waveDir[1].y ); + undulateAmt += waveData[2].y * sin( elapsedTime * waveData[2].x + + undulatePos.x * waveDir[2].x + + undulatePos.y * waveDir[2].y ); + + float undulateFade = 1; + + // Scale down wave magnitude amount based on distance from the camera. + float dist = distance( IN_position.xyz, eyePos ); + dist = clamp( dist, 1.0, undulateMaxDist ); + undulateFade *= ( 1 - dist / undulateMaxDist ); + + // Also scale down wave magnitude if the camera is very very close. + undulateFade *= saturate( ( distance( IN_position.xyz, eyePos ) - 0.5 ) / 10.0 ); + + undulateAmt *= undulateFade; + + OUT_rippleTexCoord2.w = undulateAmt / ( waveData[0].y + waveData[1].y + waveData[2].y ); + OUT_rippleTexCoord2.w = saturate( OUT_rippleTexCoord2.w - 0.2 ) / 0.8; + + // Apply wave undulation to the vertex. + OUT_posPostWave = IN_position; + OUT_posPostWave.xyz += IN_normal.xyz * undulateAmt; + + // Convert to screen + OUT_posPostWave = tMul( modelview, OUT_posPostWave ); + + // Setup the OUT position symantic variable + OUT_hpos = OUT_posPostWave; + //OUT_hpos.z = mix( OUT_hpos.z, OUT_hpos.w, IN_horizonFactor.x ); + + // if ( IN_horizonFactor.x > 0 ) + // { + // vec3 awayVec = normalize( OUT_objPos.xyz - eyePos ); + // OUT_objPos.xy += awayVec.xy * 1000.0; + // } + + // Save world space camera dist/depth of the outgoing pixel + OUT_rippleTexCoord2.z = OUT_hpos.z; + + // Convert to reflection texture space + OUT_posPostWave = tMul( texGen, OUT_posPostWave ); + + vec2 txPos = undulatePos; + if ( bool(IN_horizonFactor.x) ) + txPos = normalize( txPos ) * 50000.0; + + // set up tex coordinates for the 3 interacting normal maps + OUT_rippleTexCoord01.xy = txPos * rippleTexScale[0]; + OUT_rippleTexCoord01.xy += rippleDir[0] * elapsedTime * rippleSpeed.x; + + mat2 texMat; + texMat[0][0] = rippleMat[0].x; + texMat[1][0] = rippleMat[0].y; + texMat[0][1] = rippleMat[0].z; + texMat[1][1] = rippleMat[0].w; + OUT_rippleTexCoord01.xy = tMul( texMat, OUT_rippleTexCoord01.xy ); + + OUT_rippleTexCoord01.zw = txPos * rippleTexScale[1]; + OUT_rippleTexCoord01.zw += rippleDir[1] * elapsedTime * rippleSpeed.y; + + texMat[0][0] = rippleMat[1].x; + texMat[1][0] = rippleMat[1].y; + texMat[0][1] = rippleMat[1].z; + texMat[1][1] = rippleMat[1].w; + OUT_rippleTexCoord01.zw = tMul( texMat, OUT_rippleTexCoord01.zw ); + + OUT_rippleTexCoord2.xy = txPos * rippleTexScale[2]; + OUT_rippleTexCoord2.xy += rippleDir[2] * elapsedTime * rippleSpeed.z; + + texMat[0][0] = rippleMat[2].x; + texMat[1][0] = rippleMat[2].y; + texMat[0][1] = rippleMat[2].z; + texMat[1][1] = rippleMat[2].w; + OUT_rippleTexCoord2.xy = tMul( texMat, OUT_rippleTexCoord2.xy ); + + OUT_foamTexCoords.xy = txPos * foamTexScale.xy + foamDir.xy * foamSpeed.x * elapsedTime; + OUT_foamTexCoords.zw = txPos * foamTexScale.zw + foamDir.zw * foamSpeed.y * elapsedTime; + + + vec3 binormal = vec3 ( 1, 0, 0 ); + vec3 tangent = vec3 ( 0, 1, 0 ); + vec3 normal; + for ( int i = 0; i < 3; i++ ) + { + binormal.z += undulateFade * waveDir[i].x * waveData[i].y * cos( waveDir[i].x * undulatePos.x + waveDir[i].y * undulatePos.y + elapsedTime * waveData[i].x ); + tangent.z += undulateFade * waveDir[i].y * waveData[i].y * cos( waveDir[i].x * undulatePos.x + waveDir[i].y * undulatePos.y + elapsedTime * waveData[i].x ); + } + + binormal = binormal; + tangent = tangent; + normal = cross( binormal, tangent ); + + mat3 worldToTangent; + worldToTangent[0] = binormal; + worldToTangent[1] = tangent; + worldToTangent[2] = normal; + + OUT_tangentMat = transpose(worldToTangent); + + gl_Position = OUT_hpos; + correctSSP(gl_Position); +} + diff --git a/Templates/BaseGame/game/core/rendering/shaders/water/waterBasicP.hlsl b/Templates/BaseGame/game/core/rendering/shaders/water/waterBasicP.hlsl new file mode 100644 index 000000000..9cacfdf7a --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/water/waterBasicP.hlsl @@ -0,0 +1,213 @@ +//----------------------------------------------------------------------------- +// 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 "../torque.hlsl" + +//----------------------------------------------------------------------------- +// Defines +//----------------------------------------------------------------------------- + +// miscParams +#define FRESNEL_BIAS miscParams[0] +#define FRESNEL_POWER miscParams[1] +#define CLARITY miscParams[2] +#define ISRIVER miscParams[3] + +// reflectParams +#define REFLECT_PLANE_Z reflectParams[0] +#define REFLECT_MIN_DIST reflectParams[1] +#define REFLECT_MAX_DIST reflectParams[2] +#define NO_REFLECT reflectParams[3] + +// distortionParams +#define DISTORT_START_DIST distortionParams[0] +#define DISTORT_END_DIST distortionParams[1] +#define DISTORT_FULL_DEPTH distortionParams[2] + +// ConnectData.misc +#define LIGHT_VEC IN.misc.xyz +#define WORLD_Z IN.objPos.w + +// specularParams +#define SPEC_POWER specularParams[3] +#define SPEC_COLOR specularParams.xyz + +//----------------------------------------------------------------------------- +// Structures +//----------------------------------------------------------------------------- + +struct ConnectData +{ + float4 hpos : TORQUE_POSITION; + + // TexCoord 0 and 1 (xy,zw) for ripple texture lookup + float4 rippleTexCoord01 : TEXCOORD0; + + // TexCoord 2 for ripple texture lookup + float2 rippleTexCoord2 : TEXCOORD1; + + // Screenspace vert position BEFORE wave transformation + float4 posPreWave : TEXCOORD2; + + // Screenspace vert position AFTER wave transformation + float4 posPostWave : TEXCOORD3; + + // Worldspace unit distance/depth of this vertex/pixel + float pixelDist : TEXCOORD4; + + // Objectspace vert position BEFORE wave transformation + // w coord is world space z position. + float4 objPos : TEXCOORD5; + + float3 misc : TEXCOORD6; +}; + +//----------------------------------------------------------------------------- +// approximate Fresnel function +//----------------------------------------------------------------------------- +float fresnel(float NdotV, float bias, float power) +{ + return bias + (1.0-bias)*pow(abs(1.0 - max(NdotV, 0)), power); +} + +//----------------------------------------------------------------------------- +// Uniforms +//----------------------------------------------------------------------------- +TORQUE_UNIFORM_SAMPLER2D(bumpMap,0); +//uniform sampler2D deferredTex : register( S1 ); +TORQUE_UNIFORM_SAMPLER2D(reflectMap,2); +TORQUE_UNIFORM_SAMPLER2D(refractBuff,3); +TORQUE_UNIFORM_SAMPLERCUBE(skyMap,4); +//uniform sampler foamMap : register( S5 ); +uniform float4 baseColor; +uniform float4 miscParams; +uniform float4 reflectParams; +uniform float3 ambientColor; +uniform float3 eyePos; +uniform float3 distortionParams; +uniform float3 fogData; +uniform float4 fogColor; +uniform float4 rippleMagnitude; +uniform float4 specularParams; +uniform float4x4 modelMat; + +//----------------------------------------------------------------------------- +// Main +//----------------------------------------------------------------------------- +float4 main( ConnectData IN ) : TORQUE_TARGET0 +{ + // Modulate baseColor by the ambientColor. + float4 waterBaseColor = baseColor * float4( ambientColor.rgb, 1 ); + + // Get the bumpNorm... + float3 bumpNorm = ( TORQUE_TEX2D( bumpMap, IN.rippleTexCoord01.xy ).rgb * 2.0 - 1.0 ) * rippleMagnitude.x; + bumpNorm += ( TORQUE_TEX2D( bumpMap, IN.rippleTexCoord01.zw ).rgb * 2.0 - 1.0 ) * rippleMagnitude.y; + bumpNorm += ( TORQUE_TEX2D( bumpMap, IN.rippleTexCoord2 ).rgb * 2.0 - 1.0 ) * rippleMagnitude.z; + + bumpNorm = normalize( bumpNorm ); + bumpNorm = lerp( bumpNorm, float3(0,0,1), 1.0 - rippleMagnitude.w ); + + // We subtract a little from it so that we don't + // distort where the water surface intersects the + // camera near plane. + float distortAmt = saturate( IN.pixelDist / 1.0 ) * 0.8; + + float4 distortPos = IN.posPostWave; + distortPos.xy += bumpNorm.xy * distortAmt; + + #ifdef UNDERWATER + return hdrEncode( TORQUE_TEX2DPROJ( refractBuff, distortPos ) ); + #else + + float3 eyeVec = IN.objPos.xyz - eyePos; + eyeVec = mul( (float3x3)modelMat, eyeVec ); + float3 reflectionVec = reflect( eyeVec, bumpNorm ); + + // Color that replaces the reflection color when we do not + // have one that is appropriate. + float4 fakeColor = float4(ambientColor,1); + + // Use fakeColor for ripple-normals that are angled towards the camera + eyeVec = -eyeVec; + eyeVec = normalize( eyeVec ); + float ang = saturate( dot( eyeVec, bumpNorm ) ); + float fakeColorAmt = ang; + + // Get reflection map color + float4 refMapColor = hdrDecode( TORQUE_TEX2DPROJ( reflectMap, distortPos ) ); + // If we do not have a reflection texture then we use the cubemap. + refMapColor = lerp( refMapColor, TORQUE_TEXCUBE( skyMap, reflectionVec ), NO_REFLECT ); + + // Combine reflection color and fakeColor. + float4 reflectColor = lerp( refMapColor, fakeColor, fakeColorAmt ); + //return refMapColor; + + // Get refract color + float4 refractColor = hdrDecode( TORQUE_TEX2DPROJ( refractBuff, distortPos ) ); + + // calc "diffuse" color by lerping from the water color + // to refraction image based on the water clarity. + float4 diffuseColor = lerp( refractColor, waterBaseColor, 1.0f - CLARITY ); + + // fresnel calculation + float fresnelTerm = fresnel( ang, FRESNEL_BIAS, FRESNEL_POWER ); + //return float4( fresnelTerm.rrr, 1 ); + + // Also scale the frensel by our distance to the + // water surface. This removes the hard reflection + // when really close to the water surface. + fresnelTerm *= saturate( IN.pixelDist - 0.1 ); + + // Combine the diffuse color and reflection image via the + // fresnel term and set out output color. + float4 OUT = lerp( diffuseColor, reflectColor, fresnelTerm ); + + #ifdef WATER_SPEC + + // Get some specular reflection. + float3 newbump = bumpNorm; + newbump.xy *= 3.5; + newbump = normalize( bumpNorm ); + half3 halfAng = normalize( eyeVec + -LIGHT_VEC ); + float specular = saturate( dot( newbump, halfAng ) ); + specular = pow( specular, SPEC_POWER ); + + OUT.rgb = OUT.rgb + ( SPEC_COLOR * specular.xxx ); + + #else // Disable fogging if spec is on because otherwise we run out of instructions. + + // Fog it. + float factor = computeSceneFog( eyePos, + IN.objPos.xyz, + WORLD_Z, + fogData.x, + fogData.y, + fogData.z ); + + //OUT.rgb = lerp( OUT.rgb, fogColor.rgb, 1.0 - saturate( factor ) ); + + #endif + + return hdrEncode( OUT ); + +#endif +} diff --git a/Templates/BaseGame/game/core/rendering/shaders/water/waterBasicV.hlsl b/Templates/BaseGame/game/core/rendering/shaders/water/waterBasicV.hlsl new file mode 100644 index 000000000..310647c90 --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/water/waterBasicV.hlsl @@ -0,0 +1,237 @@ +//----------------------------------------------------------------------------- +// 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 "../shaderModel.hlsl" +//----------------------------------------------------------------------------- +// Structures +//----------------------------------------------------------------------------- +struct VertData +{ + float3 position : POSITION; + float3 normal : NORMAL; + float2 undulateData : TEXCOORD0; + float4 horizonFactor : TEXCOORD1; +}; + +struct ConnectData +{ + float4 hpos : TORQUE_POSITION; + + // TexCoord 0 and 1 (xy,zw) for ripple texture lookup + float4 rippleTexCoord01 : TEXCOORD0; + + // TexCoord 2 for ripple texture lookup + float2 rippleTexCoord2 : TEXCOORD1; + + // Screenspace vert position BEFORE wave transformation + float4 posPreWave : TEXCOORD2; + + // Screenspace vert position AFTER wave transformation + float4 posPostWave : TEXCOORD3; + + // Worldspace unit distance/depth of this vertex/pixel + float pixelDist : TEXCOORD4; + + // Objectspace vert position BEFORE wave transformation + // w coord is world space z position. + float4 objPos : TEXCOORD5; + + float3 misc : TEXCOORD6; +}; + +//----------------------------------------------------------------------------- +// Uniforms +//----------------------------------------------------------------------------- +uniform float4x4 modelMat; +uniform float4x4 modelview; +uniform float4 rippleMat[3]; +uniform float3 eyePos; +uniform float2 waveDir[3]; +uniform float2 waveData[3]; +uniform float2 rippleDir[3]; +uniform float2 rippleTexScale[3]; +uniform float3 rippleSpeed; +uniform float3 inLightVec; +uniform float3 reflectNormal; +uniform float gridElementSize; +uniform float elapsedTime; +uniform float undulateMaxDist; + +//----------------------------------------------------------------------------- +// Main +//----------------------------------------------------------------------------- +ConnectData main( VertData IN ) +{ + ConnectData OUT; + + // use projection matrix for reflection / refraction texture coords + float4x4 texGen = { 0.5, 0.0, 0.0, 0.5, + 0.0, -0.5, 0.0, 0.5, + 0.0, 0.0, 1.0, 0.0, + 0.0, 0.0, 0.0, 1.0 }; + + // Move the vertex based on the horizonFactor if specified to do so for this vert. + // if ( IN.horizonFactor.z > 0 ) + // { + // float2 offsetXY = eyePos.xy - eyePos.xy % gridElementSize; + // IN.position.xy += offsetXY; + // IN.undulateData += offsetXY; + // } + float4 inPos = float4(IN.position, 1.0); + float4 worldPos = mul(modelMat, inPos); + + IN.position.z = lerp( IN.position.z, eyePos.z, IN.horizonFactor.x ); + + //OUT.objPos = worldPos; + OUT.objPos.xyz = IN.position; + OUT.objPos.w = worldPos.z; + + // Send pre-undulation screenspace position + OUT.posPreWave = mul( modelview, inPos ); + OUT.posPreWave = mul( texGen, OUT.posPreWave ); + + // Calculate the undulation amount for this vertex. + float2 undulatePos = mul( modelMat, float4( IN.undulateData.xy, 0, 1 )).xy; + //if ( undulatePos.x < 0 ) + // undulatePos = IN.position.xy; + + float undulateAmt = 0.0; + + undulateAmt += waveData[0].y * sin( elapsedTime * waveData[0].x + + undulatePos.x * waveDir[0].x + + undulatePos.y * waveDir[0].y ); + undulateAmt += waveData[1].y * sin( elapsedTime * waveData[1].x + + undulatePos.x * waveDir[1].x + + undulatePos.y * waveDir[1].y ); + undulateAmt += waveData[2].y * sin( elapsedTime * waveData[2].x + + undulatePos.x * waveDir[2].x + + undulatePos.y * waveDir[2].y ); + + float undulateFade = 1; + + // Scale down wave magnitude amount based on distance from the camera. + float dist = distance( IN.position, eyePos ); + dist = clamp( dist, 1.0, undulateMaxDist ); + undulateFade *= ( 1 - dist / undulateMaxDist ); + + // Also scale down wave magnitude if the camera is very very close. + undulateFade *= saturate( ( distance( IN.position, eyePos ) - 0.5 ) / 10.0 ); + + undulateAmt *= undulateFade; + + //#endif + //undulateAmt = 0; + + // Apply wave undulation to the vertex. + OUT.posPostWave = inPos; + OUT.posPostWave.xyz += IN.normal.xyz * undulateAmt; + + // Save worldSpace position of this pixel/vert + //OUT.worldPos = OUT.posPostWave.xyz; + //OUT.worldPos = mul( modelMat, OUT.posPostWave.xyz ); + //OUT.worldPos.z += objTrans[2][2]; //91.16; + + // OUT.misc.w = mul( modelMat, OUT.fogPos ).z; + // if ( IN.horizonFactor.x > 0 ) + // { + // float3 awayVec = normalize( OUT.fogPos.xyz - eyePos ); + // OUT.fogPos.xy += awayVec.xy * 1000.0; + // } + + // Convert to screen + OUT.posPostWave = mul( modelview, OUT.posPostWave ); // mul( modelview, float4( OUT.posPostWave.xyz, 1 ) ); + + // Setup the OUT position symantic variable + OUT.hpos = OUT.posPostWave; // mul( modelview, float4( IN.position.xyz, 1 ) ); //float4( OUT.posPostWave.xyz, 1 ); + //OUT.hpos.z = lerp( OUT.hpos.z, OUT.hpos.w, IN.horizonFactor.x ); + + // Save world space camera dist/depth of the outgoing pixel + OUT.pixelDist = OUT.hpos.z; + + // Convert to reflection texture space + OUT.posPostWave = mul( texGen, OUT.posPostWave ); + + float2 txPos = undulatePos; + if ( IN.horizonFactor.x ) + txPos = normalize( txPos ) * 50000.0; + + // set up tex coordinates for the 3 interacting normal maps + OUT.rippleTexCoord01.xy = txPos * rippleTexScale[0]; + OUT.rippleTexCoord01.xy += rippleDir[0] * elapsedTime * rippleSpeed.x; + + float2x2 texMat; + texMat[0][0] = rippleMat[0].x; + texMat[0][1] = rippleMat[0].y; + texMat[1][0] = rippleMat[0].z; + texMat[1][1] = rippleMat[0].w; + OUT.rippleTexCoord01.xy = mul( texMat, OUT.rippleTexCoord01.xy ); + + OUT.rippleTexCoord01.zw = txPos * rippleTexScale[1]; + OUT.rippleTexCoord01.zw += rippleDir[1] * elapsedTime * rippleSpeed.y; + + texMat[0][0] = rippleMat[1].x; + texMat[0][1] = rippleMat[1].y; + texMat[1][0] = rippleMat[1].z; + texMat[1][1] = rippleMat[1].w; + OUT.rippleTexCoord01.zw = mul( texMat, OUT.rippleTexCoord01.zw ); + + OUT.rippleTexCoord2.xy = txPos * rippleTexScale[2]; + OUT.rippleTexCoord2.xy += rippleDir[2] * elapsedTime * rippleSpeed.z; + + texMat[0][0] = rippleMat[2].x; + texMat[0][1] = rippleMat[2].y; + texMat[1][0] = rippleMat[2].z; + texMat[1][1] = rippleMat[2].w; + OUT.rippleTexCoord2.xy = mul( texMat, OUT.rippleTexCoord2.xy ); + +#ifdef WATER_SPEC + + float3 binormal = float3( 1, 0, 0 ); + float3 tangent = float3( 0, 1, 0 ); + float3 normal; + for ( int i = 0; i < 3; i++ ) + { + binormal.z += undulateFade * waveDir[i].x * waveData[i].y * cos( waveDir[i].x * IN.undulateData.x + waveDir[i].y * IN.undulateData.y + elapsedTime * waveData[i].x ); + tangent.z += undulateFade * waveDir[i].y * waveData[i].y * cos( waveDir[i].x * IN.undulateData.x + waveDir[i].y * IN.undulateData.y + elapsedTime * waveData[i].x ); + } + + binormal = normalize( binormal ); + tangent = normalize( tangent ); + normal = cross( binormal, tangent ); + + float3x3 worldToTangent; + worldToTangent[0] = binormal; + worldToTangent[1] = tangent; + worldToTangent[2] = normal; + + OUT.misc.xyz = mul( inLightVec, modelMat ); + OUT.misc.xyz = mul( worldToTangent, OUT.misc.xyz ); + +#else + + OUT.misc.xyz = inLightVec; + +#endif + + return OUT; +} + diff --git a/Templates/BaseGame/game/core/rendering/shaders/water/waterP.hlsl b/Templates/BaseGame/game/core/rendering/shaders/water/waterP.hlsl new file mode 100644 index 000000000..59bdad05d --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/water/waterP.hlsl @@ -0,0 +1,383 @@ +//----------------------------------------------------------------------------- +// 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 "../shaderModelAutoGen.hlsl" +#include "../torque.hlsl" + +//----------------------------------------------------------------------------- +// Defines +//----------------------------------------------------------------------------- + +#define PIXEL_DIST IN.rippleTexCoord2.z +// miscParams +#define FRESNEL_BIAS miscParams[0] +#define FRESNEL_POWER miscParams[1] +// miscParams[2] is unused +#define ISRIVER miscParams[3] + +// reflectParams +#define REFLECT_PLANE_Z reflectParams[0] +#define REFLECT_MIN_DIST reflectParams[1] +#define REFLECT_MAX_DIST reflectParams[2] +#define NO_REFLECT reflectParams[3] + +// fogParams +#define FOG_DENSITY fogParams[0] +#define FOG_DENSITY_OFFSET fogParams[1] + +// wetnessParams +#define WET_DEPTH wetnessParams[0] +#define WET_COLOR_FACTOR wetnessParams[1] + +// distortionParams +#define DISTORT_START_DIST distortionParams[0] +#define DISTORT_END_DIST distortionParams[1] +#define DISTORT_FULL_DEPTH distortionParams[2] + +// foamParams +#define FOAM_OPACITY foamParams[0] +#define FOAM_MAX_DEPTH foamParams[1] +#define FOAM_AMBIENT_LERP foamParams[2] +#define FOAM_RIPPLE_INFLUENCE foamParams[3] + +// specularParams +#define SPEC_POWER specularParams[3] +#define SPEC_COLOR specularParams.xyz + +//----------------------------------------------------------------------------- +// Structures +//----------------------------------------------------------------------------- + +struct ConnectData +{ + float4 hpos : TORQUE_POSITION; + + // TexCoord 0 and 1 (xy,zw) for ripple texture lookup + float4 rippleTexCoord01 : TEXCOORD0; + + // xy is TexCoord 2 for ripple texture lookup + // z is the Worldspace unit distance/depth of this vertex/pixel + // w is amount of the crestFoam ( more at crest of waves ). + float4 rippleTexCoord2 : TEXCOORD1; + + // Screenspace vert position BEFORE wave transformation + float4 posPreWave : TEXCOORD2; + + // Screenspace vert position AFTER wave transformation + float4 posPostWave : TEXCOORD3; + + // Objectspace vert position BEFORE wave transformation + // w coord is world space z position. + float4 objPos : TEXCOORD4; + + float4 foamTexCoords : TEXCOORD5; + + float3x3 tangentMat : TEXCOORD6; +}; + +//----------------------------------------------------------------------------- +// approximate Fresnel function +//----------------------------------------------------------------------------- +float fresnel(float NdotV, float bias, float power) +{ + return bias + (1.0-bias)*pow(abs(1.0 - max(NdotV, 0)), power); +} + +//----------------------------------------------------------------------------- +// Uniforms +//----------------------------------------------------------------------------- +TORQUE_UNIFORM_SAMPLER2D(bumpMap,0); +TORQUE_UNIFORM_SAMPLER2D(deferredTex, 1); +TORQUE_UNIFORM_SAMPLER2D(reflectMap, 2); +TORQUE_UNIFORM_SAMPLER2D(refractBuff, 3); +TORQUE_UNIFORM_SAMPLERCUBE(skyMap, 4); +TORQUE_UNIFORM_SAMPLER2D(foamMap, 5); +TORQUE_UNIFORM_SAMPLER1D(depthGradMap, 6); +uniform float4 specularParams; +uniform float4 baseColor; +uniform float4 miscParams; +uniform float2 fogParams; +uniform float4 reflectParams; +uniform float3 reflectNormal; +uniform float2 wetnessParams; +uniform float farPlaneDist; +uniform float3 distortionParams; +uniform float4 foamParams; +uniform float3 ambientColor; +uniform float3 eyePos; // This is in object space! +uniform float3 fogData; +uniform float4 fogColor; +uniform float4 rippleMagnitude; +uniform float4 rtParams1; +uniform float depthGradMax; +uniform float3 inLightVec; +uniform float4x4 modelMat; +uniform float4 sunColor; +uniform float sunBrightness; +uniform float reflectivity; + +//----------------------------------------------------------------------------- +// Main +//----------------------------------------------------------------------------- +float4 main( ConnectData IN ) : TORQUE_TARGET0 +{ + // Get the bumpNorm... + float3 bumpNorm = ( TORQUE_TEX2D( bumpMap, IN.rippleTexCoord01.xy ).rgb * 2.0 - 1.0 ) * rippleMagnitude.x; + bumpNorm += ( TORQUE_TEX2D( bumpMap, IN.rippleTexCoord01.zw ).rgb * 2.0 - 1.0 ) * rippleMagnitude.y; + bumpNorm += ( TORQUE_TEX2D( bumpMap, IN.rippleTexCoord2.xy ).rgb * 2.0 - 1.0 ) * rippleMagnitude.z; + + bumpNorm = normalize( bumpNorm ); + bumpNorm = lerp( bumpNorm, float3(0,0,1), 1.0 - rippleMagnitude.w ); + bumpNorm = mul( bumpNorm, IN.tangentMat ); + + // Get depth of the water surface (this pixel). + // Convert from WorldSpace to EyeSpace. + float pixelDepth = PIXEL_DIST / farPlaneDist; + + float2 deferredCoord = viewportCoordToRenderTarget( IN.posPostWave, rtParams1 ); + + float startDepth = TORQUE_DEFERRED_UNCONDITION( deferredTex, deferredCoord ).w; + + // The water depth in world units of the undistorted pixel. + float startDelta = ( startDepth - pixelDepth ); + startDelta = max( startDelta, 0.0 ); + startDelta *= farPlaneDist; + + // Calculate the distortion amount for the water surface. + // + // We subtract a little from it so that we don't + // distort where the water surface intersects the + // camera near plane. + float distortAmt = saturate( ( PIXEL_DIST - DISTORT_START_DIST ) / DISTORT_END_DIST ); + + // Scale down distortion in shallow water. + distortAmt *= saturate( startDelta / DISTORT_FULL_DEPTH ); + + // Do the intial distortion... we might remove it below. + float2 distortDelta = bumpNorm.xy * distortAmt; + float4 distortPos = IN.posPostWave; + distortPos.xy += distortDelta; + + deferredCoord = viewportCoordToRenderTarget( distortPos, rtParams1 ); + + // Get deferred depth at the position of this distorted pixel. + float deferredDepth = TORQUE_DEFERRED_UNCONDITION( deferredTex, deferredCoord ).w; + if ( deferredDepth > 0.99 ) + deferredDepth = 5.0; + + float delta = ( deferredDepth - pixelDepth ) * farPlaneDist; + + if ( delta < 0.0 ) + { + // If we got a negative delta then the distorted + // sample is above the water surface. Mask it out + // by removing the distortion. + distortPos = IN.posPostWave; + delta = startDelta; + distortAmt = 0; + } + else + { + float diff = ( deferredDepth - startDepth ) * farPlaneDist; + + if ( diff < 0 ) + { + distortAmt = saturate( ( PIXEL_DIST - DISTORT_START_DIST ) / DISTORT_END_DIST ); + distortAmt *= saturate( delta / DISTORT_FULL_DEPTH ); + + distortDelta = bumpNorm.xy * distortAmt; + + distortPos = IN.posPostWave; + distortPos.xy += distortDelta; + + deferredCoord = viewportCoordToRenderTarget( distortPos, rtParams1 ); + + // Get deferred depth at the position of this distorted pixel. + deferredDepth = TORQUE_DEFERRED_UNCONDITION( deferredTex, deferredCoord ).w; + if ( deferredDepth > 0.99 ) + deferredDepth = 5.0; + delta = ( deferredDepth - pixelDepth ) * farPlaneDist; + } + + if ( delta < 0.1 ) + { + // If we got a negative delta then the distorted + // sample is above the water surface. Mask it out + // by removing the distortion. + distortPos = IN.posPostWave; + delta = startDelta; + distortAmt = 0; + } + } + + float4 temp = IN.posPreWave; + temp.xy += bumpNorm.xy * distortAmt; + float2 reflectCoord = viewportCoordToRenderTarget( temp, rtParams1 ); + + float2 refractCoord = viewportCoordToRenderTarget( distortPos, rtParams1 ); + + float4 fakeColor = float4(ambientColor,1); + float3 eyeVec = IN.objPos.xyz - eyePos; + eyeVec = mul( (float3x3)modelMat, eyeVec ); + eyeVec = mul( IN.tangentMat, eyeVec ); + float3 reflectionVec = reflect( eyeVec, bumpNorm ); + + // Use fakeColor for ripple-normals that are angled towards the camera + eyeVec = -eyeVec; + eyeVec = normalize( eyeVec ); + float ang = saturate( dot( eyeVec, bumpNorm ) ); + float fakeColorAmt = ang; + + // for verts far from the reflect plane z position + float rplaneDist = abs( REFLECT_PLANE_Z - IN.objPos.w ); + rplaneDist = saturate( ( rplaneDist - 1.0 ) / 2.0 ); + rplaneDist *= ISRIVER; + fakeColorAmt = max( fakeColorAmt, rplaneDist ); + +#ifndef UNDERWATER + + // Get foam color and amount + float2 foamRippleOffset = bumpNorm.xy * FOAM_RIPPLE_INFLUENCE; + IN.foamTexCoords.xy += foamRippleOffset; + IN.foamTexCoords.zw += foamRippleOffset; + + float4 foamColor = TORQUE_TEX2D( foamMap, IN.foamTexCoords.xy ); + foamColor += TORQUE_TEX2D( foamMap, IN.foamTexCoords.zw ); + foamColor = saturate( foamColor ); + + // Modulate foam color by ambient color + // so we don't have glowing white foam at night. + foamColor.rgb = lerp( foamColor.rgb, ambientColor.rgb, FOAM_AMBIENT_LERP ); + + float foamDelta = saturate( delta / FOAM_MAX_DEPTH ); + float foamAmt = 1 - pow( foamDelta, 2 ); + + // Fade out the foam in very very low depth, + // this improves the shoreline a lot. + float diff = 0.8 - foamAmt; + if ( diff < 0.0 ) + foamAmt -= foamAmt * abs( diff ) / 0.2; + + foamAmt *= FOAM_OPACITY * foamColor.a; + + foamColor.rgb *= FOAM_OPACITY * foamAmt * foamColor.a; + + // Get reflection map color. + float4 refMapColor = TORQUE_TEX2D( reflectMap, reflectCoord ); + + // If we do not have a reflection texture then we use the cubemap. + refMapColor = lerp( refMapColor, TORQUE_TEXCUBE( skyMap, reflectionVec ), NO_REFLECT ); + + fakeColor = ( TORQUE_TEXCUBE( skyMap, reflectionVec ) ); + fakeColor.a = 1; + // Combine reflection color and fakeColor. + float4 reflectColor = lerp( refMapColor, fakeColor, fakeColorAmt ); + + // Get refract color + float4 refractColor = hdrDecode( TORQUE_TEX2D( refractBuff, refractCoord ) ); + + // We darken the refraction color a bit to make underwater + // elements look wet. We fade out this darkening near the + // surface in order to not have hard water edges. + // @param WET_DEPTH The depth in world units at which full darkening will be recieved. + // @param WET_COLOR_FACTOR The refract color is scaled down by this amount when at WET_DEPTH + refractColor.rgb *= 1.0f - ( saturate( delta / WET_DEPTH ) * WET_COLOR_FACTOR ); + + // Add Water fog/haze. + float fogDelta = delta - FOG_DENSITY_OFFSET; + + if ( fogDelta < 0.0 ) + fogDelta = 0.0; + float fogAmt = 1.0 - saturate( exp( -FOG_DENSITY * fogDelta ) ); + + // Calculate the water "base" color based on depth. + float4 waterBaseColor = baseColor * TORQUE_TEX1D( depthGradMap, saturate( delta / depthGradMax ) ); + + // Modulate baseColor by the ambientColor. + waterBaseColor *= float4( ambientColor.rgb, 1 ); + + // calc "diffuse" color by lerping from the water color + // to refraction image based on the water clarity. + float4 diffuseColor = lerp( refractColor, waterBaseColor, fogAmt ); + + // fresnel calculation + float fresnelTerm = fresnel( ang, FRESNEL_BIAS, FRESNEL_POWER ); + + // Scale the frensel strength by fog amount + // so that parts that are very clear get very little reflection. + fresnelTerm *= fogAmt; + + // Also scale the frensel by our distance to the + // water surface. This removes the hard reflection + // when really close to the water surface. + fresnelTerm *= saturate( PIXEL_DIST - 0.1 ); + + fresnelTerm *= reflectivity; + + // Combine the diffuse color and reflection image via the + // fresnel term and set out output color. + float4 OUT = lerp( diffuseColor, reflectColor, fresnelTerm ); + + float3 lightVec = inLightVec; + + // Get some specular reflection. + float3 newbump = bumpNorm; + newbump.xy *= 3.5; + newbump = normalize( newbump ); + float3 halfAng = normalize( eyeVec + -lightVec ); + float specular = saturate( dot( newbump, halfAng ) ); + specular = pow( specular, SPEC_POWER ); + + // Scale down specularity in very shallow water to improve the transparency of the shoreline. + specular *= saturate( delta / 2 ); + OUT.rgb = OUT.rgb + ( SPEC_COLOR * specular.xxx ); + +#else + + float4 refractColor = hdrDecode( TORQUE_TEX2D( refractBuff, refractCoord ) ); + float4 OUT = refractColor; + +#endif + +#ifndef UNDERWATER + + OUT.rgb = OUT.rgb + foamColor.rgb; + + float factor = computeSceneFog( eyePos, + IN.objPos.xyz, + IN.objPos.w, + fogData.x, + fogData.y, + fogData.z ); + + OUT.rgb = lerp( OUT.rgb, fogColor.rgb, 1.0 - saturate( factor ) ); + + //OUT.rgb = fogColor.rgb; + +#endif + + OUT.a = 1.0; + + //return OUT; + + return hdrEncode( OUT ); +} diff --git a/Templates/BaseGame/game/core/rendering/shaders/water/waterV.hlsl b/Templates/BaseGame/game/core/rendering/shaders/water/waterV.hlsl new file mode 100644 index 000000000..c869f0e9f --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/water/waterV.hlsl @@ -0,0 +1,216 @@ +//----------------------------------------------------------------------------- +// 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 "../shaderModel.hlsl" + +//----------------------------------------------------------------------------- +// Structures +//----------------------------------------------------------------------------- +struct VertData +{ + float3 position : POSITION; + float3 normal : NORMAL; + float2 undulateData : TEXCOORD0; + float4 horizonFactor : TEXCOORD1; +}; + +struct ConnectData +{ + float4 hpos : TORQUE_POSITION; + + // TexCoord 0 and 1 (xy,zw) for ripple texture lookup + float4 rippleTexCoord01 : TEXCOORD0; + + // xy is TexCoord 2 for ripple texture lookup + // z is the Worldspace unit distance/depth of this vertex/pixel + // w is amount of the crestFoam ( more at crest of waves ). + float4 rippleTexCoord2 : TEXCOORD1; + + // Screenspace vert position BEFORE wave transformation + float4 posPreWave : TEXCOORD2; + + // Screenspace vert position AFTER wave transformation + float4 posPostWave : TEXCOORD3; + + // Objectspace vert position BEFORE wave transformation + // w coord is world space z position. + float4 objPos : TEXCOORD4; + + float4 foamTexCoords : TEXCOORD5; + + float3x3 tangentMat : TEXCOORD6; +}; + +//----------------------------------------------------------------------------- +// Uniforms +//----------------------------------------------------------------------------- +uniform float4x4 modelMat; +uniform float4x4 modelview; +uniform float4 rippleMat[3]; +uniform float3 eyePos; +uniform float2 waveDir[3]; +uniform float2 waveData[3]; +uniform float2 rippleDir[3]; +uniform float2 rippleTexScale[3]; +uniform float3 rippleSpeed; +uniform float4 foamDir; +uniform float4 foamTexScale; +uniform float2 foamSpeed; +uniform float3 inLightVec; +uniform float gridElementSize; +uniform float elapsedTime; +uniform float undulateMaxDist; + +//----------------------------------------------------------------------------- +// Main +//----------------------------------------------------------------------------- +ConnectData main( VertData IN ) +{ + ConnectData OUT; + + // use projection matrix for reflection / refraction texture coords + float4x4 texGen = { 0.5, 0.0, 0.0, 0.5, + 0.0, -0.5, 0.0, 0.5, + 0.0, 0.0, 1.0, 0.0, + 0.0, 0.0, 0.0, 1.0 }; + + IN.position.z = lerp( IN.position.z, eyePos.z, IN.horizonFactor.x ); + float4 inPos = float4( IN.position, 1.0); + OUT.objPos = inPos; + OUT.objPos.w = mul( modelMat, inPos ).z; + + // Send pre-undulation screenspace position + OUT.posPreWave = mul( modelview, inPos ); + OUT.posPreWave = mul( texGen, OUT.posPreWave ); + + // Calculate the undulation amount for this vertex. + float2 undulatePos = mul( modelMat, float4( IN.undulateData.xy, 0, 1 ) ).xy; + float undulateAmt = 0.0; + + undulateAmt += waveData[0].y * sin( elapsedTime * waveData[0].x + + undulatePos.x * waveDir[0].x + + undulatePos.y * waveDir[0].y ); + undulateAmt += waveData[1].y * sin( elapsedTime * waveData[1].x + + undulatePos.x * waveDir[1].x + + undulatePos.y * waveDir[1].y ); + undulateAmt += waveData[2].y * sin( elapsedTime * waveData[2].x + + undulatePos.x * waveDir[2].x + + undulatePos.y * waveDir[2].y ); + + float undulateFade = 1; + + // Scale down wave magnitude amount based on distance from the camera. + float dist = distance( IN.position.xyz, eyePos ); + dist = clamp( dist, 1.0, undulateMaxDist ); + undulateFade *= ( 1 - dist / undulateMaxDist ); + + // Also scale down wave magnitude if the camera is very very close. + undulateFade *= saturate( ( distance( IN.position.xyz, eyePos ) - 0.5 ) / 10.0 ); + + undulateAmt *= undulateFade; + + OUT.rippleTexCoord2.w = undulateAmt / ( waveData[0].y + waveData[1].y + waveData[2].y ); + OUT.rippleTexCoord2.w = saturate( OUT.rippleTexCoord2.w - 0.2 ) / 0.8; + + // Apply wave undulation to the vertex. + OUT.posPostWave = inPos; + OUT.posPostWave.xyz += IN.normal.xyz * undulateAmt; + + // Convert to screen + OUT.posPostWave = mul( modelview, OUT.posPostWave ); + + // Setup the OUT position symantic variable + OUT.hpos = OUT.posPostWave; + //OUT.hpos.z = lerp( OUT.hpos.z, OUT.hpos.w, IN.horizonFactor.x ); + + // if ( IN.horizonFactor.x > 0 ) + // { + // float3 awayVec = normalize( OUT.objPos.xyz - eyePos ); + // OUT.objPos.xy += awayVec.xy * 1000.0; + // } + + // Save world space camera dist/depth of the outgoing pixel + OUT.rippleTexCoord2.z = OUT.hpos.z; + + // Convert to reflection texture space + OUT.posPostWave = mul( texGen, OUT.posPostWave ); + + float2 txPos = undulatePos; + if ( IN.horizonFactor.x ) + txPos = normalize( txPos ) * 50000.0; + + // set up tex coordinates for the 3 interacting normal maps + OUT.rippleTexCoord01.xy = txPos * rippleTexScale[0]; + OUT.rippleTexCoord01.xy += rippleDir[0] * elapsedTime * rippleSpeed.x; + + float2x2 texMat; + texMat[0][0] = rippleMat[0].x; + texMat[0][1] = rippleMat[0].y; + texMat[1][0] = rippleMat[0].z; + texMat[1][1] = rippleMat[0].w; + OUT.rippleTexCoord01.xy = mul( texMat, OUT.rippleTexCoord01.xy ); + + OUT.rippleTexCoord01.zw = txPos * rippleTexScale[1]; + OUT.rippleTexCoord01.zw += rippleDir[1] * elapsedTime * rippleSpeed.y; + + texMat[0][0] = rippleMat[1].x; + texMat[0][1] = rippleMat[1].y; + texMat[1][0] = rippleMat[1].z; + texMat[1][1] = rippleMat[1].w; + OUT.rippleTexCoord01.zw = mul( texMat, OUT.rippleTexCoord01.zw ); + + OUT.rippleTexCoord2.xy = txPos * rippleTexScale[2]; + OUT.rippleTexCoord2.xy += rippleDir[2] * elapsedTime * rippleSpeed.z; + + texMat[0][0] = rippleMat[2].x; + texMat[0][1] = rippleMat[2].y; + texMat[1][0] = rippleMat[2].z; + texMat[1][1] = rippleMat[2].w; + OUT.rippleTexCoord2.xy = mul( texMat, OUT.rippleTexCoord2.xy ); + + OUT.foamTexCoords.xy = txPos * foamTexScale.xy + foamDir.xy * foamSpeed.x * elapsedTime; + OUT.foamTexCoords.zw = txPos * foamTexScale.zw + foamDir.zw * foamSpeed.y * elapsedTime; + + + float3 binormal = float3( 1, 0, 0 ); + float3 tangent = float3( 0, 1, 0 ); + float3 normal; + for ( int i = 0; i < 3; i++ ) + { + binormal.z += undulateFade * waveDir[i].x * waveData[i].y * cos( waveDir[i].x * undulatePos.x + waveDir[i].y * undulatePos.y + elapsedTime * waveData[i].x ); + tangent.z += undulateFade * waveDir[i].y * waveData[i].y * cos( waveDir[i].x * undulatePos.x + waveDir[i].y * undulatePos.y + elapsedTime * waveData[i].x ); + } + + binormal = binormal; + tangent = tangent; + normal = cross( binormal, tangent ); + + float3x3 worldToTangent; + worldToTangent[0] = binormal; + worldToTangent[1] = tangent; + worldToTangent[2] = normal; + + OUT.tangentMat = worldToTangent; + + return OUT; +} + diff --git a/Templates/BaseGame/game/core/rendering/shaders/wavesP.hlsl b/Templates/BaseGame/game/core/rendering/shaders/wavesP.hlsl new file mode 100644 index 000000000..c51eb4b89 --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/wavesP.hlsl @@ -0,0 +1,89 @@ +//----------------------------------------------------------------------------- +// 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. +//----------------------------------------------------------------------------- + +#define IN_HLSL +#include "shdrConsts.h" +#include "shaderModel.hlsl" + +//----------------------------------------------------------------------------- +// Data +//----------------------------------------------------------------------------- +struct v2f +{ + float4 HPOS : TORQUE_POSITION; + float2 TEX0 : TEXCOORD0; + float4 tangentToCube0 : TEXCOORD1; + float4 tangentToCube1 : TEXCOORD2; + float4 tangentToCube2 : TEXCOORD3; + float4 lightVec : TEXCOORD4; + float3 pixPos : TEXCOORD5; + float3 eyePos : TEXCOORD6; +}; + + + +struct Fragout +{ + float4 col : TORQUE_TARGET0; +}; + +// Uniforms +TORQUE_UNIFORM_SAMPLER2D(diffMap,0); +//TORQUE_UNIFORM_SAMPLERCUBE(cubeMap, 1); not used? +TORQUE_UNIFORM_SAMPLER2D(bumpMap,2); + +uniform float4 specularColor : register(PC_MAT_SPECCOLOR); +uniform float4 ambient : register(PC_AMBIENT_COLOR); +uniform float specularPower : register(PC_MAT_SPECPOWER); +uniform float accumTime : register(PC_ACCUM_TIME); + +//----------------------------------------------------------------------------- +// Main +//----------------------------------------------------------------------------- +Fragout main(v2f IN) +{ + Fragout OUT; + + float2 texOffset; + float sinOffset1 = sin( accumTime * 1.5 + IN.TEX0.y * 6.28319 * 3.0 ) * 0.03; + float sinOffset2 = sin( accumTime * 3.0 + IN.TEX0.y * 6.28319 ) * 0.04; + + texOffset.x = IN.TEX0.x + sinOffset1 + sinOffset2; + texOffset.y = IN.TEX0.y + cos( accumTime * 3.0 + IN.TEX0.x * 6.28319 * 2.0 ) * 0.05; + + + float4 bumpNorm = TORQUE_TEX2D( bumpMap, texOffset ) * 2.0 - 1.0; + float4 diffuse = TORQUE_TEX2D( diffMap, texOffset ); + + OUT.col = diffuse * (saturate( dot( IN.lightVec, bumpNorm.xyz ) ) + ambient); + + float3 eyeVec = normalize(IN.eyePos - IN.pixPos); + float3 halfAng = normalize(eyeVec + IN.lightVec.xyz); + float specular = saturate( dot(bumpNorm, halfAng) ) * IN.lightVec.w; + specular = pow(abs(specular), specularPower); + OUT.col += specularColor * specular; + + + + return OUT; +} + diff --git a/Templates/BaseGame/game/core/rendering/shaders/wavesV.hlsl b/Templates/BaseGame/game/core/rendering/shaders/wavesV.hlsl new file mode 100644 index 000000000..fccef9d25 --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/wavesV.hlsl @@ -0,0 +1,90 @@ +//----------------------------------------------------------------------------- +// 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. +//----------------------------------------------------------------------------- + +#define IN_HLSL +#include "shdrConsts.h" +#include "hlslStructs.hlsl" + +//----------------------------------------------------------------------------- +// Constants +//----------------------------------------------------------------------------- + +struct Conn +{ + float4 HPOS : POSITION; + float2 TEX0 : TEXCOORD0; + float4 tangentToCube0 : TEXCOORD1; + float4 tangentToCube1 : TEXCOORD2; + float4 tangentToCube2 : TEXCOORD3; + float4 outLightVec : TEXCOORD4; + float3 pos : TEXCOORD5; + float3 outEyePos : TEXCOORD6; + +}; + + +uniform float4x4 modelview : register(VC_WORLD_PROJ); +uniform float3x3 cubeTrans : register(VC_CUBE_TRANS); +uniform float3 cubeEyePos : register(VC_CUBE_EYE_POS); +uniform float3 inLightVec : register(VC_LIGHT_DIR1); +uniform float3 eyePos : register(VC_EYE_POS); + +//----------------------------------------------------------------------------- +// Main +//----------------------------------------------------------------------------- +Conn main( VertexIn_PNTTTB In) +{ + Conn Out; + + Out.HPOS = mul(modelview, float4(In.pos,1.0)); + Out.TEX0 = In.uv0; + + + float3x3 objToTangentSpace; + objToTangentSpace[0] = In.T; + objToTangentSpace[1] = In.B; + objToTangentSpace[2] = In.normal; + + + Out.tangentToCube0.xyz = mul( objToTangentSpace, cubeTrans[0].xyz ); + Out.tangentToCube1.xyz = mul( objToTangentSpace, cubeTrans[1].xyz ); + Out.tangentToCube2.xyz = mul( objToTangentSpace, cubeTrans[2].xyz ); + + float3 pos = mul( cubeTrans, In.pos ).xyz; + float3 eye = cubeEyePos - pos; + normalize( eye ); + + Out.tangentToCube0.w = eye.x; + Out.tangentToCube1.w = eye.y; + Out.tangentToCube2.w = eye.z; + + Out.outLightVec.xyz = -inLightVec; + Out.outLightVec.xyz = mul(objToTangentSpace, Out.outLightVec); + Out.pos = mul(objToTangentSpace, In.pos.xyz / 100.0); + Out.outEyePos.xyz = mul(objToTangentSpace, eyePos.xyz / 100.0); + Out.outLightVec.w = step( 0.0, dot( -inLightVec, In.normal ) ); + + + return Out; +} + + diff --git a/Templates/BaseGame/game/core/rendering/shaders/wind.hlsl b/Templates/BaseGame/game/core/rendering/shaders/wind.hlsl new file mode 100644 index 000000000..b3fee7721 --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/wind.hlsl @@ -0,0 +1,101 @@ +//----------------------------------------------------------------------------- +// 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. +//----------------------------------------------------------------------------- + +// +// A tip of the hat.... +// +// The following wind effects were derived from the GPU Gems +// 3 chapter "Vegetation Procedural Animation and Shading in Crysis" +// by Tiago Sousa of Crytek. +// + +float4 smoothCurve( float4 x ) +{ + return x * x * ( 3.0 - 2.0 * x ); +} + +float4 triangleWave( float4 x ) +{ + return abs( frac( x + 0.5 ) * 2.0 - 1.0 ); +} + +float4 smoothTriangleWave( float4 x ) +{ + return smoothCurve( triangleWave( x ) ); +} + +float3 windTrunkBending( float3 vPos, float2 vWind, float fBendFactor ) +{ + // Smooth the bending factor and increase + // the near by height limit. + fBendFactor += 1.0; + fBendFactor *= fBendFactor; + fBendFactor = fBendFactor * fBendFactor - fBendFactor; + + // Displace the vert. + float3 vNewPos = vPos; + vNewPos.xy += vWind * fBendFactor; + + // Limit the length which makes the bend more + // spherical and prevents stretching. + float fLength = length( vPos ); + vPos = normalize( vNewPos ) * fLength; + + return vPos; +} + +float3 windBranchBending( float3 vPos, + float3 vNormal, + + float fTime, + float fWindSpeed, + + float fBranchPhase, + float fBranchAmp, + float fBranchAtten, + + float fDetailPhase, + float fDetailAmp, + float fDetailFreq, + + float fEdgeAtten ) +{ + float fVertPhase = dot( vPos, fDetailPhase + fBranchPhase ); + + float2 vWavesIn = fTime + float2( fVertPhase, fBranchPhase ); + + float4 vWaves = ( frac( vWavesIn.xxyy * + float4( 1.975, 0.793, 0.375, 0.193 ) ) * + 2.0 - 1.0 ) * fWindSpeed * fDetailFreq; + + vWaves = smoothTriangleWave( vWaves ); + + float2 vWavesSum = vWaves.xz + vWaves.yw; + + // We want the branches to bend both up and down. + vWavesSum.y = 1 - ( vWavesSum.y * 2 ); + + vPos += vWavesSum.xxy * float3( fEdgeAtten * fDetailAmp * vNormal.xy, + fBranchAtten * fBranchAmp ); + + return vPos; +} diff --git a/Templates/BaseGame/game/core/sfx/Core_SFX.cs b/Templates/BaseGame/game/core/sfx/Core_SFX.cs new file mode 100644 index 000000000..acd5c6e08 --- /dev/null +++ b/Templates/BaseGame/game/core/sfx/Core_SFX.cs @@ -0,0 +1,15 @@ + +function Core_SFX::onCreate(%this) +{ + exec("./scripts/audio.cs"); + exec("./scripts/audioData.cs"); + exec("./scripts/audioAmbience.cs"); + exec("./scripts/audioDescriptions.cs"); + exec("./scripts/audioEnvironments.cs"); + exec("./scripts/audioStates.cs"); + +} + +function Core_SFX::onDestroy(%this) +{ +} \ No newline at end of file diff --git a/Templates/BaseGame/game/core/sfx/Core_SFX.module b/Templates/BaseGame/game/core/sfx/Core_SFX.module new file mode 100644 index 000000000..855fe2a11 --- /dev/null +++ b/Templates/BaseGame/game/core/sfx/Core_SFX.module @@ -0,0 +1,9 @@ + + \ No newline at end of file diff --git a/Templates/BaseGame/game/core/sfx/scripts/audio.cs b/Templates/BaseGame/game/core/sfx/scripts/audio.cs new file mode 100644 index 000000000..a5932de8f --- /dev/null +++ b/Templates/BaseGame/game/core/sfx/scripts/audio.cs @@ -0,0 +1,436 @@ +//----------------------------------------------------------------------------- +// 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. +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// Source groups. +//----------------------------------------------------------------------------- + +singleton SFXDescription( AudioMaster ); +singleton SFXSource( AudioChannelMaster ) +{ + description = AudioMaster; +}; + +singleton SFXDescription( AudioChannel ) +{ + sourceGroup = AudioChannelMaster; +}; + +singleton SFXSource( AudioChannelDefault ) +{ + description = AudioChannel; +}; +singleton SFXSource( AudioChannelGui ) +{ + description = AudioChannel; +}; +singleton SFXSource( AudioChannelEffects ) +{ + description = AudioChannel; +}; +singleton SFXSource( AudioChannelMessages ) +{ + description = AudioChannel; +}; +singleton SFXSource( AudioChannelMusic ) +{ + description = AudioChannel; +}; + +// Set default playback states of the channels. + +AudioChannelMaster.play(); +AudioChannelDefault.play(); + +AudioChannelGui.play(); +AudioChannelMusic.play(); +AudioChannelMessages.play(); + +// Stop in-game effects channels. +AudioChannelEffects.stop(); + +//----------------------------------------------------------------------------- +// Master SFXDescriptions. +//----------------------------------------------------------------------------- + +// Master description for interface audio. +singleton SFXDescription( AudioGui ) +{ + volume = 1.0; + sourceGroup = AudioChannelGui; +}; + +// Master description for game effects audio. +singleton SFXDescription( AudioEffect ) +{ + volume = 1.0; + sourceGroup = AudioChannelEffects; +}; + +// Master description for audio in notifications. +singleton SFXDescription( AudioMessage ) +{ + volume = 1.0; + sourceGroup = AudioChannelMessages; +}; + +// Master description for music. +singleton SFXDescription( AudioMusic ) +{ + volume = 1.0; + sourceGroup = AudioChannelMusic; +}; + +//----------------------------------------------------------------------------- +// SFX Functions. +//----------------------------------------------------------------------------- + +/// This initializes the sound system device from +/// the defaults in the $pref::SFX:: globals. +function sfxStartup() +{ + echo( "\nsfxStartup..." ); + + // If we have a provider set, try initialize a device now. + + if( $pref::SFX::provider !$= "" ) + { + if( sfxInit() ) + return; + else + { + // Force auto-detection. + $pref::SFX::autoDetect = true; + } + } + + // If enabled autodetect a safe device. + + if( ( !isDefined( "$pref::SFX::autoDetect" ) || $pref::SFX::autoDetect ) && + sfxAutodetect() ) + return; + + // Failure. + + error( " Failed to initialize device!\n\n" ); + + $pref::SFX::provider = ""; + $pref::SFX::device = ""; + + return; +} + + +/// This initializes the sound system device from +/// the defaults in the $pref::SFX:: globals. +function sfxInit() +{ + // If already initialized, shut down the current device first. + + if( sfxGetDeviceInfo() !$= "" ) + sfxShutdown(); + + // Start it up! + %maxBuffers = $pref::SFX::useHardware ? -1 : $pref::SFX::maxSoftwareBuffers; + if ( !sfxCreateDevice( $pref::SFX::provider, $pref::SFX::device, $pref::SFX::useHardware, %maxBuffers ) ) + return false; + + // This returns a tab seperated string with + // the initialized system info. + %info = sfxGetDeviceInfo(); + $pref::SFX::provider = getField( %info, 0 ); + $pref::SFX::device = getField( %info, 1 ); + $pref::SFX::useHardware = getField( %info, 2 ); + %useHardware = $pref::SFX::useHardware ? "Yes" : "No"; + %maxBuffers = getField( %info, 3 ); + + echo( " Provider: " @ $pref::SFX::provider ); + echo( " Device: " @ $pref::SFX::device ); + echo( " Hardware: " @ %useHardware ); + echo( " Max Buffers: " @ %maxBuffers ); + echo( " " ); + + if( isDefined( "$pref::SFX::distanceModel" ) ) + sfxSetDistanceModel( $pref::SFX::distanceModel ); + if( isDefined( "$pref::SFX::dopplerFactor" ) ) + sfxSetDopplerFactor( $pref::SFX::dopplerFactor ); + if( isDefined( "$pref::SFX::rolloffFactor" ) ) + sfxSetRolloffFactor( $pref::SFX::rolloffFactor ); + + // Restore master volume. + + sfxSetMasterVolume( $pref::SFX::masterVolume ); + + // Restore channel volumes. + + for( %channel = 0; %channel <= 8; %channel ++ ) + sfxSetChannelVolume( %channel, $pref::SFX::channelVolume[ %channel ] ); + + return true; +} + + +/// Destroys the current sound system device. +function sfxShutdown() +{ + // Store volume prefs. + + $pref::SFX::masterVolume = sfxGetMasterVolume(); + + for( %channel = 0; %channel <= 8; %channel ++ ) + $pref::SFX::channelVolume[ %channel ] = sfxGetChannelVolume( %channel ); + + // We're assuming here that a null info + // string means that no device is loaded. + if( sfxGetDeviceInfo() $= "" ) + return; + + sfxDeleteDevice(); +} + + +/// Determines which of the two SFX providers is preferable. +function sfxCompareProvider( %providerA, %providerB ) +{ + if( %providerA $= %providerB ) + return 0; + + switch$( %providerA ) + { + // Always prefer FMOD over anything else. + case "FMOD": + return 1; + + // Prefer OpenAL over anything but FMOD. + case "OpenAL": + if( %providerB $= "FMOD" ) + return -1; + else + return 1; + + // choose XAudio over DirectSound + case "XAudio": + if( %providerB $= "FMOD" || %providerB $= "OpenAL" ) + return -1; + else + return 0; + + case "DirectSound": + if( %providerB !$= "FMOD" && %providerB !$= "OpenAL" && %providerB !$= "XAudio" ) + return 1; + else + return -1; + + default: + return -1; + } +} + + +/// Try to detect and initalize the best SFX device available. +function sfxAutodetect() +{ + // Get all the available devices. + + %devices = sfxGetAvailableDevices(); + + // Collect and sort the devices by preferentiality. + + %deviceTrySequence = new ArrayObject(); + %bestMatch = -1; + %count = getRecordCount( %devices ); + for( %i = 0; %i < %count; %i ++ ) + { + %info = getRecord( %devices, %i ); + %provider = getField( %info, 0 ); + + %deviceTrySequence.push_back( %provider, %info ); + } + + %deviceTrySequence.sortfkd( "sfxCompareProvider" ); + + // Try the devices in order. + + %count = %deviceTrySequence.count(); + for( %i = 0; %i < %count; %i ++ ) + { + %provider = %deviceTrySequence.getKey( %i ); + %info = %deviceTrySequence.getValue( %i ); + + $pref::SFX::provider = %provider; + $pref::SFX::device = getField( %info, 1 ); + $pref::SFX::useHardware = getField( %info, 2 ); + + // By default we've decided to avoid hardware devices as + // they are buggy and prone to problems. + $pref::SFX::useHardware = false; + + if( sfxInit() ) + { + $pref::SFX::autoDetect = false; + %deviceTrySequence.delete(); + return true; + } + } + + // Found no suitable device. + + error( "sfxAutodetect - Could not initialize a valid SFX device." ); + + $pref::SFX::provider = ""; + $pref::SFX::device = ""; + $pref::SFX::useHardware = ""; + + %deviceTrySequence.delete(); + + return false; +} + + +//----------------------------------------------------------------------------- +// Backwards-compatibility with old channel system. +//----------------------------------------------------------------------------- + +// Volume channel IDs for backwards-compatibility. + +$GuiAudioType = 1; // Interface. +$SimAudioType = 2; // Game. +$MessageAudioType = 3; // Notifications. +$MusicAudioType = 4; // Music. + +$AudioChannels[ 0 ] = AudioChannelDefault; +$AudioChannels[ $GuiAudioType ] = AudioChannelGui; +$AudioChannels[ $SimAudioType ] = AudioChannelEffects; +$AudioChannels[ $MessageAudioType ] = AudioChannelMessages; +$AudioChannels[ $MusicAudioType ] = AudioChannelMusic; + +function sfxOldChannelToGroup( %channel ) +{ + return $AudioChannels[ %channel ]; +} + +function sfxGroupToOldChannel( %group ) +{ + %id = %group.getId(); + for( %i = 0;; %i ++ ) + if( !isObject( $AudioChannels[ %i ] ) ) + return -1; + else if( $AudioChannels[ %i ].getId() == %id ) + return %i; + + return -1; +} + +function sfxSetMasterVolume( %volume ) +{ + AudioChannelMaster.setVolume( %volume ); +} + +function sfxGetMasterVolume( %volume ) +{ + return AudioChannelMaster.getVolume(); +} + +function sfxStopAll( %channel ) +{ + // Don't stop channel itself since that isn't quite what the function + // here intends. + + %channel = sfxOldChannelToGroup( %channel ); + if (isObject(%channel)) + { + foreach( %source in %channel ) + %source.stop(); + } +} + +function sfxGetChannelVolume( %channel ) +{ + %obj = sfxOldChannelToGroup( %channel ); + if( isObject( %obj ) ) + return %obj.getVolume(); +} + +function sfxSetChannelVolume( %channel, %volume ) +{ + %obj = sfxOldChannelToGroup( %channel ); + if( isObject( %obj ) ) + %obj.setVolume( %volume ); +} + +/*singleton SimSet( SFXPausedSet ); + + +/// Pauses the playback of active sound sources. +/// +/// @param %channels An optional word list of channel indices or an empty +/// string to pause sources on all channels. +/// @param %pauseSet An optional SimSet which is filled with the paused +/// sources. If not specified the global SfxSourceGroup +/// is used. +/// +/// @deprecated +/// +function sfxPause( %channels, %pauseSet ) +{ + // Did we get a set to populate? + if ( !isObject( %pauseSet ) ) + %pauseSet = SFXPausedSet; + + %count = SFXSourceSet.getCount(); + for ( %i = 0; %i < %count; %i++ ) + { + %source = SFXSourceSet.getObject( %i ); + + %channel = sfxGroupToOldChannel( %source.getGroup() ); + if( %channels $= "" || findWord( %channels, %channel ) != -1 ) + { + %source.pause(); + %pauseSet.add( %source ); + } + } +} + + +/// Resumes the playback of paused sound sources. +/// +/// @param %pauseSet An optional SimSet which contains the paused sound +/// sources to be resumed. If not specified the global +/// SfxSourceGroup is used. +/// @deprecated +/// +function sfxResume( %pauseSet ) +{ + if ( !isObject( %pauseSet ) ) + %pauseSet = SFXPausedSet; + + %count = %pauseSet.getCount(); + for ( %i = 0; %i < %count; %i++ ) + { + %source = %pauseSet.getObject( %i ); + %source.play(); + } + + // Clear our pause set... the caller is left + // to clear his own if he passed one. + %pauseSet.clear(); +}*/ diff --git a/Templates/BaseGame/game/core/sfx/scripts/audioAmbience.cs b/Templates/BaseGame/game/core/sfx/scripts/audioAmbience.cs new file mode 100644 index 000000000..8c2bf270c --- /dev/null +++ b/Templates/BaseGame/game/core/sfx/scripts/audioAmbience.cs @@ -0,0 +1,44 @@ +//----------------------------------------------------------------------------- +// 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. +//----------------------------------------------------------------------------- + +singleton SFXAmbience( AudioAmbienceDefault ) +{ + environment = AudioEnvOff; +}; + +singleton SFXAmbience( AudioAmbienceOutside ) +{ + environment = AudioEnvPlain; + states[ 0 ] = AudioLocationOutside; +}; + +singleton SFXAmbience( AudioAmbienceInside ) +{ + environment = AudioEnvRoom; + states[ 0 ] = AudioLocationInside; +}; + +singleton SFXAmbience( AudioAmbienceUnderwater ) +{ + environment = AudioEnvUnderwater; + states[ 0 ] = AudioLocationUnderwater; +}; diff --git a/Templates/BaseGame/game/core/sfx/scripts/audioData.cs b/Templates/BaseGame/game/core/sfx/scripts/audioData.cs new file mode 100644 index 000000000..8584ce50e --- /dev/null +++ b/Templates/BaseGame/game/core/sfx/scripts/audioData.cs @@ -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. +//----------------------------------------------------------------------------- + +// Game specific audio descriptions. Always declare SFXDescription's (the type of sound) +// before SFXProfile's (the sound itself) when creating new ones + +singleton SFXDescription(BulletFireDesc : AudioEffect ) +{ + isLooping = false; + is3D = true; + ReferenceDistance = 10.0; + MaxDistance = 60.0; +}; + +singleton SFXDescription(BulletImpactDesc : AudioEffect ) +{ + isLooping = false; + is3D = true; + ReferenceDistance = 10.0; + MaxDistance = 30.0; + volume = 0.4; + pitch = 1.4; +}; diff --git a/Templates/BaseGame/game/core/sfx/scripts/audioDescriptions.cs b/Templates/BaseGame/game/core/sfx/scripts/audioDescriptions.cs new file mode 100644 index 000000000..d682461cf --- /dev/null +++ b/Templates/BaseGame/game/core/sfx/scripts/audioDescriptions.cs @@ -0,0 +1,143 @@ +//----------------------------------------------------------------------------- +// 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. +//----------------------------------------------------------------------------- + +// Always declare SFXDescription's (the type of sound) before SFXProfile's (the +// sound itself) when creating new ones + +//----------------------------------------------------------------------------- +// 3D Sounds +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// Single shot sounds +//----------------------------------------------------------------------------- + +singleton SFXDescription( AudioDefault3D : AudioEffect ) +{ + is3D = true; + ReferenceDistance = 20.0; + MaxDistance = 100.0; +}; + +singleton SFXDescription( AudioSoft3D : AudioEffect ) +{ + is3D = true; + ReferenceDistance = 20.0; + MaxDistance = 100.0; + volume = 0.4; +}; + +singleton SFXDescription( AudioClose3D : AudioEffect ) +{ + is3D = true; + ReferenceDistance = 10.0; + MaxDistance = 60.0; +}; + +singleton SFXDescription( AudioClosest3D : AudioEffect ) +{ + is3D = true; + ReferenceDistance = 5.0; + MaxDistance = 10.0; +}; + +//----------------------------------------------------------------------------- +// Looping sounds +//----------------------------------------------------------------------------- + +singleton SFXDescription( AudioDefaultLoop3D : AudioEffect ) +{ + isLooping = true; + is3D = true; + ReferenceDistance = 20.0; + MaxDistance = 100.0; +}; + +singleton SFXDescription( AudioCloseLoop3D : AudioEffect ) +{ + isLooping = true; + is3D = true; + ReferenceDistance = 18.0; + MaxDistance = 25.0; +}; + +singleton SFXDescription( AudioClosestLoop3D : AudioEffect ) +{ + isLooping = true; + is3D = true; + ReferenceDistance = 5.0; + MaxDistance = 10.0; +}; + +//----------------------------------------------------------------------------- +// 2d sounds +//----------------------------------------------------------------------------- + +// Used for non-looping environmental sounds (like power on, power off) +singleton SFXDescription( Audio2D : AudioEffect ) +{ + isLooping = false; +}; + +// Used for Looping Environmental Sounds +singleton SFXDescription( AudioLoop2D : AudioEffect ) +{ + isLooping = true; +}; + +singleton SFXDescription( AudioStream2D : AudioEffect ) +{ + isStreaming = true; +}; +singleton SFXDescription( AudioStreamLoop2D : AudioEffect ) +{ + isLooping = true; + isStreaming = true; +}; + +//----------------------------------------------------------------------------- +// Music +//----------------------------------------------------------------------------- + +singleton SFXDescription( AudioMusic2D : AudioMusic ) +{ + isStreaming = true; +}; + +singleton SFXDescription( AudioMusicLoop2D : AudioMusic ) +{ + isLooping = true; + isStreaming = true; +}; + +singleton SFXDescription( AudioMusic3D : AudioMusic ) +{ + isStreaming = true; + is3D = true; +}; + +singleton SFXDescription( AudioMusicLoop3D : AudioMusic ) +{ + isStreaming = true; + is3D = true; + isLooping = true; +}; diff --git a/Templates/BaseGame/game/core/sfx/scripts/audioEnvironments.cs b/Templates/BaseGame/game/core/sfx/scripts/audioEnvironments.cs new file mode 100644 index 000000000..671825b6b --- /dev/null +++ b/Templates/BaseGame/game/core/sfx/scripts/audioEnvironments.cs @@ -0,0 +1,916 @@ +//----------------------------------------------------------------------------- +// 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. +//----------------------------------------------------------------------------- + +// Reverb environment presets. +// +// For customized presets, best derive from one of these presets. + +singleton SFXEnvironment( AudioEnvOff ) +{ + envSize = "7.5"; + envDiffusion = "1.0"; + room = "-10000"; + roomHF = "-10000"; + roomLF = "0"; + decayTime = "1.0"; + decayHFRatio = "1.0"; + decayLFRatio = "1.0"; + reflections = "-2602"; + reflectionsDelay = "0.007"; + reflectionsPan[ 0 ] = "0.0"; + reflectionsPan[ 1 ] = "0.0"; + reflectionsPan[ 2 ] = "0.0"; + reverb = "200"; + reverbDelay = "0.011"; + reverbPan[ 0 ] = "0.0"; + reverbPan[ 1 ] = "0.0"; + reverbPan[ 2 ] = "0.0"; + echoTime = "0.25"; + echoDepth = "0.0"; + modulationTime = "0.25"; + modulationDepth = "0.0"; + airAbsorptionHF = "-5.0"; + HFReference = "5000.0"; + LFReference = "250.0"; + roomRolloffFactor = "0.0"; + diffusion = "0.0"; + density = "0.0"; + flags = 0x33; +}; + +singleton SFXEnvironment( AudioEnvGeneric ) +{ + envSize = "7.5"; + envDiffusion = "1.0"; + room = "-1000"; + roomHF = "-100"; + roomLF = "0"; + decayTime = "1.49"; + decayHFRatio = "0.83"; + decayLFRatio = "1.0"; + reflections = "-2602"; + reflectionsDelay = "0.007"; + reflectionsPan[ 0 ] = "0.0"; + reflectionsPan[ 1 ] = "0.0"; + reflectionsPan[ 2 ] = "0.0"; + reverb = "200"; + reverbDelay = "0.011"; + reverbPan[ 0 ] = "0.0"; + reverbPan[ 1 ] = "0.0"; + reverbPan[ 2 ] = "0.0"; + echoTime = "0.25"; + echoDepth = "0.0"; + modulationTime = "0.25"; + modulationDepth = "0.0"; + airAbsorptionHF = "-5.0"; + HFReference = "5000.0"; + LFReference = "250.0"; + roomRolloffFactor = "0.0"; + diffusion = "100.0"; + density = "100.0"; + flags = 0x3f; +}; + +singleton SFXEnvironment( AudioEnvRoom ) +{ + envSize = "1.9"; + envDiffusion = "1.0"; + room = "-1000"; + roomHF = "-454"; + roomLF = "0"; + decayTime = "0.4"; + decayHFRatio = "0.83"; + decayLFRatio = "1.0"; + reflections = "-1646"; + reflectionsDelay = "0.002"; + reflectionsPan[ 0 ] = "0.0"; + reflectionsPan[ 1 ] = "0.0"; + reflectionsPan[ 2 ] = "0.0"; + reverb = "53"; + reverbDelay = "0.003"; + reverbPan[ 0 ] = "0.0"; + reverbPan[ 1 ] = "0.0"; + reverbPan[ 2 ] = "0.0"; + echoTime = "0.25"; + echoDepth = "0.0"; + modulationTime = "0.25"; + modulationDepth = "0.0"; + airAbsorptionHF = "-5.0"; + HFReference = "5000.0"; + LFReference = "250.0"; + roomRolloffFactor = "0.0"; + diffusion = "100.0"; + density = "100.0"; + flags = 0x3f; +}; + +singleton SFXEnvironment( AudioEnvPaddedCell ) +{ + envSize = "1.4"; + envDiffusion = "1.0"; + room = "-1000"; + roomHF = "-6000"; + roomLF = "0"; + decayTime = "0.17"; + decayHFRatio = "0.1"; + decayLFRatio = "1.0"; + reflections = "-1204"; + reflectionsDelay = "0.001"; + reflectionsPan[ 0 ] = "0.0"; + reflectionsPan[ 1 ] = "0.0"; + reflectionsPan[ 2 ] = "0.0"; + reverb = "207"; + reverbDelay = "0.002"; + reverbPan[ 0 ] = "0.0"; + reverbPan[ 1 ] = "0.0"; + reverbPan[ 2 ] = "0.0"; + echoTime = "0.25"; + echoDepth = "0.0"; + modulationTime = "0.25"; + modulationDepth = "0.0"; + airAbsorptionHF = "-5.0"; + HFReference = "5000.0"; + LFReference = "250.0"; + roomRolloffFactor = "0.0"; + diffusion = "100.0"; + density = "100.0"; + flags = 0x3f; +}; + +singleton SFXEnvironment( AudioEnvBathroom ) +{ + envSize = "1.4"; + envDiffusion = "1.0"; + room = "-1000"; + roomHF = "-1200"; + roomLF = "0"; + decayTime = "1.49"; + decayHFRatio = "0.54"; + decayLFRatio = "1.0"; + reflections = "-370"; + reflectionsDelay = "0.007"; + reflectionsPan[ 0 ] = "0.0"; + reflectionsPan[ 1 ] = "0.0"; + reflectionsPan[ 2 ] = "0.0"; + reverb = "1030"; + reverbDelay = "0.011"; + reverbPan[ 0 ] = "0.0"; + reverbPan[ 1 ] = "0.0"; + reverbPan[ 2 ] = "0.0"; + echoTime = "0.25"; + echoDepth = "0.0"; + modulationTime = "0.25"; + modulationDepth = "0.0"; + airAbsorptionHF = "-5.0"; + HFReference = "5000.0"; + LFReference = "250.0"; + roomRolloffFactor = "0.0"; + diffusion = "100.0"; + density = "60.0"; + flags = 0x3f; +}; + +singleton SFXEnvironment( AudioEnvLivingRoom ) +{ + envSize = "2.5"; + envDiffusion = "1.0"; + room = "-1000"; + roomHF = "-6000"; + roomLF = "0"; + decayTime = "0.5"; + decayHFRatio = "0.1"; + decayLFRatio = "1.0"; + reflections = "-1376"; + reflectionsDelay = "0.003"; + reflectionsPan[ 0 ] = "0.0"; + reflectionsPan[ 1 ] = "0.0"; + reflectionsPan[ 2 ] = "0.0"; + reverb = "-1104"; + reverbDelay = "0.004"; + reverbPan[ 0 ] = "0.0"; + reverbPan[ 1 ] = "0.0"; + reverbPan[ 2 ] = "0.0"; + echoTime = "0.25"; + echoDepth = "0.0"; + modulationTime = "0.25"; + modulationDepth = "0.0"; + airAbsorptionHF = "-5.0"; + HFReference = "5000.0"; + LFReference = "250.0"; + roomRolloffFactor = "0.0"; + diffusion = "100.0"; + density = "100.0"; + flags = 0x3f; +}; + +singleton SFXEnvironment( AudioEnvStoneRoom ) +{ + envSize = "11.6"; + envDiffusion = "1.0"; + room = "-1000"; + roomHF = "300"; + roomLF = "0"; + decayTime = "2.31"; + decayHFRatio = "0.64"; + decayLFRatio = "1.0"; + reflections = "-711"; + reflectionsDelay = "0.012"; + reflectionsPan[ 0 ] = "0.0"; + reflectionsPan[ 1 ] = "0.0"; + reflectionsPan[ 2 ] = "0.0"; + reverb = "83"; + reverbDelay = "0.017"; + reverbPan[ 0 ] = "0.0"; + reverbPan[ 1 ] = "0.0"; + reverbPan[ 2 ] = "0.0"; + echoTime = "0.25"; + echoDepth = "0.0"; + modulationTime = "0.25"; + modulationDepth = "0.0"; + airAbsorptionHF = "-5.0"; + HFReference = "-5000.0"; + LFReference = "250.0"; + roomRolloffFactor = "0.0"; + diffusion = "100.0"; + density = "100.0"; + flags = 0x3f; +}; + +singleton SFXEnvironment( AudioEnvAuditorium ) +{ + envSize = "21.6"; + envDiffusion = "1.0"; + room = "-1000"; + roomHF = "-476"; + roomLF = "0"; + decayTime = "4.32"; + decayHFRatio = "0.59"; + decayLFRatio = "1.0"; + reflections = "1"; + reflectionsDelay = "0.02"; + reflectionsPan[ 0 ] = "0.0"; + reflectionsPan[ 1 ] = "0.0"; + reflectionsPan[ 2 ] = "0.0"; + reverb = "-289"; + reverbDelay = "0.03"; + reverbPan[ 0 ] = "0.0"; + reverbPan[ 1 ] = "0.0"; + reverbPan[ 2 ] = "0.0"; + echoTime = "0.25"; + echoDepth = "0.0"; + modulationTime = "0.25"; + modulationDepth = "0.0"; + airAbsorptionHF = "-5.0"; + HFReference = "5000.0"; + LFReference = "250.0"; + roomRolloffFactor = "0.0"; + diffusion = "100.0"; + density = "100.0"; + flags = 0x3f; +}; + +singleton SFXEnvironment( AudioEnvConcertHall ) +{ + envSize = "19.6"; + envDiffusion = "1.0"; + room = "-1000"; + roomHF = "-500"; + roomLF = "0"; + decayTime = "3.92"; + decayHFRatio = "0.7"; + decayLFRatio = "1.0"; + reflections = "-1230"; + reflectionsDelay = "0.02"; + reflectionsPan[ 0 ] = "0.0"; + reflectionsPan[ 1 ] = "0.0"; + reflectionsPan[ 2 ] = "0.0"; + reverb = "-2"; + reverbDelay = "0.029"; + reverbPan[ 0 ] = "0.0"; + reverbPan[ 1 ] = "0.0"; + reverbPan[ 2 ] = "0.0"; + echoTime = "0.25"; + echoDepth = "0.0"; + modulationTime = "0.25"; + modulationDepth = "0.0"; + airAbsorptionHF = "-5.0"; + HFReference = "5000.0"; + LFReference = "250.0"; + roomRolloffFactor = "0.0"; + diffusion = "100.0"; + density = "100.0"; + flags = 0x3f; +}; + +singleton SFXEnvironment( AudioEnvCave ) +{ + envSize = "14.6"; + envDiffusion = "1.0"; + room = "-1000"; + roomHF = "0"; + roomLF = "0"; + decayTime = "2.91"; + decayHFRatio = "1.3"; + decayLFRatio = "1.0"; + reflections = "-602"; + reflectionsDelay = "0.015"; + reflectionsPan[ 0 ] = "0.0"; + reflectionsPan[ 1 ] = "0.0"; + reflectionsPan[ 2 ] = "0.0"; + reverb = "-302"; + reverbDelay = "0.022"; + reverbPan[ 0 ] = "0.0"; + reverbPan[ 1 ] = "0.0"; + reverbPan[ 2 ] = "0.0"; + echoTime = "0.25"; + echoDepth = "0.0"; + modulationTime = "0.25"; + modulationDepth = "0.0"; + airAbsorptionHF = "-5.0"; + HFReference = "5000.0"; + LFReference = "250.0"; + roomRolloffFactor = "0.0"; + diffusion = "100.0"; + density = "100.0"; + flags = 0x1f; +}; + +singleton SFXEnvironment( AudioEnvArena ) +{ + envSize = "36.2f"; + envDiffusion = "1.0"; + room = "-1000"; + roomHF = "-698"; + roomLF = "0"; + decayTime = "7.24"; + decayHFRatio = "0.33"; + decayLFRatio = "1.0"; + reflections = "-1166"; + reflectionsDelay = "0.02"; + reflectionsPan[ 0 ] = "0.0"; + reflectionsPan[ 1 ] = "0.0"; + reflectionsPan[ 2 ] = "0.0"; + reverb = "16"; + reverbDelay = "0.03"; + reverbPan[ 0 ] = "0.0"; + reverbPan[ 1 ] = "0.0"; + reverbPan[ 2 ] = "0.0"; + echoTime = "0.25"; + echoDepth = "0.0"; + modulationTime = "0.25"; + modulationDepth = "0.0"; + airAbsorptionHF = "-5.0"; + HFReference = "5000.0"; + LFReference = "250.0"; + roomRolloffFactor = "0.0"; + diffusion = "100.0"; + density = "100.0"; + flags = 0x3f; +}; + +singleton SFXEnvironment( AudioEnvHangar ) +{ + envSize = "50.3"; + envDiffusion = "1.0"; + room = "-1000"; + roomHF = "-1000"; + roomLF = "0"; + decayTime = "10.05"; + decayHFRatio = "0.23"; + decayLFRatio = "1.0"; + reflections = "-602"; + reflectionsDelay = "0.02"; + reflectionsPan[ 0 ] = "0.0"; + reflectionsPan[ 1 ] = "0.0"; + reflectionsPan[ 2 ] = "0.0"; + reverb = "198"; + reverbDelay = "0.03"; + reverbPan[ 0 ] = "0.0"; + reverbPan[ 1 ] = "0.0"; + reverbPan[ 2 ] = "0.0"; + echoTime = "0.25"; + echoDepth = "0.0"; + modulationTime = "0.25"; + modulationDepth = "0.0"; + airAbsorptionHF = "-5.0"; + HFReference = "5000.0"; + LFReference = "250.0"; + roomRolloffFactor = "0.0"; + diffusion = "100.0"; + density = "100.0"; + flags = 0x3f; +}; + +singleton SFXEnvironment( AudioEnvCarpettedHallway ) +{ + envSize = "1.9"; + envDiffusion = "1.0"; + room = "-1000"; + roomHF = "-4000"; + roomLF = "0"; + decayTime = "0.3"; + decayHFRatio = "0.1"; + decayLFRatio = "1.0"; + reflections = "-1831"; + reflectionsDelay = "0.002"; + reflectionsPan[ 0 ] = "0.0"; + reflectionsPan[ 1 ] = "0.0"; + reflectionsPan[ 2 ] = "0.0"; + reverb = "-1630"; + reverbDelay = "0.03"; + reverbPan[ 0 ] = "0.0"; + reverbPan[ 1 ] = "0.0"; + reverbPan[ 2 ] = "0.0"; + echoTime = "0.25"; + echoDepth = "0.0"; + modulationTime = "0.25"; + modulationDepth = "0.0"; + airAbsorptionHF = "-5.0"; + HFReference = "5000.0"; + LFReference = "250.0"; + roomRolloffFactor = "0.0"; + diffusion = "100.0"; + density = "100.0"; + flags = 0x3f; +}; + +singleton SFXEnvironment( AudioEnvHallway ) +{ + envSize = "1.8"; + envDiffusion = "1.0"; + room = "-1000"; + roomHF = "-300"; + roomLF = "0"; + decayTime = "1.49"; + decayHFRatio = "0.59"; + decayLFRatio = "1.0"; + reflections = "-1219"; + reflectionsDelay = "0.007"; + reflectionsPan[ 0 ] = "0.0"; + reflectionsPan[ 1 ] = "0.0"; + reflectionsPan[ 2 ] = "0.0"; + reverb = "441"; + reverbDelay = "0.011"; + reverbPan[ 0 ] = "0.0"; + reverbPan[ 1 ] = "0.0"; + reverbPan[ 2 ] = "0.0"; + echoTime = "0.25"; + echoDepth = "0.0"; + modulationTime = "0.25"; + modulationDepth = "0.0"; + airAbsorptionHF = "-5.0"; + HFReference = "5000.0"; + LFReference = "250.0"; + roomRolloffFactor = "0.0"; + diffusion = "100.0"; + density = "100.0"; + flags = 0x3f; +}; + +singleton SFXEnvironment( AudioEnvStoneCorridor ) +{ + envSize = "13.5"; + envDiffusion = "1.0"; + room = "-1000"; + roomHF = "-237"; + roomLF = "0"; + decayTime = "2.7"; + decayHFRatio = "0.79"; + decayLFRatio = "1.0"; + reflections = "-1214"; + reflectionsDelay = "0.013"; + reflectionsPan[ 0 ] = "0.0"; + reflectionsPan[ 1 ] = "0.0"; + reflectionsPan[ 2 ] = "0.0"; + reverb = "395"; + reverbDelay = "0.02"; + reverbPan[ 0 ] = "0.0"; + reverbPan[ 1 ] = "0.0"; + reverbPan[ 2 ] = "0.0"; + echoTime = "0.25"; + echoDepth = "0.0"; + modulationTime = "0.25"; + modulationDepth = "0.0"; + airAbsorptionHF = "-5.0"; + HFReference = "5000.0"; + LFReference = "250.0"; + roomRolloffFactor = "0.0"; + diffusion = "100.0"; + density = "100.0"; + flags = 0x3f; +}; + +singleton SFXEnvironment( AudioEnvAlley ) +{ + envSize = "7.5"; + envDiffusion = "0.3"; + room = "-1000"; + roomHF = "-270"; + roomLF = "0"; + decayTime = "1.49"; + decayHFRatio = "0.86"; + decayLFRatio = "1.0"; + reflections = "-1204"; + reflectionsDelay = "0.007"; + reflectionsPan[ 0 ] = "0.0"; + reflectionsPan[ 1 ] = "0.0"; + reflectionsPan[ 2 ] = "0.0"; + reverb = "-4"; + reverbDelay = "0.011"; + reverbPan[ 0 ] = "0.0"; + reverbPan[ 1 ] = "0.0"; + reverbPan[ 2 ] = "0.0"; + echoTime = "0.125"; + echoDepth = "0.95"; + modulationTime = "0.25"; + modulationDepth = "0.0"; + airAbsorptionHF = "-5.0"; + HFReference = "5000.0"; + LFReference = "250.0"; + roomRolloffFactor = "0.0"; + diffusion = "100.0"; + density = "100.0"; + flags = 0x3f; +}; + +singleton SFXEnvironment( AudioEnvForest ) +{ + envSize = "38.0"; + envDiffusion = "0.3"; + room = "-1000"; + roomHF = "-3300"; + roomLF = "0"; + decayTime = "1.49"; + decayHFRatio = "0.54"; + decayLFRatio = "1.0"; + reflections = "-2560"; + reflectionsDelay = "0.162"; + reflectionsPan[ 0 ] = "0.0"; + reflectionsPan[ 1 ] = "0.0"; + reflectionsPan[ 2 ] = "0.0"; + reverb = "-229"; + reverbDelay = "0.088"; + reverbPan[ 0 ] = "0.0"; + reverbPan[ 1 ] = "0.0"; + reverbPan[ 2 ] = "0.0"; + echoTime = "0.125"; + echoDepth = "1.0"; + modulationTime = "0.25"; + modulationDepth = "0.0"; + airAbsorptionHF = "-5.0"; + HFReference = "5000.0"; + LFReference = "250.0"; + roomRolloffFactor = "0.0"; + diffusion = "79.0"; + density = "100.0"; + flags = 0x3f; +}; + +singleton SFXEnvironment( AudioEnvCity ) +{ + envSize = "7.5"; + envDiffusion = "0.5"; + room = "-1000"; + roomHF = "-800"; + roomLF = "0"; + decayTime = "1.49"; + decayHFRatio = "0.67"; + decayLFRatio = "1.0"; + reflections = "-2273"; + reflectionsDelay = "0.007"; + reflectionsPan[ 0 ] = "0.0"; + reflectionsPan[ 1 ] = "0.0"; + reflectionsPan[ 2 ] = "0.0"; + reverb = "-1691"; + reverbDelay = "0.011"; + reverbPan[ 0 ] = "0.0"; + reverbPan[ 1 ] = "0.0"; + reverbPan[ 2 ] = "0.0"; + echoTime = "0.25"; + echoDepth = "0.0"; + modulationTime = "0.25"; + modulationDepth = "0.0"; + airAbsorptionHF = "-5.0"; + HFReference = "5000.0"; + LFReference = "250.0"; + roomRolloffFactor = "0.0"; + diffusion = "50.0"; + density = "100.0"; + flags = 0x3f; +}; + +singleton SFXEnvironment( AudioEnvMountains ) +{ + envSize = "100.0"; + envDiffusion = "0.27"; + room = "-1000"; + roomHF = "-2500"; + roomLF = "0"; + decayTime = "1.49"; + decayHFRatio = "0.21"; + decayLFRatio = "1.0"; + reflections = "-2780"; + reflectionsDelay = "0.3"; + reflectionsPan[ 0 ] = "0.0"; + reflectionsPan[ 1 ] = "0.0"; + reflectionsPan[ 2 ] = "0.0"; + reverb = "-1434"; + reverbDelay = "0.1"; + reverbPan[ 0 ] = "0.0"; + reverbPan[ 1 ] = "0.0"; + reverbPan[ 2 ] = "0.0"; + echoTime = "0.25"; + echoDepth = "1.0"; + modulationTime = "0.25"; + modulationDepth = "0.0"; + airAbsorptionHF = "-5.0"; + HFReference = "5000.0"; + LFReference = "250.0"; + roomRolloffFactor = "0.0"; + diffusion = "27.0"; + density = "100.0"; + flags = 0x1f; +}; + +singleton SFXEnvironment( AudioEnvQuary ) +{ + envSize = "17.5"; + envDiffusion = "1.0"; + room = "-1000"; + roomHF = "-1000"; + roomLF = "0"; + decayTime = "1.49"; + decayHFRatio = "0.83"; + decayLFRatio = "1.0"; + reflections = "-10000"; + reflectionsDelay = "0.061"; + reflectionsPan[ 0 ] = "0.0"; + reflectionsPan[ 1 ] = "0.0"; + reflectionsPan[ 2 ] = "0.0"; + reverb = "500"; + reverbDelay = "0.025"; + reverbPan[ 0 ] = "0.0"; + reverbPan[ 1 ] = "0.0"; + reverbPan[ 2 ] = "0.0"; + echoTime = "0.125"; + echoDepth = "0.7"; + modulationTime = "0.25"; + modulationDepth = "0.0"; + airAbsorptionHF = "-5.0"; + HFReference = "5000.0"; + LFReference = "250.0"; + roomRolloffFactor = "0.0"; + diffusion = "100.0"; + density = "100.0"; + flags = 0x3f; +}; + +singleton SFXEnvironment( AudioEnvPlain ) +{ + envSize = "42.5"; + envDiffusion = "0.21"; + room = "-1000"; + roomHF = "-2000"; + roomLF = "0"; + decayTime = "1.49"; + decayHFRatio = "0.5"; + decayLFRatio = "1.0"; + reflections = "-2466"; + reflectionsDelay = "0.179"; + reflectionsPan[ 0 ] = "0.0"; + reflectionsPan[ 1 ] = "0.0"; + reflectionsPan[ 2 ] = "0.0"; + reverb = "-1926"; + reverbDelay = "0.1"; + reverbPan[ 0 ] = "0.0"; + reverbPan[ 1 ] = "0.0"; + reverbPan[ 2 ] = "0.0"; + echoTime = "0.25"; + echoDepth = "1.0"; + modulationTime = "0.25"; + modulationDepth = "0.0"; + airAbsorptionHF = "-5.0"; + HFReference = "5000.0"; + LFReference = "250.0"; + roomRolloffFactor = "0.0"; + diffusion = "21.0"; + density = "100.0"; + flags = 0x3f; +}; + +singleton SFXEnvironment( AudioEnvParkingLot ) +{ + envSize = "8.3"; + envDiffusion = "1.0"; + room = "-1000"; + roomHF = "0"; + roomLF = "0"; + decayTime = "1.65"; + decayHFRatio = "1.5"; + decayLFRatio = "1.0"; + reflections = "-1363"; + reflectionsDelay = "0.008"; + reflectionsPan[ 0 ] = "0.0"; + reflectionsPan[ 1 ] = "0.0"; + reflectionsPan[ 2 ] = "0.0"; + reverb = "-1153"; + reverbDelay = "0.012"; + reverbPan[ 0 ] = "0.0"; + reverbPan[ 1 ] = "0.0"; + reverbPan[ 2 ] = "0.0"; + echoTime = "0.25"; + echoDepth = "0.0"; + modulationTime = "0.25"; + modulationDepth = "0.0"; + airAbsorptionHF = "-5.0"; + HFReference = "5000.0"; + LFReference = "250.0"; + roomRolloffFactor = "0.0"; + diffusion = "100.0"; + density = "100.0"; + flags = 0x1f; +}; + +singleton SFXEnvironment( AudioEnvSewerPipe ) +{ + envSize = "1.7"; + envDiffusion = "0.8"; + room = "-1000"; + roomHF = "-1000"; + roomLF = "0"; + decayTime = "2.81"; + decayHFRatio = "0.14"; + decayLFRatio = "1.0"; + reflections = "429"; + reflectionsDelay = "0.014"; + reflectionsPan[ 0 ] = "0.0"; + reflectionsPan[ 1 ] = "0.0"; + reflectionsPan[ 2 ] = "0.0"; + reverb = "1023"; + reverbDelay = "0.21"; + reverbPan[ 0 ] = "0.0"; + reverbPan[ 1 ] = "0.0"; + reverbPan[ 2 ] = "0.0"; + echoTime = "0.25"; + echoDepth = "0.0"; + modulationTime = "0.25"; + modulationDepth = "0.0"; + airAbsorptionHF = "-5.0"; + HFReference = "5000.0"; + LFReference = "250.0"; + roomRolloffFactor = "0.0"; + diffusion = "80.0"; + density = "60.0"; + flags = 0x3f; +}; + +singleton SFXEnvironment( AudioEnvUnderwater ) +{ + envSize = "1.8"; + envDiffusion = "1.0"; + room = "-1000"; + roomHF = "-4000"; + roomLF = "0"; + decayTime = "1.49"; + decayHFRatio = "0.1"; + decayLFRatio = "1.0"; + reflections = "-449"; + reflectionsDelay = "0.007"; + reflectionsPan[ 0 ] = "0.0"; + reflectionsPan[ 1 ] = "0.0"; + reflectionsPan[ 2 ] = "0.0"; + reverb = "1700"; + reverbDelay = "0.011"; + reverbPan[ 0 ] = "0.0"; + reverbPan[ 1 ] = "0.0"; + reverbPan[ 2 ] = "0.0"; + echoTime = "0.25"; + echoDepth = "0.0"; + modulationTime = "1.18"; + modulationDepth = "0.348"; + airAbsorptionHF = "-5.0"; + HFReference = "5000.0"; + LFReference = "250.0"; + roomRolloffFactor = "0.0"; + diffusion = "100.0"; + density = "100.0"; + flags = 0x3f; +}; + +singleton SFXEnvironment( AudioEnvDrugged ) +{ + envSize = "1.9"; + envDiffusion = "0.5"; + room = "-1000"; + roomHF = "0"; + roomLF = "0"; + decayTime = "8.39"; + decayHFRatio = "1.39"; + decayLFRatio = "1.0"; + reflections = "-115"; + reflectionsDelay = "0.002"; + reflectionsPan[ 0 ] = "0.0"; + reflectionsPan[ 1 ] = "0.0"; + reflectionsPan[ 2 ] = "0.0"; + reverb = "985"; + reverbDelay = "0.03"; + reverbPan[ 0 ] = "0.0"; + reverbPan[ 1 ] = "0.0"; + reverbPan[ 2 ] = "0.0"; + echoTime = "0.25"; + echoDepth = "0.0"; + modulationTime = "0.25"; + modulationDepth = "1.0"; + airAbsorptionHF = "-5.0"; + HFReference = "5000.0"; + LFReference = "250.0"; + roomRolloffFactor = "0.0"; + diffusion = "100.0"; + density = "100.0"; + flags = 0x1f; +}; + +singleton SFXEnvironment( AudioEnvDizzy ) +{ + envSize = "1.8"; + envDiffusion = "0.6"; + room = "-1000.0"; + roomHF = "-400"; + roomLF = "0"; + decayTime = "17.23"; + decayHFRatio = "0.56"; + decayLFRatio = "1.0"; + reflections = "-1713"; + reflectionsDelay = "0.02"; + reflectionsPan[ 0 ] = "0.0"; + reflectionsPan[ 1 ] = "0.0"; + reflectionsPan[ 2 ] = "0.0"; + reverb = "-613"; + reverbDelay = "0.03"; + reverbPan[ 0 ] = "0.0"; + reverbPan[ 1 ] = "0.0"; + reverbPan[ 2 ] = "0.0"; + echoTime = "0.25"; + echoDepth = "1.0"; + modulationTime = "0.81"; + modulationDepth = "0.31"; + airAbsorptionHF = "-5.0"; + HFReference = "5000.0"; + LFReference = "250.0"; + roomRolloffFactor = "0.0"; + diffusion = "100.0"; + density = "100.0"; + flags = 0x1f; +}; + +singleton SFXEnvironment( AudioEnvPsychotic ) +{ + envSize = "1.0"; + envDiffusion = "0.5"; + room = "-1000"; + roomHF = "-151"; + roomLF = "0"; + decayTime = "7.56"; + decayHFRatio = "0.91"; + decayLFRatio = "1.0"; + reflections = "-626"; + reflectionsDelay = "0.02"; + reflectionsPan[ 0 ] = "0.0"; + reflectionsPan[ 1 ] = "0.0"; + reflectionsPan[ 2 ] = "0.0"; + reverb = "774"; + reverbDelay = "0.03"; + reverbPan[ 0 ] = "0.0"; + reverbPan[ 1 ] = "0.0"; + reverbPan[ 2 ] = "0.0"; + echoTime = "0.25"; + echoDepth = "0.0"; + modulationTime = "4.0"; + modulationDepth = "1.0"; + airAbsorptionHF = "-5.0"; + HFReference = "5000.0"; + LFReference = "250.0"; + roomRolloffFactor = "0.0"; + diffusion = "100.0"; + density = "100.0"; + flags = 0x1f; +}; diff --git a/Templates/BaseGame/game/core/sfx/scripts/audioStates.cs b/Templates/BaseGame/game/core/sfx/scripts/audioStates.cs new file mode 100644 index 000000000..3ab55cf78 --- /dev/null +++ b/Templates/BaseGame/game/core/sfx/scripts/audioStates.cs @@ -0,0 +1,158 @@ +//----------------------------------------------------------------------------- +// 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. +//----------------------------------------------------------------------------- + +// Some state presets. + + +/// Return the first active SFXState in the given SimSet/SimGroup. +function sfxGetActiveStateInGroup( %group ) +{ + %count = %group.getCount(); + for( %i = 0; %i < %count; %i ++ ) + { + %obj = %group.getObject( %i ); + if( !%obj.isMemberOfClass( "SFXState" ) ) + continue; + + if( %obj.isActive() ) + return %obj; + } + + return 0; +} + + +//----------------------------------------------------------------------------- +// Special audio state that will always and only be active when no other +// state is active. Useful for letting slots apply specifically when no +// other slot in a list applies. + +singleton SFXState( AudioStateNone ) {}; + +AudioStateNone.activate(); + +function SFXState::onActivate( %this ) +{ + if( %this.getId() != AudioStateNone.getId() ) + AudioStateNone.disable(); +} + +function SFXState::onDeactivate( %this ) +{ + if( %this.getId() != AudioStateNone.getId() ) + AudioStateNone.enable(); +} + +//----------------------------------------------------------------------------- +// AudioStateExclusive class. +// +// Automatically deactivates sibling SFXStates in its parent SimGroup +// when activated. + +function AudioStateExclusive::onActivate( %this ) +{ + Parent::onActivate( %this ); + + %group = %this.parentGroup; + %count = %group.getCount(); + + for( %i = 0; %i < %count; %i ++ ) + { + %obj = %group.getObject( %i ); + + if( %obj != %this && %obj.isMemberOfClass( "SFXState" ) && %obj.isActive() ) + %obj.deactivate(); + } +} + +//----------------------------------------------------------------------------- +// Location-dependent states. + +singleton SimGroup( AudioLocation ); + +/// State when the listener is outside. +singleton SFXState( AudioLocationOutside ) +{ + parentGroup = AudioLocation; + className = "AudioStateExclusive"; +}; + +/// State when the listener is submerged. +singleton SFXState( AudioLocationUnderwater ) +{ + parentGroup = AudioLocation; + className = "AudioStateExclusive"; +}; + +/// State when the listener is indoors. +singleton SFXState( AudioLocationInside ) +{ + parentGroup = AudioLocation; + className = "AudioStateExclusive"; +}; + +/// Return the currently active SFXState in AudioLocation. +function sfxGetLocation() +{ + return sfxGetActiveStateInGroup( AudioLocation ); +} + +//----------------------------------------------------------------------------- +// Mood-dependent states. + +singleton SimGroup( AudioMood ); + +singleton SFXState( AudioMoodNeutral ) +{ + parentGroup = AudioMood; + className = "AudioStateExclusive"; +}; + +singleton SFXState( AudioMoodAggressive ) +{ + parentGroup = AudioMood; + className = "AudioStateExclusive"; +}; + +singleton SFXState( AudioMoodTense ) +{ + parentGroup = AudioMood; + className = "AudioStateExclusive"; +}; + +singleton SFXState( AudioMoodVictory ) +{ + parentGroup = AudioMood; + className = "AudioStateExclusive"; +}; + +singleton SFXState( AudioMoodCalm ) +{ + parentGroup = AudioMood; + className = "AudioStateExclusive"; +}; + +/// Return the currently active SFXState in AudioMood. +function sfxGetMood() +{ + return sfxGetActiveStateInGroup( AudioMood ); +} diff --git a/Templates/BaseGame/game/core/utility/Core_Utility.cs b/Templates/BaseGame/game/core/utility/Core_Utility.cs new file mode 100644 index 000000000..d412f3544 --- /dev/null +++ b/Templates/BaseGame/game/core/utility/Core_Utility.cs @@ -0,0 +1,11 @@ + +function Core_Utility::onCreate(%this) +{ + exec("./scripts/parseArgs.cs"); + exec("./scripts/globals.cs"); + exec("./scripts/helperFunctions.cs"); +} + +function Core_Utility::onDestroy(%this) +{ +} \ No newline at end of file diff --git a/Templates/BaseGame/game/core/utility/Core_Utility.module b/Templates/BaseGame/game/core/utility/Core_Utility.module new file mode 100644 index 000000000..cb6539040 --- /dev/null +++ b/Templates/BaseGame/game/core/utility/Core_Utility.module @@ -0,0 +1,9 @@ + + \ No newline at end of file diff --git a/Templates/BaseGame/game/core/utility/scripts/globals.cs b/Templates/BaseGame/game/core/utility/scripts/globals.cs new file mode 100644 index 000000000..fcf52390a --- /dev/null +++ b/Templates/BaseGame/game/core/utility/scripts/globals.cs @@ -0,0 +1,102 @@ +//----------------------------------------------------------------------------- +// 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. +//----------------------------------------------------------------------------- + +// ---------------------------------------------------------------------------- +// DInput keyboard, mouse, and joystick prefs +// ---------------------------------------------------------------------------- + +$pref::Input::MouseEnabled = 1; +$pref::Input::LinkMouseSensitivity = 1; +$pref::Input::KeyboardEnabled = 1; +$pref::Input::KeyboardTurnSpeed = 0.1; +$pref::Input::JoystickEnabled = 0; + +// ---------------------------------------------------------------------------- +// Video Preferences +// ---------------------------------------------------------------------------- + +// Set directory paths for various data or default images. +$pref::Video::ProfilePath = "core/rendering/scripts/gfxprofile"; +/*$pref::Video::missingTexturePath = "core/images/missingTexture.png"; +$pref::Video::unavailableTexturePath = "core/images/unavailable.png"; +$pref::Video::warningTexturePath = "core/images/warnMat.dds";*/ + +$pref::Video::disableVerticalSync = 1; +$pref::Video::mode = "800 600 false 32 60 4"; +$pref::Video::defaultFenceCount = 0; + +// This disables the hardware FSAA/MSAA so that we depend completely on the FXAA +// post effect which works on all cards and in deferred mode. Note that the new +// Intel Hybrid graphics on laptops will fail to initialize when hardware AA is +// enabled... so you've been warned. +$pref::Video::disableHardwareAA = true; + +$pref::Video::disableNormalmapping = false; +$pref::Video::disablePixSpecular = false; +$pref::Video::disableCubemapping = false; +$pref::Video::disableParallaxMapping = false; + +// The number of mipmap levels to drop on loaded textures to reduce video memory +// usage. It will skip any textures that have been defined as not allowing down +// scaling. +$pref::Video::textureReductionLevel = 0; + +$pref::Video::defaultAnisotropy = 1; +//$pref::Video::Gamma = 1.0; + +/// AutoDetect graphics quality levels the next startup. +$pref::Video::autoDetect = 1; + +// ---------------------------------------------------------------------------- +// Shader stuff +// ---------------------------------------------------------------------------- + +// This is the path used by ShaderGen to cache procedural shaders. If left +// blank ShaderGen will only cache shaders to memory and not to disk. +$shaderGen::cachePath = "data/shaderCache"; + +// Uncomment to disable ShaderGen, useful when debugging +//$ShaderGen::GenNewShaders = false; + +// Uncomment to dump disassembly for any shader that is compiled to disk. These +// will appear as shadername_dis.txt in the same path as the shader file. +//$gfx::disassembleAllShaders = true; + +// ---------------------------------------------------------------------------- +// Lighting and shadowing +// ---------------------------------------------------------------------------- + +// Uncomment to enable AdvancedLighting on the Mac (T3D 2009 Beta 3) +//$pref::machax::enableAdvancedLighting = true; + +$sceneLighting::cacheSize = 20000; +$sceneLighting::purgeMethod = "lastCreated"; +$sceneLighting::cacheLighting = 1; + +$pref::Shadows::textureScalar = 1.0; +$pref::Shadows::disable = false; + +// Sets the shadow filtering mode. +// None - Disables filtering. +// SoftShadow - Does a simple soft shadow +// SoftShadowHighQuality +$pref::Shadows::filterMode = "SoftShadow"; diff --git a/Templates/BaseGame/game/core/utility/scripts/helperFunctions.cs b/Templates/BaseGame/game/core/utility/scripts/helperFunctions.cs new file mode 100644 index 000000000..8abe3e6e6 --- /dev/null +++ b/Templates/BaseGame/game/core/utility/scripts/helperFunctions.cs @@ -0,0 +1,1158 @@ +//----------------------------------------------------------------------------- +// 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. +//----------------------------------------------------------------------------- + + +//------------------------------------------------------------------------------ +// Check if a script file exists, compiled or not. +function isScriptFile(%path) +{ + if( isFile(%path @ ".dso") || isFile(%path) ) + return true; + + return false; +} + +function loadMaterials() +{ + // Load any materials files for which we only have DSOs. + + for( %file = findFirstFile( "*/materials.cs.dso" ); + %file !$= ""; + %file = findNextFile( "*/materials.cs.dso" )) + { + // Only execute, if we don't have the source file. + %csFileName = getSubStr( %file, 0, strlen( %file ) - 4 ); + if( !isFile( %csFileName ) ) + exec( %csFileName ); + } + + // Load all source material files. + + for( %file = findFirstFile( "*/materials.cs" ); + %file !$= ""; + %file = findNextFile( "*/materials.cs" )) + { + exec( %file ); + } + + // Load all materials created by the material editor if + // the folder exists + if( IsDirectory( "materialEditor" ) ) + { + for( %file = findFirstFile( "materialEditor/*.cs.dso" ); + %file !$= ""; + %file = findNextFile( "materialEditor/*.cs.dso" )) + { + // Only execute, if we don't have the source file. + %csFileName = getSubStr( %file, 0, strlen( %file ) - 4 ); + if( !isFile( %csFileName ) ) + exec( %csFileName ); + } + + for( %file = findFirstFile( "materialEditor/*.cs" ); + %file !$= ""; + %file = findNextFile( "materialEditor/*.cs" )) + { + exec( %file ); + } + } +} + +function reloadMaterials() +{ + reloadTextures(); + loadMaterials(); + reInitMaterials(); +} + +function loadDatablockFiles( %datablockFiles, %recurse ) +{ + if ( %recurse ) + { + recursiveLoadDatablockFiles( %datablockFiles, 9999 ); + return; + } + + %count = %datablockFiles.count(); + for ( %i=0; %i < %count; %i++ ) + { + %file = %datablockFiles.getKey( %i ); + if ( !isFile(%file @ ".dso") && !isFile(%file) ) + continue; + + exec( %file ); + } + + // Destroy the incoming list. + //%datablockFiles.delete(); +} + +function recursiveLoadDatablockFiles( %datablockFiles, %previousErrors ) +{ + %reloadDatablockFiles = new ArrayObject(); + + // Keep track of the number of datablocks that + // failed during this pass. + %failedDatablocks = 0; + + // Try re-executing the list of datablock files. + %count = %datablockFiles.count(); + for ( %i=0; %i < %count; %i++ ) + { + %file = %datablockFiles.getKey( %i ); + if ( !isFile(%file @ ".dso") && !isFile(%file) ) + continue; + + // Start counting copy constructor creation errors. + $Con::objectCopyFailures = 0; + + exec( %file ); + + // If errors occured then store this file for re-exec later. + if ( $Con::objectCopyFailures > 0 ) + { + %reloadDatablockFiles.add( %file ); + %failedDatablocks = %failedDatablocks + $Con::objectCopyFailures; + } + } + + // Clear the object copy failure counter so that + // we get console error messages again. + $Con::objectCopyFailures = -1; + + // Delete the old incoming list... we're done with it. + //%datablockFiles.delete(); + + // If we still have datablocks to retry. + %newCount = %reloadDatablockFiles.count(); + if ( %newCount > 0 ) + { + // If the datablock failures have not been reduced + // from the last pass then we must have a real syntax + // error and not just a bad dependancy. + if ( %previousErrors > %failedDatablocks ) + recursiveLoadDatablockFiles( %reloadDatablockFiles, %failedDatablocks ); + + else + { + // Since we must have real syntax errors do one + // last normal exec to output error messages. + loadDatablockFiles( %reloadDatablockFiles, false ); + } + + return; + } + + // Cleanup the empty reload list. + %reloadDatablockFiles.delete(); +} + +function getUserPath() +{ + %temp = getUserHomeDirectory(); + echo(%temp); + if(!isDirectory(%temp)) + { + %temp = getUserDataDirectory(); + echo(%temp); + if(!isDirectory(%temp)) + { + %userPath = "data"; + } + else + { + //put it in appdata/roaming + %userPath = %temp @ "/" @ $appName; + } + } + else + { + //put it in user/documents + %userPath = %temp @ "/" @ $appName; + } + return %userPath; +} + +function getPrefpath() +{ + $prefPath = getUserPath() @ "/preferences"; + return $prefPath; +} + +function updateTSShapeLoadProgress(%progress, %msg) +{ + // Check if the loading GUI is visible and use that instead of the + // separate import progress GUI if possible + /* if ( isObject(LoadingGui) && LoadingGui.isAwake() ) + { + // Save/Restore load progress at the start/end of the import process + if ( %progress == 0 ) + { + ColladaImportProgress.savedProgress = LoadingProgress.getValue(); + ColladaImportProgress.savedText = LoadingProgressTxt.getValue(); + + ColladaImportProgress.msgPrefix = "Importing " @ %msg; + %msg = "Reading file into memory..."; + } + else if ( %progress == 1.0 ) + { + LoadingProgress.setValue( ColladaImportProgress.savedProgress ); + LoadingProgressTxt.setValue( ColladaImportProgress.savedText ); + } + + %msg = ColladaImportProgress.msgPrefix @ ": " @ %msg; + + %progressCtrl = LoadingProgress; + %textCtrl = LoadingProgressTxt; + } + else + { + //it's probably the editors using it + if(isFunction("updateToolTSShapeLoadProgress")) + { + updateToolTSShapeLoadProgress(%progress, %msg); + } + } + + // Update progress indicators + if (%progress == 0) + { + %progressCtrl.setValue(0.001); + %textCtrl.setText(%msg); + } + else if (%progress != 1.0) + { + %progressCtrl.setValue(%progress); + %textCtrl.setText(%msg); + } + + Canvas.repaint(33);*/ +} + +/// A helper function which will return the ghosted client object +/// from a server object when connected to a local server. +function serverToClientObject( %serverObject ) +{ + assert( isObject( LocalClientConnection ), "serverToClientObject() - No local client connection found!" ); + assert( isObject( ServerConnection ), "serverToClientObject() - No server connection found!" ); + + %ghostId = LocalClientConnection.getGhostId( %serverObject ); + if ( %ghostId == -1 ) + return 0; + + return ServerConnection.resolveGhostID( %ghostId ); +} + +//---------------------------------------------------------------------------- +// Debug commands +//---------------------------------------------------------------------------- + +function netSimulateLag( %msDelay, %packetLossPercent ) +{ + if ( %packetLossPercent $= "" ) + %packetLossPercent = 0; + + commandToServer( 'NetSimulateLag', %msDelay, %packetLossPercent ); +} + +//Various client functions + +function validateDatablockName(%name) +{ + // remove whitespaces at beginning and end + %name = trim( %name ); + + // remove numbers at the beginning + %numbers = "0123456789"; + while( strlen(%name) > 0 ) + { + // the first character + %firstChar = getSubStr( %name, 0, 1 ); + // if the character is a number remove it + if( strpos( %numbers, %firstChar ) != -1 ) + { + %name = getSubStr( %name, 1, strlen(%name) -1 ); + %name = ltrim( %name ); + } + else + break; + } + + // replace whitespaces with underscores + %name = strreplace( %name, " ", "_" ); + + // remove any other invalid characters + %invalidCharacters = "-+*/%$&§=()[].?\"#,;!~<>|°^{}"; + %name = stripChars( %name, %invalidCharacters ); + + if( %name $= "" ) + %name = "Unnamed"; + + return %name; +} + +//-------------------------------------------------------------------------- +// Finds location of %word in %text, starting at %start. Works just like strPos +//-------------------------------------------------------------------------- + +function wordPos(%text, %word, %start) +{ + if (%start $= "") %start = 0; + + if (strpos(%text, %word, 0) == -1) return -1; + %count = getWordCount(%text); + if (%start >= %count) return -1; + for (%i = %start; %i < %count; %i++) + { + if (getWord( %text, %i) $= %word) return %i; + } + return -1; +} + +//-------------------------------------------------------------------------- +// Finds location of %field in %text, starting at %start. Works just like strPos +//-------------------------------------------------------------------------- + +function fieldPos(%text, %field, %start) +{ + if (%start $= "") %start = 0; + + if (strpos(%text, %field, 0) == -1) return -1; + %count = getFieldCount(%text); + if (%start >= %count) return -1; + for (%i = %start; %i < %count; %i++) + { + if (getField( %text, %i) $= %field) return %i; + } + return -1; +} + +//-------------------------------------------------------------------------- +// returns the text in a file with "\n" at the end of each line +//-------------------------------------------------------------------------- + +function loadFileText( %file) +{ + %fo = new FileObject(); + %fo.openForRead(%file); + %text = ""; + while(!%fo.isEOF()) + { + %text = %text @ %fo.readLine(); + if (!%fo.isEOF()) %text = %text @ "\n"; + } + + %fo.delete(); + return %text; +} + +function setValueSafe(%dest, %val) +{ + %cmd = %dest.command; + %alt = %dest.altCommand; + %dest.command = ""; + %dest.altCommand = ""; + + %dest.setValue(%val); + + %dest.command = %cmd; + %dest.altCommand = %alt; +} + +function shareValueSafe(%source, %dest) +{ + setValueSafe(%dest, %source.getValue()); +} + +function shareValueSafeDelay(%source, %dest, %delayMs) +{ + schedule(%delayMs, 0, shareValueSafe, %source, %dest); +} + + +//------------------------------------------------------------------------------ +// An Aggregate Control is a plain GuiControl that contains other controls, +// which all share a single job or represent a single value. +//------------------------------------------------------------------------------ + +// AggregateControl.setValue( ) propagates the value to any control that has an +// internal name. +function AggregateControl::setValue(%this, %val, %child) +{ + for(%i = 0; %i < %this.getCount(); %i++) + { + %obj = %this.getObject(%i); + if( %obj == %child ) + continue; + + if(%obj.internalName !$= "") + setValueSafe(%obj, %val); + } +} + +// AggregateControl.getValue() uses the value of the first control that has an +// internal name, if it has not cached a value via .setValue +function AggregateControl::getValue(%this) +{ + for(%i = 0; %i < %this.getCount(); %i++) + { + %obj = %this.getObject(%i); + if(%obj.internalName !$= "") + { + //error("obj = " @ %obj.getId() @ ", " @ %obj.getName() @ ", " @ %obj.internalName ); + //error(" value = " @ %obj.getValue()); + return %obj.getValue(); + } + } +} + +// AggregateControl.updateFromChild( ) is called by child controls to propagate +// a new value, and to trigger the onAction() callback. +function AggregateControl::updateFromChild(%this, %child) +{ + %val = %child.getValue(); + if(%val == mCeil(%val)){ + %val = mCeil(%val); + }else{ + if ( %val <= -100){ + %val = mCeil(%val); + }else if ( %val <= -10){ + %val = mFloatLength(%val, 1); + }else if ( %val < 0){ + %val = mFloatLength(%val, 2); + }else if ( %val >= 1000){ + %val = mCeil(%val); + }else if ( %val >= 100){ + %val = mFloatLength(%val, 1); + }else if ( %val >= 10){ + %val = mFloatLength(%val, 2); + }else if ( %val > 0){ + %val = mFloatLength(%val, 3); + } + } + %this.setValue(%val, %child); + %this.onAction(); +} + +// default onAction stub, here only to prevent console spam warnings. +function AggregateControl::onAction(%this) +{ +} + +// call a method on all children that have an internalName and that implement the method. +function AggregateControl::callMethod(%this, %method, %args) +{ + for(%i = 0; %i < %this.getCount(); %i++) + { + %obj = %this.getObject(%i); + if(%obj.internalName !$= "" && %obj.isMethod(%method)) + eval(%obj @ "." @ %method @ "( " @ %args @ " );"); + } + +} + +//------------------------------------------------------------------------------ +// Altered Version of TGB's QuickEditDropDownTextEditCtrl +//------------------------------------------------------------------------------ +function QuickEditDropDownTextEditCtrl::onRenameItem( %this ) +{ +} + +function QuickEditDropDownTextEditCtrl::updateFromChild( %this, %ctrl ) +{ + if( %ctrl.internalName $= "PopUpMenu" ) + { + %this->TextEdit.setText( %ctrl.getText() ); + } + else if ( %ctrl.internalName $= "TextEdit" ) + { + %popup = %this->PopupMenu; + %popup.changeTextById( %popup.getSelected(), %ctrl.getText() ); + %this.onRenameItem(); + } +} + +// Writes out all script functions to a file. +function writeOutFunctions() +{ + new ConsoleLogger(logger, "scriptFunctions.txt", false); + dumpConsoleFunctions(); + logger.delete(); +} + +// Writes out all script classes to a file. +function writeOutClasses() +{ + new ConsoleLogger(logger, "scriptClasses.txt", false); + dumpConsoleClasses(); + logger.delete(); +} + +// +function compileFiles(%pattern) +{ + %path = filePath(%pattern); + + %saveDSO = $Scripts::OverrideDSOPath; + %saveIgnore = $Scripts::ignoreDSOs; + + $Scripts::OverrideDSOPath = %path; + $Scripts::ignoreDSOs = false; + %mainCsFile = makeFullPath("main.cs"); + + for (%file = findFirstFileMultiExpr(%pattern); %file !$= ""; %file = findNextFileMultiExpr(%pattern)) + { + // we don't want to try and compile the primary main.cs + if(%mainCsFile !$= %file) + compile(%file, true); + } + + $Scripts::OverrideDSOPath = %saveDSO; + $Scripts::ignoreDSOs = %saveIgnore; + +} + +function displayHelp() +{ + // Notes on logmode: console logging is written to console.log. + // -log 0 disables console logging. + // -log 1 appends to existing logfile; it also closes the file + // (flushing the write buffer) after every write. + // -log 2 overwrites any existing logfile; it also only closes + // the logfile when the application shuts down. (default) + + error( + "Torque Demo command line options:\n"@ + " -log Logging behavior; see main.cs comments for details\n"@ + " -game Reset list of mods to only contain \n"@ + " Works like the -game argument\n"@ + " -dir Add to list of directories\n"@ + " -console Open a separate console\n"@ + " -jSave Record a journal\n"@ + " -jPlay Play back a journal\n"@ + " -help Display this help message\n" + ); +} + +// Execute startup scripts for each mod, starting at base and working up +function loadDir(%dir) +{ + pushback($userDirs, %dir, ";"); + + if (isScriptFile(%dir @ "/main.cs")) + exec(%dir @ "/main.cs"); +} + +function loadDirs(%dirPath) +{ + %dirPath = nextToken(%dirPath, token, ";"); + if (%dirPath !$= "") + loadDirs(%dirPath); + + if(exec(%token @ "/main.cs") != true) + { + error("Error: Unable to find specified directory: " @ %token ); + $dirCount--; + } +} + +//------------------------------------------------------------------------------ +// Utility remap functions: +//------------------------------------------------------------------------------ + +function ActionMap::copyBind( %this, %otherMap, %command ) +{ + if ( !isObject( %otherMap ) ) + { + error( "ActionMap::copyBind - \"" @ %otherMap @ "\" is not an object!" ); + return; + } + + %bind = %otherMap.getBinding( %command ); + if ( %bind !$= "" ) + { + %device = getField( %bind, 0 ); + %action = getField( %bind, 1 ); + %flags = %otherMap.isInverted( %device, %action ) ? "SDI" : "SD"; + %deadZone = %otherMap.getDeadZone( %device, %action ); + %scale = %otherMap.getScale( %device, %action ); + %this.bind( %device, %action, %flags, %deadZone, %scale, %command ); + } +} + +//------------------------------------------------------------------------------ +function ActionMap::blockBind( %this, %otherMap, %command ) +{ + if ( !isObject( %otherMap ) ) + { + error( "ActionMap::blockBind - \"" @ %otherMap @ "\" is not an object!" ); + return; + } + + %bind = %otherMap.getBinding( %command ); + if ( %bind !$= "" ) + %this.bind( getField( %bind, 0 ), getField( %bind, 1 ), "" ); +} + +//Dev helpers +/// Shortcut for typing dbgSetParameters with the default values torsion uses. +function dbgTorsion() +{ + dbgSetParameters( 6060, "password", false ); +} + +/// Reset the input state to a default of all-keys-up. +/// A helpful remedy for when Torque misses a button up event do to your breakpoints +/// and can't stop shooting / jumping / strafing. +function mvReset() +{ + for ( %i = 0; %i < 6; %i++ ) + setVariable( "mvTriggerCount" @ %i, 0 ); + + $mvUpAction = 0; + $mvDownAction = 0; + $mvLeftAction = 0; + $mvRightAction = 0; + + // There are others. +} + +//Persistance Manager tests + +new PersistenceManager(TestPManager); + +function runPManTest(%test) +{ + if (!isObject(TestPManager)) + return; + + if (%test $= "") + %test = 100; + + switch(%test) + { + case 0: + TestPManager.testFieldUpdates(); + case 1: + TestPManager.testObjectRename(); + case 2: + TestPManager.testNewObject(); + case 3: + TestPManager.testNewGroup(); + case 4: + TestPManager.testMoveObject(); + case 5: + TestPManager.testObjectRemove(); + case 100: + TestPManager.testFieldUpdates(); + TestPManager.testObjectRename(); + TestPManager.testNewObject(); + TestPManager.testNewGroup(); + TestPManager.testMoveObject(); + TestPManager.testObjectRemove(); + } +} + +function TestPManager::testFieldUpdates(%doNotSave) +{ + // Set some objects as dirty + TestPManager.setDirty(AudioGui); + TestPManager.setDirty(AudioSim); + TestPManager.setDirty(AudioMessage); + + // Alter some of the existing fields + AudioEffect.isLooping = true; + AudioMessage.isLooping = true; + AudioEffect.is3D = true; + + // Test removing a field + TestPManager.removeField(AudioGui, "isLooping"); + + // Alter some of the persistent fields + AudioGui.referenceDistance = 0.8; + AudioMessage.referenceDistance = 0.8; + + // Add some new dynamic fields + AudioGui.foo = "bar"; + AudioEffect.foo = "bar"; + + // Remove an object from the dirty list + // It shouldn't get updated in the file + TestPManager.removeDirty(AudioEffect); + + // Dirty an object in another file as well + TestPManager.setDirty(WarningMaterial); + + // Update a field that doesn't exist + WarningMaterial.glow[0] = true; + + // Drity another object to test for crashes + // when a dirty object is deleted + TestPManager.setDirty(SFXPausedSet); + + // Delete the object + SFXPausedSet.delete(); + + // Unless %doNotSave is set (by a batch/combo test) + // then go ahead and save now + if (!%doNotSave) + TestPManager.saveDirty(); +} + +function TestPManager::testObjectRename(%doNotSave) +{ + // Flag an object as dirty + if (isObject(AudioGui)) + TestPManager.setDirty(AudioGui); + else if (isObject(AudioGuiFoo)) + TestPManager.setDirty(AudioGuiFoo); + + // Rename it + if (isObject(AudioGui)) + AudioGui.setName(AudioGuiFoo); + else if (isObject(AudioGuiFoo)) + AudioGuiFoo.setName(AudioGui); + + // Unless %doNotSave is set (by a batch/combo test) + // then go ahead and save now + if (!%doNotSave) + TestPManager.saveDirty(); +} + +function TestPManager::testNewObject(%doNotSave) +{ + // Test adding a new named object + new SFXDescription(AudioNew) + { + volume = 0.5; + isLooping = true; + channel = $GuiAudioType; + foo = 2; + }; + + // Flag it as dirty + TestPManager.setDirty(AudioNew, "core/scripts/client/audio.cs"); + + // Test adding a new unnamed object + %obj = new SFXDescription() + { + volume = 0.75; + isLooping = true; + bar = 3; + }; + + // Flag it as dirty + TestPManager.setDirty(%obj, "core/scripts/client/audio.cs"); + + // Test adding an "empty" object + new SFXDescription(AudioEmpty); + + TestPManager.setDirty(AudioEmpty, "core/scripts/client/audio.cs"); + + // Unless %doNotSave is set (by a batch/combo test) + // then go ahead and save now + if (!%doNotSave) + TestPManager.saveDirty(); +} + +function TestPManager::testNewGroup(%doNotSave) +{ + // Test adding a new named SimGroup + new SimGroup(TestGroup) + { + foo = "bar"; + + new SFXDescription(TestObject) + { + volume = 0.5; + isLooping = true; + channel = $GuiAudioType; + foo = 1; + }; + new SimGroup(SubGroup) + { + foo = 2; + + new SFXDescription(SubObject) + { + volume = 0.5; + isLooping = true; + channel = $GuiAudioType; + foo = 3; + }; + }; + }; + + // Flag this as dirty + TestPManager.setDirty(TestGroup, "core/scripts/client/audio.cs"); + + // Test adding a new unnamed SimGroup + %group = new SimGroup() + { + foo = "bar"; + + new SFXDescription() + { + volume = 0.75; + channel = $GuiAudioType; + foo = 4; + }; + new SimGroup() + { + foo = 5; + + new SFXDescription() + { + volume = 0.75; + isLooping = true; + channel = $GuiAudioType; + foo = 6; + }; + }; + }; + + // Flag this as dirty + TestPManager.setDirty(%group, "core/scripts/client/audio.cs"); + + // Test adding a new unnamed SimSet + %set = new SimSet() + { + foo = "bar"; + + new SFXDescription() + { + volume = 0.75; + channel = $GuiAudioType; + foo = 7; + }; + new SimGroup() + { + foo = 8; + + new SFXDescription() + { + volume = 0.75; + isLooping = true; + channel = $GuiAudioType; + foo = 9; + }; + }; + }; + + // Flag this as dirty + TestPManager.setDirty(%set, "core/scripts/client/audio.cs"); + + // Unless %doNotSave is set (by a batch/combo test) + // then go ahead and save now + if (!%doNotSave) + TestPManager.saveDirty(); +} + +function TestPManager::testMoveObject(%doNotSave) +{ + // First add a couple of groups to the file + new SimGroup(MoveGroup1) + { + foo = "bar"; + + new SFXDescription(MoveObject1) + { + volume = 0.5; + isLooping = true; + channel = $GuiAudioType; + foo = 1; + }; + + new SimSet(SubGroup1) + { + new SFXDescription(SubObject1) + { + volume = 0.75; + isLooping = true; + channel = $GuiAudioType; + foo = 2; + }; + }; + }; + + // Flag this as dirty + TestPManager.setDirty(MoveGroup1, "core/scripts/client/audio.cs"); + + new SimGroup(MoveGroup2) + { + foo = "bar"; + + new SFXDescription(MoveObject2) + { + volume = 0.5; + isLooping = true; + channel = $GuiAudioType; + foo = 3; + }; + }; + + // Flag this as dirty + TestPManager.setDirty(MoveGroup2, "core/scripts/client/audio.cs"); + + // Unless %doNotSave is set (by a batch/combo test) + // then go ahead and save now + if (!%doNotSave) + TestPManager.saveDirty(); + + // Set them as dirty again + TestPManager.setDirty(MoveGroup1); + TestPManager.setDirty(MoveGroup2); + + // Give the subobject an new value + MoveObject1.foo = 4; + + // Move it into the other group + MoveGroup1.add(MoveObject2); + + // Switch the other subobject + MoveGroup2.add(MoveObject1); + + // Also add a new unnamed object to one of the groups + %obj = new SFXDescription() + { + volume = 0.75; + isLooping = true; + bar = 5; + }; + + MoveGroup1.add(%obj); + + // Unless %doNotSave is set (by a batch/combo test) + // then go ahead and save now + if (!%doNotSave) + TestPManager.saveDirty(); +} + +function TestPManager::testObjectRemove(%doNotSave) +{ + TestPManager.removeObjectFromFile(AudioSim); +} + +//Game Object management +function findGameObject(%name) +{ + //find all GameObjectAssets + %assetQuery = new AssetQuery(); + if(!AssetDatabase.findAssetType(%assetQuery, "GameObjectAsset")) + return 0; //if we didn't find ANY, just exit + + %count = %assetQuery.getCount(); + + for(%i=0; %i < %count; %i++) + { + %assetId = %assetQuery.getAsset(%i); + + //%assetName = AssetDatabase.getAssetName(%assetId); + + if(%assetId $= %name) + { + %gameObjectAsset = AssetDatabase.acquireAsset(%assetId); + + %assetQuery.delete(); + return %gameObjectAsset; + } + } + + %assetQuery.delete(); + return 0; +} + +function spawnGameObject(%name, %addToMissionGroup) +{ + if(%addToMissionGroup $= "") + %addToMissionGroup = true; + + //First, check if this already exists in our GameObjectPool + if(isObject(GameObjectPool)) + { + %goCount = GameObjectPool.countKey(%name); + + //if we have some already in the pool, pull it out and use that + if(%goCount != 0) + { + %goIdx = GameObjectPool.getIndexFromKey(%name); + %go = GameObjectPool.getValue(%goIdx); + + %go.setHidden(false); + %go.setScopeAlways(); + + if(%addToMissionGroup == true) //save instance when saving level + MissionGroup.add(%go); + else // clear instance on level exit + MissionCleanup.add(%go); + + //remove from the object pool's list + GameObjectPool.erase(%goIdx); + + return %go; + } + } + + //We have no existing pool, or no existing game objects of this type, so spawn a new one + + %gameObjectAsset = findGameObject(%name); + + if(isObject(%gameObjectAsset)) + { + %newSGOObject = TamlRead(%gameObjectAsset.TAMLFilePath); + + if(%addToMissionGroup == true) //save instance when saving level + MissionGroup.add(%newSGOObject); + else // clear instance on level exit + MissionCleanup.add(%newSGOObject); + + return %newSGOObject; + } + + return 0; +} + +function saveGameObject(%name, %tamlPath, %scriptPath) +{ + %gameObjectAsset = findGameObject(%name); + + //find if it already exists. If it does, we'll update it, if it does not, we'll make a new asset + if(isObject(%gameObjectAsset)) + { + %assetID = %gameObjectAsset.getAssetId(); + + %gameObjectAsset.TAMLFilePath = %tamlPath; + %gameObjectAsset.scriptFilePath = %scriptPath; + + TAMLWrite(%gameObjectAsset, AssetDatabase.getAssetFilePath(%assetID)); + AssetDatabase.refreshAsset(%assetID); + } + else + { + //Doesn't exist, so make a new one + %gameObjectAsset = new GameObjectAsset() + { + assetName = %name @ "Asset"; + gameObjectName = %name; + TAMLFilePath = %tamlPath; + scriptFilePath = %scriptPath; + }; + + //Save it alongside the taml file + %path = filePath(%tamlPath); + + TAMLWrite(%gameObjectAsset, %path @ "/" @ %name @ ".asset.taml"); + AssetDatabase.refreshAllAssets(true); + } +} + +//Allocates a number of a game object into a pool to be pulled from as needed +function allocateGameObjects(%name, %amount) +{ + //First, we need to make sure our pool exists + if(!isObject(GameObjectPool)) + { + new ArrayObject(GameObjectPool); + } + + //Next, we loop and generate our game objects, and add them to the pool + for(%i=0; %i < %amount; %i++) + { + %go = spawnGameObject(%name, false); + + //When our object is in the pool, it's not "real", so we need to make sure + //that we don't ghost it to clients untill we actually spawn it. + %go.clearScopeAlways(); + + //We also hide it, so that we don't 'exist' in the scene until we spawn + %go.hidden = true; + + //Lastly, add us to the pool, with the key being our game object type + GameObjectPool.add(%name, %go); + } +} + +function Entity::delete(%this) +{ + //we want to intercept the delete call, and add it to our GameObjectPool + //if it's a game object + if(%this.gameObjectAsset !$= "") + { + %this.setHidden(true); + %this.clearScopeAlways(); + + if(!isObject(GameObjectPool)) + { + new ArrayObject(GameObjectPool); + } + + GameObjectPool.add(%this.gameObjectAsset, %this); + + %missionSet = %this.getGroup(); + %missionSet.remove(%this); + } + else + { + %this.superClass.delete(); + } +} + +function clearGameObjectPool() +{ + if(isObject(GameObjectPool)) + { + %count = GameObjectPool.count(); + + for(%i=0; %i < %count; %i++) + { + %go = GameObjectPool.getValue(%i); + + %go.superClass.delete(); + } + + GameObjectPool.empty(); + } +} + +// +function switchCamera(%client, %newCamEntity) +{ + if(!isObject(%client) || !isObject(%newCamEntity)) + return error("SwitchCamera: No client or target camera!"); + + %cam = %newCamEntity.getComponent(CameraComponent); + + if(!isObject(%cam)) + return error("SwitchCamera: Target camera doesn't have a camera behavior!"); + + //TODO: Cleanup clientOwner for previous camera! + if(%cam.clientOwner == 0 || %cam.clientOwner $= "") + %cam.clientOwner = 0; + + %cam.scopeToClient(%client); + %cam.setDirty(); + + %client.setCameraObject(%newCamEntity); + %client.setControlCameraFov(%cam.FOV); + + %client.camera = %newCamEntity; +} \ No newline at end of file diff --git a/Templates/BaseGame/game/core/utility/scripts/parseArgs.cs b/Templates/BaseGame/game/core/utility/scripts/parseArgs.cs new file mode 100644 index 000000000..811cee00c --- /dev/null +++ b/Templates/BaseGame/game/core/utility/scripts/parseArgs.cs @@ -0,0 +1,392 @@ +//----------------------------------------------------------------------------- +// 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. +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// Support functions used to manage the directory list +function pushFront(%list, %token, %delim) +{ + if (%list !$= "") + return %token @ %delim @ %list; + return %token; +} + +function pushBack(%list, %token, %delim) +{ + if (%list !$= "") + return %list @ %delim @ %token; + return %token; +} + +function popFront(%list, %delim) +{ + return nextToken(%list, unused, %delim); +} + +function parseArgs() +{ + for ($i = 1; $i < $Game::argc ; $i++) + { + $arg = $Game::argv[$i]; + $nextArg = $Game::argv[$i+1]; + $hasNextArg = $Game::argc - $i > 1; + $logModeSpecified = false; + + // Check for dedicated run + /*if( stricmp($arg,"-dedicated") == 0 ) + { + $userDirs = $defaultGame; + $dirCount = 1; + $isDedicated = true; + }*/ + + switch$ ($arg) + { + //-------------------- + case "-dedicated": + $userDirs = $defaultGame; + $dirCount = 1; + $isDedicated = true; + $Server::Dedicated = true; + enableWinConsole(true); + $argUsed[%i]++; + + //-------------------- + case "-mission": + $argUsed[%i]++; + if ($hasNextArg) + { + $missionArg = $nextArg; + $argUsed[%i+1]++; + %i++; + } + else + error("Error: Missing Command Line argument. Usage: -mission "); + + //-------------------- + case "-connect": + $argUsed[%i]++; + if ($hasNextArg) + { + $JoinGameAddress = $nextArg; + $argUsed[%i+1]++; + %i++; + } + else + error("Error: Missing Command Line argument. Usage: -connect "); + + + //-------------------- + case "-log": + $argUsed[$i]++; + if ($hasNextArg) + { + // Turn on console logging + if ($nextArg != 0) + { + // Dump existing console to logfile first. + $nextArg += 4; + } + setLogMode($nextArg); + $logModeSpecified = true; + $argUsed[$i+1]++; + $i++; + } + else + error("Error: Missing Command Line argument. Usage: -log "); + + //-------------------- + case "-dir": + $argUsed[$i]++; + if ($hasNextArg) + { + // Append the mod to the end of the current list + $userDirs = strreplace($userDirs, $nextArg, ""); + $userDirs = pushFront($userDirs, $nextArg, ";"); + $argUsed[$i+1]++; + $i++; + $dirCount++; + } + else + error("Error: Missing Command Line argument. Usage: -dir "); + + //-------------------- + // changed the default behavior of this command line arg. It now + // defaults to ONLY loading the game, not tools + // default auto-run already loads in tools --SRZ 11/29/07 + case "-game": + $argUsed[$i]++; + if ($hasNextArg) + { + // Set the selected dir --NOTE: we no longer allow tools with this argument + /* + if( $isDedicated ) + { + $userDirs = $nextArg; + $dirCount = 1; + } + else + { + $userDirs = "tools;" @ $nextArg; + $dirCount = 2; + } + */ + $userDirs = $nextArg; + $dirCount = 1; + $argUsed[$i+1]++; + $i++; + error($userDirs); + } + else + error("Error: Missing Command Line argument. Usage: -game "); + + //-------------------- + case "-console": + enableWinConsole(true); + $argUsed[$i]++; + + //-------------------- + case "-jSave": + $argUsed[$i]++; + if ($hasNextArg) + { + echo("Saving event log to journal: " @ $nextArg); + saveJournal($nextArg); + $argUsed[$i+1]++; + $i++; + } + else + error("Error: Missing Command Line argument. Usage: -jSave "); + + //-------------------- + case "-jPlay": + $argUsed[$i]++; + if ($hasNextArg) + { + playJournal($nextArg); + $argUsed[$i+1]++; + $i++; + } + else + error("Error: Missing Command Line argument. Usage: -jPlay "); + + //-------------------- + case "-jPlayToVideo": + $argUsed[$i]++; + if ($hasNextArg) + { + $VideoCapture::journalName = $nextArg; + $VideoCapture::captureFromJournal = true; + $argUsed[$i+1]++; + $i++; + } + else + error("Error: Missing Command Line argument. Usage: -jPlayToVideo "); + + //-------------------- + case "-vidCapFile": + $argUsed[$i]++; + if ($hasNextArg) + { + $VideoCapture::fileName = $nextArg; + $argUsed[$i+1]++; + $i++; + } + else + error("Error: Missing Command Line argument. Usage: -vidCapFile "); + + //-------------------- + case "-vidCapFPS": + $argUsed[$i]++; + if ($hasNextArg) + { + $VideoCapture::fps = $nextArg; + $argUsed[$i+1]++; + $i++; + } + else + error("Error: Missing Command Line argument. Usage: -vidCapFPS "); + + //-------------------- + case "-vidCapEncoder": + $argUsed[$i]++; + if ($hasNextArg) + { + $VideoCapture::encoder = $nextArg; + $argUsed[$i+1]++; + $i++; + } + else + error("Error: Missing Command Line argument. Usage: -vidCapEncoder "); + + //-------------------- + case "-vidCapWidth": + $argUsed[$i]++; + if ($hasNextArg) + { + $videoCapture::width = $nextArg; + $argUsed[$i+1]++; + $i++; + } + else + error("Error: Missing Command Line argument. Usage: -vidCapWidth "); + + //-------------------- + case "-vidCapHeight": + $argUsed[$i]++; + if ($hasNextArg) + { + $videoCapture::height = $nextArg; + $argUsed[$i+1]++; + $i++; + } + else + error("Error: Missing Command Line argument. Usage: -vidCapHeight "); + + //-------------------- + case "-level": + $argUsed[$i]++; + if ($hasNextArg) + { + %hasExt = strpos($nextArg, ".mis"); + if(%hasExt == -1) + { + $levelToLoad = $nextArg @ " "; + + for(%i = $i + 2; %i < $Game::argc; %i++) + { + $arg = $Game::argv[%i]; + %hasExt = strpos($arg, ".mis"); + + if(%hasExt == -1) + { + $levelToLoad = $levelToLoad @ $arg @ " "; + } else + { + $levelToLoad = $levelToLoad @ $arg; + break; + } + } + } + else + { + $levelToLoad = $nextArg; + } + + $argUsed[$i+1]++; + $i++; + } + else + error("Error: Missing Command Line argument. Usage: -level "); + + //------------------- + case "-worldeditor": + $startWorldEditor = true; + $argUsed[$i]++; + + //------------------- + case "-guieditor": + $startGUIEditor = true; + $argUsed[$i]++; + + //------------------- + case "-help": + $displayHelp = true; + $argUsed[$i]++; + + //------------------- + case "-compileAll": + $compileAll = true; + $argUsed[$i]++; + + //------------------- + case "-compileTools": + $compileTools = true; + $argUsed[$i]++; + + //------------------- + case "-genScript": + $genScript = true; + $argUsed[$i]++; + + case "-fullscreen": + $cliFullscreen = true; + $argUsed[%i]++; + + case "-windowed": + $cliFullscreen = false; + $argUsed[%i]++; + + case "-openGL": + $pref::Video::displayDevice = "OpenGL"; + $argUsed[%i]++; + + case "-directX": + $pref::Video::displayDevice = "D3D"; + $argUsed[%i]++; + + case "-autoVideo": + $pref::Video::displayDevice = ""; + $argUsed[%i]++; + + case "-prefs": + $argUsed[%i]++; + if ($hasNextArg) { + exec($nextArg, true, true); + $argUsed[%i+1]++; + %i++; + } + else + error("Error: Missing Command Line argument. Usage: -prefs "); + + + //------------------- + default: + $argUsed[$i]++; + if($userDirs $= "") + $userDirs = $arg; + } + } + + //----------------------------------------------- + // Play journal to video file? + if ($VideoCapture::captureFromJournal && $VideoCapture::journalName !$= "") + { + if ($VideoCapture::fileName $= "") + $VideoCapture::fileName = $VideoCapture::journalName; + + if ($VideoCapture::encoder $= "") + $VideoCapture::encoder = "THEORA"; + + if ($VideoCapture::fps $= "") + $VideoCapture::fps = 30; + + if ($videoCapture::width $= "") + $videoCapture::width = 0; + + if ($videoCapture::height $= "") + $videoCapture::height = 0; + + playJournalToVideo( $VideoCapture::journalName, $VideoCapture::fileName, + $VideoCapture::encoder, $VideoCapture::fps, + $videoCapture::width SPC $videoCapture::height ); + } +} \ No newline at end of file diff --git a/Templates/BaseGame/game/core/vr/Core_VR.cs b/Templates/BaseGame/game/core/vr/Core_VR.cs new file mode 100644 index 000000000..42b2df7e0 --- /dev/null +++ b/Templates/BaseGame/game/core/vr/Core_VR.cs @@ -0,0 +1,9 @@ + +function Core_VR::onCreate(%this) +{ + exec("./scripts/oculusVR.cs"); +} + +function Core_VR::onDestroy(%this) +{ +} \ No newline at end of file diff --git a/Templates/BaseGame/game/core/vr/Core_VR.module b/Templates/BaseGame/game/core/vr/Core_VR.module new file mode 100644 index 000000000..960a5a85a --- /dev/null +++ b/Templates/BaseGame/game/core/vr/Core_VR.module @@ -0,0 +1,9 @@ + + \ No newline at end of file diff --git a/Templates/BaseGame/game/core/vr/guis/oculusVROverlay.gui b/Templates/BaseGame/game/core/vr/guis/oculusVROverlay.gui new file mode 100644 index 000000000..62a9f719c --- /dev/null +++ b/Templates/BaseGame/game/core/vr/guis/oculusVROverlay.gui @@ -0,0 +1,19 @@ +//--- OBJECT WRITE BEGIN --- +%guiContent = singleton GuiControl(OculusVROverlay) { + canSaveDynamicFields = "0"; + Enabled = "1"; + isContainer = "1"; + Profile = "GuiContentProfile"; + HorizSizing = "width"; + VertSizing = "height"; + Position = "0 0"; + Extent = "512 512"; + MinExtent = "8 8"; + canSave = "1"; + Visible = "1"; + tooltipprofile = "GuiToolTipProfile"; + hovertime = "1000"; + useVariable = "0"; + tile = "0"; +}; +//--- OBJECT WRITE END --- diff --git a/Templates/BaseGame/game/core/vr/scripts/oculusVR.cs b/Templates/BaseGame/game/core/vr/scripts/oculusVR.cs new file mode 100644 index 000000000..fa9562c18 --- /dev/null +++ b/Templates/BaseGame/game/core/vr/scripts/oculusVR.cs @@ -0,0 +1,248 @@ +//----------------------------------------------------------------------------- +// 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. +//----------------------------------------------------------------------------- + +// Only load these functions if an Oculus VR device is present +if(!isFunction(isOculusVRDeviceActive)) + return; + +function setupOculusActionMaps() +{ + if (isObject(OculusWarningMap)) + return; + + new ActionMap(OculusWarningMap); + new ActionMap(OculusCanvasMap); + + OculusWarningMap.bind(keyboard, space, dismissOculusVRWarnings); + + OculusCanvasMap.bind( mouse, xaxis, oculusYaw ); + OculusCanvasMap.bind( mouse, yaxis, oculusPitch ); + OculusCanvasMap.bind( mouse, button0, oculusClick ); +} + +function oculusYaw(%val) +{ + OculusCanvas.cursorNudge(%val * 0.10, 0); +} + +function oculusPitch(%val) +{ + OculusCanvas.cursorNudge(0, %val * 0.10); +} + +function oculusClick(%active) +{ + OculusCanvas.cursorClick(0, %active); +} + +function GuiOffscreenCanvas::checkCursor(%this) +{ + %count = %this.getCount(); + for(%i = 0; %i < %count; %i++) + { + %control = %this.getObject(%i); + if ((%control.noCursor $= "") || !%control.noCursor) + { + %this.cursorOn(); + return true; + } + } + // If we get here, every control requested a hidden cursor, so we oblige. + + %this.cursorOff(); + return false; +} + +function GuiOffscreenCanvas::pushDialog(%this, %ctrl, %layer, %center) +{ + Parent::pushDialog(%this, %ctrl, %layer, %center); + %cursorVisible = %this.checkCursor(); + + if (%cursorVisible) + { + echo("OffscreenCanvas visible"); + OculusCanvasMap.pop(); + OculusCanvasMap.push(); + } + else + { + echo("OffscreenCanvas not visible"); + OculusCanvasMap.pop(); + } +} + +function GuiOffscreenCanvas::popDialog(%this, %ctrl) +{ + Parent::popDialog(%this, %ctrl); + %cursorVisible = %this.checkCursor(); + + if (%cursorVisible) + { + echo("OffscreenCanvas visible"); + OculusCanvasMap.pop(); + OculusCanvasMap.push(); + } + else + { + echo("OffscreenCanvas not visible"); + OculusCanvasMap.pop(); + } +} + + +//----------------------------------------------------------------------------- + +function oculusSensorMetricsCallback() +{ + return ovrDumpMetrics(0); +} + + +//----------------------------------------------------------------------------- +function onOculusStatusUpdate(%status) +{ + $LastOculusTrackingState = %status; +} + +//----------------------------------------------------------------------------- + +// Call this function from createCanvas() to have the Canvas attach itself +// to the Rift's display. The Canvas' window will still open on the primary +// display if that is different from the Rift, but it will move to the Rift +// when it goes full screen. If the Rift is not connected then nothing +// will happen. +function pointCanvasToOculusVRDisplay() +{ + $pref::Video::displayOutputDevice = getOVRHMDDisplayDeviceName(0); +} + +//----------------------------------------------------------------------------- + +// Call this function from GameConnection::initialControlSet() just before +// your "Canvas.setContent(PlayGui);" call, or at any time you wish to switch +// to a side-by-side rendering and the appropriate barrel distortion. This +// will turn on side-by-side rendering and tell the GameConnection to use the +// Rift as its display device. +// Parameters: +// %gameConnection - The client GameConnection instance +// %trueStereoRendering - If true will enable stereo rendering with an eye +// offset for each viewport. This will render each frame twice. If false +// then a pseudo stereo rendering is done with only a single render per frame. +function enableOculusVRDisplay(%gameConnection, %trueStereoRendering) +{ + setOVRHMDAsGameConnectionDisplayDevice(%gameConnection); + PlayGui.renderStyle = "stereo side by side"; + setOptimalOVRCanvasSize(Canvas); + + if (!isObject(OculusCanvas)) + { + new GuiOffscreenCanvas(OculusCanvas) { + targetSize = "512 512"; + targetName = "oculusCanvas"; + dynamicTarget = true; + }; + } + + if (!isObject(OculusVROverlay)) + { + exec("core/vr/guis/oculusVROverlay.gui"); + } + + OculusCanvas.setContent(OculusVROverlay); + OculusCanvas.setCursor(DefaultCursor); + PlayGui.setStereoGui(OculusCanvas); + OculusCanvas.setCursorPos("128 128"); + OculusCanvas.cursorOff(); + $GameCanvas = OculusCanvas; + + %ext = Canvas.getExtent(); + $OculusMouseScaleX = 512.0 / 1920.0; + $OculusMouseScaleY = 512.0 / 1060.0; + + //$gfx::wireframe = true; + // Reset all sensors + ovrResetAllSensors(); +} + +// Call this function when ever you wish to turn off the stereo rendering +// and barrel distortion for the Rift. +function disableOculusVRDisplay(%gameConnection) +{ + OculusCanvas.popDialog(); + OculusWarningMap.pop(); + $GameCanvas = Canvas; + + if (isObject(gameConnection)) + { + %gameConnection.clearDisplayDevice(); + } + PlayGui.renderStyle = "standard"; +} + +// Helper function to set the standard Rift control scheme. You could place +// this function in GameConnection::initialControlSet() at the same time +// you call enableOculusVRDisplay(). +function setStandardOculusVRControlScheme(%gameConnection) +{ + if($OculusVR::SimulateInput) + { + // We are simulating a HMD so allow the mouse and gamepad to control + // both yaw and pitch. + %gameConnection.setControlSchemeParameters(true, true, true); + } + else + { + // A HMD is connected so have the mouse and gamepad only add to yaw + %gameConnection.setControlSchemeParameters(true, true, false); + } +} + +//----------------------------------------------------------------------------- + +// Helper function to set the resolution for the Rift. +// Parameters: +// %fullscreen - If true then the display will be forced to full screen. If +// pointCanvasToOculusVRDisplay() was called before the Canvas was created, then +// the full screen display will appear on the Rift. +function setVideoModeForOculusVRDisplay(%fullscreen) +{ + %res = getOVRHMDResolution(0); + Canvas.setVideoMode(%res.x, %res.y, %fullscreen, 32, 4); +} + +//----------------------------------------------------------------------------- + +// Reset all Oculus Rift sensors. This will make the Rift's current heading +// be considered the origin. +function resetOculusVRSensors() +{ + ovrResetAllSensors(); +} + +function dismissOculusVRWarnings(%value) +{ + //if (%value) + //{ + ovrDismissWarnings(); + OculusWarningMap.pop(); + //} +} \ No newline at end of file diff --git a/Templates/BaseGame/game/tools/levels/BlankRoom.postfxpreset.cs b/Templates/BaseGame/game/tools/levels/BlankRoom.postfxpreset.cs index 8b616a84a..23a6c3ced 100644 --- a/Templates/BaseGame/game/tools/levels/BlankRoom.postfxpreset.cs +++ b/Templates/BaseGame/game/tools/levels/BlankRoom.postfxpreset.cs @@ -1,4 +1,4 @@ -$PostFXManager::Settings::ColorCorrectionRamp = "core/images/null_color_ramp.png"; +$PostFXManager::Settings::ColorCorrectionRamp = "core/postFX/images/null_color_ramp.png"; $PostFXManager::Settings::DOF::BlurCurveFar = ""; $PostFXManager::Settings::DOF::BlurCurveNear = ""; $PostFXManager::Settings::DOF::BlurMax = ""; From 5037d7e046a9dba9bcafe4f8e33eb809453d8fc4 Mon Sep 17 00:00:00 2001 From: Areloch Date: Sun, 2 Sep 2018 04:49:58 -0500 Subject: [PATCH 28/34] Updated the main.cs.in file to account for core module-ification. --- Templates/BaseGame/game/main.cs.in | 47 ++++-------------------------- 1 file changed, 5 insertions(+), 42 deletions(-) diff --git a/Templates/BaseGame/game/main.cs.in b/Templates/BaseGame/game/main.cs.in index 3eed267df..1e3e37c44 100644 --- a/Templates/BaseGame/game/main.cs.in +++ b/Templates/BaseGame/game/main.cs.in @@ -16,39 +16,12 @@ $appName = "@TORQUE_APP_NAME@"; //----------------------------------------------------------------------------- // Load up scripts to initialise subsystems. -exec("core/main.cs"); - -// Parse the command line arguments -echo("\n--------- Parsing Arguments ---------"); -parseArgs(); - -// The canvas needs to be initialized before any gui scripts are run since -// some of the controls assume that the canvas exists at load time. -createCanvas($appName); +ModuleDatabase.setModuleExtension("module"); +ModuleDatabase.scanModules( "core", false ); +ModuleDatabase.LoadExplicit( "CoreModule" ); //----------------------------------------------------------------------------- -// Load console. -exec("core/console/main.cs"); - -// Init the physics plugin. -physicsInit(); - -sfxStartup(); - -// Set up networking. -setNetPort(0); - -// Start processing file change events. -startFileChangeNotifications(); - -// If we have editors, initialize them here as well -if (isToolBuild()) -{ - if(isFile("tools/main.cs") && !$isDedicated) - exec("tools/main.cs"); -} - -ModuleDatabase.setModuleExtension("module"); +// Load any gameplay modules ModuleDatabase.scanModules( "data", false ); ModuleDatabase.LoadGroup( "Game" ); @@ -85,14 +58,4 @@ else closeSplashWindow(); } -echo("Engine initialized..."); - -//----------------------------------------------------------------------------- -// Called when the engine is shutting down. -function onExit() -{ - // Stop file change events. - stopFileChangeNotifications(); - - ModuleDatabase.UnloadExplicit( "Game" ); -} \ No newline at end of file +echo("Engine initialized..."); \ No newline at end of file From c17ae947456ecd0b6172ad56dbb3cafa5b6650ce Mon Sep 17 00:00:00 2001 From: Areloch Date: Wed, 19 Sep 2018 16:03:58 -0500 Subject: [PATCH 29/34] Moved VR module from core to a regular module, as not all games are necessarily going to use VR. Also corrected some of the default posteffect settings for the levels. --- Templates/BaseGame/game/core/Core.cs | 2 -- Templates/BaseGame/game/core/vr/Core_VR.cs | 9 --------- Templates/Modules/vr/VR.cs | 9 +++++++++ .../game/core/vr/Core_VR.module => Modules/vr/VR.module} | 6 +++--- .../game/core => Modules}/vr/guis/oculusVROverlay.gui | 0 .../game/core => Modules}/vr/scripts/oculusVR.cs | 0 6 files changed, 12 insertions(+), 14 deletions(-) delete mode 100644 Templates/BaseGame/game/core/vr/Core_VR.cs create mode 100644 Templates/Modules/vr/VR.cs rename Templates/{BaseGame/game/core/vr/Core_VR.module => Modules/vr/VR.module} (75%) rename Templates/{BaseGame/game/core => Modules}/vr/guis/oculusVROverlay.gui (100%) rename Templates/{BaseGame/game/core => Modules}/vr/scripts/oculusVR.cs (100%) diff --git a/Templates/BaseGame/game/core/Core.cs b/Templates/BaseGame/game/core/Core.cs index 480c0331c..5559760ae 100644 --- a/Templates/BaseGame/game/core/Core.cs +++ b/Templates/BaseGame/game/core/Core.cs @@ -24,8 +24,6 @@ function CoreModule::onCreate(%this) ModuleDatabase.LoadExplicit( "Core_Lighting" ); ModuleDatabase.LoadExplicit( "Core_SFX" ); ModuleDatabase.LoadExplicit( "Core_PostFX" ); - ModuleDatabase.LoadExplicit( "Core_VR" ); - ModuleDatabase.LoadExplicit( "Core_VR" ); ModuleDatabase.LoadExplicit( "Core_ClientServer" ); %prefPath = getPrefpath(); diff --git a/Templates/BaseGame/game/core/vr/Core_VR.cs b/Templates/BaseGame/game/core/vr/Core_VR.cs deleted file mode 100644 index 42b2df7e0..000000000 --- a/Templates/BaseGame/game/core/vr/Core_VR.cs +++ /dev/null @@ -1,9 +0,0 @@ - -function Core_VR::onCreate(%this) -{ - exec("./scripts/oculusVR.cs"); -} - -function Core_VR::onDestroy(%this) -{ -} \ No newline at end of file diff --git a/Templates/Modules/vr/VR.cs b/Templates/Modules/vr/VR.cs new file mode 100644 index 000000000..ea0ffd7a5 --- /dev/null +++ b/Templates/Modules/vr/VR.cs @@ -0,0 +1,9 @@ + +function VR::onCreate(%this) +{ + exec("./scripts/oculusVR.cs"); +} + +function VR::onDestroy(%this) +{ +} \ No newline at end of file diff --git a/Templates/BaseGame/game/core/vr/Core_VR.module b/Templates/Modules/vr/VR.module similarity index 75% rename from Templates/BaseGame/game/core/vr/Core_VR.module rename to Templates/Modules/vr/VR.module index 960a5a85a..14ccec0e0 100644 --- a/Templates/BaseGame/game/core/vr/Core_VR.module +++ b/Templates/Modules/vr/VR.module @@ -1,9 +1,9 @@ + Group="Game"> \ No newline at end of file diff --git a/Templates/BaseGame/game/core/vr/guis/oculusVROverlay.gui b/Templates/Modules/vr/guis/oculusVROverlay.gui similarity index 100% rename from Templates/BaseGame/game/core/vr/guis/oculusVROverlay.gui rename to Templates/Modules/vr/guis/oculusVROverlay.gui diff --git a/Templates/BaseGame/game/core/vr/scripts/oculusVR.cs b/Templates/Modules/vr/scripts/oculusVR.cs similarity index 100% rename from Templates/BaseGame/game/core/vr/scripts/oculusVR.cs rename to Templates/Modules/vr/scripts/oculusVR.cs From 2ed30ffeaecf3062c67ae352d4385351be942b4c Mon Sep 17 00:00:00 2001 From: OTHGMars Date: Mon, 24 Sep 2018 18:56:46 -0400 Subject: [PATCH 30/34] Adds Clamp to QuatF::dot() Clamps output of QuatF::dot() to [-1, 1]. --- 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 ca6ed5d82..261b66a88 100644 --- a/Engine/source/math/mQuat.h +++ b/Engine/source/math/mQuat.h @@ -222,7 +222,7 @@ inline QuatF& QuatF::neg() inline F32 QuatF::dot( const QuatF &q ) const { - return (w*q.w + x*q.x + y*q.y + z*q.z); + return mClampF(w*q.w + x*q.x + y*q.y + z*q.z, -1.0f, 1.0f); } inline F32 QuatF::angleBetween( const QuatF & q ) From e3793184b6bd9956f32486fffe566dba0c9e3985 Mon Sep 17 00:00:00 2001 From: OTHGMars Date: Sat, 6 Oct 2018 03:29:15 -0400 Subject: [PATCH 31/34] Improved BitStream writeQuat/readQuat methods. Replaces the writeQuat/readQuat implementations with one that utilizes smallest three compression. --- Engine/source/core/stream/bitStream.cpp | 53 +++++++++++++++++++------ Engine/source/core/stream/bitStream.h | 8 ++-- 2 files changed, 44 insertions(+), 17 deletions(-) diff --git a/Engine/source/core/stream/bitStream.cpp b/Engine/source/core/stream/bitStream.cpp index 1a5ab3202..704da2b11 100644 --- a/Engine/source/core/stream/bitStream.cpp +++ b/Engine/source/core/stream/bitStream.cpp @@ -488,24 +488,51 @@ void BitStream::readAffineTransform(MatrixF* matrix) void BitStream::writeQuat( const QuatF& quat, U32 bitCount ) { - writeSignedFloat( quat.x, bitCount ); - writeSignedFloat( quat.y, bitCount ); - writeSignedFloat( quat.z, bitCount ); - writeFlag( quat.w < 0.0f ); + F32 quatVals[4] = { quat.x, quat.y, quat.z, quat.w }; + bool flipQuat = (quatVals[0] < 0); + F32 maxVal = mFabs(quatVals[0]); + S32 idxMax = 0; + + for (S32 i = 1; i < 4; ++i) + { + if (mFabs(quatVals[i]) > maxVal) + { + idxMax = i; + maxVal = mFabs(quatVals[i]); + flipQuat = (quatVals[i] < 0); + } + } + writeInt(idxMax, 2); + + for (S32 i = 0; i < 4; ++i) + { + if (i == idxMax) + continue; + F32 curValue = (flipQuat ? -quatVals[i] : quatVals[i]) * (F32) M_SQRT2; + writeSignedFloat( curValue, bitCount ); + } } void BitStream::readQuat( QuatF *outQuat, U32 bitCount ) { - outQuat->x = readSignedFloat( bitCount ); - outQuat->y = readSignedFloat( bitCount ); - outQuat->z = readSignedFloat( bitCount ); + F32 quatVals[4]; + F32 sum = 0.0f; - outQuat->w = mSqrt( 1.0 - getMin( mSquared( outQuat->x ) + - mSquared( outQuat->y ) + - mSquared( outQuat->z ), - 1.0f ) ); - if ( readFlag() ) - outQuat->w = -outQuat->w; + S32 idxMax = readInt( 2 ); + for (S32 i = 0; i < 4; ++i) + { + if (i == idxMax) + continue; + quatVals[i] = readSignedFloat( bitCount ) * M_SQRTHALF_F; + sum += quatVals[i] * quatVals[i]; + } + + if (sum > 1.0f) + quatVals[idxMax] = 1.0f; + else + quatVals[idxMax] = mSqrt(1.0f - sum); + + outQuat->set(quatVals[0], quatVals[1], quatVals[2], quatVals[3]); } void BitStream::writeBits( const BitVector &bitvec ) diff --git a/Engine/source/core/stream/bitStream.h b/Engine/source/core/stream/bitStream.h index b0bb2f22a..bd81f3b1b 100644 --- a/Engine/source/core/stream/bitStream.h +++ b/Engine/source/core/stream/bitStream.h @@ -207,18 +207,18 @@ public: void readAffineTransform(MatrixF*); /// Writes a quaternion in a lossy compressed format that - /// is ( bitCount * 3 ) + 1 bits in size. + /// is ( bitCount * 3 ) + 2 bits in size. /// /// @param quat The normalized quaternion to write. - /// @param bitCount The the storage space for the xyz component of + /// @param bitCount The the storage space for the packed components of /// the quaternion. /// void writeQuat( const QuatF& quat, U32 bitCount = 9 ); /// Reads a quaternion written with writeQuat. /// - /// @param quat The normalized quaternion to write. - /// @param bitCount The the storage space for the xyz component of + /// @param quat The quaternion that was read. + /// @param bitCount The the storage space for the packed components of /// the quaternion. Must match the bitCount at write. /// @see writeQuat /// From af247391376d9000c7adfcb6987232b735b8b39c Mon Sep 17 00:00:00 2001 From: OTHGMars Date: Fri, 23 Nov 2018 16:03:00 -0500 Subject: [PATCH 32/34] Adds handlers for sdl focus events. --- Engine/source/windowManager/sdl/sdlWindow.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/Engine/source/windowManager/sdl/sdlWindow.cpp b/Engine/source/windowManager/sdl/sdlWindow.cpp index 149825b98..ea2b29061 100644 --- a/Engine/source/windowManager/sdl/sdlWindow.cpp +++ b/Engine/source/windowManager/sdl/sdlWindow.cpp @@ -244,7 +244,7 @@ const char * PlatformWindowSDL::getCaption() void PlatformWindowSDL::setFocus() { - SDL_SetWindowGrab( mWindowHandle, SDL_TRUE ); + SDL_SetWindowInputFocus(mWindowHandle); } void PlatformWindowSDL::setClientExtent( const Point2I newExtent ) @@ -577,9 +577,7 @@ void PlatformWindowSDL::_processSDLEvent(SDL_Event &evt) case SDL_MOUSEBUTTONDOWN: case SDL_MOUSEBUTTONUP: { - appEvent.trigger(getWindowId(), GainFocus); _triggerMouseButtonNotify(evt); - break; } @@ -587,6 +585,12 @@ void PlatformWindowSDL::_processSDLEvent(SDL_Event &evt) { switch( evt.window.event ) { + case SDL_WINDOWEVENT_FOCUS_GAINED: + appEvent.trigger(getWindowId(), GainFocus); + break; + case SDL_WINDOWEVENT_FOCUS_LOST: + appEvent.trigger(getWindowId(), LoseFocus); + break; case SDL_WINDOWEVENT_MAXIMIZED: case SDL_WINDOWEVENT_RESIZED: { From 49fa248ec4aa9c482d0a1d7149b560f6795dc313 Mon Sep 17 00:00:00 2001 From: OTHGMars Date: Sat, 24 Nov 2018 03:12:07 -0500 Subject: [PATCH 33/34] Fills in monitor functions in PlatformWindowManagerSDL Adds the sdl implementation for all used PlatformWindowManager monitor functions. [This unit test](https://github.com/GarageGames/Torque3D/blob/development/Engine/source/windowManager/test/windowManagerTest.cpp#L28) will now pass for the SDL platform. Here is the equivalent in TorqueScript to test the functions via the Canvas object:```//Canvas.listDisplays(); function Canvas::listDisplays(%this) { %count = %this.getMonitorCount(); echo(%count SPC "monitor(s) detected."); for (%i = 0; %i < %count; %i++) { echo("Monitor #" @ (%i + 1) SPC %this.getMonitorName(%i) @ ": " @ %this.getMonitorRect(%i)); } }``` --- .../source/windowManager/sdl/sdlWindowMgr.cpp | 57 +++++++++++-------- .../source/windowManager/sdl/sdlWindowMgr.h | 3 - 2 files changed, 34 insertions(+), 26 deletions(-) diff --git a/Engine/source/windowManager/sdl/sdlWindowMgr.cpp b/Engine/source/windowManager/sdl/sdlWindowMgr.cpp index 68adf002e..f503c4fb1 100644 --- a/Engine/source/windowManager/sdl/sdlWindowMgr.cpp +++ b/Engine/source/windowManager/sdl/sdlWindowMgr.cpp @@ -61,8 +61,6 @@ PlatformWindowManagerSDL::PlatformWindowManagerSDL() mOffscreenRender = false; mInputState = KeyboardInputState::NONE; - - buildMonitorsList(); } PlatformWindowManagerSDL::~PlatformWindowManagerSDL() @@ -75,9 +73,8 @@ PlatformWindowManagerSDL::~PlatformWindowManagerSDL() RectI PlatformWindowManagerSDL::getPrimaryDesktopArea() { - // TODO SDL - AssertFatal(0, ""); - return RectI(0,0,0,0); + // Primary is monitor 0 + return getMonitorRect(0); } Point2I PlatformWindowManagerSDL::getDesktopResolution() @@ -100,46 +97,60 @@ S32 PlatformWindowManagerSDL::getDesktopBitDepth() return bbp; } -void PlatformWindowManagerSDL::buildMonitorsList() -{ - // TODO SDL -} - S32 PlatformWindowManagerSDL::findFirstMatchingMonitor(const char* name) { - /// TODO SDL - AssertFatal(0, ""); + S32 count = SDL_GetNumVideoDisplays(); + for (U32 index = 0; index < count; ++index) + { + if (dStrstr(name, SDL_GetDisplayName(index)) == name) + return index; + } return 0; } U32 PlatformWindowManagerSDL::getMonitorCount() { - // TODO SDL - AssertFatal(0, ""); - return 1; + S32 monitorCount = SDL_GetNumVideoDisplays(); + if (monitorCount < 0) + { + Con::errorf("SDL_GetNumVideoDisplays() failed: %s", SDL_GetError()); + monitorCount = 0; + } + + return (U32)monitorCount; } const char* PlatformWindowManagerSDL::getMonitorName(U32 index) { - // TODO SDL - AssertFatal(0, ""); + const char* monitorName = SDL_GetDisplayName(index); + if (monitorName == NULL) + Con::errorf("SDL_GetDisplayName() failed: %s", SDL_GetError()); - return "Monitor"; + return monitorName; } RectI PlatformWindowManagerSDL::getMonitorRect(U32 index) { - // TODO SDL - AssertFatal(0, ""); + SDL_Rect sdlRect; + if (0 != SDL_GetDisplayBounds(index, &sdlRect)) + { + Con::errorf("SDL_GetDisplayBounds() failed: %s", SDL_GetError()); + return RectI(0, 0, 0, 0); + } - return RectI(0, 0, 0,0 ); + return RectI(sdlRect.x, sdlRect.y, sdlRect.w, sdlRect.h); } void PlatformWindowManagerSDL::getMonitorRegions(Vector ®ions) { - // TODO SDL - AssertFatal(0, ""); + SDL_Rect sdlRect; + S32 monitorCount = SDL_GetNumVideoDisplays(); + for (S32 index = 0; index < monitorCount; ++index) + { + if (0 == SDL_GetDisplayBounds(index, &sdlRect)) + regions.push_back(RectI(sdlRect.x, sdlRect.y, sdlRect.w, sdlRect.h)); + } } void PlatformWindowManagerSDL::getWindows(VectorPtr &windows) diff --git a/Engine/source/windowManager/sdl/sdlWindowMgr.h b/Engine/source/windowManager/sdl/sdlWindowMgr.h index aacc348f2..fd8a762df 100644 --- a/Engine/source/windowManager/sdl/sdlWindowMgr.h +++ b/Engine/source/windowManager/sdl/sdlWindowMgr.h @@ -105,9 +105,6 @@ public: virtual S32 getDesktopBitDepth(); virtual Point2I getDesktopResolution(); - /// Build out the monitors list. - virtual void buildMonitorsList(); - virtual S32 findFirstMatchingMonitor(const char* name); virtual U32 getMonitorCount(); virtual const char* getMonitorName(U32 index); From a7fc40728472aff6fe19b734724f9ef1b8e1355b Mon Sep 17 00:00:00 2001 From: Azaezel Date: Wed, 12 Dec 2018 14:52:14 -0600 Subject: [PATCH 34/34] corrects a pair of conversions. one object oriented, one not. --- Engine/source/gui/editor/popupMenu.cpp | 2 +- Engine/source/testing/unitTesting.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Engine/source/gui/editor/popupMenu.cpp b/Engine/source/gui/editor/popupMenu.cpp index 5d2d5c9ee..308fb4e67 100644 --- a/Engine/source/gui/editor/popupMenu.cpp +++ b/Engine/source/gui/editor/popupMenu.cpp @@ -509,7 +509,7 @@ DefineEngineMethod(PopupMenu, getItemCount, S32, (), , "()") return object->getItemCount(); } -DefineConsoleMethod(PopupMenu, clearItems, void, (), , "()") +DefineEngineMethod(PopupMenu, clearItems, void, (), , "()") { return object->clearItems(); } diff --git a/Engine/source/testing/unitTesting.cpp b/Engine/source/testing/unitTesting.cpp index a86a28eb3..5d353f75c 100644 --- a/Engine/source/testing/unitTesting.cpp +++ b/Engine/source/testing/unitTesting.cpp @@ -76,7 +76,7 @@ public: TorqueUnitTestListener( bool verbose ) : mVerbose( verbose ) {} }; -DefineConsoleFunction( runAllUnitTests, int, (const char* testSpecs), (""), +DefineEngineFunction( runAllUnitTests, int, (const char* testSpecs), (""), "Runs engine unit tests. Some tests are marked as 'stress' tests which do not " "necessarily check correctness, just performance or possible nondeterministic " "glitches. There may also be interactive or networking tests which may be "