diff --git a/Engine/source/T3D/lightAnimData.cpp b/Engine/source/T3D/lightAnimData.cpp index b61d2b47d9..c5ef93b0f2 100644 --- a/Engine/source/T3D/lightAnimData.cpp +++ b/Engine/source/T3D/lightAnimData.cpp @@ -190,13 +190,15 @@ void LightAnimData::AnimValue::updateKey() } template -bool LightAnimData::AnimValue::animate( F32 time, F32 *output ) +bool LightAnimData::AnimValue::animate(F32 time, F32 *output, bool multiply) { F32 scaledTime, lerpFactor, valueRange, keyFrameLerp; U32 posFrom, posTo; S32 keyFrameFrom, keyFrameTo; F32 initialValue = *output; - + if (!multiply) + initialValue = 1; + bool wasAnimated = false; for ( U32 i=0; i < COUNT; i++ ) @@ -305,6 +307,6 @@ void LightAnimData::animate( LightInfo *lightInfo, LightAnimState *state ) lightInfo->setColor( color ); F32 brightness = state->brightness; - mBrightness.animate( time, &brightness ); + mBrightness.animate( time, &brightness, true ); lightInfo->setBrightness( brightness ); } diff --git a/Engine/source/T3D/lightAnimData.h b/Engine/source/T3D/lightAnimData.h index 69b2ff65df..d8c933674a 100644 --- a/Engine/source/T3D/lightAnimData.h +++ b/Engine/source/T3D/lightAnimData.h @@ -151,7 +151,7 @@ class LightAnimData : public SimDataBlock /// Performs the animation returning the results in the output if /// the time scale is greater than zero. /// @return Returns true if the animation was performed. - bool animate( F32 time, F32 *output ); + bool animate(F32 time, F32 *output, bool multiply = false); /// Called when the key string is changed to update the /// key length and time scale. diff --git a/Engine/source/T3D/physics/bullet/btBody.cpp b/Engine/source/T3D/physics/bullet/btBody.cpp index 77c3b81159..95625d5203 100644 --- a/Engine/source/T3D/physics/bullet/btBody.cpp +++ b/Engine/source/T3D/physics/bullet/btBody.cpp @@ -378,3 +378,25 @@ void BtBody::setSimulationEnabled( bool enabled ) mIsEnabled = enabled; } + +void BtBody::moveKinematicTo(const MatrixF &transform) +{ + AssertFatal(mActor, "BtBody::moveKinematicTo - The actor is null!"); + + U32 bodyflags = mActor->getCollisionFlags(); + const bool isKinematic = bodyflags & BF_KINEMATIC; + if (!isKinematic) + { + Con::errorf("BtBody::moveKinematicTo is only for kinematic bodies."); + return; + } + + if (mCenterOfMass) + { + MatrixF xfm; + xfm.mul(transform, *mCenterOfMass); + mActor->setCenterOfMassTransform(btCast(xfm)); + } + else + mActor->setCenterOfMassTransform(btCast(transform)); +} \ No newline at end of file diff --git a/Engine/source/T3D/physics/bullet/btBody.h b/Engine/source/T3D/physics/bullet/btBody.h index 0f1ab669cf..fa6561c27a 100644 --- a/Engine/source/T3D/physics/bullet/btBody.h +++ b/Engine/source/T3D/physics/bullet/btBody.h @@ -111,6 +111,8 @@ class BtBody : public PhysicsBody F32 staticFriction ); virtual void applyCorrection( const MatrixF &xfm ); virtual void applyImpulse( const Point3F &origin, const Point3F &force ); + virtual void moveKinematicTo(const MatrixF &xfm); + }; #endif // _T3D_PHYSICS_BTBODY_H_ diff --git a/Engine/source/T3D/physics/bullet/btPlayer.cpp b/Engine/source/T3D/physics/bullet/btPlayer.cpp index 6e22b0cf81..793f6053cb 100644 --- a/Engine/source/T3D/physics/bullet/btPlayer.cpp +++ b/Engine/source/T3D/physics/bullet/btPlayer.cpp @@ -71,6 +71,7 @@ void BtPlayer::init( const char *type, mObject = obj; mWorld = (BtWorld*)world; + mSlopeAngle = runSurfaceCos; mStepHeight = stepHeight; //if ( dStricmp( type, "Capsule" ) == 0 ) @@ -102,6 +103,17 @@ Point3F BtPlayer::move( const VectorF &disp, CollisionList &outCol ) { AssertFatal( mGhostObject, "BtPlayer::move - The controller is null!" ); + if (!mWorld->isEnabled()) + { + btTransform currentTrans = mGhostObject->getWorldTransform(); + btVector3 currentPos = currentTrans.getOrigin(); + + Point3F returnPos = btCast(currentPos); + + returnPos.z -= mOriginOffset; + return returnPos; + } + // First recover from any penetrations from the previous tick. U32 numPenetrationLoops = 0; bool touchingContact = false; @@ -305,16 +317,9 @@ bool BtPlayer::_sweep( btVector3 *inOutCurrPos, const btVector3 &disp, Collision col.normal = btCast( callback.m_hitNormalWorld ); col.object = PhysicsUserData::getObject( callback.m_hitCollisionObject->getUserPointer() ); - if (disp.z() < 0.0f) - { - // We're sweeping down as part of the stepping routine. In this - // case we want to have the collision normal only point in the opposite direction. - // i.e. up If we include the sideways part of the normal then the Player class - // velocity calculations using this normal will affect the player's forwards - // momentum. This is especially noticable on stairs as the rounded bottom of - // the capsule slides up the corner of a stair. - col.normal.set(0.0f, 0.0f, 1.0f); - } + F32 vd = col.normal.z; + if (vd < mSlopeAngle) + return false; } return true; diff --git a/Engine/source/T3D/physics/bullet/btPlayer.h b/Engine/source/T3D/physics/bullet/btPlayer.h index 388035431c..2ad89a946a 100644 --- a/Engine/source/T3D/physics/bullet/btPlayer.h +++ b/Engine/source/T3D/physics/bullet/btPlayer.h @@ -57,6 +57,10 @@ class BtPlayer : public PhysicsPlayer /// F32 mOriginOffset; + /// + F32 mSlopeAngle; + /// + /// F32 mStepHeight; /// diff --git a/Engine/source/T3D/physics/physicsBody.h b/Engine/source/T3D/physics/physicsBody.h index 15e94bcbd3..a5250dea65 100644 --- a/Engine/source/T3D/physics/physicsBody.h +++ b/Engine/source/T3D/physics/physicsBody.h @@ -113,6 +113,10 @@ class PhysicsBody : public PhysicsObject /// virtual void applyImpulse( const Point3F &origin, const Point3F &force ) = 0; + + /// + virtual void moveKinematicTo(const MatrixF &xfm) = 0; + }; diff --git a/Engine/source/T3D/physics/physx3/px3Body.cpp b/Engine/source/T3D/physics/physx3/px3Body.cpp index 026309f088..e2fc3916fd 100644 --- a/Engine/source/T3D/physics/physx3/px3Body.cpp +++ b/Engine/source/T3D/physics/physx3/px3Body.cpp @@ -417,3 +417,22 @@ void Px3Body::applyImpulse( const Point3F &origin, const Point3F &force ) } +void Px3Body::moveKinematicTo(const MatrixF &transform) +{ + AssertFatal(mActor, "Px3Body::moveKinematicTo - The actor is null!"); + + const bool isKinematic = mBodyFlags & BF_KINEMATIC; + if (!isKinematic) + { + Con::errorf("Px3Body::moveKinematicTo is only for kinematic bodies."); + return; + } + + mWorld->lockScene(); + + physx::PxRigidDynamic *actor = mActor->is(); + actor->setKinematicTarget(px3Cast(transform)); + + mWorld->unlockScene(); +} + diff --git a/Engine/source/T3D/physics/physx3/px3Body.h b/Engine/source/T3D/physics/physx3/px3Body.h index 79096f57b1..223418c350 100644 --- a/Engine/source/T3D/physics/physx3/px3Body.h +++ b/Engine/source/T3D/physics/physx3/px3Body.h @@ -117,6 +117,8 @@ class Px3Body : public PhysicsBody F32 staticFriction ); virtual void applyCorrection( const MatrixF &xfm ); virtual void applyImpulse( const Point3F &origin, const Point3F &force ); + virtual void moveKinematicTo(const MatrixF &xfm); + }; #endif // _PX3BODY_H_ diff --git a/Engine/source/T3D/physics/physx3/px3Player.cpp b/Engine/source/T3D/physics/physx3/px3Player.cpp index e831c939c4..10dc65e86c 100644 --- a/Engine/source/T3D/physics/physx3/px3Player.cpp +++ b/Engine/source/T3D/physics/physx3/px3Player.cpp @@ -329,3 +329,33 @@ Box3F Px3Player::getWorldBounds() return px3Cast( bounds ); } +bool Px3Player::testSpacials(const Point3F &nPos, const Point3F &nSize) const +{ + F32 offset = nSize.z * 0.5f; + F32 radius = getMax(nSize.x, nSize.y) * 0.5f - mSkinWidth; + F32 height = (nSize.z - (radius * 2.0f)) * 0.5f; + height -= mSkinWidth * 2.0f; + physx::PxCapsuleGeometry geom(radius, height); + + physx::PxVec3 pos(nPos.x, nPos.y, nPos.z + offset); + physx::PxQuat orientation(Float_HalfPi, physx::PxVec3(0.0f, 1.0f, 0.0f)); + + physx::PxOverlapBuffer hit; + physx::PxQueryFilterData queryFilter(physx::PxQueryFlag::eANY_HIT | physx::PxQueryFlag::eSTATIC | physx::PxQueryFlag::eDYNAMIC); + queryFilter.data.word0 = PX3_DEFAULT; + bool hasHit = mWorld->getScene()->overlap(geom, physx::PxTransform(pos, orientation), hit, queryFilter); + + return !hasHit; // Return true if there are no overlapping objects +} + +void Px3Player::setSpacials(const Point3F &nPos, const Point3F &nSize) +{ + mOriginOffset = nSize.z * 0.5f; + F32 radius = getMax(nSize.x, nSize.y) * 0.5f - mSkinWidth; + 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/px3Player.h b/Engine/source/T3D/physics/physx3/px3Player.h index 55a1409cdb..bd0546663e 100644 --- a/Engine/source/T3D/physics/physx3/px3Player.h +++ b/Engine/source/T3D/physics/physx3/px3Player.h @@ -94,8 +94,8 @@ class Px3Player : public PhysicsPlayer, public physx::PxUserControllerHitReport PhysicsWorld *world ); virtual Point3F move( const VectorF &displacement, CollisionList &outCol ); virtual void findContact( SceneObject **contactObject, VectorF *contactNormal, Vector *outOverlapObjects ) const; - virtual bool testSpacials( const Point3F &nPos, const Point3F &nSize ) const { return true; } - virtual void setSpacials( const Point3F &nPos, const Point3F &nSize ) {} + virtual bool testSpacials( const Point3F &nPos, const Point3F &nSize ) const; + virtual void setSpacials( const Point3F &nPos, const Point3F &nSize ); virtual void enableCollision(); virtual void disableCollision(); }; diff --git a/Engine/source/T3D/physics/physx3/px3World.cpp b/Engine/source/T3D/physics/physx3/px3World.cpp index c073423e9e..ca5be23026 100644 --- a/Engine/source/T3D/physics/physx3/px3World.cpp +++ b/Engine/source/T3D/physics/physx3/px3World.cpp @@ -62,7 +62,8 @@ Px3World::Px3World(): mScene( NULL ), mIsEnabled( false ), mEditorTimeScale( 1.0f ), mAccumulator( 0 ), - mControllerManager( NULL ) + mControllerManager(NULL), + mIsSceneLocked(false) { } @@ -335,6 +336,62 @@ void Px3World::releaseWriteLock() //AssertFatal( mScene->isWritable(), "PhysX3World::releaseWriteLock() - We should have been writable now!" ); } +void Px3World::lockScenes() +{ + Px3World *world = dynamic_cast(PHYSICSMGR->getWorld("server")); + + if (world) + world->lockScene(); + + world = dynamic_cast(PHYSICSMGR->getWorld("client")); + + if (world) + world->lockScene(); +} + +void Px3World::unlockScenes() +{ + Px3World *world = dynamic_cast(PHYSICSMGR->getWorld("server")); + + if (world) + world->unlockScene(); + + world = dynamic_cast(PHYSICSMGR->getWorld("client")); + + if (world) + world->unlockScene(); +} + +void Px3World::lockScene() +{ + if (!mScene) + return; + + if (mIsSceneLocked) + { + Con::printf("Px3World: Attempting to lock a scene that is already locked."); + return; + } + + mScene->lockWrite(); + mIsSceneLocked = true; +} + +void Px3World::unlockScene() +{ + if (!mScene) + return; + + if (!mIsSceneLocked) + { + Con::printf("Px3World: Attempting to unlock a scene that is not locked."); + return; + } + + mScene->unlockWrite(); + mIsSceneLocked = false; +} + bool Px3World::castRay( const Point3F &startPnt, const Point3F &endPnt, RayInfo *ri, const Point3F &impulse ) { diff --git a/Engine/source/T3D/physics/physx3/px3World.h b/Engine/source/T3D/physics/physx3/px3World.h index a1235d160e..9556aac4b9 100644 --- a/Engine/source/T3D/physics/physx3/px3World.h +++ b/Engine/source/T3D/physics/physx3/px3World.h @@ -56,6 +56,7 @@ class Px3World : public PhysicsWorld bool mIsEnabled; bool mIsSimulating; bool mIsServer; + bool mIsSceneLocked; U32 mTickCount; ProcessList *mProcessList; F32 mEditorTimeScale; @@ -96,11 +97,15 @@ class Px3World : public PhysicsWorld void releaseWriteLock(); 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 setTiming(F32 stepTime,U32 maxIterations); + static void lockScenes(); + static void unlockScenes(); }; #endif // _PX3WORLD_H_ diff --git a/Engine/source/T3D/shapeBase.cpp b/Engine/source/T3D/shapeBase.cpp index 52ea070e37..6f40cc134d 100644 --- a/Engine/source/T3D/shapeBase.cpp +++ b/Engine/source/T3D/shapeBase.cpp @@ -4881,17 +4881,18 @@ DefineEngineMethod( ShapeBase, getTargetCount, S32, (),, "@see getTargetName()\n") { - ShapeBase *obj = dynamic_cast< ShapeBase* > ( object ); - if(obj) - { - // Try to use the client object (so we get the reskinned targets in the Material Editor) - if ((ShapeBase*)obj->getClientObject()) - obj = (ShapeBase*)obj->getClientObject(); + ShapeBase *obj = dynamic_cast< ShapeBase* > ( object ); + if(obj) + { + // Try to use the client object (so we get the reskinned targets in the Material Editor) + if ((ShapeBase*)obj->getClientObject()) + obj = (ShapeBase*)obj->getClientObject(); - return obj->getShapeInstance()->getTargetCount(); + if (obj->getShapeInstance() != NULL) + return obj->getShapeInstance()->getTargetCount(); } - - return -1; + + return -1; } DefineEngineMethod( ShapeBase, changeMaterial, void, ( const char* mapTo, Material* oldMat, Material* newMat ),, diff --git a/Engine/source/T3D/vehicles/vehicle.cpp b/Engine/source/T3D/vehicles/vehicle.cpp index 1f18b426f0..b6516fc3f4 100644 --- a/Engine/source/T3D/vehicles/vehicle.cpp +++ b/Engine/source/T3D/vehicles/vehicle.cpp @@ -46,6 +46,9 @@ #include "gfx/primBuilder.h" #include "gfx/gfxDrawUtil.h" #include "materials/materialDefinition.h" +#include "T3D/physics/physicsPlugin.h" +#include "T3D/physics/physicsBody.h" +#include "T3D/physics/physicsCollision.h" namespace { @@ -203,7 +206,8 @@ VehicleData::VehicleData() dMemset(waterSound, 0, sizeof(waterSound)); collDamageThresholdVel = 20; - collDamageMultiplier = 0.05f; + collDamageMultiplier = 0.05f; + enablePhysicsRep = true; } @@ -315,6 +319,7 @@ void VehicleData::packData(BitStream* stream) stream->write(softSplashSoundVel); stream->write(medSplashSoundVel); stream->write(hardSplashSoundVel); + stream->write(enablePhysicsRep); // write the water sound profiles for(i = 0; i < MaxSounds; i++) @@ -411,6 +416,7 @@ void VehicleData::unpackData(BitStream* stream) stream->read(&softSplashSoundVel); stream->read(&medSplashSoundVel); stream->read(&hardSplashSoundVel); + stream->read(&enablePhysicsRep); // write the water sound profiles for(i = 0; i < MaxSounds; i++) @@ -465,6 +471,11 @@ void VehicleData::unpackData(BitStream* stream) void VehicleData::initPersistFields() { + addGroup("Physics"); + addField("enablePhysicsRep", TypeBool, Offset(enablePhysicsRep, VehicleData), + "@brief Creates a representation of the object in the physics plugin.\n"); + endGroup("Physics"); + addField( "jetForce", TypeF32, Offset(jetForce, VehicleData), "@brief Additional force applied to the vehicle when it is jetting.\n\n" "For WheeledVehicles, the force is applied in the forward direction. For " @@ -682,6 +693,8 @@ Vehicle::Vehicle() mWorkingQueryBox.minExtents.set(-1e9f, -1e9f, -1e9f); mWorkingQueryBox.maxExtents.set(-1e9f, -1e9f, -1e9f); mWorkingQueryBoxCountDown = sWorkingQueryBoxStaleThreshold; + + mPhysicsRep = NULL; } U32 Vehicle::getCollisionMask() @@ -695,6 +708,25 @@ Point3F Vehicle::getVelocity() const return mRigid.linVelocity; } +void Vehicle::_createPhysics() +{ + SAFE_DELETE(mPhysicsRep); + + if (!PHYSICSMGR || !mDataBlock->enablePhysicsRep) + return; + + TSShape *shape = mShapeInstance->getShape(); + PhysicsCollision *colShape = NULL; + colShape = shape->buildColShape(false, getScale()); + + if (colShape) + { + PhysicsWorld *world = PHYSICSMGR->getWorld(isServerObject() ? "server" : "client"); + mPhysicsRep = PHYSICSMGR->createBody(); + mPhysicsRep->init(colShape, 0, PhysicsBody::BF_KINEMATIC, this, world); + mPhysicsRep->setTransform(getTransform()); + } +} //---------------------------------------------------------------------------- bool Vehicle::onAdd() @@ -776,11 +808,15 @@ bool Vehicle::onAdd() mConvex.box.maxExtents.convolve(mObjScale); mConvex.findNodeTransform(); + _createPhysics(); + return true; } void Vehicle::onRemove() { + SAFE_DELETE(mPhysicsRep); + U32 i=0; for( i=0; ienablePhysicsRep is false as mPhysicsRep will be NULL if it is + if (mPhysicsRep) + mPhysicsRep->moveKinematicTo(getTransform()); } } diff --git a/Engine/source/T3D/vehicles/vehicle.h b/Engine/source/T3D/vehicles/vehicle.h index 695c166861..dd8619fd66 100644 --- a/Engine/source/T3D/vehicles/vehicle.h +++ b/Engine/source/T3D/vehicles/vehicle.h @@ -127,6 +127,8 @@ struct VehicleData: public ShapeBaseData F32 splashFreqMod; F32 splashVelEpsilon; + bool enablePhysicsRep; + // VehicleData(); bool preload(bool server, String &errorStr); @@ -142,6 +144,7 @@ struct VehicleData: public ShapeBaseData //---------------------------------------------------------------------------- +class PhysicsBody; class Vehicle: public ShapeBase { @@ -177,6 +180,8 @@ class Vehicle: public ShapeBase Point3F cameraRotVec; }; + PhysicsBody *mPhysicsRep; + StateDelta mDelta; S32 mPredictionCount; ///< Number of ticks to predict VehicleData* mDataBlock; @@ -262,6 +267,8 @@ class Vehicle: public ShapeBase bool onAdd(); void onRemove(); + void _createPhysics(); + /// Interpolates between move ticks @see processTick /// @param dt Change in time between the last call and this call to the function void interpolateTick(F32 dt); diff --git a/Engine/source/console/consoleTypes.h b/Engine/source/console/consoleTypes.h index c026b8e1ac..ab5b97d62f 100644 --- a/Engine/source/console/consoleTypes.h +++ b/Engine/source/console/consoleTypes.h @@ -74,6 +74,8 @@ DefineConsoleType( TypeCommand, String ) DefineConsoleType( TypeFilename, const char * ) DefineConsoleType( TypeStringFilename, String ) +DefineConsoleType(TypeRotationF, RotationF) + /// A universally unique identifier. DefineConsoleType( TypeUUID, Torque::UUID ) diff --git a/Engine/source/gfx/gfxDrawUtil.cpp b/Engine/source/gfx/gfxDrawUtil.cpp index 9598220001..42b146a10c 100644 --- a/Engine/source/gfx/gfxDrawUtil.cpp +++ b/Engine/source/gfx/gfxDrawUtil.cpp @@ -1015,7 +1015,7 @@ void GFXDrawUtil::_drawSolidPolyhedron( const GFXStateBlockDesc &desc, const Any // Allocate a temp buffer for the face indices. - const U32 numIndices = poly.getNumEdges() * 2; + const U32 numIndices = poly.getNumEdges() * 3; const U32 numPlanes = poly.getNumPlanes(); GFXPrimitiveBufferHandle prims( mDevice, numIndices, 0, GFXBufferTypeVolatile ); diff --git a/Engine/source/gfx/gl/gfxGLCardProfiler.cpp b/Engine/source/gfx/gl/gfxGLCardProfiler.cpp index 46119253bb..760a0d5ed7 100644 --- a/Engine/source/gfx/gl/gfxGLCardProfiler.cpp +++ b/Engine/source/gfx/gl/gfxGLCardProfiler.cpp @@ -56,54 +56,32 @@ void GFXGLCardProfiler::setupCardCapabilities() { GLint maxTexSize; glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxTexSize); - - const char* versionString = reinterpret_cast(glGetString(GL_VERSION)); - F32 glVersion = dAtof(versionString); // OpenGL doesn't have separate maximum width/height. setCapability("maxTextureWidth", maxTexSize); setCapability("maxTextureHeight", maxTexSize); setCapability("maxTextureSize", maxTexSize); - // If extensions haven't been inited, we're in trouble here. - bool suppVBO = (gglHasExtension(ARB_vertex_buffer_object) || glVersion >= 1.499f); - setCapability("GL::suppVertexBufferObject", suppVBO); + // Check for anisotropic filtering support. + setCapability("GL_EXT_texture_filter_anisotropic", gglHasExtension(EXT_texture_filter_anisotropic)); - // check if render to texture supported is available - bool suppRTT = gglHasExtension(EXT_framebuffer_object); - setCapability("GL::suppRenderTexture", suppRTT); - - bool suppBlit = gglHasExtension(EXT_framebuffer_blit); - setCapability("GL::suppRTBlit", suppBlit); - - bool suppFloatTex = gglHasExtension(ARB_texture_float); - setCapability("GL::suppFloatTexture", suppFloatTex); + // Check for buffer storage + setCapability("GL_ARB_buffer_storage", gglHasExtension(ARB_buffer_storage)); - // Check for anisotropic filtering support. - bool suppAnisotropic = gglHasExtension( EXT_texture_filter_anisotropic ); - setCapability( "GL::suppAnisotropic", suppAnisotropic ); - - // check to see if we have the fragment shader extension or the gl version is high enough for glsl to be core - // also check to see if the language version is high enough - F32 glslVersion = dAtof(reinterpret_cast(glGetString( GL_SHADING_LANGUAGE_VERSION))); - bool suppSPU = (gglHasExtension(ARB_fragment_shader) || glVersion >= 1.999f) && glslVersion >= 1.0999; - setCapability("GL::suppFragmentShader", suppSPU); - - bool suppAppleFence = gglHasExtension(APPLE_fence); - setCapability("GL::APPLE::suppFence", suppAppleFence); - - // When enabled, call glGenerateMipmapEXT() to generate mipmaps instead of relying on GL_GENERATE_MIPMAP - setCapability("GL::Workaround::needsExplicitGenerateMipmap", false); - // When enabled, binds and unbinds a texture target before doing the depth buffer copy. Failure to do - // so will cause a hard freeze on Mac OS 10.4 with a Radeon X1600 - setCapability("GL::Workaround::X1600DepthBufferCopy", false); - // When enabled, does not copy the last column and row of the depth buffer in a depth buffer copy. Failure - // to do so will cause a kernel panic on Mac OS 10.5(.1) with a Radeon HD 2600 (fixed in 10.5.2) - setCapability("GL::Workaround::HD2600DepthBufferCopy", false); - - // Certain Intel drivers have a divide by 0 crash if mipmaps are specified with - // glTexSubImage2D. - setCapability("GL::Workaround::noManualMips", false); + // Check for shader model 5.0 + setCapability("GL_ARB_gpu_shader5", gglHasExtension(ARB_gpu_shader5)); + + // Check for texture storage + setCapability("GL_ARB_texture_storage", gglHasExtension(ARB_texture_storage)); + + // Check for sampler objects + setCapability("GL_ARB_sampler_objects", gglHasExtension(ARB_sampler_objects)); + + // Check for copy image support + setCapability("GL_ARB_copy_image", gglHasExtension(ARB_copy_image)); + + // Check for vertex attrib binding + setCapability("GL_ARB_vertex_attrib_binding", gglHasExtension(ARB_vertex_attrib_binding)); } bool GFXGLCardProfiler::_queryCardCap(const String& query, U32& foundResult) diff --git a/Engine/source/gfx/gl/gfxGLCircularVolatileBuffer.h b/Engine/source/gfx/gl/gfxGLCircularVolatileBuffer.h index 6d7d0e4b11..a3d2cb1dde 100644 --- a/Engine/source/gfx/gl/gfxGLCircularVolatileBuffer.h +++ b/Engine/source/gfx/gl/gfxGLCircularVolatileBuffer.h @@ -20,7 +20,8 @@ class GLFenceRange } void init(U32 start, U32 end) - { + { + PROFILE_SCOPE(GFXGLQueryFence_issue); mStart = start; mEnd = end; mSync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0); @@ -35,7 +36,8 @@ class GLFenceRange } void wait() - { + { + PROFILE_SCOPE(GFXGLQueryFence_block); GLbitfield waitFlags = 0; GLuint64 waitDuration = 0; while( 1 ) @@ -158,7 +160,7 @@ class GLCircularVolatileBuffer const U32 cSizeInMB = 10; mBufferSize = (cSizeInMB << 20); - if( gglHasExtension(ARB_buffer_storage) ) + if( GFXGL->mCapabilities.bufferStorage ) { const GLbitfield flags = GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT; glBufferStorage(mBinding, mBufferSize, NULL, flags); @@ -198,7 +200,7 @@ class GLCircularVolatileBuffer outOffset = mBufferFreePos; - if( gglHasExtension(ARB_buffer_storage) ) + if( GFXGL->mCapabilities.bufferStorage ) { outPtr = (U8*)(mBufferPtr) + mBufferFreePos; } @@ -227,7 +229,7 @@ class GLCircularVolatileBuffer void unlock() { - if( gglHasExtension(ARB_buffer_storage) ) + if( GFXGL->mCapabilities.bufferStorage ) { return; } diff --git a/Engine/source/gfx/gl/gfxGLDevice.cpp b/Engine/source/gfx/gl/gfxGLDevice.cpp index f59e8ac920..190de2f5a8 100644 --- a/Engine/source/gfx/gl/gfxGLDevice.cpp +++ b/Engine/source/gfx/gl/gfxGLDevice.cpp @@ -140,10 +140,18 @@ void GFXGLDevice::initGLState() glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + // [JTH 5/6/2016] GLSL 1.50 is really SM 4.0 // Setting mPixelShaderVersion to 3.0 will allow Advanced Lighting to run. mPixelShaderVersion = 3.0; - mSupportsAnisotropic = mCardProfiler->queryProfile( "GL::suppAnisotropic" ); + // Set capability extensions. + mCapabilities.anisotropicFiltering = mCardProfiler->queryProfile("GL_EXT_texture_filter_anisotropic"); + mCapabilities.bufferStorage = mCardProfiler->queryProfile("GL_ARB_buffer_storage"); + mCapabilities.shaderModel5 = mCardProfiler->queryProfile("GL_ARB_gpu_shader5"); + mCapabilities.textureStorage = mCardProfiler->queryProfile("GL_ARB_texture_storage"); + mCapabilities.samplerObjects = mCardProfiler->queryProfile("GL_ARB_sampler_objects"); + mCapabilities.copyImage = mCardProfiler->queryProfile("GL_ARB_copy_image"); + mCapabilities.vertexAttributeBinding = mCardProfiler->queryProfile("GL_ARB_vertex_attrib_binding"); String vendorStr = (const char*)glGetString( GL_VENDOR ); if( vendorStr.find("NVIDIA", 0, String::NoCase | String::Left) != String::NPos) @@ -216,6 +224,9 @@ GFXGLDevice::GFXGLDevice(U32 adapterIndex) : mCurrentVB_Divisor[i] = 0; } + // Initiailize capabilities to false. + memset(&mCapabilities, 0, sizeof(GLCapabilities)); + loadGLCore(); GFXGLEnumTranslate::init(); @@ -325,6 +336,7 @@ void GFXGLDevice::resurrect() GFXVertexBuffer* GFXGLDevice::findVolatileVBO(U32 numVerts, const GFXVertexFormat *vertexFormat, U32 vertSize) { + PROFILE_SCOPE(GFXGLDevice_findVBPool); for(U32 i = 0; i < mVolatileVBs.size(); i++) if ( mVolatileVBs[i]->mNumVerts >= numVerts && mVolatileVBs[i]->mVertexFormat.isEqual( *vertexFormat ) && @@ -333,6 +345,7 @@ GFXVertexBuffer* GFXGLDevice::findVolatileVBO(U32 numVerts, const GFXVertexForma return mVolatileVBs[i]; // No existing VB, so create one + PROFILE_SCOPE(GFXGLDevice_createVBPool); StrongRefPtr buf(new GFXGLVertexBuffer(GFX, numVerts, vertexFormat, vertSize, GFXBufferTypeVolatile)); buf->registerResourceWithDevice(this); mVolatileVBs.push_back(buf); @@ -358,6 +371,7 @@ GFXVertexBuffer *GFXGLDevice::allocVertexBuffer( U32 numVerts, GFXBufferType bufferType, void* data ) { + PROFILE_SCOPE(GFXGLDevice_allocVertexBuffer); if(bufferType == GFXBufferTypeVolatile) return findVolatileVBO(numVerts, vertexFormat, vertSize); @@ -523,6 +537,7 @@ inline GLsizei GFXGLDevice::primCountToIndexCount(GFXPrimitiveType primType, U32 GFXVertexDecl* GFXGLDevice::allocVertexDecl( const GFXVertexFormat *vertexFormat ) { + PROFILE_SCOPE(GFXGLDevice_allocVertexDecl); typedef Map GFXGLVertexDeclMap; static GFXGLVertexDeclMap declMap; GFXGLVertexDeclMap::Iterator itr = declMap.find( (void*)vertexFormat->getDescription().c_str() ); // description string are interned, safe to use c_str() @@ -855,6 +870,7 @@ void GFXGLDevice::setShader(GFXShader *shader, bool force) void GFXGLDevice::setShaderConstBufferInternal(GFXShaderConstBuffer* buffer) { + PROFILE_SCOPE(GFXGLDevice_setShaderConstBufferInternal); static_cast(buffer)->activate(); } diff --git a/Engine/source/gfx/gl/gfxGLDevice.h b/Engine/source/gfx/gl/gfxGLDevice.h index 902bfb3f6c..fc37d32207 100644 --- a/Engine/source/gfx/gl/gfxGLDevice.h +++ b/Engine/source/gfx/gl/gfxGLDevice.h @@ -45,6 +45,18 @@ class GFXGLVertexDecl; class GFXGLDevice : public GFXDevice { public: + struct GLCapabilities + { + bool anisotropicFiltering; + bool bufferStorage; + bool shaderModel5; + bool textureStorage; + bool samplerObjects; + bool copyImage; + bool vertexAttributeBinding; + }; + GLCapabilities mCapabilities; + void zombify(); void resurrect(); GFXGLDevice(U32 adapterIndex); diff --git a/Engine/source/gfx/gl/gfxGLShader.cpp b/Engine/source/gfx/gl/gfxGLShader.cpp index 2e63c61fea..890a6c2c51 100644 --- a/Engine/source/gfx/gl/gfxGLShader.cpp +++ b/Engine/source/gfx/gl/gfxGLShader.cpp @@ -23,6 +23,7 @@ #include "platform/platform.h" #include "gfx/gl/gfxGLShader.h" #include "gfx/gl/gfxGLVertexAttribLocation.h" +#include "gfx/gl/gfxGLDevice.h" #include "core/frameAllocator.h" #include "core/stream/fileStream.h" @@ -344,6 +345,7 @@ void GFXGLShaderConstBuffer::set(GFXShaderConstHandle* handle, const MatrixF* ma void GFXGLShaderConstBuffer::activate() { + PROFILE_SCOPE(GFXGLShaderConstBuffer_activate); mShader->setConstantsFromBuffer(this); mWasLost = false; } @@ -394,6 +396,7 @@ void GFXGLShader::clearShaders() bool GFXGLShader::_init() { + PROFILE_SCOPE(GFXGLShader_Init); // Don't initialize empty shaders. if ( mVertexFile.isEmpty() && mPixelFile.isEmpty() ) return false; @@ -956,7 +959,7 @@ bool GFXGLShader::_loadShaderFromStream( GLuint shader, buffers.push_back( dStrdup( versionDecl ) ); lengths.push_back( dStrlen( versionDecl ) ); - if(gglHasExtension(ARB_gpu_shader5)) + if(GFXGL->mCapabilities.shaderModel5) { const char *extension = "#extension GL_ARB_gpu_shader5 : enable\r\n"; buffers.push_back( dStrdup( extension ) ); @@ -1013,6 +1016,7 @@ bool GFXGLShader::initShader( const Torque::Path &file, bool isVertex, const Vector ¯os ) { + PROFILE_SCOPE(GFXGLShader_CompileShader); GLuint activeShader = glCreateShader(isVertex ? GL_VERTEX_SHADER : GL_FRAGMENT_SHADER); if(isVertex) mVertexShader = activeShader; @@ -1072,6 +1076,7 @@ bool GFXGLShader::initShader( const Torque::Path &file, /// Returns our list of shader constants, the material can get this and just set the constants it knows about const Vector& GFXGLShader::getShaderConstDesc() const { + PROFILE_SCOPE(GFXGLShader_GetShaderConstants); return mConstants; } diff --git a/Engine/source/gfx/gl/gfxGLStateBlock.cpp b/Engine/source/gfx/gl/gfxGLStateBlock.cpp index 34f816dc90..9d446f27aa 100644 --- a/Engine/source/gfx/gl/gfxGLStateBlock.cpp +++ b/Engine/source/gfx/gl/gfxGLStateBlock.cpp @@ -39,7 +39,7 @@ GFXGLStateBlock::GFXGLStateBlock(const GFXStateBlockDesc& desc) : mDesc(desc), mCachedHashValue(desc.getHashValue()) { - if( !gglHasExtension(ARB_sampler_objects) ) + if( !GFXGL->mCapabilities.samplerObjects ) return; static Map mSamplersMap; @@ -88,6 +88,7 @@ const GFXStateBlockDesc& GFXGLStateBlock::getDesc() const /// @param oldState The current state, used to make sure we don't set redundant states on the device. Pass NULL to reset all states. void GFXGLStateBlock::activate(const GFXGLStateBlock* oldState) { + PROFILE_SCOPE(GFXGLStateBlock_Activate); // Big scary warning copied from Apple docs // http://developer.apple.com/documentation/GraphicsImaging/Conceptual/OpenGL-MacProgGuide/opengl_performance/chapter_13_section_2.html#//apple_ref/doc/uid/TP40001987-CH213-SW12 // Don't set a state that's already set. Once a feature is enabled, it does not need to be enabled again. @@ -165,7 +166,7 @@ void GFXGLStateBlock::activate(const GFXGLStateBlock* oldState) #undef CHECK_TOGGLE_STATE //sampler objects - if( gglHasExtension(ARB_sampler_objects) ) + if( GFXGL->mCapabilities.samplerObjects ) { for (U32 i = 0; i < getMin(getOwningDevice()->getNumSamplers(), (U32) TEXTURE_STAGE_COUNT); i++) { diff --git a/Engine/source/gfx/gl/gfxGLTextureManager.cpp b/Engine/source/gfx/gl/gfxGLTextureManager.cpp index 478465bf4d..1f8436dde4 100644 --- a/Engine/source/gfx/gl/gfxGLTextureManager.cpp +++ b/Engine/source/gfx/gl/gfxGLTextureManager.cpp @@ -146,7 +146,7 @@ void GFXGLTextureManager::innerCreateTexture( GFXGLTextureObject *retTex, glTexParameteri(binding, GL_TEXTURE_MAX_LEVEL, retTex->mMipLevels-1 ); - if( gglHasExtension(ARB_texture_storage) ) + if( GFXGL->mCapabilities.textureStorage ) { if(binding == GL_TEXTURE_2D) glTexStorage2D( retTex->getBinding(), retTex->mMipLevels, GFXGLTextureInternalFormat[format], width, height ); @@ -234,6 +234,7 @@ static void _fastTextureLoad(GFXGLTextureObject* texture, GBitmap* pDL) if(pDL->getFormat() == GFXFormatR8G8B8A8 || pDL->getFormat() == GFXFormatR8G8B8X8) { + PROFILE_SCOPE(Swizzle32_Upload); U8* pboMemory = (U8*)dMalloc(bufSize); GFX->getDeviceSwizzle32()->ToBuffer(pboMemory, pDL->getBits(0), bufSize); glBufferSubData(GL_PIXEL_UNPACK_BUFFER_ARB, 0, bufSize, pboMemory ); @@ -241,6 +242,7 @@ static void _fastTextureLoad(GFXGLTextureObject* texture, GBitmap* pDL) } else { + PROFILE_SCOPE(SwizzleNull_Upload); glBufferSubData(GL_PIXEL_UNPACK_BUFFER_ARB, 0, bufSize, pDL->getBits(0) ); } @@ -262,6 +264,7 @@ static void _slowTextureLoad(GFXGLTextureObject* texture, GBitmap* pDL) bool GFXGLTextureManager::_loadTexture(GFXTextureObject *aTexture, GBitmap *pDL) { + PROFILE_SCOPE(GFXGLTextureManager_loadTexture); GFXGLTextureObject *texture = static_cast(aTexture); AssertFatal(texture->getBinding() == GL_TEXTURE_1D || texture->getBinding() == GL_TEXTURE_2D, @@ -291,6 +294,8 @@ bool GFXGLTextureManager::_loadTexture(GFXTextureObject *aTexture, GBitmap *pDL) bool GFXGLTextureManager::_loadTexture(GFXTextureObject *aTexture, DDSFile *dds) { + PROFILE_SCOPE(GFXGLTextureManager_loadTextureDDS); + AssertFatal(!(dds->mFormat == GFXFormatDXT2 || dds->mFormat == GFXFormatDXT4), "GFXGLTextureManager::_loadTexture - OpenGL does not support DXT2 or DXT4 compressed textures"); GFXGLTextureObject* texture = static_cast(aTexture); @@ -304,10 +309,11 @@ bool GFXGLTextureManager::_loadTexture(GFXTextureObject *aTexture, DDSFile *dds) glBindTexture(texture->getBinding(), texture->getHandle()); texture->mFormat = dds->mFormat; U32 numMips = dds->mSurfaces[0]->mMips.size(); - if(GFX->getCardProfiler()->queryProfile("GL::Workaround::noManualMips")) - numMips = 1; + for(U32 i = 0; i < numMips; i++) { + PROFILE_SCOPE(GFXGLTexMan_loadSurface); + if(isCompressedFormat(dds->mFormat)) { if((!isPow2(dds->getWidth()) || !isPow2(dds->getHeight())) && GFX->getCardProfiler()->queryProfile("GL::Workaround::noCompressedNPoTTextures")) @@ -344,6 +350,7 @@ bool GFXGLTextureManager::_loadTexture(GFXTextureObject *aTexture, DDSFile *dds) bool GFXGLTextureManager::_loadTexture(GFXTextureObject *aTexture, void *raw) { + PROFILE_SCOPE(GFXGLTextureManager_loadTextureRaw); if(aTexture->getDepth() < 1) return false; diff --git a/Engine/source/gfx/gl/gfxGLTextureObject.cpp b/Engine/source/gfx/gl/gfxGLTextureObject.cpp index ed229e5d90..9c60229705 100644 --- a/Engine/source/gfx/gl/gfxGLTextureObject.cpp +++ b/Engine/source/gfx/gl/gfxGLTextureObject.cpp @@ -96,6 +96,9 @@ void GFXGLTextureObject::unlock(U32 mipLevel) if(!mLockedRect.bits) return; + // I know this is in unlock, but in GL we actually do our submission in unlock. + PROFILE_SCOPE(GFXGLTextureObject_lockRT); + PRESERVE_TEXTURE(mBinding); glBindTexture(mBinding, mHandle); glBindBuffer(GL_PIXEL_UNPACK_BUFFER_ARB, mBuffer); @@ -175,6 +178,7 @@ bool GFXGLTextureObject::copyToBmp(GBitmap * bmp) glGetTexImage(mBinding, 0, GFXGLTextureFormat[mFormat], GFXGLTextureType[mFormat], orig); + PROFILE_START(GFXGLTextureObject_copyToBmp_pixCopy); for(int i = 0; i < srcPixelCount; ++i) { dest[0] = orig[0]; @@ -186,6 +190,7 @@ bool GFXGLTextureObject::copyToBmp(GBitmap * bmp) orig += srcBytesPerPixel; dest += dstBytesPerPixel; } + PROFILE_END(); return true; } @@ -211,7 +216,7 @@ void GFXGLTextureObject::bind(U32 textureUnit) glBindTexture(mBinding, mHandle); GFXGL->getOpenglCache()->setCacheBindedTex(textureUnit, mBinding, mHandle); - if( gglHasExtension(ARB_sampler_objects) ) + if(GFXGL->mCapabilities.samplerObjects) return; GFXGLStateBlockRef sb = mGLDevice->getCurrentStateBlock(); @@ -298,8 +303,8 @@ void GFXGLTextureObject::reloadFromCache() else if(mBinding == GL_TEXTURE_1D) glTexSubImage1D(mBinding, 0, 0, (mTextureSize.x > 1 ? mTextureSize.x : mTextureSize.y), GFXGLTextureFormat[mFormat], GFXGLTextureType[mFormat], mZombieCache); - if(GFX->getCardProfiler()->queryProfile("GL::Workaround::needsExplicitGenerateMipmap") && mMipLevels != 1) - glGenerateMipmapEXT(mBinding); + if(mMipLevels != 1) + glGenerateMipmap(mBinding); delete[] mZombieCache; mZombieCache = NULL; diff --git a/Engine/source/gfx/gl/gfxGLTextureTarget.cpp b/Engine/source/gfx/gl/gfxGLTextureTarget.cpp index 2022651072..384871dd9a 100644 --- a/Engine/source/gfx/gl/gfxGLTextureTarget.cpp +++ b/Engine/source/gfx/gl/gfxGLTextureTarget.cpp @@ -410,7 +410,7 @@ void GFXGLTextureTarget::resolveTo(GFXTextureObject* obj) AssertFatal(dynamic_cast(obj), "GFXGLTextureTarget::resolveTo - Incorrect type of texture, expected a GFXGLTextureObject"); GFXGLTextureObject* glTexture = static_cast(obj); - if( gglHasExtension(ARB_copy_image) && mTargets[Color0]->isCompatible(glTexture) ) + if( GFXGL->mCapabilities.copyImage && mTargets[Color0]->isCompatible(glTexture) ) { GLenum binding = mTargets[Color0]->getBinding(); binding = (binding >= GL_TEXTURE_CUBE_MAP_POSITIVE_X && binding <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z) ? GL_TEXTURE_CUBE_MAP : binding; diff --git a/Engine/source/gfx/gl/gfxGLVertexBuffer.cpp b/Engine/source/gfx/gl/gfxGLVertexBuffer.cpp index 132172c1ad..2cf4cb6255 100644 --- a/Engine/source/gfx/gl/gfxGLVertexBuffer.cpp +++ b/Engine/source/gfx/gl/gfxGLVertexBuffer.cpp @@ -78,7 +78,7 @@ void GFXGLVertexBuffer::lock( U32 vertexStart, U32 vertexEnd, void **vertexPtr ) if( mBufferType == GFXBufferTypeVolatile ) { AssertFatal(vertexStart == 0, ""); - if( gglHasExtension(ARB_vertex_attrib_binding) ) + if( GFXGL->mCapabilities.vertexAttributeBinding ) { getCircularVolatileVertexBuffer()->lock( mNumVerts * mVertexSize, 0, mBufferOffset, *vertexPtr ); } @@ -136,7 +136,7 @@ void GFXGLVertexBuffer::prepare() void GFXGLVertexBuffer::prepare(U32 stream, U32 divisor) { - if( gglHasExtension(ARB_vertex_attrib_binding) ) + if( GFXGL->mCapabilities.vertexAttributeBinding ) { glBindVertexBuffer( stream, mBuffer, mBufferOffset, mVertexSize ); glVertexBindingDivisor( stream, divisor ); diff --git a/Engine/source/gfx/gl/gfxGLVertexDecl.cpp b/Engine/source/gfx/gl/gfxGLVertexDecl.cpp index 10eda4401f..948a2b2de7 100644 --- a/Engine/source/gfx/gl/gfxGLVertexDecl.cpp +++ b/Engine/source/gfx/gl/gfxGLVertexDecl.cpp @@ -15,7 +15,7 @@ void GFXGLVertexDecl::init(const GFXVertexFormat *format) void GFXGLVertexDecl::prepareVertexFormat() const { AssertFatal(mFormat, "GFXGLVertexDecl - Not inited"); - if( gglHasExtension(ARB_vertex_attrib_binding) ) + if( GFXGL->mCapabilities.vertexAttributeBinding ) { for ( U32 i=0; i < glVerticesFormat.size(); i++ ) { @@ -36,7 +36,7 @@ void GFXGLVertexDecl::prepareBuffer_old(U32 stream, GLint mBuffer, GLint mDiviso PROFILE_SCOPE(GFXGLVertexDecl_prepare); AssertFatal(mFormat, "GFXGLVertexDecl - Not inited"); - if( gglHasExtension(ARB_vertex_attrib_binding) ) + if( GFXGL->mCapabilities.vertexAttributeBinding ) return; // Bind the buffer... diff --git a/Engine/source/gfx/gl/gfxGLWindowTarget.cpp b/Engine/source/gfx/gl/gfxGLWindowTarget.cpp index 5f8808cae0..116ad75e35 100644 --- a/Engine/source/gfx/gl/gfxGLWindowTarget.cpp +++ b/Engine/source/gfx/gl/gfxGLWindowTarget.cpp @@ -78,7 +78,7 @@ void GFXGLWindowTarget::resolveTo(GFXTextureObject* obj) AssertFatal(dynamic_cast(obj), "GFXGLTextureTarget::resolveTo - Incorrect type of texture, expected a GFXGLTextureObject"); GFXGLTextureObject* glTexture = static_cast(obj); - if( gglHasExtension(ARB_copy_image) ) + if( GFXGL->mCapabilities.copyImage ) { if(mBackBufferColorTex.getWidth() == glTexture->getWidth() && mBackBufferColorTex.getHeight() == glTexture->getHeight() diff --git a/Engine/source/gui/editor/inspector/field.cpp b/Engine/source/gui/editor/inspector/field.cpp index ac72b2e043..45aa1b2b0d 100644 --- a/Engine/source/gui/editor/inspector/field.cpp +++ b/Engine/source/gui/editor/inspector/field.cpp @@ -284,7 +284,8 @@ void GuiInspectorField::setData( const char* data, bool callbacks ) || type == TypeMatrixPosition || type == TypeMatrixRotation || type == TypeBox3F - || type == TypeRectUV ) + || type == TypeRectUV + || type == TypeRotationF) { //TODO: we should actually take strings into account and not chop things up between quotes diff --git a/Engine/source/materials/materialFeatureTypes.cpp b/Engine/source/materials/materialFeatureTypes.cpp index 85fbd2895b..513474c778 100644 --- a/Engine/source/materials/materialFeatureTypes.cpp +++ b/Engine/source/materials/materialFeatureTypes.cpp @@ -30,7 +30,6 @@ ImplementFeatureType( MFT_VertTransform, MFG_Transform, 0, true ); ImplementFeatureType( MFT_TexAnim, MFG_PreTexture, 1.0f, true ); ImplementFeatureType( MFT_Parallax, MFG_PreTexture, 2.0f, true ); -ImplementFeatureType( MFT_DiffuseVertColor, MFG_PreTexture, 3.0f, true ); ImplementFeatureType( MFT_AccuScale, MFG_PreTexture, 4.0f, true ); ImplementFeatureType( MFT_AccuDirection, MFG_PreTexture, 4.0f, true ); @@ -42,6 +41,7 @@ ImplementFeatureType( MFT_DiffuseMap, MFG_Texture, 2.0f, true ); ImplementFeatureType( MFT_OverlayMap, MFG_Texture, 3.0f, true ); ImplementFeatureType( MFT_DetailMap, MFG_Texture, 4.0f, true ); ImplementFeatureType( MFT_DiffuseColor, MFG_Texture, 5.0f, true ); +ImplementFeatureType( MFT_DiffuseVertColor, MFG_Texture, 6.0f, true ); ImplementFeatureType( MFT_AlphaTest, MFG_Texture, 7.0f, true ); ImplementFeatureType( MFT_SpecularMap, MFG_Texture, 8.0f, true ); ImplementFeatureType( MFT_NormalMap, MFG_Texture, 9.0f, true ); diff --git a/Engine/source/materials/processedShaderMaterial.cpp b/Engine/source/materials/processedShaderMaterial.cpp index 6ff609ebeb..cd230ef534 100644 --- a/Engine/source/materials/processedShaderMaterial.cpp +++ b/Engine/source/materials/processedShaderMaterial.cpp @@ -1153,7 +1153,8 @@ void ProcessedShaderMaterial::_setShaderConstants(SceneRenderState * state, cons // Deferred Shading: Determine Material Info Flags S32 matInfoFlags = - (mMaterial->mEmissive[stageNum] ? 1 : 0); + (mMaterial->mEmissive[stageNum] ? 1 : 0) | //emissive + (mMaterial->mSubSurface[stageNum] ? 2 : 0); //subsurface mMaterial->mMatInfoFlags[stageNum] = matInfoFlags / 255.0f; shaderConsts->setSafe(handles->mMatInfoFlagsSC, mMaterial->mMatInfoFlags[stageNum]); if( handles->mAccuScaleSC->isValid() ) diff --git a/Engine/source/math/mBox.h b/Engine/source/math/mBox.h index 379d5291a1..b81775bb0e 100644 --- a/Engine/source/math/mBox.h +++ b/Engine/source/math/mBox.h @@ -415,7 +415,7 @@ inline void Box3F::extend(const Point3F & p) #define EXTEND_AXIS(AXIS) \ if (p.AXIS < minExtents.AXIS) \ minExtents.AXIS = p.AXIS; \ -else if (p.AXIS > maxExtents.AXIS) \ +if (p.AXIS > maxExtents.AXIS) \ maxExtents.AXIS = p.AXIS; EXTEND_AXIS(x) diff --git a/Engine/source/math/mMath.h b/Engine/source/math/mMath.h index a1e070db77..4710f6bf0f 100644 --- a/Engine/source/math/mMath.h +++ b/Engine/source/math/mMath.h @@ -48,5 +48,8 @@ #ifndef _MEASE_H_ #include "math/mEase.h" #endif +#ifndef MROTATION_H +#include "math/mRotation.h" +#endif #endif //_MMATH_H_ diff --git a/Engine/source/math/mPolyhedron.impl.h b/Engine/source/math/mPolyhedron.impl.h index ef74995abd..796f113506 100644 --- a/Engine/source/math/mPolyhedron.impl.h +++ b/Engine/source/math/mPolyhedron.impl.h @@ -385,6 +385,8 @@ U32 PolyhedronImpl< Base >::extractFace( U32 plane, IndexType* outIndices, U32 m // so it should be sufficiently fast to just loop over the original // set. + U32 indexItr = 0; + do { // Add the vertex for the current edge. @@ -392,7 +394,15 @@ U32 PolyhedronImpl< Base >::extractFace( U32 plane, IndexType* outIndices, U32 m if( idx >= maxOutIndices ) return 0; - outIndices[ idx ++ ] = currentVertex; + ++indexItr; + + if (indexItr >= 3) + { + outIndices[idx++] = firstEdge->vertex[0]; + indexItr = 0; + } + + outIndices[idx++] = currentVertex; // Look for next edge. diff --git a/Engine/source/math/mRotation.cpp b/Engine/source/math/mRotation.cpp new file mode 100644 index 0000000000..69dfca35d0 --- /dev/null +++ b/Engine/source/math/mRotation.cpp @@ -0,0 +1,348 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2012 GarageGames, LLC +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION 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 "math/mRotation.h" +#include "console/console.h" +#include "console/engineAPI.h" + +#ifdef TORQUE_TESTS_ENABLED +#include "testing/unitTesting.h" +#endif + +//==================================================================== +//Eulers setup +//==================================================================== +RotationF::RotationF(EulerF _euler, UnitFormat format) +{ + set(_euler.x, _euler.y, _euler.z, format); +} + +RotationF::RotationF(F32 _x, F32 _y, F32 _z, UnitFormat format) +{ + set(_x, _y, _z, format); +} + +void RotationF::set(EulerF _euler, UnitFormat format) +{ + x = format == Degrees ? mDegToRad(_euler.x) : _euler.x; + y = format == Degrees ? mDegToRad(_euler.y) : _euler.y; + z = format == Degrees ? mDegToRad(_euler.z) : _euler.z; + + mRotationType = Euler; +} + +void RotationF::set(F32 _x, F32 _y, F32 _z, UnitFormat format) +{ + EulerF tempEul; + if (format == Degrees) + { + tempEul.set(mDegToRad(_x), mDegToRad(_y), mDegToRad(_z)); + } + else + { + tempEul.set(_x, _y, _z); + } + + set(tempEul); +} + +//==================================================================== +//AxisAngle setup +//==================================================================== +RotationF::RotationF(AngAxisF _aa, UnitFormat format) +{ + set(_aa, format); +} + +void RotationF::set(AngAxisF _aa, UnitFormat format) +{ + x = _aa.axis.x; + y = _aa.axis.y; + z = _aa.axis.z; + + w = format == Degrees ? mDegToRad(_aa.angle) : _aa.angle; + + mRotationType = AxisAngle; +} + +//==================================================================== +//QuatF setup +//==================================================================== +RotationF::RotationF(QuatF _quat) +{ + set(_quat); +} + +void RotationF::set(QuatF _quat) +{ + AngAxisF tmpAA; + tmpAA.set(_quat); + + set(tmpAA); +} + +//==================================================================== +//MatrixF setup +//==================================================================== +RotationF::RotationF(MatrixF _mat) +{ + set(_mat); +} + +void RotationF::set(MatrixF _mat) +{ + set(_mat.toEuler()); +} + +// +inline F32 RotationF::len() const +{ + return asEulerF().len(); +} + +inline void RotationF::interpolate(const RotationF& _from, const RotationF& _to, F32 _factor) +{ + QuatF tmpQuat; + + tmpQuat.interpolate(_from.asQuatF(), _to.asQuatF(), _factor); + + set(tmpQuat); +} + +void RotationF::lookAt(const Point3F& _origin, const Point3F& _target, const Point3F& _up) +{ + MatrixF mat; + + VectorF newForward = _target - _origin; + newForward.normalize(); + + VectorF up(0.0f, 0.0f, 1.0f); + VectorF axisX; + VectorF axisY = newForward; + VectorF axisZ; + + if (_up != VectorF::Zero) + up = _up; + + // Validate and normalize input: + F32 lenSq; + lenSq = axisY.lenSquared(); + if (lenSq < 0.000001f) + { + //degenerate forward vector + axisY.set(0.0f, 1.0f, 0.0f); + } + else + { + axisY /= mSqrt(lenSq); + } + + + lenSq = up.lenSquared(); + if (lenSq < 0.000001f) + { + //degenerate up vector - too small + up.set(0.0f, 0.0f, 1.0f); + } + else + { + up /= mSqrt(lenSq); + } + + if (fabsf(mDot(up, axisY)) > 0.9999f) + { + //degenerate up vector - same as forward + F32 tmp = up.x; + up.x = -up.y; + up.y = up.z; + up.z = tmp; + } + + // construct the remaining axes: + mCross(axisY, up, &axisX); + mCross(axisX, axisY, &axisZ); + + mat.setColumn(0, axisX); + mat.setColumn(1, axisY); + mat.setColumn(2, axisZ); + + set(mat); +} + +//======================================================== +EulerF RotationF::asEulerF(UnitFormat _format) const +{ + if (mRotationType == Euler) + { + if (_format == Degrees) + { + return EulerF(mRadToDeg(x), mRadToDeg(y), mRadToDeg(z)); + } + else + { + return EulerF(x, y, z); + } + } + else + { + EulerF returnEuler = asMatrixF().toEuler(); + + if (_format == Degrees) + { + returnEuler.x = mRadToDeg(returnEuler.x); + returnEuler.y = mRadToDeg(returnEuler.y); + returnEuler.z = mRadToDeg(returnEuler.z); + } + + return returnEuler; + } +} + +AngAxisF RotationF::asAxisAngle(UnitFormat format) const +{ + AngAxisF returnAA; + + if (mRotationType == Euler) + { + returnAA.set(EulerF(x, y, z)); + } + else + { + returnAA.set(Point3F(x, y, z), w); + } + + if (format == Radians) + { + returnAA.angle = mDegToRad(returnAA.angle); + } + + return returnAA; +} + +MatrixF RotationF::asMatrixF() const +{ + MatrixF returnMat; + if (mRotationType == Euler) + { + returnMat.set(EulerF(x, y, z)); + } + else + { + AngAxisF aa; + aa.set(Point3F(x, y, z), w); + + aa.setMatrix(&returnMat); + } + + return returnMat; +} + +QuatF RotationF::asQuatF() const +{ + QuatF returnQuat; + if (mRotationType == Euler) + { + returnQuat.set(EulerF(x, y, z)); + } + else + { + AngAxisF aa; + aa.set(Point3F(x, y, z), w); + + returnQuat.set(aa); + } + + return returnQuat; +} + +void RotationF::normalize() +{ + if (mRotationType == Euler) + { + EulerF eul = EulerF(x, y, z); + eul.normalize(); + set(eul); + } + else + { + QuatF quat; + quat.set(Point3F(x, y, z), w); + + quat.normalize(); + + set(quat); + } +} + +//Testing +#ifdef TORQUE_TESTS_ENABLED +TEST(Maths, RotationF_Calculations) +{ + //TODO: implement unit test +}; +#endif + +DefineConsoleStaticMethod(Rotation, Add, RotationF, (RotationF a, RotationF b), , + "Adds two rotations together.\n" + "@param a Rotation one." + "@param b Rotation two." + "@returns v sum of both rotations." + "@ingroup Math") +{ + return a + b; +} + +DefineConsoleStaticMethod(Rotation, Subtract, RotationF, (RotationF a, RotationF b), , + "Subtracts two rotations.\n" + "@param a Rotation one." + "@param b Rotation two." + "@returns v difference of both rotations." + "@ingroup Math") +{ + return a - b; +} + +DefineConsoleStaticMethod(Rotation, Interpolate, RotationF, (RotationF a, RotationF b, F32 factor), , + "Interpolates between two rotations.\n" + "@param a Rotation one." + "@param b Rotation two." + "@param factor The amount to interpolate between the two." + "@returns v, interpolated result." + "@ingroup Math") +{ + RotationF result; + result.interpolate(a, b, factor); + return result; +} + +DefineConsoleStaticMethod(Rotation, LookAt, 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." + "@param target Position to be looked at." + "@param up The up angle to orient the rotation." + "@returns v orientation result." + "@ingroup Math") +{ + RotationF result; + result.lookAt(origin, target, up); + return result; +} \ No newline at end of file diff --git a/Engine/source/math/mRotation.h b/Engine/source/math/mRotation.h new file mode 100644 index 0000000000..a99510b8c3 --- /dev/null +++ b/Engine/source/math/mRotation.h @@ -0,0 +1,465 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2012 GarageGames, LLC +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION 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 MROTATION_H +#define MROTATION_H + +#ifndef _MMATHFN_H_ +#include "math/mMathFn.h" +#endif + +#ifndef _MPOINT3_H_ +#include "math/mPoint3.h" +#endif + +#ifndef _MQUAT_H_ +#include "math/mQuat.h" +#endif + +#ifndef _MMATRIX_H_ +#include "math/mMatrix.h" +#endif + +#ifndef _MANGAXIS_H_ +#include "math/mAngAxis.h" +#endif + +//------------------------------------------------------------------------------ +/// Rotation Interop Utility class +/// +/// Useful for easily handling rotations/orientations in transforms while manipulating or converting between formats. +class RotationF +{ + //-------------------------------------- Public data +public: + F32 x; ///< X co-ordinate. + F32 y; ///< Y co-ordinate. + F32 z; ///< Z co-ordinate. + F32 w; ///< W co-ordinate. + + enum RotationTypes + { + Euler = 0, + AxisAngle + }; + RotationTypes mRotationType; + + enum UnitFormat + { + Radians = 0, + Degrees + }; + + RotationF(); ///< Create an uninitialized point. + RotationF(const RotationF&); ///< Copy constructor. + + // + //Eulers + RotationF(EulerF euler, UnitFormat format = Radians); + RotationF(F32 _x, F32 _y, F32 _z, UnitFormat format = Radians); + + void set(EulerF euler, UnitFormat format = Radians); + void set(F32 _x, F32 _y, F32 _z, UnitFormat format = Radians); + + //As with AxisAngles, we make the assumption here that if not told otherwise, inbound rotations are in Degrees. + RotationF operator=(const EulerF&); + RotationF operator-(const EulerF&) const; + RotationF operator+(const EulerF&) const; + RotationF& operator-=(const EulerF&); + RotationF& operator+=(const EulerF&); + S32 operator==(const EulerF&) const; + S32 operator!=(const EulerF&) const; + + // + //AxisAngle + RotationF(AngAxisF aa, UnitFormat format = Radians); + void set(AngAxisF aa, UnitFormat format = Radians); + + //As with Eulers, we make the assumption here that if not told otherwise, inbound rotations are in Degrees. + RotationF operator=(const AngAxisF&); + RotationF operator-(const AngAxisF&) const; + RotationF operator+(const AngAxisF&) const; + RotationF& operator-=(const AngAxisF&); + RotationF& operator+=(const AngAxisF&); + S32 operator==(const AngAxisF&) const; + S32 operator!=(const AngAxisF&) const; + + // + //Quat + RotationF(QuatF quat); + void set(QuatF _quat); + + RotationF operator=(const QuatF&); + RotationF operator-(const QuatF&) const; + RotationF operator+(const QuatF&) const; + RotationF& operator-=(const QuatF&); + RotationF& operator+=(const QuatF&); + S32 operator==(const QuatF&) const; + S32 operator!=(const QuatF&) const; + + // + //Matrix + RotationF(MatrixF mat); + void set(MatrixF _mat); + + RotationF operator=(const MatrixF&); + RotationF operator-(const MatrixF&) const; + RotationF operator+(const MatrixF&) const; + RotationF& operator-=(const MatrixF&); + RotationF& operator+=(const MatrixF&); + S32 operator==(const MatrixF&) const; + S32 operator!=(const MatrixF&) const; + + // + void interpolate(const RotationF& _pt1, const RotationF& _pt2, F32 _factor); + void lookAt(const Point3F& _origin, const Point3F& _target, const Point3F& _up = Point3F(0, 0, 1)); + + F32 len() const; + + void normalize(); + + //Non-converting operators + S32 operator ==(const RotationF &) const; + S32 operator !=(const RotationF &) const; + + RotationF operator+(const RotationF&) const; + RotationF& operator+=(const RotationF&); + RotationF operator-(const RotationF&) const; + RotationF& operator-=(const RotationF&); + + RotationF& operator=(const RotationF&); + + //Conversion stuffs + EulerF asEulerF(UnitFormat format = Radians) const; + AngAxisF asAxisAngle(UnitFormat format = Radians) const; + MatrixF asMatrixF() const; + QuatF asQuatF() const; +}; + +inline RotationF::RotationF() +{ + x = 0; + y = 0; + z = 0; + w = 0; + + mRotationType = AxisAngle; +} + +inline RotationF::RotationF(const RotationF& _copy) + : x(_copy.x), y(_copy.y), z(_copy.z), w(_copy.w), mRotationType(_copy.mRotationType) +{} + +inline int RotationF::operator ==(const RotationF& _rotation) const +{ + return (x == _rotation.x && y == _rotation.y && z == _rotation.z && w == _rotation.w); +} + +inline int RotationF::operator !=(const RotationF& _rotation) const +{ + return (x != _rotation.x || y != _rotation.y || z != _rotation.z || w != _rotation.w); +} + +//When it comes to actually trying to add rotations, we, in fact, actually multiply their data together. +//Since we're specifically operating on usability for RotationF, we'll operate on this, rather than the literal addition of the values +inline RotationF& RotationF::operator +=(const RotationF& _rotation) +{ + if (mRotationType == Euler) + { + x += _rotation.x; + y += _rotation.y; + z += _rotation.z; + } + else + { + MatrixF tempMat = asMatrixF(); + MatrixF tempMatAdd = _rotation.asMatrixF(); + + tempMat.mul(tempMatAdd); + + this->set(tempMat); + } + + return *this; +} + +inline RotationF RotationF::operator +(const RotationF& _rotation) const +{ + RotationF result = *this; + + if (mRotationType == Euler) + { + result.x += _rotation.x; + result.y += _rotation.y; + result.z += _rotation.z; + } + else + { + MatrixF tempMat = asMatrixF(); + MatrixF tempMatAdd = _rotation.asMatrixF(); + + tempMat.mul(tempMatAdd); + + result.set(tempMat); + } + + return result; +} + +//Much like addition, when subtracting, we're not literally subtracting the values, but infact multiplying the inverse. +//This subtracts the rotation angles to get the difference +inline RotationF& RotationF::operator -=(const RotationF& _rotation) +{ + if (mRotationType == Euler) + { + x -= _rotation.x; + y -= _rotation.y; + z -= _rotation.z; + } + else + { + MatrixF tempMat = asMatrixF(); + MatrixF tempMatAdd = _rotation.asMatrixF(); + + tempMatAdd.inverse(); + + tempMat.mul(tempMatAdd); + + this->set(tempMat); + } + + return *this; +} + +inline RotationF RotationF::operator -(const RotationF& _rotation) const +{ + RotationF result = *this; + + if (mRotationType == Euler) + { + result.x += _rotation.x; + result.y += _rotation.y; + result.z += _rotation.z; + } + else + { + MatrixF tempMat = asMatrixF(); + MatrixF tempMatAdd = _rotation.asMatrixF(); + tempMatAdd.inverse(); + + tempMat.mul(tempMatAdd); + + result.set(tempMat); + } + + return result; +} + +inline RotationF& RotationF::operator =(const RotationF& _rotation) +{ + x = _rotation.x; + y = _rotation.y; + z = _rotation.z; + w = _rotation.w; + + mRotationType = _rotation.mRotationType; + + return *this; +} + +//==================================================================== +// Euler operators +//==================================================================== +inline RotationF RotationF::operator=(const EulerF& _euler) +{ + return RotationF(_euler, Radians); +} + +inline RotationF RotationF::operator-(const EulerF& _euler) const +{ + RotationF temp = *this; + temp -= RotationF(_euler, Radians); + return temp; +} + +inline RotationF RotationF::operator+(const EulerF& _euler) const +{ + RotationF temp = *this; + temp += RotationF(_euler, Radians); + return temp; +} + +inline RotationF& RotationF::operator-=(const EulerF& _euler) +{ + *this -= RotationF(_euler, Radians); + return *this; +} + +inline RotationF& RotationF::operator+=(const EulerF& _euler) +{ + *this += RotationF(_euler, Radians); + return *this; +} + +inline S32 RotationF::operator==(const EulerF& _euler) const +{ + return *this == RotationF(_euler); +} + +inline S32 RotationF::operator!=(const EulerF& _euler) const +{ + return *this != RotationF(_euler); +} + +//==================================================================== +// AxisAngle operators +//==================================================================== +inline RotationF RotationF::operator=(const AngAxisF& _aa) +{ + return RotationF(_aa, Radians); +} + +inline RotationF RotationF::operator-(const AngAxisF& _aa) const +{ + RotationF temp = *this; + temp -= RotationF(_aa, Radians); + return temp; +} + +inline RotationF RotationF::operator+(const AngAxisF& _aa) const +{ + RotationF temp = *this; + temp += RotationF(_aa, Radians); + return temp; +} + +inline RotationF& RotationF::operator-=(const AngAxisF& _aa) +{ + *this -= RotationF(_aa, Radians); + return *this; +} + +inline RotationF& RotationF::operator+=(const AngAxisF& _aa) +{ + *this += RotationF(_aa, Radians); + return *this; +} + +inline S32 RotationF::operator==(const AngAxisF& _aa) const +{ + return *this == RotationF(_aa); +} + +inline S32 RotationF::operator!=(const AngAxisF& _aa) const +{ + return *this != RotationF(_aa); +} + +//==================================================================== +// QuatF operators +//==================================================================== +inline RotationF RotationF::operator=(const QuatF& _quat) +{ + return RotationF(_quat); +} + +inline RotationF RotationF::operator-(const QuatF& _quat) const +{ + RotationF temp = *this; + temp -= RotationF(_quat); + return temp; +} + +inline RotationF RotationF::operator+(const QuatF& _quat) const +{ + RotationF temp = *this; + temp += RotationF(_quat); + return temp; +} + +inline RotationF& RotationF::operator-=(const QuatF& _quat) +{ + *this -= RotationF(_quat); + return *this; +} + +inline RotationF& RotationF::operator+=(const QuatF& _quat) +{ + *this += RotationF(_quat); + return *this; +} + +inline S32 RotationF::operator==(const QuatF& _quat) const +{ + return *this == RotationF(_quat); +} + +inline S32 RotationF::operator!=(const QuatF& _quat) const +{ + return *this != RotationF(_quat); +} + +//==================================================================== +// MatrixF operators +//==================================================================== +inline RotationF RotationF::operator=(const MatrixF& _mat) +{ + return RotationF(_mat); +} + +inline RotationF RotationF::operator-(const MatrixF& _mat) const +{ + RotationF temp = *this; + temp -= RotationF(_mat); + return temp; +} + +inline RotationF RotationF::operator+(const MatrixF& _mat) const +{ + RotationF temp = *this; + temp += RotationF(_mat); + return temp; +} + +inline RotationF& RotationF::operator-=(const MatrixF& _mat) +{ + *this -= RotationF(_mat); + return *this; +} + +inline RotationF& RotationF::operator+=(const MatrixF& _mat) +{ + *this += RotationF(_mat); + return *this; +} + +inline S32 RotationF::operator==(const MatrixF& _mat) const +{ + return *this == RotationF(_mat); +} + +inline S32 RotationF::operator!=(const MatrixF& _mat) const +{ + return *this != RotationF(_mat); +} + +#endif // MROTATION_H diff --git a/Engine/source/math/mathIO.h b/Engine/source/math/mathIO.h index ee2f0dcad4..6acbc1b522 100644 --- a/Engine/source/math/mathIO.h +++ b/Engine/source/math/mathIO.h @@ -149,6 +149,20 @@ inline bool mathRead(Stream& stream, EaseF* e) return success; } +inline bool mathRead(Stream& stream, RotationF* e) +{ + bool success = stream.read(&e->x); + success &= stream.read(&e->y); + success &= stream.read(&e->z); + success &= stream.read(&e->w); + + U32 rotType; + success &= stream.read(&rotType); + e->mRotationType = (RotationF::RotationTypes)rotType; + + return success; +} + //------------------------------------------------------------------------------ //-------------------------------------- WRITING // @@ -263,5 +277,15 @@ inline bool mathWrite(Stream& stream, const EaseF& e) return success; } +inline bool mathWrite(Stream& stream, const RotationF& e) +{ + bool success = stream.write(e.x); + success &= stream.write(e.y); + success &= stream.write(e.z); + success &= stream.write(e.w); + success &= stream.write(e.mRotationType); + return success;; +} + #endif //_MATHIO_H_ diff --git a/Engine/source/math/mathTypes.cpp b/Engine/source/math/mathTypes.cpp index 29c500b609..9e56052078 100644 --- a/Engine/source/math/mathTypes.cpp +++ b/Engine/source/math/mathTypes.cpp @@ -36,7 +36,7 @@ #include "math/mRandom.h" #include "math/mEase.h" #include "math/mathUtils.h" - +#include "math/mRotation.h" #include "core/strings/stringUnit.h" IMPLEMENT_SCOPE( MathTypes, Math,, "" ); @@ -113,7 +113,14 @@ IMPLEMENT_STRUCT( EaseF, EaseF, MathTypes, "" ) END_IMPLEMENT_STRUCT; - +IMPLEMENT_STRUCT(RotationF, + RotationF, MathTypes, + "") + FIELD(x, x, 1, "X coordinate.") + FIELD(y, y, 1, "Y coordinate.") + FIELD(z, z, 1, "Z coordinate.") + FIELD(w, w, 1, "W coordinate.") +END_IMPLEMENT_STRUCT; //----------------------------------------------------------------------------- // TypePoint2I @@ -572,6 +579,55 @@ ConsoleSetType( TypeEaseF ) } } +//----------------------------------------------------------------------------- +// TypeRotationF +//----------------------------------------------------------------------------- +ConsoleType(RotationF, TypeRotationF, RotationF, "") +ImplementConsoleTypeCasters( TypeRotationF, RotationF ) + +ConsoleGetType(TypeRotationF) +{ + RotationF *pt = (RotationF *)dptr; + static const U32 bufSize = 256; + char* returnBuffer = Con::getReturnBuffer(bufSize); + + EulerF out = pt->asEulerF(RotationF::Degrees); + dSprintf(returnBuffer, bufSize, "%g %g %g", out.x, out.y, out.z); + + return returnBuffer; +} + +ConsoleSetType(TypeRotationF) +{ + if (argc == 1) + { + U32 elements = StringUnit::getUnitCount(argv[0], " \t\n"); + if (elements == 3) + { + EulerF in; + dSscanf(argv[0], "%g %g %g", &in.x, &in.y, &in.z); + ((RotationF *)dptr)->set(in, RotationF::Degrees); + } + else + { + AngAxisF in; + dSscanf(argv[0], "%g %g %g %g", &in.axis.x, &in.axis.y, &in.axis.z, &in.angle); + ((RotationF *)dptr)->set(in, RotationF::Degrees); + } + } + else if (argc == 3) + { + EulerF in(dAtof(argv[0]), dAtof(argv[1]), dAtof(argv[2])); + ((RotationF *)dptr)->set(in, RotationF::Degrees); + } + else if (argc == 4) + { + AngAxisF in(Point3F(dAtof(argv[0]), dAtof(argv[1]), dAtof(argv[2])), dAtof(argv[3])); + ((RotationF *)dptr)->set(in, RotationF::Degrees); + } + else + Con::printf("RotationF must be set as { x, y, z, w } or \"x y z w\""); +} //----------------------------------------------------------------------------- diff --git a/Engine/source/math/mathTypes.h b/Engine/source/math/mathTypes.h index b17329cf86..043d59e1fe 100644 --- a/Engine/source/math/mathTypes.h +++ b/Engine/source/math/mathTypes.h @@ -43,7 +43,7 @@ class Box3F; class EaseF; class AngAxisF; class TransformF; - +class RotationF; DECLARE_SCOPE( MathTypes ); @@ -60,6 +60,7 @@ DECLARE_STRUCT( AngAxisF ); DECLARE_STRUCT( TransformF ); DECLARE_STRUCT( Box3F ); DECLARE_STRUCT( EaseF ); +DECLARE_STRUCT(RotationF); // Legacy console types. @@ -77,6 +78,6 @@ DefineConsoleType( TypeAngAxisF, AngAxisF ) DefineConsoleType( TypeTransformF, TransformF ) DefineConsoleType( TypeBox3F, Box3F ) DefineConsoleType( TypeEaseF, EaseF ) - +DefineConsoleType(TypeRotationF, RotationF) #endif diff --git a/Engine/source/math/mathUtils.cpp b/Engine/source/math/mathUtils.cpp index ea57d93c3b..dba228fde0 100644 --- a/Engine/source/math/mathUtils.cpp +++ b/Engine/source/math/mathUtils.cpp @@ -30,7 +30,6 @@ #include "platform/profiler.h" #include "core/tAlgorithm.h" -#include "gfx/gfxDevice.h" namespace MathUtils { @@ -1450,8 +1449,6 @@ void makeProjection( MatrixF *outMatrix, F32 farPlane, bool gfxRotate ) { - bool isGL = GFX->getAdapterType() == OpenGL; - Point4F row; row.x = 2.0*nearPlane / (right-left); row.y = 0.0; @@ -1467,13 +1464,13 @@ void makeProjection( MatrixF *outMatrix, row.x = (left+right) / (right-left); row.y = (top+bottom) / (top-bottom); - row.z = isGL ? -(farPlane + nearPlane) / (farPlane - nearPlane) : farPlane / (nearPlane - farPlane); + row.z = farPlane / (nearPlane - farPlane); row.w = -1.0; outMatrix->setRow( 2, row ); row.x = 0.0; row.y = 0.0; - row.z = isGL ? 2 * nearPlane * farPlane / (nearPlane - farPlane) : nearPlane * farPlane / (nearPlane - farPlane); + row.z = nearPlane * farPlane / (nearPlane - farPlane); row.w = 0.0; outMatrix->setRow( 3, row ); @@ -1494,8 +1491,6 @@ void makeOrthoProjection( MatrixF *outMatrix, F32 farPlane, bool gfxRotate ) { - bool isGL = GFX->getAdapterType() == OpenGL; - Point4F row; row.x = 2.0f / (right - left); row.y = 0.0f; @@ -1513,15 +1508,15 @@ void makeOrthoProjection( MatrixF *outMatrix, row.y = 0.0f; row.w = 0.0f; - // This needs to be modified to work with OpenGL (d3d has 0..1 - // projection for z, vs -1..1 in OpenGL) - row.z = isGL ? 2.0f / (nearPlane - farPlane) : 1.0f / (nearPlane - farPlane); + //Unlike D3D, which has a 0-1 range, OpenGL uses a -1-1 range. + //However, epoxy internally handles the swap, so the math here is the same for both APIs + row.z = 1.0f / (nearPlane - farPlane); outMatrix->setRow( 2, row ); row.x = (left + right) / (left - right); row.y = (top + bottom) / (bottom - top); - row.z = isGL ? (nearPlane + farPlane) / (nearPlane - farPlane) : nearPlane / (nearPlane - farPlane); + row.z = nearPlane / (nearPlane - farPlane); row.w = 1.0f; outMatrix->setRow( 3, row ); diff --git a/Engine/source/navigation/navMesh.cpp b/Engine/source/navigation/navMesh.cpp index f029c5debd..db70d1cc31 100644 --- a/Engine/source/navigation/navMesh.cpp +++ b/Engine/source/navigation/navMesh.cpp @@ -145,6 +145,17 @@ DefineConsoleFunction(NavMeshUpdateAroundObject, void, (S32 objid, bool remove), obj->enableCollision(); } + +DefineConsoleFunction(NavMeshIgnore, void, (S32 objid, bool _ignore), (0, true), + "@brief Flag this object as not generating a navmesh result.") +{ + SceneObject *obj; + if(!Sim::findObject(objid, obj)) + return; + + obj->mPathfindingIgnore = _ignore; +} + DefineConsoleFunction(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.") { @@ -839,6 +850,7 @@ void NavMesh::buildNextTile() static void buildCallback(SceneObject* object,void *key) { SceneContainer::CallbackInfo* info = reinterpret_cast(key); + if (!object->mPathfindingIgnore) object->buildPolyList(info->context,info->polyList,info->boundingBox,info->boundingSphere); } @@ -861,7 +873,7 @@ unsigned char *NavMesh::buildTileData(const Tile &tile, TileData &data, U32 &dat data.geom.clear(); info.polyList = &data.geom; info.key = this; - getContainer()->findObjects(box, StaticShapeObjectType | TerrainObjectType, buildCallback, &info); + getContainer()->findObjects(box, StaticObjectType | DynamicShapeObjectType, buildCallback, &info); // Parse water objects into the same list, but remember how much geometry was /not/ water. U32 nonWaterVertCount = data.geom.getVertCount(); diff --git a/Engine/source/platform/nativeDialogs/fileDialog.cpp b/Engine/source/platform/nativeDialogs/fileDialog.cpp index 84b367618b..08d6895854 100644 --- a/Engine/source/platform/nativeDialogs/fileDialog.cpp +++ b/Engine/source/platform/nativeDialogs/fileDialog.cpp @@ -184,40 +184,63 @@ static const U32 convertUTF16toUTF8DoubleNULL(const UTF16 *unistring, UTF8 *out // bool FileDialog::Execute() { - String suffix; + String strippedFilters; U32 filtersCount = StringUnit::getUnitCount(mData.mFilters, "|"); for (U32 i = 1; i < filtersCount; ++i) { //The first of each pair is the name, which we'll skip because NFD doesn't support named filters atm - const char *filter = StringUnit::getUnit(mData.mFilters, i, "|"); + String filter = StringUnit::getUnit(mData.mFilters, i, "|"); - if (!dStrcmp(filter, "*.*")) + if (!dStrcmp(filter.c_str(), "*.*")) continue; - U32 c = 2; - const char* tmpchr = &filter[c]; - String tString = String(tmpchr); - tString.ToLower(tString); - suffix += tString; - suffix += String(","); - suffix += tString.ToUpper(tString); + U32 subFilterCount = StringUnit::getUnitCount(filter, ";"); + + //if we have a 'super filter', break it down to sub-options as well + if (subFilterCount > 1) + { + String suffixFilter; + String subFilters; + + for (U32 f = 0; f < subFilterCount; ++f) + { + String subFilter = StringUnit::getUnit(filter, f, ";"); + + suffixFilter += String::ToLower(subFilter) + "," + String::ToUpper(subFilter) + ","; + subFilters += String::ToLower(subFilter) + "," + String::ToUpper(subFilter) + ";"; + } + + suffixFilter = suffixFilter.substr(0, suffixFilter.length() - 1); + suffixFilter += ";"; + + strippedFilters += suffixFilter + subFilters; + } + else //otherwise, just add the filter + { + strippedFilters += String::ToLower(filter) + "," + String::ToUpper(filter) + ";"; + } ++i; - if (i < filtersCount-2) - suffix += String(";"); + if (i < filtersCount - 2) + strippedFilters += String(";"); } - String strippedFilters = suffix; - strippedFilters.replace(";",","); - strippedFilters += String(";") + suffix; + + //strip the last character, if it's unneeded + if (strippedFilters.endsWith(";")) + { + strippedFilters = strippedFilters.substr(0, strippedFilters.length() - 1); + } + + strippedFilters.replace("*.", ""); // Get the current working directory, so we can back up to it once Windows has // done its craziness and messed with it. StringTableEntry cwd = Platform::getCurrentDirectory(); if (mData.mDefaultPath == StringTable->lookup("") || !Platform::isDirectory(mData.mDefaultPath)) mData.mDefaultPath = cwd; - + String rootDir = String(cwd); // Execute Dialog (Blocking Call) nfdchar_t *outPath = NULL; nfdpathset_t pathSet; @@ -226,6 +249,7 @@ bool FileDialog::Execute() String defaultPath = String(mData.mDefaultPath); #if defined(TORQUE_OS_WIN) defaultPath.replace("/", "\\"); + rootDir.replace("/", "\\"); #endif if (mData.mStyle & FileDialogData::FDS_OPEN) @@ -235,6 +259,15 @@ bool FileDialog::Execute() else if (mData.mStyle & FileDialogData::FDS_MULTIPLEFILES) result = NFD_OpenDialogMultiple(strippedFilters.c_str(), defaultPath.c_str(), &pathSet); + if (result == NFD_CANCEL) + { + return false; + } + + String resultPath = String(outPath).replace(rootDir, String("")); + resultPath = resultPath.replace(0, 1, String("")).c_str(); //kill '\\' prefix + resultPath = resultPath.replace(String("\\"), String("/")); + // Did we select a file? if (result != NFD_OKAY) { @@ -245,7 +278,7 @@ bool FileDialog::Execute() if (mData.mStyle & FileDialogData::FDS_OPEN || mData.mStyle & FileDialogData::FDS_SAVE) { // Single file selection, do it the easy way - mData.mFile = StringTable->insert(outPath); + mData.mFile = Platform::makeRelativePathName(resultPath.c_str(), NULL); } else if (mData.mStyle & FileDialogData::FDS_MULTIPLEFILES) { @@ -265,14 +298,13 @@ bool FileDialog::Execute() else { //nope, just one file, so set it as normal - setDataField(StringTable->insert("files"), "0", outPath); + setDataField(StringTable->insert("files"), "0", Platform::makeRelativePathName(resultPath.c_str(), NULL)); setDataField(StringTable->insert("fileCount"), NULL, "1"); } } // Return success. return true; - } DefineEngineMethod(FileDialog, Execute, bool, (), , diff --git a/Engine/source/scene/sceneObject.cpp b/Engine/source/scene/sceneObject.cpp index 1420bac11b..1d16377af3 100644 --- a/Engine/source/scene/sceneObject.cpp +++ b/Engine/source/scene/sceneObject.cpp @@ -144,6 +144,7 @@ SceneObject::SceneObject() mIsScopeAlways = false; mAccuTex = NULL; + mPathfindingIgnore = false; } //----------------------------------------------------------------------------- diff --git a/Engine/source/scene/sceneObject.h b/Engine/source/scene/sceneObject.h index 42c3c53ed2..3985d372c2 100644 --- a/Engine/source/scene/sceneObject.h +++ b/Engine/source/scene/sceneObject.h @@ -371,6 +371,7 @@ class SceneObject : public NetObject, private SceneContainer::Link, public Proce SceneObject(); virtual ~SceneObject(); + bool mPathfindingIgnore; /// Triggered when a SceneObject onAdd is called. static Signal< void( SceneObject* ) > smSceneObjectAdd; diff --git a/Engine/source/shaderGen/GLSL/shaderFeatureGLSL.cpp b/Engine/source/shaderGen/GLSL/shaderFeatureGLSL.cpp index 78c45a09cd..e1433c11f7 100644 --- a/Engine/source/shaderGen/GLSL/shaderFeatureGLSL.cpp +++ b/Engine/source/shaderGen/GLSL/shaderFeatureGLSL.cpp @@ -1194,7 +1194,10 @@ void DiffuseVertColorFeatureGLSL::processPix( Vector &compon } MultiLine* meta = new MultiLine; - meta->addStatement( new GenOp( " @;\r\n", assignColor( vertColor, Material::Mul ) ) ); + if (fd.features[MFT_isDeferred]) + meta->addStatement(new GenOp(" @;\r\n", assignColor(vertColor, Material::Mul, NULL, ShaderFeature::RenderTarget1))); + else + meta->addStatement(new GenOp(" @;\r\n", assignColor(vertColor, Material::Mul))); output = meta; } @@ -2805,7 +2808,7 @@ void DeferredSkyGLSL::processVert( Vector &componentList, { Var *outPosition = (Var*)LangElement::find( "gl_Position" ); MultiLine *meta = new MultiLine; - meta->addStatement( new GenOp( " @.w = @.z;\r\n", outPosition, outPosition ) ); + //meta->addStatement( new GenOp( " @.w = @.z;\r\n", outPosition, outPosition ) ); output = meta; } diff --git a/Engine/source/shaderGen/HLSL/shaderFeatureHLSL.cpp b/Engine/source/shaderGen/HLSL/shaderFeatureHLSL.cpp index 8878f26004..879176a443 100644 --- a/Engine/source/shaderGen/HLSL/shaderFeatureHLSL.cpp +++ b/Engine/source/shaderGen/HLSL/shaderFeatureHLSL.cpp @@ -1258,7 +1258,10 @@ void DiffuseVertColorFeatureHLSL::processPix( Vector &compon } MultiLine* meta = new MultiLine; - meta->addStatement( new GenOp( " @;\r\n", assignColor( vertColor, Material::Mul ) ) ); + if (fd.features[MFT_isDeferred]) + meta->addStatement(new GenOp(" @;\r\n", assignColor(vertColor, Material::Mul, NULL, ShaderFeature::RenderTarget1))); + else + meta->addStatement(new GenOp(" @;\r\n", assignColor(vertColor, Material::Mul))); output = meta; } @@ -3000,7 +3003,7 @@ void DeferredSkyHLSL::processVert( Vector &componentList, { Var *outPosition = (Var*)LangElement::find( "hpos" ); MultiLine *meta = new MultiLine; - meta->addStatement( new GenOp( " @.w = @.z;\r\n", outPosition, outPosition ) ); + //meta->addStatement( new GenOp( " @.w = @.z;\r\n", outPosition, outPosition ) ); output = meta; } diff --git a/Templates/Empty/game/core/scripts/client/defaults.cs b/Templates/Empty/game/core/scripts/client/defaults.cs index 0142a94108..d1805d337d 100644 --- a/Templates/Empty/game/core/scripts/client/defaults.cs +++ b/Templates/Empty/game/core/scripts/client/defaults.cs @@ -73,7 +73,9 @@ /// $pref::Video::disableParallaxMapping = false; -$pref::Video::Gamma = 1.0; +$pref::Video::Gamma = 2.2; +$pref::Video::Contrast = 1.0; +$pref::Video::Brightness = 0; // Console-friendly defaults if($platform $= "xenon") diff --git a/Templates/Empty/game/core/scripts/client/lighting/advanced/deferredShading.cs b/Templates/Empty/game/core/scripts/client/lighting/advanced/deferredShading.cs new file mode 100644 index 0000000000..ad9732e0f2 --- /dev/null +++ b/Templates/Empty/game/core/scripts/client/lighting/advanced/deferredShading.cs @@ -0,0 +1,147 @@ +singleton ShaderData( ClearGBufferShader ) +{ + DXVertexShaderFile = "shaders/common/lighting/advanced/deferredClearGBufferV.hlsl"; + DXPixelShaderFile = "shaders/common/lighting/advanced/deferredClearGBufferP.hlsl"; + + OGLVertexShaderFile = "shaders/common/postFx/gl/postFxV.glsl"; + OGLPixelShaderFile = "shaders/common/lighting/advanced/gl/deferredClearGBufferP.glsl"; + + pixVersion = 2.0; +}; + +singleton ShaderData( DeferredColorShader ) +{ + DXVertexShaderFile = "shaders/common/postFx/postFxV.hlsl"; + DXPixelShaderFile = "shaders/common/lighting/advanced/deferredColorShaderP.hlsl"; + + OGLVertexShaderFile = "shaders/common/postFx/gl/postFxV.glsl"; + OGLPixelShaderFile = "shaders/common/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; +}; + +new ShaderData( AL_DeferredShader ) +{ + DXVertexShaderFile = "shaders/common/postFx/postFxV.hlsl"; + DXPixelShaderFile = "shaders/common/lighting/advanced/deferredShadingP.hlsl"; + + OGLVertexShaderFile = "shaders/common/postFx/gl/postFxV.glsl"; + OGLPixelShaderFile = "shaders/common/lighting/advanced/gl/deferredShadingP.glsl"; + + samplerNames[0] = "colorBufferTex"; + samplerNames[1] = "lightPrePassTex"; + samplerNames[2] = "matInfoTex"; + samplerNames[3] = "prepassTex"; + + 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] = "#prepass"; + + target = "$backBuffer"; + renderPriority = 10000; + allowReflectPass = true; +}; + +// Debug Shaders. +new ShaderData( AL_ColorBufferShader ) +{ + DXVertexShaderFile = "shaders/common/postFx/postFxV.hlsl"; + DXPixelShaderFile = "shaders/common/lighting/advanced/dbgColorBufferP.hlsl"; + + OGLVertexShaderFile = "shaders/common/postFx/gl/postFxV.glsl"; + OGLPixelShaderFile = "shaders/common/lighting/advanced/gl/dbgColorBufferP.glsl"; + + samplerNames[0] = "colorBufferTex"; + pixVersion = 2.0; +}; + +singleton PostEffect( AL_ColorBufferVisualize ) +{ + shader = AL_ColorBufferShader; + stateBlock = AL_DefaultVisualizeState; + texture[0] = "#color"; + target = "$backBuffer"; + renderPriority = 9999; +}; + +/// Toggles the visualization of the AL lighting specular power buffer. +function toggleColorBufferViz( %enable ) +{ + if ( %enable $= "" ) + { + $AL_ColorBufferShaderVar = AL_ColorBufferVisualize.isEnabled() ? false : true; + AL_ColorBufferVisualize.toggle(); + } + else if ( %enable ) + { + AL_DeferredShading.disable(); + AL_ColorBufferVisualize.enable(); + } + else if ( !%enable ) + { + AL_ColorBufferVisualize.disable(); + AL_DeferredShading.enable(); + } +} + +new ShaderData( AL_SpecMapShader ) +{ + DXVertexShaderFile = "shaders/common/postFx/postFxV.hlsl"; + DXPixelShaderFile = "shaders/common/lighting/advanced/dbgSpecMapVisualizeP.hlsl"; + + OGLVertexShaderFile = "shaders/common/postFx/gl/postFxV.glsl"; + OGLPixelShaderFile = "shaders/common/lighting/advanced/gl/dbgSpecMapVisualizeP.glsl"; + + samplerNames[0] = "matinfoTex"; + pixVersion = 2.0; +}; + +singleton PostEffect( AL_SpecMapVisualize ) +{ + shader = AL_SpecMapShader; + stateBlock = AL_DefaultVisualizeState; + texture[0] = "#matinfo"; + target = "$backBuffer"; + renderPriority = 9999; +}; + +/// Toggles the visualization of the AL lighting specular power buffer. +function toggleSpecMapViz( %enable ) +{ + if ( %enable $= "" ) + { + $AL_SpecMapShaderVar = AL_SpecMapVisualize.isEnabled() ? false : true; + AL_SpecMapVisualize.toggle(); + } + else if ( %enable ) + AL_SpecMapVisualize.enable(); + else if ( !%enable ) + AL_SpecMapVisualize.disable(); +} \ No newline at end of file diff --git a/Templates/Empty/game/core/scripts/client/lighting/advanced/init.cs b/Templates/Empty/game/core/scripts/client/lighting/advanced/init.cs index 2c78e9ca42..d74aff69a9 100644 --- a/Templates/Empty/game/core/scripts/client/lighting/advanced/init.cs +++ b/Templates/Empty/game/core/scripts/client/lighting/advanced/init.cs @@ -43,6 +43,7 @@ exec( "./lightViz.cs" ); exec( "./shadowViz.cs" ); exec( "./shadowViz.gui" ); +exec( "./deferredShading.cs" ); function onActivateAdvancedLM() { @@ -58,12 +59,18 @@ 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() diff --git a/Templates/Empty/game/core/scripts/client/lighting/advanced/lightViz.cs b/Templates/Empty/game/core/scripts/client/lighting/advanced/lightViz.cs index 22665120df..fcaf72942b 100644 --- a/Templates/Empty/game/core/scripts/client/lighting/advanced/lightViz.cs +++ b/Templates/Empty/game/core/scripts/client/lighting/advanced/lightViz.cs @@ -56,7 +56,7 @@ OGLVertexShaderFile = "shaders/common/postFx/gl/postFxV.glsl"; OGLPixelShaderFile = "shaders/common/lighting/advanced/gl/dbgDepthVisualizeP.glsl"; - samplerNames[0] = "prepassBuffer"; + samplerNames[0] = "prepassTex"; samplerNames[1] = "depthViz"; pixVersion = 2.0; @@ -113,7 +113,7 @@ singleton PostEffect( AL_GlowVisualize ) OGLVertexShaderFile = "shaders/common/postFx/gl/postFxV.glsl"; OGLPixelShaderFile = "shaders/common/lighting/advanced/gl/dbgNormalVisualizeP.glsl"; - samplerNames[0] = "prepassBuffer"; + samplerNames[0] = "prepassTex"; pixVersion = 2.0; }; @@ -149,7 +149,7 @@ singleton PostEffect( AL_NormalsVisualize ) OGLVertexShaderFile = "shaders/common/postFx/gl/postFxV.glsl"; OGLPixelShaderFile = "shaders/common/lighting/advanced/gl/dbgLightColorVisualizeP.glsl"; - samplerNames[0] = "lightInfoBuffer"; + samplerNames[0] = "lightPrePassTex"; pixVersion = 2.0; }; @@ -184,7 +184,7 @@ singleton PostEffect( AL_LightColorVisualize ) OGLVertexShaderFile = "shaders/common/postFx/gl/postFxV.glsl"; OGLPixelShaderFile = "shaders/common/lighting/advanced/gl/dbgLightSpecularVisualizeP.glsl"; - samplerNames[0] = "lightInfoBuffer"; + samplerNames[0] = "lightPrePassTex"; pixVersion = 2.0; }; @@ -280,3 +280,16 @@ function toggleLightSpecularViz( %enable ) AL_LightSpecularVisualize.disable(); } +function toggleBackbufferViz( %enable ) +{ + if ( %enable $= "" ) + { + $AL_BackbufferVisualizeVar = AL_DeferredShading.isEnabled() ? true : false; + AL_DeferredShading.toggle(); + } + else if ( %enable ) + AL_DeferredShading.disable(); + else if ( !%enable ) + AL_DeferredShading.enable(); +} + diff --git a/Templates/Empty/game/core/scripts/client/lighting/advanced/shaders.cs b/Templates/Empty/game/core/scripts/client/lighting/advanced/shaders.cs index 2e73b65696..08a82b8dc8 100644 --- a/Templates/Empty/game/core/scripts/client/lighting/advanced/shaders.cs +++ b/Templates/Empty/game/core/scripts/client/lighting/advanced/shaders.cs @@ -36,9 +36,14 @@ samplersDefined = true; samplerStates[0] = SamplerClampPoint; // G-buffer + mSamplerNames[0] = "prePassBuffer"; samplerStates[1] = SamplerClampPoint; // Shadow Map (Do not change this to linear, as all cards can not filter equally.) - samplerStates[2] = SamplerClampLinear; // SSAO Mask - samplerStates[3] = SamplerWrapPoint; // Random Direction Map + 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; @@ -66,7 +71,9 @@ samplerNames[2] = "$dynamicShadowMap"; samplerNames[3] = "$ssaoMask"; samplerNames[4] = "$gTapRotationTex"; - + samplerNames[5] = "$lightBuffer"; + samplerNames[6] = "$colorBuffer"; + samplerNames[7] = "$matInfoBuffer"; pixVersion = 3.0; }; @@ -79,6 +86,9 @@ sampler["shadowMap"] = "$dynamiclight"; sampler["dynamicShadowMap"] = "$dynamicShadowMap"; sampler["ssaoMask"] = "#ssaoMask"; + sampler["lightBuffer"] = "#lightinfo"; + sampler["colorBuffer"] = "#color"; + sampler["matInfoBuffer"] = "#matinfo"; target = "lightinfo"; @@ -103,9 +113,13 @@ samplersDefined = true; samplerStates[0] = SamplerClampPoint; // G-buffer + mSamplerNames[0] = "prePassBuffer"; samplerStates[1] = SamplerClampPoint; // Shadow Map (Do not use linear, these are perspective projections) - samplerStates[2] = SamplerClampLinear; // Cookie Map - samplerStates[3] = SamplerWrapPoint; // Random Direction Map + 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; @@ -133,6 +147,9 @@ samplerNames[2] = "$dynamicShadowMap"; samplerNames[3] = "$cookieMap"; samplerNames[4] = "$gTapRotationTex"; + samplerNames[5] = "$lightBuffer"; + samplerNames[6] = "$colorBuffer"; + samplerNames[7] = "$matInfoBuffer"; pixVersion = 3.0; }; @@ -146,6 +163,9 @@ sampler["shadowMap"] = "$dynamiclight"; sampler["dynamicShadowMap"] = "$dynamicShadowMap"; sampler["cookieMap"] = "$dynamiclightmask"; + sampler["lightBuffer"] = "#lightinfo"; + sampler["colorBuffer"] = "#color"; + sampler["matInfoBuffer"] = "#matinfo"; target = "lightinfo"; @@ -166,6 +186,9 @@ samplerNames[2] = "$dynamicShadowMap"; samplerNames[3] = "$cookieMap"; samplerNames[4] = "$gTapRotationTex"; + samplerNames[5] = "$lightBuffer"; + samplerNames[6] = "$colorBuffer"; + samplerNames[7] = "$matInfoBuffer"; pixVersion = 3.0; }; @@ -179,6 +202,9 @@ sampler["shadowMap"] = "$dynamiclight"; sampler["dynamicShadowMap"] = "$dynamicShadowMap"; sampler["cookieMap"] = "$dynamiclightmask"; + sampler["lightBuffer"] = "#lightinfo"; + sampler["colorBuffer"] = "#color"; + sampler["matInfoBuffer"] = "#matinfo"; target = "lightinfo"; diff --git a/Templates/Empty/game/core/scripts/client/postFx/GammaPostFX.cs b/Templates/Empty/game/core/scripts/client/postFx/GammaPostFX.cs index 383a0c8cda..b88f313057 100644 --- a/Templates/Empty/game/core/scripts/client/postFx/GammaPostFX.cs +++ b/Templates/Empty/game/core/scripts/client/postFx/GammaPostFX.cs @@ -44,7 +44,7 @@ singleton GFXStateBlockData( GammaStateBlock : PFX_DefaultStateBlock ) singleton PostEffect( GammaPostFX ) { isEnabled = true; - allowReflectPass = false; + allowReflectPass = true; renderTime = "PFXBeforeBin"; renderBin = "EditorBin"; @@ -65,6 +65,8 @@ singleton PostEffect( GammaPostFX ) function GammaPostFX::setShaderConsts( %this ) { - %clampedGamma = mClamp( $pref::Video::Gamma, 0.001, 2.2); + %clampedGamma = mClamp( $pref::Video::Gamma, 2.0, 2.5); %this.setShaderConst( "$OneOverGamma", 1 / %clampedGamma ); + %this.setShaderConst( "$Brightness", $pref::Video::Brightness ); + %this.setShaderConst( "$Contrast", $pref::Video::Contrast ); } \ No newline at end of file diff --git a/Templates/Empty/game/core/scripts/client/postFx/caustics.cs b/Templates/Empty/game/core/scripts/client/postFx/caustics.cs index 3e8b14de0b..a712ef82a5 100644 --- a/Templates/Empty/game/core/scripts/client/postFx/caustics.cs +++ b/Templates/Empty/game/core/scripts/client/postFx/caustics.cs @@ -38,7 +38,7 @@ singleton ShaderData( PFX_CausticsShader ) DXVertexShaderFile = "shaders/common/postFx/postFxV.hlsl"; DXPixelShaderFile = "shaders/common/postFx/caustics/causticsP.hlsl"; - OGLVertexShaderFile = "shaders/common/postFx/gl//postFxV.glsl"; + OGLVertexShaderFile = "shaders/common/postFx/gl/postFxV.glsl"; OGLPixelShaderFile = "shaders/common/postFx/caustics/gl/causticsP.glsl"; samplerNames[0] = "$prepassTex"; @@ -51,7 +51,7 @@ singleton ShaderData( PFX_CausticsShader ) singleton PostEffect( CausticsPFX ) { isEnabled = false; - renderTime = "PFXBeforeBin"; + renderTime = "PFXAfterDiffuse"; renderBin = "ObjTranslucentBin"; //renderPriority = 0.1; diff --git a/Templates/Empty/game/core/scripts/client/postFx/hdr.cs b/Templates/Empty/game/core/scripts/client/postFx/hdr.cs index a5c450799a..6c8e870d0e 100644 --- a/Templates/Empty/game/core/scripts/client/postFx/hdr.cs +++ b/Templates/Empty/game/core/scripts/client/postFx/hdr.cs @@ -172,6 +172,8 @@ singleton ShaderData( HDR_CombineShader ) samplerNames[2] = "$bloomTex"; samplerNames[3] = "$colorCorrectionTex"; + samplerNames[4] = "prepassTex"; + pixVersion = 3.0; }; @@ -253,8 +255,10 @@ singleton GFXStateBlockData( HDRStateBlock ) %combinePass.setShaderConst( "$g_fEnableBlueShift", $HDRPostFX::enableBlueShift ); %combinePass.setShaderConst( "$g_fBlueShiftColor", $HDRPostFX::blueShiftColor ); - %clampedGamma = mClamp( $pref::Video::Gamma, 0.001, 2.2); + %clampedGamma = mClamp( $pref::Video::Gamma, 2.0, 2.5); %combinePass.setShaderConst( "$g_fOneOverGamma", 1 / %clampedGamma ); + %combinePass.setShaderConst( "$Brightness", $pref::Video::Brightness ); + %combinePass.setShaderConst( "$Contrast", $pref::Video::Contrast ); %whiteCutoff = ( $HDRPostFX::whiteCutoff * $HDRPostFX::whiteCutoff ) * ( $HDRPostFX::whiteCutoff * $HDRPostFX::whiteCutoff ); @@ -329,7 +333,7 @@ singleton GFXStateBlockData( HDRStateBlock ) singleton PostEffect( HDRPostFX ) { isEnabled = false; - allowReflectPass = false; + allowReflectPass = true; // Resolve the HDR before we render any editor stuff // and before we resolve the scene to the backbuffer. @@ -355,6 +359,7 @@ singleton PostEffect( HDRPostFX ) new PostEffect() { + allowReflectPass = true; shader = HDR_DownScale4x4Shader; stateBlock = HDR_DownSampleStateBlock; texture[0] = "$inTex"; @@ -365,6 +370,7 @@ singleton PostEffect( HDRPostFX ) new PostEffect() { + allowReflectPass = true; internalName = "bloomH"; shader = HDR_BloomGaussBlurHShader; @@ -376,6 +382,7 @@ singleton PostEffect( HDRPostFX ) new PostEffect() { + allowReflectPass = true; internalName = "bloomV"; shader = HDR_BloomGaussBlurVShader; @@ -390,6 +397,7 @@ singleton PostEffect( HDRPostFX ) // Now calculate the adapted luminance. new PostEffect() { + allowReflectPass = true; internalName = "adaptLum"; shader = HDR_SampleLumShader; @@ -401,6 +409,7 @@ singleton PostEffect( HDRPostFX ) new PostEffect() { + allowReflectPass = true; shader = HDR_DownSampleLumShader; stateBlock = HDR_DownSampleStateBlock; texture[0] = "$inTex"; @@ -411,6 +420,7 @@ singleton PostEffect( HDRPostFX ) new PostEffect() { + allowReflectPass = true; shader = HDR_DownSampleLumShader; stateBlock = HDR_DownSampleStateBlock; texture[0] = "$inTex"; @@ -421,6 +431,7 @@ singleton PostEffect( HDRPostFX ) new PostEffect() { + allowReflectPass = true; shader = HDR_DownSampleLumShader; stateBlock = HDR_DownSampleStateBlock; texture[0] = "$inTex"; @@ -434,6 +445,7 @@ singleton PostEffect( HDRPostFX ) // one... PostEffect takes care to manage that. new PostEffect() { + allowReflectPass = true; internalName = "finalLum"; shader = HDR_CalcAdaptedLumShader; stateBlock = HDR_DownSampleStateBlock; @@ -450,6 +462,7 @@ singleton PostEffect( HDRPostFX ) // version of the scene. new PostEffect() { + allowReflectPass = true; internalName = "combinePass"; shader = HDR_CombineShader; @@ -458,6 +471,7 @@ singleton PostEffect( HDRPostFX ) texture[1] = "#adaptedLum"; texture[2] = "#bloomFinal"; texture[3] = $HDRPostFX::colorCorrectionRamp; + texture[4] = "#prepass"; target = "$backBuffer"; }; }; diff --git a/Templates/Empty/game/core/scripts/client/postFx/turbulence.cs b/Templates/Empty/game/core/scripts/client/postFx/turbulence.cs index c2309f8086..dd8c0e2dc1 100644 --- a/Templates/Empty/game/core/scripts/client/postFx/turbulence.cs +++ b/Templates/Empty/game/core/scripts/client/postFx/turbulence.cs @@ -47,7 +47,7 @@ singleton PostEffect( TurbulenceFx ) isEnabled = false; allowReflectPass = true; - renderTime = "PFXAfterBin"; + renderTime = "PFXAfterDiffuse"; renderBin = "GlowBin"; renderPriority = 0.5; // Render after the glows themselves diff --git a/Templates/Empty/game/core/scripts/client/renderManager.cs b/Templates/Empty/game/core/scripts/client/renderManager.cs index 5734bbce60..f746c45278 100644 --- a/Templates/Empty/game/core/scripts/client/renderManager.cs +++ b/Templates/Empty/game/core/scripts/client/renderManager.cs @@ -33,7 +33,7 @@ function initRenderManager() { enabled = "false"; - format = "GFXFormatR8G8B8A8"; + format = "GFXFormatR16G16B16A16F"; depthFormat = "GFXFormatD24S8"; aaLevel = 0; // -1 = match backbuffer @@ -49,20 +49,21 @@ function initRenderManager() // We really need to fix the sky to render after all the // meshes... but that causes issues in reflections. - DiffuseRenderPassManager.addManager( new RenderObjectMgr() { bintype = "Sky"; renderOrder = 0.1; processAddOrder = 0.1; } ); + DiffuseRenderPassManager.addManager( new RenderObjectMgr(SkyBin) { bintype = "Sky"; renderOrder = 0.1; processAddOrder = 0.1; } ); //DiffuseRenderPassManager.addManager( new RenderVistaMgr() { bintype = "Vista"; renderOrder = 0.15; processAddOrder = 0.15; } ); - DiffuseRenderPassManager.addManager( new RenderObjectMgr() { bintype = "Begin"; renderOrder = 0.2; processAddOrder = 0.2; } ); + DiffuseRenderPassManager.addManager( new RenderObjectMgr(BeginBin) { bintype = "Begin"; renderOrder = 0.2; processAddOrder = 0.2; } ); // Normal mesh rendering. - DiffuseRenderPassManager.addManager( new RenderTerrainMgr() { renderOrder = 0.4; processAddOrder = 0.4; } ); - DiffuseRenderPassManager.addManager( new RenderMeshMgr() { bintype = "Mesh"; renderOrder = 0.5; processAddOrder = 0.5; } ); - DiffuseRenderPassManager.addManager( new RenderImposterMgr() { renderOrder = 0.56; processAddOrder = 0.56; } ); - DiffuseRenderPassManager.addManager( new RenderObjectMgr() { bintype = "Object"; renderOrder = 0.6; processAddOrder = 0.6; } ); + DiffuseRenderPassManager.addManager( new 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() { bintype = "Shadow"; renderOrder = 0.7; processAddOrder = 0.7; } ); - DiffuseRenderPassManager.addManager( new RenderMeshMgr() { bintype = "Decal"; renderOrder = 0.8; processAddOrder = 0.8; } ); - DiffuseRenderPassManager.addManager( new RenderOcclusionMgr() { bintype = "Occluder"; renderOrder = 0.9; processAddOrder = 0.9; } ); + DiffuseRenderPassManager.addManager( new RenderObjectMgr(ShadowBin) { bintype = "Shadow"; renderOrder = 0.7; processAddOrder = 0.7; } ); + DiffuseRenderPassManager.addManager( new RenderMeshMgr(DecalRoadBin) { bintype = "DecalRoad"; renderOrder = 0.8; processAddOrder = 0.8; } ); + DiffuseRenderPassManager.addManager( new RenderMeshMgr(DecalBin) { bintype = "Decal"; renderOrder = 0.81; processAddOrder = 0.81; } ); + DiffuseRenderPassManager.addManager( new RenderOcclusionMgr(OccluderBin){ bintype = "Occluder"; renderOrder = 0.9; processAddOrder = 0.9; } ); // We now render translucent objects that should handle // their own fogging and lighting. @@ -70,10 +71,10 @@ function initRenderManager() // Note that the fog effect is triggered before this bin. DiffuseRenderPassManager.addManager( new RenderObjectMgr(ObjTranslucentBin) { bintype = "ObjectTranslucent"; renderOrder = 1.0; processAddOrder = 1.0; } ); - DiffuseRenderPassManager.addManager( new RenderObjectMgr() { bintype = "Water"; renderOrder = 1.2; processAddOrder = 1.2; } ); - DiffuseRenderPassManager.addManager( new RenderObjectMgr() { bintype = "Foliage"; renderOrder = 1.3; processAddOrder = 1.3; } ); - DiffuseRenderPassManager.addManager( new RenderParticleMgr() { renderOrder = 1.35; processAddOrder = 1.35; } ); - DiffuseRenderPassManager.addManager( new RenderTranslucentMgr() { renderOrder = 1.4; processAddOrder = 1.4; } ); + DiffuseRenderPassManager.addManager( new RenderObjectMgr(WaterBin) { bintype = "Water"; renderOrder = 1.2; processAddOrder = 1.2; } ); + DiffuseRenderPassManager.addManager( new RenderObjectMgr(FoliageBin) { bintype = "Foliage"; renderOrder = 1.3; processAddOrder = 1.3; } ); + DiffuseRenderPassManager.addManager( new RenderParticleMgr(ParticleBin) { renderOrder = 1.35; processAddOrder = 1.35; } ); + DiffuseRenderPassManager.addManager( new RenderTranslucentMgr(TranslucentBin){ renderOrder = 1.4; processAddOrder = 1.4; } ); DiffuseRenderPassManager.addManager(new RenderObjectMgr(FogBin){ bintype = "ObjectVolumetricFog"; renderOrder = 1.45; processAddOrder = 1.45; } ); @@ -85,7 +86,7 @@ function initRenderManager() DiffuseRenderPassManager.addManager( new RenderObjectMgr(EditorBin) { bintype = "Editor"; renderOrder = 1.6; processAddOrder = 1.6; } ); // Resolve format change token last. - DiffuseRenderPassManager.addManager( new RenderPassStateBin() { renderOrder = 1.7; stateToken = AL_FormatToken; } ); + DiffuseRenderPassManager.addManager( new RenderPassStateBin(FinalBin) { renderOrder = 1.7; stateToken = AL_FormatToken; } ); } /// This post effect is used to copy data from the non-MSAA back-buffer to the diff --git a/Templates/Empty/game/core/scripts/client/scatterSky.cs b/Templates/Empty/game/core/scripts/client/scatterSky.cs index 48a8fdbc7a..57a8a9fb11 100644 --- a/Templates/Empty/game/core/scripts/client/scatterSky.cs +++ b/Templates/Empty/game/core/scripts/client/scatterSky.cs @@ -22,13 +22,13 @@ new GFXStateBlockData( ScatterSkySBData ) { - cullDefined = true; + //cullDefined = true; cullMode = "GFXCullNone"; zDefined = true; zEnable = true; zWriteEnable = false; - zFunc = "GFXCmpLessEqual"; + //zFunc = "GFXCmpLessEqual"; samplersDefined = true; samplerStates[0] = SamplerClampLinear; diff --git a/Templates/Empty/game/core/scripts/client/shaders.cs b/Templates/Empty/game/core/scripts/client/shaders.cs index 98d0529ebe..002053a1ac 100644 --- a/Templates/Empty/game/core/scripts/client/shaders.cs +++ b/Templates/Empty/game/core/scripts/client/shaders.cs @@ -101,4 +101,40 @@ singleton ShaderData( OffscreenParticleCompositeShaderData ) samplerNames[1] = "$alphaMap"; pixVersion = 1.4; +}; + +singleton ShaderData( VolumetricFogPrePassShader ) +{ + DXVertexShaderFile = "shaders/common/VolumetricFog/VFogPreV.hlsl"; + DXPixelShaderFile = "shaders/common/VolumetricFog/VFogPreP.hlsl"; + + OGLVertexShaderFile = "shaders/common/VolumetricFog/gl/VFogPreV.glsl"; + OGLPixelShaderFile = "shaders/common/VolumetricFog/gl/VFogPreP.glsl"; + + pixVersion = 3.0; +}; +singleton ShaderData( VolumetricFogShader ) +{ + DXVertexShaderFile = "shaders/common/VolumetricFog/VFogV.hlsl"; + DXPixelShaderFile = "shaders/common/VolumetricFog/VFogP.hlsl"; + + OGLVertexShaderFile = "shaders/common/VolumetricFog/gl/VFogV.glsl"; + OGLPixelShaderFile = "shaders/common/VolumetricFog/gl/VFogP.glsl"; + + samplerNames[0] = "$prepassTex"; + samplerNames[1] = "$depthBuffer"; + samplerNames[2] = "$frontBuffer"; + samplerNames[3] = "$density"; + + pixVersion = 3.0; +}; +singleton ShaderData( VolumetricFogReflectionShader ) +{ + DXVertexShaderFile = "shaders/common/VolumetricFog/VFogPreV.hlsl"; + DXPixelShaderFile = "shaders/common/VolumetricFog/VFogRefl.hlsl"; + + OGLVertexShaderFile = "shaders/common/VolumetricFog/gl/VFogPreV.glsl"; + OGLPixelShaderFile = "shaders/common/VolumetricFog/gl/VFogRefl.glsl"; + + pixVersion = 3.0; }; \ No newline at end of file diff --git a/Templates/Empty/game/shaders/common/basicCloudsV.hlsl b/Templates/Empty/game/shaders/common/basicCloudsV.hlsl index 477f17d508..a176fdbcdc 100644 --- a/Templates/Empty/game/shaders/common/basicCloudsV.hlsl +++ b/Templates/Empty/game/shaders/common/basicCloudsV.hlsl @@ -46,7 +46,6 @@ ConnectData main( CloudVert IN ) ConnectData OUT; OUT.hpos = mul(modelview, float4(IN.pos,1.0)); - OUT.hpos.w = OUT.hpos.z; float2 uv = IN.uv0; uv += texOffset; diff --git a/Templates/Empty/game/shaders/common/cloudLayerV.hlsl b/Templates/Empty/game/shaders/common/cloudLayerV.hlsl index 94f8b62cb6..d60dd251d8 100644 --- a/Templates/Empty/game/shaders/common/cloudLayerV.hlsl +++ b/Templates/Empty/game/shaders/common/cloudLayerV.hlsl @@ -63,7 +63,6 @@ ConnectData main( CloudVert IN ) ConnectData OUT; OUT.hpos = mul(modelview, float4(IN.pos,1.0)); - OUT.hpos.w = OUT.hpos.z; // Offset the uv so we don't have a seam directly over our head. float2 uv = IN.uv0 + float2( 0.5, 0.5 ); diff --git a/Templates/Empty/game/shaders/common/gl/basicCloudsV.glsl b/Templates/Empty/game/shaders/common/gl/basicCloudsV.glsl index 40c597120e..cccbafa8ca 100644 --- a/Templates/Empty/game/shaders/common/gl/basicCloudsV.glsl +++ b/Templates/Empty/game/shaders/common/gl/basicCloudsV.glsl @@ -41,7 +41,6 @@ out vec2 texCoord; void main() { gl_Position = tMul(modelview, IN_pos); - gl_Position.w = gl_Position.z; vec2 uv = IN_uv0; uv += texOffset; diff --git a/Templates/Empty/game/shaders/common/gl/cloudLayerV.glsl b/Templates/Empty/game/shaders/common/gl/cloudLayerV.glsl index cba5c009ad..395c6f286e 100644 --- a/Templates/Empty/game/shaders/common/gl/cloudLayerV.glsl +++ b/Templates/Empty/game/shaders/common/gl/cloudLayerV.glsl @@ -62,7 +62,6 @@ void main() vec2 IN_uv0 = vTexCoord0.st; gl_Position = modelview * IN_pos; - gl_Position.w = gl_Position.z; // Offset the uv so we don't have a seam directly over our head. vec2 uv = IN_uv0 + vec2( 0.5, 0.5 ); diff --git a/Templates/Empty/game/shaders/common/lighting/advanced/gl/deferredShadingP.glsl b/Templates/Empty/game/shaders/common/lighting/advanced/gl/deferredShadingP.glsl index 4ee4b1d81f..8af37ef0cc 100644 --- a/Templates/Empty/game/shaders/common/lighting/advanced/gl/deferredShadingP.glsl +++ b/Templates/Empty/game/shaders/common/lighting/advanced/gl/deferredShadingP.glsl @@ -22,7 +22,7 @@ #include "../../../gl/hlslCompat.glsl" #include "shadergen:/autogenConditioners.h" -#include "../../../postfx/gl/postFx.glsl" +#include "../../../postFx/gl/postFX.glsl" #include "../../../gl/torque.glsl" uniform sampler2D colorBufferTex; diff --git a/Templates/Empty/game/tools/materialEditor/gui/guiMaterialPropertiesWindow.ed.gui b/Templates/Empty/game/tools/materialEditor/gui/guiMaterialPropertiesWindow.ed.gui index 2062f43f30..63ce28e2a8 100644 --- a/Templates/Empty/game/tools/materialEditor/gui/guiMaterialPropertiesWindow.ed.gui +++ b/Templates/Empty/game/tools/materialEditor/gui/guiMaterialPropertiesWindow.ed.gui @@ -1354,132 +1354,6 @@ bitmap = "tools/gui/images/delete"; }; }; - new GuiBitmapCtrl(){ - position="6 357"; - extent ="175 2"; - HorizSizing = "width"; - bitmap ="tools/gui/images/separator-v"; - }; - new GuiContainer(){ // Environment Map - profile="ToolsGuiDefaultProfile"; - isContainer = "1"; - position = "6 359"; - Extent = "185 52"; - HorizSizing = "width"; - - new GuiBitmapCtrl() { - canSaveDynamicFields = "0"; - internalName = "envMapDisplayBitmap"; - Enabled = "1"; - isContainer = "0"; - Profile = "ToolsGuiDefaultProfile"; - HorizSizing = "right"; - VertSizing = "bottom"; - position = "1 1"; - Extent = "48 48"; - MinExtent = "8 2"; - canSave = "1"; - Visible = "1"; - hovertime = "1000"; - bitmap = "tools/materialeditor/gui/unknownImage"; - wrap = "0"; - }; - new GuiTextCtrl() { - canSaveDynamicFields = "0"; - Enabled = "1"; - isContainer = "0"; - Profile = "EditorTextProfile"; - HorizSizing = "right"; - VertSizing = "bottom"; - position = "56 -3"; - Extent = "72 18"; - MinExtent = "8 2"; - canSave = "1"; - Visible = "1"; - hovertime = "1000"; - Margin = "0 0 0 0"; - Padding = "0 0 0 0"; - AnchorTop = "1"; - AnchorBottom = "0"; - AnchorLeft = "1"; - AnchorRight = "0"; - text = "Env Map"; - maxLength = "1024"; - }; - new GuiBitmapButtonCtrl() { - canSaveDynamicFields = "0"; - Enabled = "1"; - isContainer = "0"; - Profile = "ToolsGuiDefaultProfile"; - HorizSizing = "right"; - VertSizing = "bottom"; - position = "1 1"; - Extent = "48 48"; - MinExtent = "8 2"; - canSave = "1"; - Visible = "1"; - Command = "MaterialEditorGui.updateTextureMap(\"env\", 1);"; - tooltipprofile = "ToolsGuiDefaultProfile"; - ToolTip = "Change the active Environment Map for this layer."; - hovertime = "1000"; - groupNum = "-1"; - buttonType = "PushButton"; - useMouseEvents = "0"; - bitmap = "tools/materialEditor/gui/cubemapBtnBorder"; - }; - new GuiTextCtrl() { - canSaveDynamicFields = "0"; - internalName = "envMapNameText"; - Enabled = "1"; - isContainer = "0"; - Profile = "ToolsGuiTextProfile"; - HorizSizing = "width"; - VertSizing = "bottom"; - position = "56 16"; - Extent = "143 17"; - MinExtent = "8 2"; - canSave = "1"; - Visible = "1"; - hovertime = "1000"; - Margin = "0 0 0 0"; - Padding = "0 0 0 0"; - AnchorTop = "1"; - AnchorBottom = "0"; - AnchorLeft = "1"; - AnchorRight = "0"; - text = "None"; - maxLength = "1024"; - }; - new GuiButtonCtrl(){ - profile="ToolsGuiButtonProfile"; - text ="Edit"; - HorizSizing = "left"; - VertSizing = "bottom"; - position = "134 34"; - Extent = "40 16"; - buttonType = "PushButton"; - command="MaterialEditorGui.updateTextureMap(\"env\", 1);"; - }; - new GuiBitmapButtonCtrl() { - canSaveDynamicFields = "0"; - Enabled = "1"; - isContainer = "0"; - Profile = "ToolsGuiDefaultProfile"; - HorizSizing = "left"; - VertSizing = "bottom"; - position = "177 34"; - Extent = "16 16"; - MinExtent = "8 2"; - canSave = "1"; - Visible = "1"; - Command = "MaterialEditorGui.updateTextureMap(\"env\", 0);"; - hovertime = "1000"; - groupNum = "-1"; - buttonType = "PushButton"; - useMouseEvents = "0"; - bitmap = "tools/gui/images/delete"; - }; - }; }; }; new GuiRolloutCtrl() { @@ -1491,6 +1365,7 @@ Position = "0 0"; Extent = "195 0"; Caption = "Accumulation Properties"; + Expanded = false; Margin = "-1 0 0 0"; DragSizable = false; container = true; @@ -1967,6 +1842,7 @@ Position = "0 0"; Extent = "185 0"; Caption = "Lighting Properties"; + Expanded = false; Margin = "-1 0 0 0"; DragSizable = false; container = true; @@ -2364,101 +2240,6 @@ useMouseEvents = "0"; useInactiveState = "0"; }; - new GuiCheckBoxCtrl() { - canSaveDynamicFields = "0"; - internalName = "subSurfaceCheckbox"; - Enabled = "1"; - isContainer = "0"; - Profile = "ToolsGuiCheckBoxProfile"; - HorizSizing = "right"; - VertSizing = "bottom"; - position = "8 46"; - Extent = "79 16"; - MinExtent = "8 2"; - canSave = "1"; - Visible = "1"; - Command = "MaterialEditorGui.updateActiveMaterial(\"subSurface[\" @ MaterialEditorGui.currentLayer @ \"]\", $ThisControl.getValue());"; - tooltipprofile = "ToolsGuiDefaultProfile"; - ToolTip = "Enables the use of subsurface scattering for this layer."; - hovertime = "1000"; - text = "Sub Surface"; - groupNum = "-1"; - buttonType = "ToggleButton"; - useMouseEvents = "0"; - useInactiveState = "0"; - }; - new GuiSwatchButtonCtrl() { - canSaveDynamicFields = "0"; - internalName = "subSurfaceColorSwatch"; - Enabled = "1"; - isContainer = "0"; - Profile = "GuiInspectorSwatchButtonProfile"; - HorizSizing = "right"; - VertSizing = "bottom"; - position = "90 46"; - Extent = "16 16"; - MinExtent = "8 2"; - canSave = "1"; - Visible = "1"; - Command = "getColorF(materialEd_PreviewMaterial.subSurfaceColor[MaterialEditorGui.currentLayer], \"MaterialEditorGui.updateSubSurfaceColor\");"; - tooltip = "Set the subsurface scattering color"; - hovertime = "1000"; - groupNum = "-1"; - buttonType = "PushButton"; - useMouseEvents = "0"; - }; - new GuiTextEditCtrl() { - canSaveDynamicFields = "0"; - internalName = "subSurfaceRolloffTextEdit"; - Enabled = "1"; - isContainer = "0"; - Profile = "ToolsGuiTextEditProfile"; - HorizSizing = "right"; - VertSizing = "bottom"; - position = "114 45"; - Extent = "29 18"; - MinExtent = "8 2"; - canSave = "1"; - Visible = "1"; - tooltip = "Set the subsurface rolloff factor"; - Command = "MaterialEditorGui.updateActiveMaterial(\"subSurfaceRolloff[\" @ MaterialEditorGui.currentLayer @ \"]\", $ThisControl.getText());"; - hovertime = "1000"; - AnchorTop = "1"; - AnchorBottom = "0"; - AnchorLeft = "1"; - AnchorRight = "0"; - text = "32"; - maxLength = "5"; - }; - new GuiTextCtrl() { - HorizSizing = "right"; - VertSizing = "bottom"; - position = "9 65"; - Extent = "89 16"; - text = "Minnaert constant"; - }; - new GuiTextEditCtrl() { - canSaveDynamicFields = "0"; - internalName = "minnaertTextEdit"; - Enabled = "1"; - isContainer = "0"; - Profile = "ToolsGuiTextEditProfile"; - HorizSizing = "right"; - VertSizing = "bottom"; - position = "114 65"; - Extent = "29 18"; - MinExtent = "8 2"; - canSave = "1"; - Visible = "1"; - Command = "MaterialEditorGui.updateActiveMaterial(\"minnaertConstant[\" @ MaterialEditorGui.currentLayer @ \"]\", $ThisControl.getText());"; - hovertime = "1000"; - AnchorTop = "1"; - AnchorBottom = "0"; - AnchorLeft = "1"; - AnchorRight = "0"; - text = "32"; - maxLength = "3"; - }; }; }; }; @@ -2471,9 +2252,9 @@ Position = "0 0"; Extent = "185 0"; Caption = "Animation Properties"; + Expanded = false; Margin = "-1 0 0 0"; DragSizable = false; - Expanded = false; container = true; parentRollout = %this.rollout; object = %behavior; @@ -3283,6 +3064,7 @@ Position = "0 0"; Extent = "202 0"; Caption = "Advanced (all layers)"; + Expanded = false; Margin = "4 4 4 0"; DragSizable = false; container = true; @@ -3519,7 +3301,7 @@ Profile = "ToolsGuiCheckBoxProfile"; HorizSizing = "right"; VertSizing = "bottom"; - position = "100 56"; + position = "105 55"; Extent = "85 16"; MinExtent = "8 2"; canSave = "1"; diff --git a/Templates/Empty/game/tools/materialEditor/scripts/materialEditor.ed.cs b/Templates/Empty/game/tools/materialEditor/scripts/materialEditor.ed.cs index be7d55c393..c1f01f1a77 100644 --- a/Templates/Empty/game/tools/materialEditor/scripts/materialEditor.ed.cs +++ b/Templates/Empty/game/tools/materialEditor/scripts/materialEditor.ed.cs @@ -918,9 +918,6 @@ singleton Material(notDirtyMaterial) MaterialEditorPropertiesWindow-->vertLitCheckbox.setValue((%material).vertLit[%layer]); MaterialEditorPropertiesWindow-->vertColorSwatch.color = (%material).vertColor[%layer]; MaterialEditorPropertiesWindow-->subSurfaceCheckbox.setValue((%material).subSurface[%layer]); - MaterialEditorPropertiesWindow-->subSurfaceColorSwatch.color = (%material).subSurfaceColor[%layer]; - MaterialEditorPropertiesWindow-->subSurfaceRolloffTextEdit.setText((%material).subSurfaceRolloff[%layer]); - MaterialEditorPropertiesWindow-->minnaertTextEdit.setText((%material).minnaertConstant[%layer]); // Animation properties MaterialEditorPropertiesWindow-->RotationAnimation.setValue(0); diff --git a/Templates/Empty/game/tools/shapeEditor/scripts/shapeEditor.ed.cs b/Templates/Empty/game/tools/shapeEditor/scripts/shapeEditor.ed.cs index 180a9a8ab5..391e0b2170 100644 --- a/Templates/Empty/game/tools/shapeEditor/scripts/shapeEditor.ed.cs +++ b/Templates/Empty/game/tools/shapeEditor/scripts/shapeEditor.ed.cs @@ -380,7 +380,8 @@ function strcapitalise( %str ) // Ignore assets in the tools folder %fullPath = makeRelativePath( %fullPath, getMainDotCSDir() ); - %splitPath = strreplace( %fullPath, "/", " " ); + %splitPath = strreplace( %fullPath, " ", "_" ); + %splitPath = strreplace( %splitPath, "/", " " ); if ( getWord( %splitPath, 0 ) $= "tools" ) { %fullPath = findNextFileMultiExpr( %filePatterns ); @@ -393,6 +394,7 @@ function strcapitalise( %str ) // Add this file's path ( parent folders ) to the // popup menu if it isn't there yet. %temp = strreplace( %pathFolders, " ", "/" ); + %temp = strreplace( %temp, "_", " " ); %r = ShapeEdSelectMenu.findText( %temp ); if ( %r == -1 ) ShapeEdSelectMenu.add( %temp ); diff --git a/Templates/Empty/game/tools/worldEditor/main.cs b/Templates/Empty/game/tools/worldEditor/main.cs index a6ecb2872b..59301ea53d 100644 --- a/Templates/Empty/game/tools/worldEditor/main.cs +++ b/Templates/Empty/game/tools/worldEditor/main.cs @@ -120,6 +120,9 @@ function initializeWorldEditor() EVisibility.addOption( "AL: Light Specular Viz", "$AL_LightSpecularVisualizeVar", "toggleLightSpecularViz" ); EVisibility.addOption( "AL: Normals Viz", "$AL_NormalsVisualizeVar", "toggleNormalsViz" ); EVisibility.addOption( "AL: Depth Viz", "$AL_DepthVisualizeVar", "toggleDepthViz" ); + EVisibility.addOption( "AL: Color Buffer", "$AL_ColorBufferShaderVar", "toggleColorBufferViz" ); + EVisibility.addOption( "AL: Spec Map", "$AL_SpecMapShaderVar", "toggleSpecMapViz"); + EVisibility.addOption( "AL: Backbuffer", "$AL_BackbufferVisualizeVar", "toggleBackbufferViz" ); EVisibility.addOption( "AL: Glow Buffer", "$AL_GlowVisualizeVar", "toggleGlowViz" ); EVisibility.addOption( "AL: PSSM Cascade Viz", "$AL::PSSMDebugRender", "" ); EVisibility.addOption( "Frustum Lock", "$Scene::lockCull", "" ); diff --git a/Templates/Empty/game/tools/worldEditor/scripts/editors/creator.ed.cs b/Templates/Empty/game/tools/worldEditor/scripts/editors/creator.ed.cs index dc5d7f9916..43d4fb65c1 100644 --- a/Templates/Empty/game/tools/worldEditor/scripts/editors/creator.ed.cs +++ b/Templates/Empty/game/tools/worldEditor/scripts/editors/creator.ed.cs @@ -318,7 +318,8 @@ } %fullPath = makeRelativePath( %fullPath, getMainDotCSDir() ); - %splitPath = strreplace( %fullPath, "/", " " ); + %splitPath = strreplace( %fullPath, " ", "_" ); + %splitPath = strreplace( %splitPath, "/", " " ); if( getWord(%splitPath, 0) $= "tools" ) { %fullPath = findNextFileMultiExpr( getFormatExtensions() ); @@ -332,6 +333,7 @@ // Add this file's path (parent folders) to the // popup menu if it isn't there yet. %temp = strreplace( %pathFolders, " ", "/" ); + %temp = strreplace( %temp, "_", " " ); %r = CreatorPopupMenu.findText( %temp ); if ( %r == -1 ) { @@ -430,7 +432,8 @@ while ( %fullPath !$= "" ) { %fullPath = makeRelativePath( %fullPath, getMainDotCSDir() ); - %splitPath = strreplace( %fullPath, "/", " " ); + %splitPath = strreplace( %fullPath, " ", "_" ); + %splitPath = strreplace( %splitPath, "/", " " ); if( getWord(%splitPath, 0) $= "tools" ) { %fullPath = findNextFile( %expr ); @@ -444,6 +447,7 @@ // Add this file's path (parent folders) to the // popup menu if it isn't there yet. %temp = strreplace( %pathFolders, " ", "/" ); + %temp = strreplace( %temp, "_", " " ); %r = CreatorPopupMenu.findText( %temp ); if ( %r == -1 ) { diff --git a/Templates/Empty/game/tools/worldEditor/scripts/menuHandlers.ed.cs b/Templates/Empty/game/tools/worldEditor/scripts/menuHandlers.ed.cs index 97ae5d2d70..8ee4f27ff5 100644 --- a/Templates/Empty/game/tools/worldEditor/scripts/menuHandlers.ed.cs +++ b/Templates/Empty/game/tools/worldEditor/scripts/menuHandlers.ed.cs @@ -244,6 +244,8 @@ function EditorSaveMissionMenu() function EditorSaveMission() { + // just save the mission without renaming it + // first check for dirty and read-only files: if((EWorldEditor.isDirty || ETerrainEditor.isMissionDirty) && !isWriteableFileName($Server::MissionFile)) { diff --git a/Templates/Full/game/core/art/gui/netGraphGui.gui b/Templates/Full/game/core/art/gui/netGraphGui.gui index b62e8ea23b..b034a447ee 100644 --- a/Templates/Full/game/core/art/gui/netGraphGui.gui +++ b/Templates/Full/game/core/art/gui/netGraphGui.gui @@ -73,100 +73,380 @@ new GuiControlProfile (NetGraphPacketLossProfile) }; //--- OBJECT WRITE BEGIN --- -new GuiControl(NetGraphGui) { - profile = "NetGraphProfile"; - horizSizing = "left"; - vertSizing = "bottom"; +%guiContent = new GuiControl(NetGraphGui) { position = "0 0"; - extent = "640 480"; + extent = "1024 768"; minExtent = "8 2"; + horizSizing = "left"; + vertSizing = "bottom"; + profile = "NetGraphProfile"; visible = "1"; - noCursor = "1"; - + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "1"; + canSave = "1"; + canSaveDynamicFields = "1"; + noCursor = "1"; + new GuiGraphCtrl(NetGraph) { - profile = "NetGraphKeyContainerProfile"; - horizSizing = "left"; - vertSizing = "bottom"; - position = "432 5"; + centerY = "1"; + plotColor[0] = "1 1 1 1"; + plotColor[1] = "1 0 0 1"; + plotColor[2] = "0 1 0 1"; + plotColor[3] = "0 0 1 1"; + plotColor[4] = "0 1 1 1"; + plotColor[5] = "0 0 0 1"; + plotType[0] = "PolyLine"; + plotType[1] = "PolyLine"; + plotType[2] = "PolyLine"; + plotType[3] = "PolyLine"; + plotType[4] = "PolyLine"; + plotType[5] = "PolyLine"; + plotInterval[0] = "0"; + plotInterval[1] = "0"; + plotInterval[2] = "0"; + plotInterval[3] = "0"; + plotInterval[4] = "0"; + plotInterval[5] = "0"; + position = "816 5"; extent = "200 200"; minExtent = "8 2"; + horizSizing = "left"; + vertSizing = "bottom"; + profile = "NetGraphKeyContainerProfile"; visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; }; - new GuiControl() { - profile = "NetGraphKeyContainerProfile"; + position = "816 205"; + extent = "200 104"; + minExtent = "8 2"; horizSizing = "left"; vertSizing = "bottom"; - position = "432 205"; - extent = "200 52"; - minExtent = "8 2"; + profile = "NetGraphKeyContainerProfile"; visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "1"; + canSave = "1"; + canSaveDynamicFields = "0"; new GuiTextCtrl(GhostsActive) { - profile = "NetGraphGhostsActiveProfile"; - horizSizing = "left"; - vertSizing = "bottom"; + text = "Ghosts Active"; + maxLength = "255"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "0"; + anchorLeft = "1"; + anchorRight = "0"; position = "0 0"; extent = "100 18"; minExtent = "8 2"; + horizSizing = "left"; + vertSizing = "bottom"; + profile = "NetGraphGhostsActiveProfile"; visible = "1"; - text = "Ghosts Active"; - maxLength = "255"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "1"; + canSave = "1"; + canSaveDynamicFields = "0"; }; new GuiTextCtrl(GhostUpdates) { - profile = "NetGraphGhostUpdatesProfile"; - horizSizing = "left"; - vertSizing = "bottom"; + text = "Ghost Updates"; + maxLength = "255"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "0"; + anchorLeft = "1"; + anchorRight = "0"; position = "100 0"; extent = "100 18"; minExtent = "8 2"; + horizSizing = "left"; + vertSizing = "bottom"; + profile = "NetGraphGhostUpdatesProfile"; visible = "1"; - text = "Ghost Updates"; - maxLength = "255"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "1"; + canSave = "1"; + canSaveDynamicFields = "0"; }; new GuiTextCtrl(BitsSent) { - profile = "NetGraphBitsSentProfile"; - horizSizing = "left"; - vertSizing = "bottom"; - position = "0 18 "; + text = "Bytes Sent"; + maxLength = "255"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "0"; + anchorLeft = "1"; + anchorRight = "0"; + position = "0 18"; extent = "100 18"; minExtent = "8 2"; + horizSizing = "left"; + vertSizing = "bottom"; + profile = "NetGraphBitsSentProfile"; visible = "1"; - text = "Bytes Sent"; - maxLength = "255"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "1"; + canSave = "1"; + canSaveDynamicFields = "0"; }; new GuiTextCtrl(BitsReceived) { - profile = "NetGraphBitsReceivedProfile"; - horizSizing = "left"; - vertSizing = "bottom"; + text = "Bytes Received"; + maxLength = "255"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "0"; + anchorLeft = "1"; + anchorRight = "0"; position = "100 18"; extent = "100 18"; minExtent = "8 2"; + horizSizing = "left"; + vertSizing = "bottom"; + profile = "NetGraphBitsReceivedProfile"; visible = "1"; - text = "Bytes Received"; - maxLength = "255"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "1"; + canSave = "1"; + canSaveDynamicFields = "0"; }; new GuiTextCtrl(Latency) { - profile = "NetGraphLatencyProfile"; - horizSizing = "left"; - vertSizing = "bottom"; + text = "Latency"; + maxLength = "255"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "0"; + anchorLeft = "1"; + anchorRight = "0"; position = "0 36"; extent = "100 18"; minExtent = "8 2"; + horizSizing = "left"; + vertSizing = "bottom"; + profile = "NetGraphLatencyProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "1"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiTextCtrl(PacketLoss) { + text = "Packet Loss"; + maxLength = "255"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "0"; + anchorLeft = "1"; + anchorRight = "0"; + position = "100 36"; + extent = "59 18"; + minExtent = "8 2"; + horizSizing = "left"; + vertSizing = "bottom"; + profile = "NetGraphPacketLossProfile"; visible = "1"; - text = "Latency"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "1"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiTextCtrl() { + text = "Network Simulation:"; maxLength = "255"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "0"; + anchorLeft = "1"; + anchorRight = "0"; + position = "0 52"; + extent = "97 18"; + minExtent = "8 2"; + horizSizing = "left"; + vertSizing = "bottom"; + profile = "NetGraphPacketLossProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "1"; + canSave = "1"; + canSaveDynamicFields = "0"; }; - new GuiTextCtrl(PacketLoss) { + new GuiTextCtrl() { + text = "Simulated Latency:"; + maxLength = "255"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "0"; + anchorLeft = "1"; + anchorRight = "0"; + position = "0 68"; + extent = "91 18"; + minExtent = "8 2"; + horizSizing = "left"; + vertSizing = "bottom"; profile = "NetGraphPacketLossProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "1"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiTextCtrl() { + text = "ms"; + maxLength = "255"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "0"; + anchorLeft = "1"; + anchorRight = "0"; + position = "179 68"; + extent = "20 18"; + minExtent = "8 2"; horizSizing = "left"; vertSizing = "bottom"; - position = "100 36"; - extent = "59 18"; + profile = "NetGraphPacketLossProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "1"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiTextEditCtrl(NetGraphSimLatency) { + historySize = "0"; + tabComplete = "0"; + sinkAllKeyEvents = "0"; + password = "0"; + passwordMask = "*"; + text = "0"; + maxLength = "1024"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "0"; + anchorLeft = "1"; + anchorRight = "0"; + position = "112 67"; + extent = "64 18"; minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiTextEditProfile"; visible = "1"; - text = "Packet Loss"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "1"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiTextCtrl() { + text = "Simulated Packet Loss:"; maxLength = "255"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "0"; + anchorLeft = "1"; + anchorRight = "0"; + position = "0 83"; + extent = "111 18"; + minExtent = "8 2"; + horizSizing = "left"; + vertSizing = "bottom"; + profile = "NetGraphPacketLossProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "1"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiTextCtrl() { + text = "%"; + maxLength = "255"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "0"; + anchorLeft = "1"; + anchorRight = "0"; + position = "179 84"; + extent = "20 18"; + minExtent = "8 2"; + horizSizing = "left"; + vertSizing = "bottom"; + profile = "NetGraphPacketLossProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "1"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiTextEditCtrl(NetGraphSimPacket) { + historySize = "0"; + tabComplete = "0"; + sinkAllKeyEvents = "0"; + password = "0"; + passwordMask = "*"; + text = "0"; + maxLength = "1024"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "0"; + anchorLeft = "1"; + anchorRight = "0"; + position = "112 85"; + extent = "64 18"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiTextEditProfile"; + visible = "1"; + active = "1"; + command = "if(NetGraphSimLatency.text $= \"\" || NetGraphSimLatency.text < 0)\n{\n NetGraphSimLatency.text = 0;\n}\n\nif(NetGraphSimPacket.text $= \"\" || NetGraphSimPacket.text < 0)\n{\n NetGraphSimLatency.text = 0;\n}\nelse if(NetGraphSimPacket.text > 100)\n{\n NetGraphSimPacket.text = 100;\n}\n\nnetSimulateLag( NetGraphSimLatency.text, NetGraphSimPacket.text );"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "1"; + canSave = "1"; + canSaveDynamicFields = "0"; }; }; }; @@ -186,7 +466,10 @@ function toggleNetGraph() Canvas.add(NetGraphGui); } else + { Canvas.remove(NetGraphGui); + netSimulateLag( 0, 0 ); + } } function NetGraph::updateStats() @@ -236,3 +519,39 @@ function NetGraph::toggleKey() PacketLoss.visible = 0; } } + +function NetGraphSimLatency::onReturn(%this) +{ + NetGraph.updateNetworkSimulation(); +} + +function NetGraphSimPacket::onReturn(%this) +{ + NetGraph.updateNetworkSimulation(); +} + +function NetGraph::updateNetworkSimulation(%this) +{ + %latency = NetGraphSimLatency.getText(); + + if(%latency $= "" || %latency < 0) + { + NetGraphSimLatency.text = 0; + %latency = 0; + } + + %packetLoss = NetGraphSimPacket.getText(); + + if(%packetLoss $= "" || %packetLoss < 0) + { + NetGraphSimLatency.text = 0; + %packetLoss = 0; + } + else if(%packetLoss > 100) + { + NetGraphSimPacket.text = 100; + %packetLoss = 100; + } + + netSimulateLag( %latency, %packetLoss ); +} \ No newline at end of file diff --git a/Templates/Full/game/core/scripts/client/lighting/advanced/deferredShading.cs b/Templates/Full/game/core/scripts/client/lighting/advanced/deferredShading.cs index d53e6965f6..ad9732e0f2 100644 --- a/Templates/Full/game/core/scripts/client/lighting/advanced/deferredShading.cs +++ b/Templates/Full/game/core/scripts/client/lighting/advanced/deferredShading.cs @@ -55,7 +55,7 @@ singleton ShaderData( DeferredColorShader ) singleton PostEffect( AL_DeferredShading ) { - renderTime = "PFXBeforeBin"; + renderTime = "PFXAfterBin"; renderBin = "SkyBin"; shader = AL_DeferredShader; stateBlock = AL_DeferredShadingState; diff --git a/Templates/Full/game/core/scripts/client/lighting/advanced/shaders.cs b/Templates/Full/game/core/scripts/client/lighting/advanced/shaders.cs index eaf7f70b8e..22d1bdbdf2 100644 --- a/Templates/Full/game/core/scripts/client/lighting/advanced/shaders.cs +++ b/Templates/Full/game/core/scripts/client/lighting/advanced/shaders.cs @@ -39,9 +39,11 @@ mSamplerNames[0] = "prePassBuffer"; samplerStates[1] = SamplerClampPoint; // Shadow Map (Do not change this to linear, as all cards can not filter equally.) mSamplerNames[1] = "shadowMap"; - samplerStates[2] = SamplerClampLinear; // SSAO Mask - mSamplerNames[2] = "ssaoMask"; - samplerStates[3] = SamplerWrapPoint; // Random Direction Map + 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; @@ -114,8 +116,10 @@ mSamplerNames[0] = "prePassBuffer"; samplerStates[1] = SamplerClampPoint; // Shadow Map (Do not use linear, these are perspective projections) mSamplerNames[1] = "shadowMap"; - samplerStates[2] = SamplerClampLinear; // Cookie Map - samplerStates[3] = SamplerWrapPoint; // Random Direction Map + 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; diff --git a/Templates/Full/game/scripts/client/default.bind.cs b/Templates/Full/game/scripts/client/default.bind.cs index d2ca237301..9dcbca96b5 100644 --- a/Templates/Full/game/scripts/client/default.bind.cs +++ b/Templates/Full/game/scripts/client/default.bind.cs @@ -618,7 +618,12 @@ function bringUpOptions(%val) function showMetrics(%val) { if(%val) - metrics("fps gfx shadow sfx terrain groundcover forest net"); + { + if(!Canvas.isMember(FrameOverlayGui)) + metrics("fps gfx shadow sfx terrain groundcover forest net"); + else + metrics(""); + } } GlobalActionMap.bind(keyboard, "ctrl F2", showMetrics); diff --git a/Templates/Full/game/shaders/common/basicCloudsV.hlsl b/Templates/Full/game/shaders/common/basicCloudsV.hlsl index 477f17d508..a176fdbcdc 100644 --- a/Templates/Full/game/shaders/common/basicCloudsV.hlsl +++ b/Templates/Full/game/shaders/common/basicCloudsV.hlsl @@ -46,7 +46,6 @@ ConnectData main( CloudVert IN ) ConnectData OUT; OUT.hpos = mul(modelview, float4(IN.pos,1.0)); - OUT.hpos.w = OUT.hpos.z; float2 uv = IN.uv0; uv += texOffset; diff --git a/Templates/Full/game/shaders/common/cloudLayerV.hlsl b/Templates/Full/game/shaders/common/cloudLayerV.hlsl index 94f8b62cb6..d60dd251d8 100644 --- a/Templates/Full/game/shaders/common/cloudLayerV.hlsl +++ b/Templates/Full/game/shaders/common/cloudLayerV.hlsl @@ -63,7 +63,6 @@ ConnectData main( CloudVert IN ) ConnectData OUT; OUT.hpos = mul(modelview, float4(IN.pos,1.0)); - OUT.hpos.w = OUT.hpos.z; // Offset the uv so we don't have a seam directly over our head. float2 uv = IN.uv0 + float2( 0.5, 0.5 ); diff --git a/Templates/Full/game/shaders/common/gl/basicCloudsV.glsl b/Templates/Full/game/shaders/common/gl/basicCloudsV.glsl index 40c597120e..cccbafa8ca 100644 --- a/Templates/Full/game/shaders/common/gl/basicCloudsV.glsl +++ b/Templates/Full/game/shaders/common/gl/basicCloudsV.glsl @@ -41,7 +41,6 @@ out vec2 texCoord; void main() { gl_Position = tMul(modelview, IN_pos); - gl_Position.w = gl_Position.z; vec2 uv = IN_uv0; uv += texOffset; diff --git a/Templates/Full/game/shaders/common/gl/cloudLayerV.glsl b/Templates/Full/game/shaders/common/gl/cloudLayerV.glsl index cba5c009ad..395c6f286e 100644 --- a/Templates/Full/game/shaders/common/gl/cloudLayerV.glsl +++ b/Templates/Full/game/shaders/common/gl/cloudLayerV.glsl @@ -62,7 +62,6 @@ void main() vec2 IN_uv0 = vTexCoord0.st; gl_Position = modelview * IN_pos; - gl_Position.w = gl_Position.z; // Offset the uv so we don't have a seam directly over our head. vec2 uv = IN_uv0 + vec2( 0.5, 0.5 ); diff --git a/Templates/Full/game/shaders/common/lighting/advanced/gl/pointLightP.glsl b/Templates/Full/game/shaders/common/lighting/advanced/gl/pointLightP.glsl index 8a1aae3ca5..8fe127e041 100644 --- a/Templates/Full/game/shaders/common/lighting/advanced/gl/pointLightP.glsl +++ b/Templates/Full/game/shaders/common/lighting/advanced/gl/pointLightP.glsl @@ -147,6 +147,17 @@ void main() 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 prepassSample = prepassUncondition( prePassBuffer, uvScene ); vec3 normal = prepassSample.rgb; @@ -258,6 +269,5 @@ void main() addToResult = ( 1.0 - shadowed ) * abs(lightMapParams); } - vec4 colorSample = texture( colorBuffer, uvScene ); - OUT_col = AL_DeferredOutput(lightColorOut, colorSample.rgb, matInfo, addToResult, specular, Sat_NL_Att); + OUT_col = AL_DeferredOutput(lightColorOut+subsurface*(1.0-Sat_NL_Att), colorSample.rgb, matInfo, addToResult, specular, Sat_NL_Att); } diff --git a/Templates/Full/game/shaders/common/lighting/advanced/gl/spotLightP.glsl b/Templates/Full/game/shaders/common/lighting/advanced/gl/spotLightP.glsl index e7f3e88a72..c6ffa02a0e 100644 --- a/Templates/Full/game/shaders/common/lighting/advanced/gl/spotLightP.glsl +++ b/Templates/Full/game/shaders/common/lighting/advanced/gl/spotLightP.glsl @@ -89,6 +89,17 @@ void main() 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 prepassSample = prepassUncondition( prePassBuffer, uvScene ); vec3 normal = prepassSample.rgb; @@ -195,6 +206,5 @@ void main() addToResult = ( 1.0 - shadowed ) * abs(lightMapParams); } - vec4 colorSample = texture( colorBuffer, uvScene ); - OUT_col = AL_DeferredOutput(lightColorOut, colorSample.rgb, matInfo, addToResult, specular, Sat_NL_Att); + OUT_col = AL_DeferredOutput(lightColorOut+subsurface*(1.0-Sat_NL_Att), colorSample.rgb, matInfo, addToResult, specular, Sat_NL_Att); } diff --git a/Templates/Full/game/shaders/common/lighting/advanced/gl/vectorLightP.glsl b/Templates/Full/game/shaders/common/lighting/advanced/gl/vectorLightP.glsl index 608524a5a6..15e0bf4771 100644 --- a/Templates/Full/game/shaders/common/lighting/advanced/gl/vectorLightP.glsl +++ b/Templates/Full/game/shaders/common/lighting/advanced/gl/vectorLightP.glsl @@ -202,6 +202,17 @@ void main() 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 prepassSample = prepassUncondition( prePassBuffer, uv0 ); vec3 normal = prepassSample.rgb; @@ -312,6 +323,5 @@ void main() lightColorOut = debugColor; #endif - vec4 colorSample = texture( colorBuffer, uv0 ); - OUT_col = AL_DeferredOutput(lightColorOut, colorSample.rgb, matInfo, addToResult, specular, Sat_NL_Att); + OUT_col = AL_DeferredOutput(lightColorOut+subsurface*(1.0-Sat_NL_Att), colorSample.rgb, matInfo, addToResult, specular, Sat_NL_Att); } diff --git a/Templates/Full/game/shaders/common/lighting/advanced/pointLightP.hlsl b/Templates/Full/game/shaders/common/lighting/advanced/pointLightP.hlsl index 540fd65c71..a8c0ea1059 100644 --- a/Templates/Full/game/shaders/common/lighting/advanced/pointLightP.hlsl +++ b/Templates/Full/game/shaders/common/lighting/advanced/pointLightP.hlsl @@ -149,6 +149,16 @@ float4 main( ConvexConnectP IN ) : TORQUE_TARGET0 { 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 prepassSample = TORQUE_PREPASS_UNCONDITION( prePassBuffer, uvScene ); @@ -263,6 +273,5 @@ float4 main( ConvexConnectP IN ) : TORQUE_TARGET0 addToResult = ( 1.0 - shadowed ) * abs(lightMapParams); } - float4 colorSample = TORQUE_TEX2D( colorBuffer, uvScene ); - return AL_DeferredOutput(lightColorOut, colorSample.rgb, matInfo, addToResult, specular, Sat_NL_Att); + return AL_DeferredOutput(lightColorOut+subsurface*(1.0-Sat_NL_Att), colorSample.rgb, matInfo, addToResult, specular, Sat_NL_Att); } diff --git a/Templates/Full/game/shaders/common/lighting/advanced/spotLightP.hlsl b/Templates/Full/game/shaders/common/lighting/advanced/spotLightP.hlsl index e1f3baf931..5040b15e21 100644 --- a/Templates/Full/game/shaders/common/lighting/advanced/spotLightP.hlsl +++ b/Templates/Full/game/shaders/common/lighting/advanced/spotLightP.hlsl @@ -87,6 +87,17 @@ float4 main( ConvexConnectP IN ) : TORQUE_TARGET0 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 prepassSample = TORQUE_PREPASS_UNCONDITION( prePassBuffer, uvScene ); float3 normal = prepassSample.rgb; @@ -194,6 +205,5 @@ float4 main( ConvexConnectP IN ) : TORQUE_TARGET0 addToResult = ( 1.0 - shadowed ) * abs(lightMapParams); } - float4 colorSample = TORQUE_TEX2D( colorBuffer, uvScene ); - return AL_DeferredOutput(lightColorOut, colorSample.rgb, matInfo, addToResult, specular, Sat_NL_Att); + return AL_DeferredOutput(lightColorOut+subsurface*(1.0-Sat_NL_Att), colorSample.rgb, matInfo, addToResult, specular, Sat_NL_Att); } diff --git a/Templates/Full/game/shaders/common/lighting/advanced/vectorLightP.hlsl b/Templates/Full/game/shaders/common/lighting/advanced/vectorLightP.hlsl index 1a97261718..9562279096 100644 --- a/Templates/Full/game/shaders/common/lighting/advanced/vectorLightP.hlsl +++ b/Templates/Full/game/shaders/common/lighting/advanced/vectorLightP.hlsl @@ -202,6 +202,16 @@ float4 main( FarFrustumQuadConnectP IN ) : TORQUE_TARGET0 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 prepassSample = TORQUE_PREPASS_UNCONDITION( prePassBuffer, IN.uv0 ); float3 normal = prepassSample.rgb; @@ -314,6 +324,5 @@ float4 main( FarFrustumQuadConnectP IN ) : TORQUE_TARGET0 lightColorOut = debugColor; #endif - float4 colorSample = TORQUE_TEX2D( colorBuffer, IN.uv0 ); - return AL_DeferredOutput(lightColorOut, colorSample.rgb, matInfo, addToResult, specular, Sat_NL_Att); + return AL_DeferredOutput(lightColorOut+subsurface*(1.0-Sat_NL_Att), colorSample.rgb, matInfo, addToResult, specular, Sat_NL_Att); } diff --git a/Templates/Full/game/tools/materialEditor/gui/guiMaterialPropertiesWindow.ed.gui b/Templates/Full/game/tools/materialEditor/gui/guiMaterialPropertiesWindow.ed.gui index 63ce28e2a8..1e3b98189b 100644 --- a/Templates/Full/game/tools/materialEditor/gui/guiMaterialPropertiesWindow.ed.gui +++ b/Templates/Full/game/tools/materialEditor/gui/guiMaterialPropertiesWindow.ed.gui @@ -2240,6 +2240,29 @@ useMouseEvents = "0"; useInactiveState = "0"; }; + new GuiCheckBoxCtrl() { + canSaveDynamicFields = "0"; + internalName = "subSurfaceCheckbox"; + Enabled = "1"; + isContainer = "0"; + Profile = "ToolsGuiCheckBoxProfile"; + HorizSizing = "right"; + VertSizing = "bottom"; + position = "8 46"; + Extent = "79 16"; + MinExtent = "8 2"; + canSave = "1"; + Visible = "1"; + Command = "MaterialEditorGui.updateActiveMaterial(\"subSurface[\" @ MaterialEditorGui.currentLayer @ \"]\", $ThisControl.getValue());"; + tooltipprofile = "ToolsGuiDefaultProfile"; + ToolTip = "Enables the use of subsurface scattering for this layer."; + hovertime = "1000"; + text = "Sub Surface"; + groupNum = "-1"; + buttonType = "ToggleButton"; + useMouseEvents = "0"; + useInactiveState = "0"; + }; }; }; }; diff --git a/Templates/Full/game/tools/materialEditor/scripts/materialEditor.ed.cs b/Templates/Full/game/tools/materialEditor/scripts/materialEditor.ed.cs index be7d55c393..c1f01f1a77 100644 --- a/Templates/Full/game/tools/materialEditor/scripts/materialEditor.ed.cs +++ b/Templates/Full/game/tools/materialEditor/scripts/materialEditor.ed.cs @@ -918,9 +918,6 @@ singleton Material(notDirtyMaterial) MaterialEditorPropertiesWindow-->vertLitCheckbox.setValue((%material).vertLit[%layer]); MaterialEditorPropertiesWindow-->vertColorSwatch.color = (%material).vertColor[%layer]; MaterialEditorPropertiesWindow-->subSurfaceCheckbox.setValue((%material).subSurface[%layer]); - MaterialEditorPropertiesWindow-->subSurfaceColorSwatch.color = (%material).subSurfaceColor[%layer]; - MaterialEditorPropertiesWindow-->subSurfaceRolloffTextEdit.setText((%material).subSurfaceRolloff[%layer]); - MaterialEditorPropertiesWindow-->minnaertTextEdit.setText((%material).minnaertConstant[%layer]); // Animation properties MaterialEditorPropertiesWindow-->RotationAnimation.setValue(0); diff --git a/Templates/Full/game/tools/shapeEditor/scripts/shapeEditor.ed.cs b/Templates/Full/game/tools/shapeEditor/scripts/shapeEditor.ed.cs index 180a9a8ab5..391e0b2170 100644 --- a/Templates/Full/game/tools/shapeEditor/scripts/shapeEditor.ed.cs +++ b/Templates/Full/game/tools/shapeEditor/scripts/shapeEditor.ed.cs @@ -380,7 +380,8 @@ function strcapitalise( %str ) // Ignore assets in the tools folder %fullPath = makeRelativePath( %fullPath, getMainDotCSDir() ); - %splitPath = strreplace( %fullPath, "/", " " ); + %splitPath = strreplace( %fullPath, " ", "_" ); + %splitPath = strreplace( %splitPath, "/", " " ); if ( getWord( %splitPath, 0 ) $= "tools" ) { %fullPath = findNextFileMultiExpr( %filePatterns ); @@ -393,6 +394,7 @@ function strcapitalise( %str ) // Add this file's path ( parent folders ) to the // popup menu if it isn't there yet. %temp = strreplace( %pathFolders, " ", "/" ); + %temp = strreplace( %temp, "_", " " ); %r = ShapeEdSelectMenu.findText( %temp ); if ( %r == -1 ) ShapeEdSelectMenu.add( %temp ); diff --git a/Templates/Full/game/tools/worldEditor/scripts/editors/creator.ed.cs b/Templates/Full/game/tools/worldEditor/scripts/editors/creator.ed.cs index 6832410dde..9f015f3590 100644 --- a/Templates/Full/game/tools/worldEditor/scripts/editors/creator.ed.cs +++ b/Templates/Full/game/tools/worldEditor/scripts/editors/creator.ed.cs @@ -318,7 +318,8 @@ } %fullPath = makeRelativePath( %fullPath, getMainDotCSDir() ); - %splitPath = strreplace( %fullPath, "/", " " ); + %splitPath = strreplace( %fullPath, " ", "_" ); + %splitPath = strreplace( %splitPath, "/", " " ); if( getWord(%splitPath, 0) $= "tools" ) { %fullPath = findNextFileMultiExpr( getFormatExtensions() ); @@ -332,6 +333,7 @@ // Add this file's path (parent folders) to the // popup menu if it isn't there yet. %temp = strreplace( %pathFolders, " ", "/" ); + %temp = strreplace( %temp, "_", " " ); %r = CreatorPopupMenu.findText( %temp ); if ( %r == -1 ) { @@ -430,7 +432,8 @@ while ( %fullPath !$= "" ) { %fullPath = makeRelativePath( %fullPath, getMainDotCSDir() ); - %splitPath = strreplace( %fullPath, "/", " " ); + %splitPath = strreplace( %fullPath, " ", "_" ); + %splitPath = strreplace( %splitPath, "/", " " ); if( getWord(%splitPath, 0) $= "tools" ) { %fullPath = findNextFile( %expr ); @@ -444,6 +447,7 @@ // Add this file's path (parent folders) to the // popup menu if it isn't there yet. %temp = strreplace( %pathFolders, " ", "/" ); + %temp = strreplace( %temp, "_", " " ); %r = CreatorPopupMenu.findText( %temp ); if ( %r == -1 ) { diff --git a/Templates/Full/game/tools/worldEditor/scripts/menuHandlers.ed.cs b/Templates/Full/game/tools/worldEditor/scripts/menuHandlers.ed.cs index b2a2f209e8..61f2141516 100644 --- a/Templates/Full/game/tools/worldEditor/scripts/menuHandlers.ed.cs +++ b/Templates/Full/game/tools/worldEditor/scripts/menuHandlers.ed.cs @@ -770,6 +770,15 @@ function EditorMenuEditPaste() // Set up min/max camera slider range eval("CameraSpeedDropdownCtrlContainer-->Slider.range = \"" @ %minSpeed @ " " @ %maxSpeed @ "\";"); } + +////////////////////////////////////////////////////////////////////////// +// Tools Menu Handler +////////////////////////////////////////////////////////////////////////// +function EditorUtilitiesMenu::onSelectItem(%this, %id, %text) +{ + return Parent::onSelectItem(%this, %id, %text); +} + ////////////////////////////////////////////////////////////////////////// // World Menu Handler Object Menu ////////////////////////////////////////////////////////////////////////// diff --git a/Templates/Full/game/tools/worldEditor/scripts/menus.ed.cs b/Templates/Full/game/tools/worldEditor/scripts/menus.ed.cs index 1e378ae112..0916a00655 100644 --- a/Templates/Full/game/tools/worldEditor/scripts/menus.ed.cs +++ b/Templates/Full/game/tools/worldEditor/scripts/menus.ed.cs @@ -252,6 +252,19 @@ class = "EditorLightingMenu"; // last menu items in EditorLightingMenu::onAdd(). }; %this.menuBar.insert(%lightingMenu, %this.menuBar.getCount()); + + // Tools Menu + %toolsMenu = new PopupMenu() + { + superClass = "MenuBuilder"; + class = "EditorUtilitiesMenu"; + + barTitle = "Tools"; + + item[0] = "Network Graph" TAB "n" TAB "toggleNetGraph();"; + item[1] = "Profiler" TAB "ctrl F2" TAB "showMetrics(true);"; + }; + %this.menuBar.insert(%toolsMenu, %this.menuBar.getCount()); // Help Menu %helpMenu = new PopupMenu()