Bladeren bron

Merge branch 'development' of https://github.com/GarageGames/Torque3D into development

Areloch 9 jaren geleden
bovenliggende
commit
9d47830a8b
36 gewijzigde bestanden met toevoegingen van 615 en 163 verwijderingen
  1. 1 1
      Engine/source/gfx/gfxDrawUtil.cpp
  2. 18 40
      Engine/source/gfx/gl/gfxGLCardProfiler.cpp
  3. 7 5
      Engine/source/gfx/gl/gfxGLCircularVolatileBuffer.h
  4. 17 1
      Engine/source/gfx/gl/gfxGLDevice.cpp
  5. 12 0
      Engine/source/gfx/gl/gfxGLDevice.h
  6. 6 1
      Engine/source/gfx/gl/gfxGLShader.cpp
  7. 3 2
      Engine/source/gfx/gl/gfxGLStateBlock.cpp
  8. 10 3
      Engine/source/gfx/gl/gfxGLTextureManager.cpp
  9. 8 3
      Engine/source/gfx/gl/gfxGLTextureObject.cpp
  10. 1 1
      Engine/source/gfx/gl/gfxGLTextureTarget.cpp
  11. 2 2
      Engine/source/gfx/gl/gfxGLVertexBuffer.cpp
  12. 2 2
      Engine/source/gfx/gl/gfxGLVertexDecl.cpp
  13. 1 1
      Engine/source/gfx/gl/gfxGLWindowTarget.cpp
  14. 1 1
      Engine/source/math/mBox.h
  15. 11 1
      Engine/source/math/mPolyhedron.impl.h
  16. 50 1
      Engine/source/math/mRotation.cpp
  17. 1 1
      Engine/source/math/mathTypes.cpp
  18. 6 11
      Engine/source/math/mathUtils.cpp
  19. 51 19
      Engine/source/platform/nativeDialogs/fileDialog.cpp
  20. 1 1
      Engine/source/shaderGen/GLSL/shaderFeatureGLSL.cpp
  21. 1 1
      Engine/source/shaderGen/HLSL/shaderFeatureHLSL.cpp
  22. 1 1
      Templates/Empty/game/core/scripts/client/lighting/advanced/deferredShading.cs
  23. 9 5
      Templates/Empty/game/core/scripts/client/lighting/advanced/shaders.cs
  24. 0 1
      Templates/Empty/game/shaders/common/basicCloudsV.hlsl
  25. 0 1
      Templates/Empty/game/shaders/common/cloudLayerV.hlsl
  26. 0 1
      Templates/Empty/game/shaders/common/gl/basicCloudsV.glsl
  27. 0 1
      Templates/Empty/game/shaders/common/gl/cloudLayerV.glsl
  28. 364 45
      Templates/Full/game/core/art/gui/netGraphGui.gui
  29. 1 1
      Templates/Full/game/core/scripts/client/lighting/advanced/deferredShading.cs
  30. 9 5
      Templates/Full/game/core/scripts/client/lighting/advanced/shaders.cs
  31. 0 1
      Templates/Full/game/shaders/common/basicCloudsV.hlsl
  32. 0 1
      Templates/Full/game/shaders/common/cloudLayerV.hlsl
  33. 0 1
      Templates/Full/game/shaders/common/gl/basicCloudsV.glsl
  34. 0 1
      Templates/Full/game/shaders/common/gl/cloudLayerV.glsl
  35. 9 0
      Templates/Full/game/tools/worldEditor/scripts/menuHandlers.ed.cs
  36. 12 0
      Templates/Full/game/tools/worldEditor/scripts/menus.ed.cs

+ 1 - 1
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 );

+ 18 - 40
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<const char*>(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<const char*>(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)

+ 7 - 5
Engine/source/gfx/gl/gfxGLCircularVolatileBuffer.h

@@ -20,7 +20,8 @@ public:
    }
 
    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 @@ public:
    }
 
    void wait()
-   {      
+   {   
+      PROFILE_SCOPE(GFXGLQueryFence_block);
       GLbitfield waitFlags = 0;
       GLuint64 waitDuration = 0;
       while( 1 ) 
@@ -158,7 +160,7 @@ public:
       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 @@ public:
 
       outOffset = mBufferFreePos;
 
-      if( gglHasExtension(ARB_buffer_storage) )
+      if( GFXGL->mCapabilities.bufferStorage )
       {         
          outPtr = (U8*)(mBufferPtr) + mBufferFreePos; 
       }
@@ -227,7 +229,7 @@ public:
 
    void unlock()
    {
-      if( gglHasExtension(ARB_buffer_storage) )
+      if( GFXGL->mCapabilities.bufferStorage )
       {
          return;
       }

+ 17 - 1
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<GFXGLVertexBuffer> 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<void*, GFXGLVertexDecl> 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<GFXGLShaderConstBuffer*>(buffer)->activate();
 }
 

+ 12 - 0
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);

+ 6 - 1
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<GFXShaderMacro> &macros )
 {
+   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<GFXShaderConstDesc>& GFXGLShader::getShaderConstDesc() const
 {
+   PROFILE_SCOPE(GFXGLShader_GetShaderConstants);
    return mConstants;
 }
 

+ 3 - 2
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<GFXSamplerStateDesc, U32> 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++)
       {

+ 10 - 3
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);
       FrameAllocatorMarker mem;
       U8* pboMemory = (U8*)mem.alloc(bufSize);
       GFX->getDeviceSwizzle32()->ToBuffer(pboMemory, pDL->getBits(0), bufSize);
@@ -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<GFXGLTextureObject*>(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<GFXGLTextureObject*>(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;
    

+ 8 - 3
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;

+ 1 - 1
Engine/source/gfx/gl/gfxGLTextureTarget.cpp

@@ -410,7 +410,7 @@ void GFXGLTextureTarget::resolveTo(GFXTextureObject* obj)
    AssertFatal(dynamic_cast<GFXGLTextureObject*>(obj), "GFXGLTextureTarget::resolveTo - Incorrect type of texture, expected a GFXGLTextureObject");
    GFXGLTextureObject* glTexture = static_cast<GFXGLTextureObject*>(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;

+ 2 - 2
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 );

+ 2 - 2
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...

+ 1 - 1
Engine/source/gfx/gl/gfxGLWindowTarget.cpp

@@ -78,7 +78,7 @@ void GFXGLWindowTarget::resolveTo(GFXTextureObject* obj)
    AssertFatal(dynamic_cast<GFXGLTextureObject*>(obj), "GFXGLTextureTarget::resolveTo - Incorrect type of texture, expected a GFXGLTextureObject");
    GFXGLTextureObject* glTexture = static_cast<GFXGLTextureObject*>(obj);
 
-   if( gglHasExtension(ARB_copy_image) )
+   if( GFXGL->mCapabilities.copyImage )
    {
       if(mBackBufferColorTex.getWidth() == glTexture->getWidth()
          && mBackBufferColorTex.getHeight() == glTexture->getHeight()

+ 1 - 1
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)

+ 11 - 1
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.
 

+ 50 - 1
Engine/source/math/mRotation.cpp

@@ -20,6 +20,8 @@
 // IN THE SOFTWARE.
 //-----------------------------------------------------------------------------
 #include "math/mRotation.h"
+#include "console/console.h"
+#include "console/engineAPI.h"
 
 #ifdef TORQUE_TESTS_ENABLED
 #include "testing/unitTesting.h"
@@ -296,4 +298,51 @@ TEST(Maths, RotationF_Calculations)
 {
    //TODO: implement unit test
 };
-#endif
+#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;
+}

+ 1 - 1
Engine/source/math/mathTypes.cpp

@@ -583,7 +583,7 @@ ConsoleSetType( TypeEaseF )
 // TypeRotationF
 //-----------------------------------------------------------------------------
 ConsoleType(RotationF, TypeRotationF, RotationF, "")
-//ImplementConsoleTypeCasters( TypeRotationF, RotationF )
+ImplementConsoleTypeCasters( TypeRotationF, RotationF )
 
 ConsoleGetType(TypeRotationF)
 {

+ 6 - 11
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 );
 

+ 51 - 19
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, (), ,

+ 1 - 1
Engine/source/shaderGen/GLSL/shaderFeatureGLSL.cpp

@@ -2805,7 +2805,7 @@ void DeferredSkyGLSL::processVert( Vector<ShaderComponent*> &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;
 }

+ 1 - 1
Engine/source/shaderGen/HLSL/shaderFeatureHLSL.cpp

@@ -3000,7 +3000,7 @@ void DeferredSkyHLSL::processVert( Vector<ShaderComponent*> &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;
 }

+ 1 - 1
Templates/Empty/game/core/scripts/client/lighting/advanced/deferredShading.cs

@@ -55,7 +55,7 @@ new ShaderData( AL_DeferredShader )
 
 singleton PostEffect( AL_DeferredShading )
 {
-   renderTime = "PFXBeforeBin";
+   renderTime = "PFXAfterBin";
    renderBin = "SkyBin";
    shader = AL_DeferredShader;
    stateBlock = AL_DeferredShadingState;

+ 9 - 5
Templates/Empty/game/core/scripts/client/lighting/advanced/shaders.cs

@@ -39,9 +39,11 @@ new GFXStateBlockData( AL_VectorLightState )
    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 @@ new GFXStateBlockData( AL_ConvexLightState )
    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;

+ 0 - 1
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;

+ 0 - 1
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 );
    

+ 0 - 1
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;

+ 0 - 1
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 );

+ 364 - 45
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 );
+}

+ 1 - 1
Templates/Full/game/core/scripts/client/lighting/advanced/deferredShading.cs

@@ -55,7 +55,7 @@ new ShaderData( AL_DeferredShader )
 
 singleton PostEffect( AL_DeferredShading )
 {
-   renderTime = "PFXBeforeBin";
+   renderTime = "PFXAfterBin";
    renderBin = "SkyBin";
    shader = AL_DeferredShader;
    stateBlock = AL_DeferredShadingState;

+ 9 - 5
Templates/Full/game/core/scripts/client/lighting/advanced/shaders.cs

@@ -39,9 +39,11 @@ new GFXStateBlockData( AL_VectorLightState )
    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 @@ new GFXStateBlockData( AL_ConvexLightState )
    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;

+ 0 - 1
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;

+ 0 - 1
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 );
    

+ 0 - 1
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;

+ 0 - 1
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 );

+ 9 - 0
Templates/Full/game/tools/worldEditor/scripts/menuHandlers.ed.cs

@@ -770,6 +770,15 @@ function EditorCameraSpeedMenu::setupGuiControls(%this)
    // 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
 //////////////////////////////////////////////////////////////////////////

+ 12 - 0
Templates/Full/game/tools/worldEditor/scripts/menus.ed.cs

@@ -252,6 +252,18 @@ function EditorGui::buildMenus(%this)
          // 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();";
+   };
+   %this.menuBar.insert(%toolsMenu, %this.menuBar.getCount());
       
    // Help Menu
    %helpMenu = new PopupMenu()