瀏覽代碼

Merge pull request #1223 from marauder2k9-torque/ShaderConstBuffer-CleanupRefactor

GFX Shader Refactor
Brian Roberts 1 年之前
父節點
當前提交
b624ec230a
共有 45 個文件被更改,包括 4374 次插入2324 次删除
  1. 118 68
      Engine/source/gfx/D3D11/gfxD3D11Device.cpp
  2. 22 14
      Engine/source/gfx/D3D11/gfxD3D11Device.h
  3. 287 444
      Engine/source/gfx/D3D11/gfxD3D11Shader.cpp
  4. 67 311
      Engine/source/gfx/D3D11/gfxD3D11Shader.h
  5. 6 4
      Engine/source/gfx/bitmap/loaders/bitmapSTB.cpp
  6. 0 289
      Engine/source/gfx/genericConstBuffer.cpp
  7. 0 374
      Engine/source/gfx/genericConstBuffer.h
  8. 269 85
      Engine/source/gfx/gfxDrawUtil.cpp
  9. 58 24
      Engine/source/gfx/gfxDrawUtil.h
  10. 43 29
      Engine/source/gfx/gfxEnums.h
  11. 40 15
      Engine/source/gfx/gfxShader.cpp
  12. 62 44
      Engine/source/gfx/gfxShader.h
  13. 121 87
      Engine/source/gfx/gl/gfxGLDevice.cpp
  14. 42 33
      Engine/source/gfx/gl/gfxGLDevice.h
  15. 517 292
      Engine/source/gfx/gl/gfxGLShader.cpp
  16. 153 76
      Engine/source/gfx/gl/gfxGLShader.h
  17. 1003 0
      Engine/source/gui/shaderEditor/guiShaderEditor.cpp
  18. 147 0
      Engine/source/gui/shaderEditor/guiShaderEditor.h
  19. 203 0
      Engine/source/gui/shaderEditor/guiShaderNode.cpp
  20. 159 0
      Engine/source/gui/shaderEditor/guiShaderNode.h
  21. 51 0
      Engine/source/gui/shaderEditor/nodes/materialOutputNode.cpp
  22. 39 0
      Engine/source/gui/shaderEditor/nodes/materialOutputNode.h
  23. 49 0
      Engine/source/gui/shaderEditor/nodes/mathNode.cpp
  24. 39 0
      Engine/source/gui/shaderEditor/nodes/mathNode.h
  25. 0 1
      Engine/source/materials/processedCustomMaterial.cpp
  26. 0 1
      Engine/source/materials/processedShaderMaterial.cpp
  27. 100 72
      Engine/source/materials/shaderData.cpp
  28. 15 15
      Engine/source/materials/shaderData.h
  29. 14 14
      Engine/source/platformWin32/winPlatformCPUCount.cpp
  30. 3 3
      Engine/source/scene/sceneQueryUtil.h
  31. 9 9
      Engine/source/shaderGen/HLSL/debugVizFeatureHLSL.cpp
  32. 22 19
      Engine/source/shaderGen/shaderGen.cpp
  33. 38 0
      Templates/BaseGame/game/core/rendering/scripts/gfxData/shaders.tscript
  34. 66 0
      Templates/BaseGame/game/core/rendering/shaders/fixedFunction/circleP.hlsl
  35. 62 0
      Templates/BaseGame/game/core/rendering/shaders/fixedFunction/gl/circleP.glsl
  36. 98 0
      Templates/BaseGame/game/core/rendering/shaders/fixedFunction/gl/roundedRectangleP.glsl
  37. 67 0
      Templates/BaseGame/game/core/rendering/shaders/fixedFunction/gl/thickLineG.glsl
  38. 30 0
      Templates/BaseGame/game/core/rendering/shaders/fixedFunction/gl/thickLineP.glsl
  39. 103 0
      Templates/BaseGame/game/core/rendering/shaders/fixedFunction/roundedRectangleP.hlsl
  40. 77 0
      Templates/BaseGame/game/core/rendering/shaders/fixedFunction/thickLineG.hlsl
  41. 34 0
      Templates/BaseGame/game/core/rendering/shaders/fixedFunction/thickLineP.hlsl
  42. 10 0
      Templates/BaseGame/game/tools/gui/profiles.ed.tscript
  43. 7 0
      Templates/BaseGame/game/tools/shaderEditor/gui/shaderEditorGui.asset.taml
  44. 122 0
      Templates/BaseGame/game/tools/shaderEditor/gui/shaderEditorGui.ed.gui
  45. 2 1
      Tools/CMake/modules/tools.cmake

+ 118 - 68
Engine/source/gfx/D3D11/gfxD3D11Device.cpp

@@ -105,6 +105,7 @@ GFXD3D11Device::GFXD3D11Device(U32 index)
 
    mLastVertShader = NULL;
    mLastPixShader = NULL;
+   mLastGeoShader = NULL;
 
    mCanCurrentlyRender = false;
    mTextureManager = NULL;
@@ -159,6 +160,11 @@ GFXD3D11Device::~GFXD3D11Device()
    for (; sampIter != mSamplersMap.end(); ++sampIter)
       SAFE_RELEASE(sampIter->value);
 
+   // Free device buffers
+   DeviceBufferMap::Iterator bufferIter = mDeviceBufferMap.begin();
+   for (; bufferIter != mDeviceBufferMap.end(); ++bufferIter)
+      SAFE_RELEASE(bufferIter->value);
+
    // Free the vertex declarations.
    VertexDeclMap::Iterator iter = mVertexDecls.begin();
    for (; iter != mVertexDecls.end(); ++iter)
@@ -202,7 +208,7 @@ GFXFormat GFXD3D11Device::selectSupportedFormat(GFXTextureProfile *profile, cons
        features |= D3D11_FORMAT_SUPPORT_BLENDABLE;
    if(mustfilter)
        features |= D3D11_FORMAT_SUPPORT_SHADER_SAMPLE;
-   
+
    for(U32 i = 0; i < formats.size(); i++)
    {
       if(GFXD3D11TextureFormat[formats[i]] == DXGI_FORMAT_UNKNOWN)
@@ -213,7 +219,7 @@ GFXFormat GFXD3D11Device::selectSupportedFormat(GFXTextureProfile *profile, cons
       if(supportFlag & features)
          return formats[i];
    }
-   
+
    return GFXFormatR8G8B8A8;
 }
 
@@ -261,7 +267,7 @@ void GFXD3D11Device::enumerateAdapters(Vector<GFXAdapter*> &adapterList)
 
    CreateDXGIFactory1(__uuidof(IDXGIFactory1), reinterpret_cast<void**>(&DXGIFactory));
 
-   for(U32 adapterIndex = 0; DXGIFactory->EnumAdapters1(adapterIndex, &EnumAdapter) != DXGI_ERROR_NOT_FOUND; ++adapterIndex) 
+   for(U32 adapterIndex = 0; DXGIFactory->EnumAdapters1(adapterIndex, &EnumAdapter) != DXGI_ERROR_NOT_FOUND; ++adapterIndex)
    {
       GFXAdapter *toAdd = new GFXAdapter;
       toAdd->mType  = Direct3D11;
@@ -286,7 +292,7 @@ void GFXD3D11Device::enumerateAdapters(Vector<GFXAdapter*> &adapterList)
       dStrncpy(toAdd->mName, Description.c_str(), GFXAdapter::MaxAdapterNameLen);
       dStrncat(toAdd->mName, " (D3D11)", sizeof(toAdd->mName) - strlen(toAdd->mName) - 1);
 
-      IDXGIOutput* pOutput = NULL; 
+      IDXGIOutput* pOutput = NULL;
       HRESULT hr;
 
       hr = EnumAdapter->EnumOutputs(adapterIndex, &pOutput);
@@ -310,7 +316,7 @@ void GFXD3D11Device::enumerateAdapters(Vector<GFXAdapter*> &adapterList)
       if(FAILED(hr))
          AssertFatal(false, "GFXD3D11Device::enumerateAdapters -> GetDisplayModeList call failure");
 
-      displayModes = new DXGI_MODE_DESC[numModes]; 
+      displayModes = new DXGI_MODE_DESC[numModes];
 
       // Get the list
       hr = pOutput->GetDisplayModeList(format, 0, &numModes, displayModes);
@@ -376,7 +382,7 @@ void GFXD3D11Device::enumerateAdapters(Vector<GFXAdapter*> &adapterList)
    SAFE_RELEASE(DXGIFactory);
 }
 
-void GFXD3D11Device::enumerateVideoModes() 
+void GFXD3D11Device::enumerateVideoModes()
 {
    mVideoModes.clear();
 
@@ -389,9 +395,9 @@ void GFXD3D11Device::enumerateVideoModes()
    if (FAILED(hr))
       AssertFatal(false, "GFXD3D11Device::enumerateVideoModes -> CreateDXGIFactory1 call failure");
 
-   for(U32 adapterIndex = 0; DXGIFactory->EnumAdapters1(adapterIndex, &EnumAdapter) != DXGI_ERROR_NOT_FOUND; ++adapterIndex) 
+   for(U32 adapterIndex = 0; DXGIFactory->EnumAdapters1(adapterIndex, &EnumAdapter) != DXGI_ERROR_NOT_FOUND; ++adapterIndex)
    {
-      IDXGIOutput* pOutput = NULL;      
+      IDXGIOutput* pOutput = NULL;
 
       hr = EnumAdapter->EnumOutputs(adapterIndex, &pOutput);
 
@@ -414,7 +420,7 @@ void GFXD3D11Device::enumerateVideoModes()
       if(FAILED(hr))
          AssertFatal(false, "GFXD3D11Device::enumerateVideoModes -> GetDisplayModeList call failure");
 
-      displayModes = new DXGI_MODE_DESC[numModes]; 
+      displayModes = new DXGI_MODE_DESC[numModes];
 
       // Get the list
       hr = pOutput->GetDisplayModeList(format, 0, &numModes, displayModes);
@@ -519,14 +525,16 @@ void GFXD3D11Device::init(const GFXVideoMode &mode, PlatformWindow *window)
    {
    case D3D_FEATURE_LEVEL_11_1:
    case D3D_FEATURE_LEVEL_11_0:
-      mVertexShaderTarget = "vs_5_0";
-      mPixelShaderTarget = "ps_5_0";
+      mVertexShaderTarget     = "vs_5_0";
+      mPixelShaderTarget      = "ps_5_0";
+      mGeometryShaderTarget   = "gs_5_0";
       mPixVersion = 5.0f;
       mShaderModel = "50";
       break;
    case D3D_FEATURE_LEVEL_10_1:
-      mVertexShaderTarget = "vs_4_1";
-      mPixelShaderTarget = "ps_4_1";
+      mVertexShaderTarget     = "vs_4_1";
+      mPixelShaderTarget      = "ps_4_1";
+      mGeometryShaderTarget   = "gs_4_1";
       mPixVersion = 4.1f;
       mShaderModel = "41";
       break;
@@ -546,7 +554,7 @@ void GFXD3D11Device::init(const GFXVideoMode &mode, PlatformWindow *window)
    SAFE_RELEASE(testQuery);
 
    Con::printf("Hardware occlusion query detected: %s", mOcclusionQuerySupported ? "Yes" : "No");
-   
+
    mCardProfiler = new GFXD3D11CardProfiler();
    mCardProfiler->init();
 
@@ -589,10 +597,10 @@ void GFXD3D11Device::_suppressDebugMessages()
    }
 }
 
-bool GFXD3D11Device::beginSceneInternal() 
+bool GFXD3D11Device::beginSceneInternal()
 {
    mCanCurrentlyRender = true;
-   return mCanCurrentlyRender;  
+   return mCanCurrentlyRender;
 }
 
 GFXWindowTarget * GFXD3D11Device::allocWindowTarget(PlatformWindow *window)
@@ -739,7 +747,7 @@ void GFXD3D11Device::setupGenericShaders(GenericShaderType type)
       _updateRenderTargets();
    }
 
-   MatrixF tempMatrix =  mProjectionMatrix * mViewMatrix * mWorldMatrix[mWorldStackSize];  
+   MatrixF tempMatrix =  mProjectionMatrix * mViewMatrix * mWorldMatrix[mWorldStackSize];
    mGenericShaderBuffer[type]->setSafe(mModelViewProjSC[type], tempMatrix);
 
    setShader(mGenericShader[type]);
@@ -764,7 +772,7 @@ void GFXD3D11Device::setStateBlockInternal(GFXStateBlock* block, bool force)
    if (force)
       d3dCurrent = NULL;
 
-   d3dBlock->activate(d3dCurrent);   
+   d3dBlock->activate(d3dCurrent);
 }
 
 /// Called by base GFXDevice to actually set a const buffer
@@ -863,7 +871,7 @@ void GFXD3D11Device::clearColorAttachment(const U32 attachment, const LinearColo
    mD3DDeviceContext->ClearRenderTargetView(rtView, clearColor);
 }
 
-void GFXD3D11Device::endSceneInternal() 
+void GFXD3D11Device::endSceneInternal()
 {
    mCanCurrentlyRender = false;
 }
@@ -875,7 +883,7 @@ void GFXD3D11Device::_updateRenderTargets()
       if (mRTDeactivate)
       {
          mRTDeactivate->deactivate();
-         mRTDeactivate = NULL;   
+         mRTDeactivate = NULL;
       }
 
       // NOTE: The render target changes are not really accurate
@@ -887,7 +895,7 @@ void GFXD3D11Device::_updateRenderTargets()
       mCurrentRT->activate();
 
       mRTDirty = false;
-   }  
+   }
 
    if (mViewportDirty)
    {
@@ -906,7 +914,7 @@ void GFXD3D11Device::_updateRenderTargets()
    }
 }
 
-void GFXD3D11Device::releaseDefaultPoolResources() 
+void GFXD3D11Device::releaseDefaultPoolResources()
 {
    // Release all the dynamic vertex buffer arrays
    // Forcibly clean up the pools
@@ -919,7 +927,7 @@ void GFXD3D11Device::releaseDefaultPoolResources()
 
    // We gotta clear the current const buffer else the next
    // activate may erroneously think the device is still holding
-   // this state and fail to set it.   
+   // this state and fail to set it.
    mCurrentConstBuffer = NULL;
 
    // Set current VB to NULL and set state dirty
@@ -943,7 +951,7 @@ void GFXD3D11Device::releaseDefaultPoolResources()
    mPrimitiveBufferDirty = true;
 
    // Zombify texture manager (for D3D this only modifies default pool textures)
-   if( mTextureManager ) 
+   if( mTextureManager )
       mTextureManager->zombify();
 
    // Set global dirty state so the IB/PB and VB get reset
@@ -958,7 +966,7 @@ void GFXD3D11Device::releaseDefaultPoolResources()
    }
 }
 
-void GFXD3D11Device::reacquireDefaultPoolResources() 
+void GFXD3D11Device::reacquireDefaultPoolResources()
 {
    // Now do the dynamic index buffers
    if( mDynamicPB == NULL )
@@ -974,7 +982,7 @@ void GFXD3D11Device::reacquireDefaultPoolResources()
 
    HRESULT hr = D3D11DEVICE->CreateBuffer(&desc, NULL, &mDynamicPB->ib);
 
-   if(FAILED(hr)) 
+   if(FAILED(hr))
    {
       AssertFatal(false, "Failed to allocate dynamic IB");
    }
@@ -1020,7 +1028,7 @@ GFXD3D11VertexBuffer * GFXD3D11Device::createVBPool( const GFXVertexFormat *vert
    newBuff->mDevice = this;
 
    // Requesting it will allocate it.
-   vertexFormat->getDecl(); 
+   vertexFormat->getDecl();
 
    D3D11_BUFFER_DESC desc;
    desc.ByteWidth = vertSize * GFX_MAX_DYNAMIC_VERTS;
@@ -1032,7 +1040,7 @@ GFXD3D11VertexBuffer * GFXD3D11Device::createVBPool( const GFXVertexFormat *vert
 
    HRESULT hr = D3D11DEVICE->CreateBuffer(&desc, NULL, &newBuff->vb);
 
-   if(FAILED(hr)) 
+   if(FAILED(hr))
    {
       AssertFatal(false, "Failed to allocate dynamic VB");
    }
@@ -1042,9 +1050,9 @@ GFXD3D11VertexBuffer * GFXD3D11Device::createVBPool( const GFXVertexFormat *vert
 
 //-----------------------------------------------------------------------------
 
-void GFXD3D11Device::setClipRect( const RectI &inRect ) 
+void GFXD3D11Device::setClipRect( const RectI &inRect )
 {
-   // We transform the incoming rect by the view 
+   // We transform the incoming rect by the view
    // matrix first, so that it can be used to pan
    // and scale the clip rect.
    //
@@ -1052,7 +1060,7 @@ void GFXD3D11Device::setClipRect( const RectI &inRect )
    Point3F pos( inRect.point.x, inRect.point.y, 0.0f );
    Point3F extent( inRect.extent.x, inRect.extent.y, 0.0f );
    getViewMatrix().mulP( pos );
-   getViewMatrix().mulV( extent );  
+   getViewMatrix().mulV( extent );
    RectI rect( pos.x, pos.y, extent.x, extent.y );
 
    // Clip the rect against the renderable size.
@@ -1068,8 +1076,8 @@ void GFXD3D11Device::setClipRect( const RectI &inRect )
    F32 b = F32( mClipRect.point.y + mClipRect.extent.y );
    F32 t = F32( mClipRect.point.y );
 
-   // Set up projection matrix, 
-   static Point4F pt;   
+   // Set up projection matrix,
+   static Point4F pt;
    pt.set(2.0f / (r - l), 0.0f, 0.0f, 0.0f);
    mTempMatrix.setColumn(0, pt);
 
@@ -1085,7 +1093,7 @@ void GFXD3D11Device::setClipRect( const RectI &inRect )
    setProjectionMatrix( mTempMatrix );
 
    // Set up world/view matrix
-   mTempMatrix.identity();   
+   mTempMatrix.identity();
    setWorldMatrix( mTempMatrix );
 
    setViewport( mClipRect );
@@ -1097,7 +1105,7 @@ void GFXD3D11Device::setVertexStream( U32 stream, GFXVertexBuffer *buffer )
 
    if ( stream == 0 )
    {
-      // Set the volatile buffer which is used to 
+      // Set the volatile buffer which is used to
       // offset the start index when doing draw calls.
       if ( d3dBuffer && d3dBuffer->mVolatileStart > 0 )
          mVolatileVB = d3dBuffer;
@@ -1106,7 +1114,7 @@ void GFXD3D11Device::setVertexStream( U32 stream, GFXVertexBuffer *buffer )
    }
 
    // NOTE: We do not use the stream offset here for stream 0
-   // as that feature is *supposedly* not as well supported as 
+   // as that feature is *supposedly* not as well supported as
    // using the start index in drawPrimitive.
    //
    // If we can verify that this is not the case then we should
@@ -1125,7 +1133,7 @@ void GFXD3D11Device::setVertexStreamFrequency( U32 stream, U32 frequency )
       mDrawInstancesCount = frequency; // instances count
 }
 
-void GFXD3D11Device::_setPrimitiveBuffer( GFXPrimitiveBuffer *buffer ) 
+void GFXD3D11Device::_setPrimitiveBuffer( GFXPrimitiveBuffer *buffer )
 {
    mCurrentPB = static_cast<GFXD3D11PrimitiveBuffer *>( buffer );
 
@@ -1160,7 +1168,7 @@ U32 GFXD3D11Device::primCountToIndexCount(GFXPrimitiveType primType, U32 primiti
 }
 
 
-void GFXD3D11Device::drawPrimitive( GFXPrimitiveType primType, U32 vertexStart, U32 primitiveCount ) 
+void GFXD3D11Device::drawPrimitive( GFXPrimitiveType primType, U32 vertexStart, U32 primitiveCount )
 {
    // This is done to avoid the function call overhead if possible
    if( mStateDirty )
@@ -1172,12 +1180,12 @@ void GFXD3D11Device::drawPrimitive( GFXPrimitiveType primType, U32 vertexStart,
        vertexStart += mVolatileVB->mVolatileStart;
 
    mD3DDeviceContext->IASetPrimitiveTopology(GFXD3D11PrimType[primType]);
-   
+
    if ( mDrawInstancesCount )
       mD3DDeviceContext->DrawInstanced(primCountToIndexCount(primType, primitiveCount), mDrawInstancesCount, vertexStart, 0);
    else
       mD3DDeviceContext->Draw(primCountToIndexCount(primType, primitiveCount), vertexStart);
-  
+
    mDeviceStatistics.mDrawCalls++;
    if ( mVertexBufferFrequency[0] > 1 )
       mDeviceStatistics.mPolyCount += primitiveCount * mVertexBufferFrequency[0];
@@ -1185,12 +1193,12 @@ void GFXD3D11Device::drawPrimitive( GFXPrimitiveType primType, U32 vertexStart,
       mDeviceStatistics.mPolyCount += primitiveCount;
 }
 
-void GFXD3D11Device::drawIndexedPrimitive( GFXPrimitiveType primType, 
-                                          U32 startVertex, 
-                                          U32 minIndex, 
-                                          U32 numVerts, 
-                                          U32 startIndex, 
-                                          U32 primitiveCount ) 
+void GFXD3D11Device::drawIndexedPrimitive( GFXPrimitiveType primType,
+                                          U32 startVertex,
+                                          U32 minIndex,
+                                          U32 numVerts,
+                                          U32 startIndex,
+                                          U32 primitiveCount )
 {
    // This is done to avoid the function call overhead if possible
    if( mStateDirty )
@@ -1204,11 +1212,11 @@ void GFXD3D11Device::drawIndexedPrimitive( GFXPrimitiveType primType,
       startVertex += mVolatileVB->mVolatileStart;
 
    mD3DDeviceContext->IASetPrimitiveTopology(GFXD3D11PrimType[primType]);
-  
+
    if ( mDrawInstancesCount )
       mD3DDeviceContext->DrawIndexedInstanced(primCountToIndexCount(primType, primitiveCount), mDrawInstancesCount, mCurrentPB->mVolatileStart + startIndex, startVertex, 0);
    else
-      mD3DDeviceContext->DrawIndexed(primCountToIndexCount(primType,primitiveCount), mCurrentPB->mVolatileStart + startIndex, startVertex);   
+      mD3DDeviceContext->DrawIndexed(primCountToIndexCount(primType,primitiveCount), mCurrentPB->mVolatileStart + startIndex, startVertex);
 
    mDeviceStatistics.mDrawCalls++;
    if ( mVertexBufferFrequency[0] > 1 )
@@ -1245,7 +1253,13 @@ void GFXD3D11Device::setShader(GFXShader *shader, bool force)
       {
         mD3DDeviceContext->VSSetShader( d3dShader->mVertShader, NULL, 0);
         mLastVertShader = d3dShader->mVertShader;
-      }     
+      }
+
+      if (d3dShader->mGeoShader != mLastGeoShader || force)
+      {
+         mD3DDeviceContext->GSSetShader(d3dShader->mGeoShader, NULL, 0);
+         mLastGeoShader = d3dShader->mGeoShader;
+      }
    }
    else
    {
@@ -1308,7 +1322,7 @@ GFXPrimitiveBuffer * GFXD3D11Device::allocPrimitiveBuffer(U32 numIndices, U32 nu
 
       HRESULT hr = D3D11DEVICE->CreateBuffer(&desc, NULL, &res->ib);
 
-      if(FAILED(hr)) 
+      if(FAILED(hr))
       {
          AssertFatal(false, "Failed to allocate an index buffer.");
       }
@@ -1329,12 +1343,12 @@ GFXVertexBuffer * GFXD3D11Device::allocVertexBuffer(U32 numVerts, const GFXVerte
 {
    PROFILE_SCOPE( GFXD3D11Device_allocVertexBuffer );
 
-   GFXD3D11VertexBuffer *res = new GFXD3D11VertexBuffer(   this, 
-                                                         numVerts, 
-                                                         vertexFormat, 
-                                                         vertSize, 
+   GFXD3D11VertexBuffer *res = new GFXD3D11VertexBuffer(   this,
+                                                         numVerts,
+                                                         vertexFormat,
+                                                         vertSize,
                                                          bufferType );
-   
+
    // Determine usage flags
    D3D11_USAGE usage = D3D11_USAGE_DEFAULT;
 
@@ -1387,7 +1401,7 @@ GFXVertexBuffer * GFXD3D11Device::allocVertexBuffer(U32 numVerts, const GFXVerte
 
       HRESULT hr = D3D11DEVICE->CreateBuffer(&desc, NULL, &res->vb);
 
-      if(FAILED(hr)) 
+      if(FAILED(hr))
       {
          AssertFatal(false, "Failed to allocate VB");
       }
@@ -1540,16 +1554,16 @@ GFXVertexDecl* GFXD3D11Device::allocVertexDecl( const GFXVertexFormat *vertexFor
       return decl;
 
    U32 elemCount = vertexFormat->getElementCount();
- 
+
    ID3DBlob* code = NULL;
-  
+
    // We have to generate a temporary shader here for now since the input layout creation
    // expects a shader to be already compiled to verify the vertex layout structure. The problem
    // is that most of the time the regular shaders are compiled AFTER allocVertexDecl is called.
    if(!decl)
    {
       //TODO: Perhaps save/cache the ID3DBlob for later use on identical vertex formats,save creating/compiling the temp shader everytime
-      String shaderData = _createTempShaderInternal(vertexFormat);     
+      String shaderData = _createTempShaderInternal(vertexFormat);
 
 #ifdef TORQUE_DEBUG
       U32 flags = D3DCOMPILE_DEBUG | D3DCOMPILE_ENABLE_STRICTNESS | D3DCOMPILE_WARNINGS_ARE_ERRORS;
@@ -1569,11 +1583,11 @@ GFXVertexDecl* GFXD3D11Device::allocVertexDecl( const GFXVertexFormat *vertexFor
 
       SAFE_RELEASE(errorBlob);
    }
-   
+
    AssertFatal(code, "D3D11Device::allocVertexDecl - compiled vert shader code missing!");
 
    // Setup the declaration struct.
-   
+
    U32 stream;
    D3D11_INPUT_ELEMENT_DESC *vd = new D3D11_INPUT_ELEMENT_DESC[ elemCount];
 
@@ -1599,7 +1613,7 @@ GFXVertexDecl* GFXD3D11Device::allocVertexDecl( const GFXVertexFormat *vertexFor
          vd[i].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA;
          vd[i].InstanceDataStepRate = 0;
       }
-      // We force the usage index of 0 for everything but 
+      // We force the usage index of 0 for everything but
       // texture coords for now... this may change later.
       vd[i].SemanticIndex = 0;
 
@@ -1634,7 +1648,7 @@ GFXVertexDecl* GFXD3D11Device::allocVertexDecl( const GFXVertexFormat *vertexFor
 
    decl = new D3D11VertexDecl();
    HRESULT hr = mD3DDevice->CreateInputLayout(vd, elemCount,code->GetBufferPointer(), code->GetBufferSize(), &decl->decl);
-   
+
    if (FAILED(hr))
    {
       AssertFatal(false, "GFXD3D11Device::allocVertexDecl - Failed to create vertex input layout!");
@@ -1654,7 +1668,7 @@ void GFXD3D11Device::setVertexDecl( const GFXVertexDecl *decl )
    ID3D11InputLayout *dx11Decl = NULL;
    if (decl)
       dx11Decl = static_cast<const D3D11VertexDecl*>(decl)->decl;
-   
+
    mD3DDeviceContext->IASetInputLayout(dx11Decl);
 }
 
@@ -1709,7 +1723,7 @@ GFXFence *GFXD3D11Device::createFence()
    }
 
    // CodeReview: At some point I would like a specialized implementation of
-   // the method used by the general fence, only without the overhead incurred 
+   // the method used by the general fence, only without the overhead incurred
    // by using the GFX constructs. Primarily the lock() method on texture handles
    // will do a data copy, and this method doesn't require a copy, just a lock
    // [5/10/2007 Pat]
@@ -1719,12 +1733,12 @@ GFXFence *GFXD3D11Device::createFence()
 }
 
 GFXOcclusionQuery* GFXD3D11Device::createOcclusionQuery()
-{  
+{
    GFXOcclusionQuery *query;
    if (mOcclusionQuerySupported)
       query = new GFXD3D11OcclusionQuery( this );
    else
-      return NULL;      
+      return NULL;
 
    query->registerResourceWithDevice(this);
    return query;
@@ -1794,7 +1808,7 @@ const char* GFXD3D11Device::interpretDebugResult(long result)
    //generics
    case E_UNEXPECTED:
       error = "E_UNEXPECTED";
-      break;      
+      break;
    case E_NOTIMPL:
       error = "E_NOTIMPL";
       break;
@@ -1852,3 +1866,39 @@ const char* GFXD3D11Device::interpretDebugResult(long result)
    }
    return error;
 }
+
+ID3D11Buffer* GFXD3D11Device::getDeviceBuffer(const GFXShaderConstDesc desc)
+{
+   String name(desc.name + "_" + String::ToString(desc.size));
+   DeviceBufferMap::Iterator buf = mDeviceBufferMap.find(name);
+   if (buf != mDeviceBufferMap.end())
+   {
+      mDeviceBufferMap[name]->AddRef();
+      return mDeviceBufferMap[name];
+   }
+
+   ID3D11Buffer* tempBuf;
+   D3D11_BUFFER_DESC cbDesc;
+   cbDesc.ByteWidth = desc.size;
+   cbDesc.Usage = D3D11_USAGE_DEFAULT;
+   cbDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
+   cbDesc.CPUAccessFlags = 0;
+   cbDesc.MiscFlags = 0;
+   cbDesc.StructureByteStride = 0;
+
+   HRESULT hr;
+   hr = D3D11DEVICE->CreateBuffer(&cbDesc, NULL, &tempBuf);
+
+   if (FAILED(hr))
+   {
+      AssertFatal(false, "Failed to create device buffer.");
+   }
+
+   mDeviceBufferMap[name] = tempBuf;
+
+#ifdef TORQUE_DEBUG
+   tempBuf->SetPrivateData(WKPDID_D3DDebugObjectName, name.size(), name.c_str());
+#endif
+
+   return tempBuf;
+}

+ 22 - 14
Engine/source/gfx/D3D11/gfxD3D11Device.h

@@ -51,6 +51,7 @@ class GFXD3D11Device : public GFXDevice
 {
 public:
    typedef Map<U32, ID3D11SamplerState*> SamplerMap;
+   typedef Map<String, ID3D11Buffer*> DeviceBufferMap;
 private:
 
    friend class GFXResource;
@@ -105,6 +106,7 @@ protected:
 
    /// Used to lookup sampler state for a given hash key
    SamplerMap mSamplersMap;
+   DeviceBufferMap mDeviceBufferMap;
 
    ID3D11RenderTargetView* mDeviceBackBufferView;
    ID3D11DepthStencilView* mDeviceDepthStencilView;
@@ -121,6 +123,7 @@ protected:
 
    ID3D11VertexShader *mLastVertShader;
    ID3D11PixelShader *mLastPixShader;
+   ID3D11GeometryShader *mLastGeoShader;
 
    S32 mCreateFenceType;
 
@@ -140,6 +143,7 @@ protected:
    // Shader Model targers
    String mVertexShaderTarget;
    String mPixelShaderTarget;
+   String mGeometryShaderTarget;
    // String for use with shader macros in the form of shader model version * 10
    String mShaderModel;
    bool mDebugLayers;
@@ -148,7 +152,7 @@ protected:
 
    bool mOcclusionQuerySupported;
 
-   U32 mDrawInstancesCount;   
+   U32 mDrawInstancesCount;
 
    /// To manage creating and re-creating of these when device is aquired
    void reacquireDefaultPoolResources();
@@ -181,11 +185,11 @@ protected:
    // Index buffer management
    // {
    virtual void _setPrimitiveBuffer( GFXPrimitiveBuffer *buffer );
-   virtual void drawIndexedPrimitive(  GFXPrimitiveType primType, 
-                                       U32 startVertex, 
-                                       U32 minIndex, 
-                                       U32 numVerts, 
-                                       U32 startIndex, 
+   virtual void drawIndexedPrimitive(  GFXPrimitiveType primType,
+                                       U32 startVertex,
+                                       U32 minIndex,
+                                       U32 numVerts,
+                                       U32 startIndex,
                                        U32 primitiveCount );
    // }
 
@@ -197,7 +201,7 @@ protected:
    String _createTempShaderInternal(const GFXVertexFormat *vertexFormat);
    // Supress any debug layer messages we don't want to see
    void _suppressDebugMessages();
-   
+
 public:
 
    static GFXDevice *createInstance( U32 adapterIndex );
@@ -229,7 +233,7 @@ public:
    virtual GFXTextureArray* createTextureArray();
 
    virtual F32  getPixelShaderVersion() const { return mPixVersion; }
-   virtual void setPixelShaderVersion( F32 version ){ mPixVersion = version;} 
+   virtual void setPixelShaderVersion( F32 version ){ mPixVersion = version;}
 
    virtual void setShader(GFXShader *shader, bool force = false);
    virtual U32  getNumSamplers() const { return 16; }
@@ -252,10 +256,10 @@ public:
    virtual void setClipRect( const RectI &rect );
    virtual const RectI& getClipRect() const { return mClipRect; }
 
-   // }   
+   // }
+
 
 
-   
    /// @name Render Targets
    /// @{
    virtual void _updateRenderTargets();
@@ -263,14 +267,14 @@ public:
 
    // Vertex/Index buffer management
    // {
-   virtual GFXVertexBuffer* allocVertexBuffer(  U32 numVerts, 
+   virtual GFXVertexBuffer* allocVertexBuffer(  U32 numVerts,
                                                 const GFXVertexFormat *vertexFormat,
                                                 U32 vertSize,
                                                 GFXBufferType bufferType,
                                                 void* data = NULL);
 
-   virtual GFXPrimitiveBuffer *allocPrimitiveBuffer(  U32 numIndices, 
-                                                      U32 numPrimitives, 
+   virtual GFXPrimitiveBuffer *allocPrimitiveBuffer(  U32 numIndices,
+                                                      U32 numPrimitives,
                                                       GFXBufferType bufferType,
                                                       void* data = NULL);
 
@@ -307,7 +311,7 @@ public:
 
    GFXFence *createFence();
 
-   GFXOcclusionQuery* createOcclusionQuery();   
+   GFXOcclusionQuery* createOcclusionQuery();
 
    // Default multisample parameters
    DXGI_SAMPLE_DESC getMultisampleType() const { return mMultisampleDesc; }
@@ -317,12 +321,16 @@ public:
    // Shader Model targers
    const String &getVertexShaderTarget() const { return mVertexShaderTarget; }
    const String &getPixelShaderTarget() const { return mPixelShaderTarget; }
+   const String &getGeometryShaderTarget() const { return mGeometryShaderTarget; }
    const String &getShaderModel() const { return mShaderModel; }
 
    // grab the sampler map
    const SamplerMap &getSamplersMap() const { return mSamplersMap; }
    SamplerMap &getSamplersMap(){ return mSamplersMap; }
    const char* interpretDebugResult(long result);
+
+   // grab device buffer.
+   ID3D11Buffer* getDeviceBuffer(const GFXShaderConstDesc desc);
 };
 
 #endif

文件差異過大導致無法顯示
+ 287 - 444
Engine/source/gfx/D3D11/gfxD3D11Shader.cpp


+ 67 - 311
Engine/source/gfx/D3D11/gfxD3D11Shader.h

@@ -29,282 +29,87 @@
 #include "core/util/tDictionary.h"
 #include "gfx/gfxShader.h"
 #include "gfx/gfxResource.h"
-#include "gfx/genericConstBuffer.h"
 #include "gfx/D3D11/gfxD3D11Device.h"
 
 class GFXD3D11Shader;
 
-enum CONST_CLASS
-{
-	D3DPC_SCALAR,
-	D3DPC_VECTOR,
-	D3DPC_MATRIX_ROWS,
-	D3DPC_MATRIX_COLUMNS,
-	D3DPC_OBJECT,
-	D3DPC_STRUCT
-};
-
-enum CONST_TYPE 
-{ 
-   D3DPT_VOID, 
-   D3DPT_BOOL, 
-   D3DPT_INT, 
-   D3DPT_FLOAT, 
-   D3DPT_STRING, 
-   D3DPT_TEXTURE, 
-   D3DPT_TEXTURE1D, 
-   D3DPT_TEXTURE2D, 
-   D3DPT_TEXTURE3D, 
-   D3DPT_TEXTURECUBE, 
-   D3DPT_SAMPLER, 
-   D3DPT_SAMPLER1D, 
-   D3DPT_SAMPLER2D, 
-   D3DPT_SAMPLER3D, 
-   D3DPT_SAMPLERCUBE, 
-   D3DPT_PIXELSHADER, 
-   D3DPT_VERTEXSHADER, 
-   D3DPT_PIXELFRAGMENT, 
-   D3DPT_VERTEXFRAGMENT
-};
-
-enum REGISTER_TYPE
-{
-	D3DRS_BOOL,
-	D3DRS_INT4,
-	D3DRS_FLOAT4,
-	D3DRS_SAMPLER
-};
-
-struct ConstantDesc
-{
-   String Name = String::EmptyString;
-   S32 RegisterIndex = 0;
-   S32 RegisterCount = 0;
-   S32 Rows = 0;
-   S32 Columns = 0;
-   S32 Elements = 0;
-   S32 StructMembers = 0;
-   REGISTER_TYPE RegisterSet = D3DRS_FLOAT4;
-   CONST_CLASS Class = D3DPC_SCALAR;
-   CONST_TYPE Type = D3DPT_FLOAT;
-   U32 Bytes = 0;
-};
-
-class ConstantTable
-{
-public:
-   bool Create(const void* data);
-
-   U32 GetConstantCount() const { return m_constants.size(); }
-   const String& GetCreator() const { return m_creator; } 
-
-   const ConstantDesc* GetConstantByIndex(U32 i) const { return &m_constants[i]; }
-   const ConstantDesc* GetConstantByName(const String& name) const;
-
-   void ClearConstants() { m_constants.clear(); }
-
-private:
-   Vector<ConstantDesc> m_constants;
-   String m_creator;
-};
+typedef CompoundKey<U32, U32> BufferKey;
 
-// Structs
-struct CTHeader
+struct BufferRange
 {
-   U32 Size;
-   U32 Creator;
-   U32 Version;
-   U32 Constants;
-   U32 ConstantInfo;
-   U32 Flags;
-   U32 Target;
-};
-
-struct CTInfo
-{
-   U32 Name;
-   U16 RegisterSet;
-   U16 RegisterIndex;
-   U16 RegisterCount;
-   U16 Reserved;
-   U32 TypeInfo;
-   U32 DefaultValue;
-};
-
-struct CTType
-{
-   U16 Class;
-   U16 Type;
-   U16 Rows;
-   U16 Columns;
-   U16 Elements;
-   U16 StructMembers;
-   U32 StructMemberInfo;
-};
-
-// Shader instruction opcodes
-const U32 SIO_COMMENT = 0x0000FFFE;
-const U32 SIO_END = 0x0000FFFF;
-const U32 SI_OPCODE_MASK = 0x0000FFFF;
-const U32 SI_COMMENTSIZE_MASK = 0x7FFF0000;
-const U32 CTAB_CONSTANT = 0x42415443;
-
-// Member functions
-inline bool ConstantTable::Create(const void* data)
-{
-   const U32* ptr = static_cast<const U32*>(data);
-   while(*++ptr != SIO_END)
-   {
-      if((*ptr & SI_OPCODE_MASK) == SIO_COMMENT)
-      {
-         // Check for CTAB comment
-         U32 comment_size = (*ptr & SI_COMMENTSIZE_MASK) >> 16;
-         if(*(ptr+1) != CTAB_CONSTANT)
-         {
-            ptr += comment_size;
-            continue;
-         }
-
-         // Read header
-         const char* ctab = reinterpret_cast<const char*>(ptr+2);
-         size_t ctab_size = (comment_size-1)*4;
-
-         const CTHeader* header = reinterpret_cast<const CTHeader*>(ctab);
-         if(ctab_size < sizeof(*header) || header->Size != sizeof(*header))
-            return false;
-         m_creator = ctab + header->Creator;
-
-         // Read constants
-         m_constants.reserve(header->Constants);
-         const CTInfo* info = reinterpret_cast<const CTInfo*>(ctab + header->ConstantInfo);
-         for(U32 i = 0; i < header->Constants; ++i)
-         {
-            const CTType* type = reinterpret_cast<const CTType*>(ctab + info[i].TypeInfo);
-
-            // Fill struct
-            ConstantDesc desc;
-            desc.Name = ctab + info[i].Name;
-            desc.RegisterSet = static_cast<REGISTER_TYPE>(info[i].RegisterSet);
-            desc.RegisterIndex = info[i].RegisterIndex;
-            desc.RegisterCount = info[i].RegisterCount;
-            desc.Rows = type->Rows;
-            desc.Class = static_cast<CONST_CLASS>(type->Class);
-            desc.Type = static_cast<CONST_TYPE>(type->Type);
-            desc.Columns = type->Columns;
-            desc.Elements = type->Elements;
-            desc.StructMembers = type->StructMembers;
-            desc.Bytes = 4 * desc.Elements * desc.Rows * desc.Columns;
-            m_constants.push_back(desc);
-         }
-
-         return true;
-      }
-   }
-   return false;
-}
+   U32 mBufMin = U32_MAX;
+   U32 mBufMax = 0;
 
-inline const ConstantDesc* ConstantTable::GetConstantByName(const String& name) const
-{
-   Vector<ConstantDesc>::const_iterator it;
-   for(it = m_constants.begin(); it != m_constants.end(); ++it)
+   inline void addSlot(U32 slot)
    {
-      if(it->Name == name)
-         return &(*it);
+      mBufMin = getMin(mBufMin, slot);
+      mBufMax = getMax(mBufMax, slot);
    }
-   return NULL;
-}
-
-/////////////////// Constant Buffers /////////////////////////////
-
-// Maximum number of CBuffers ($Globals & $Params)
-const U32 CBUFFER_MAX = 2;
-
-struct ConstSubBufferDesc
-{
-   U32 start;
-   U32 size;
 
-   ConstSubBufferDesc() : start(0), size(0){}
+   inline bool isValid() const { return mBufMin <= mBufMax; }
 };
 
-class GFXD3D11ConstBufferLayout : public GenericConstBufferLayout
+struct ConstantBuffer
 {
-public:
-   GFXD3D11ConstBufferLayout();
-   /// Get our constant sub buffer data
-   Vector<ConstSubBufferDesc> &getSubBufferDesc(){ return mSubBuffers; }
-   
-   /// We need to manually set the size due to D3D11 alignment
-   void setSize(U32 size){ mBufferSize = size;}
-
-   /// Set a parameter, given a base pointer
-   virtual bool set(const ParamDesc& pd, const GFXShaderConstType constType, const U32 size, const void* data, U8* basePointer);
-
-protected:
-   /// Set a matrix, given a base pointer
-   virtual bool setMatrix(const ParamDesc& pd, const GFXShaderConstType constType, const U32 size, const void* data, U8* basePointer);
-
-   Vector<ConstSubBufferDesc> mSubBuffers;
+   U8* data;
+   U32 size;
+   bool isDirty;
 };
 
 class GFXD3D11ShaderConstHandle : public GFXShaderConstHandle
 {
-public:   
-
-   // GFXShaderConstHandle
-   const String& getName() const;
-   GFXShaderConstType getType() const;
-   U32 getArraySize() const;
+   friend class GFXD3D11Shader;
+public:
+   typedef Map<GFXShaderStage, GFXShaderConstDesc> DescMap;
 
-   WeakRefPtr<GFXD3D11Shader> mShader;
+   GFXD3D11ShaderConstHandle(GFXD3D11Shader* shader);
+   GFXD3D11ShaderConstHandle(GFXD3D11Shader* shader,
+                              const GFXShaderConstDesc& desc);
 
-   bool mVertexConstant;
-   GenericConstBufferLayout::ParamDesc mVertexHandle;
-   bool mPixelConstant;
-   GenericConstBufferLayout::ParamDesc mPixelHandle;
-   
-   /// Is true if this constant is for hardware mesh instancing.
-   ///
-   /// Note: We currently store its settings in mPixelHandle.
-   ///
-   bool mInstancingConstant;
+   virtual ~GFXD3D11ShaderConstHandle();
+   void addDesc(GFXShaderStage stage, const GFXShaderConstDesc& desc);
+   const GFXShaderConstDesc getDesc(GFXShaderStage stage);
+   const String& getName() const { return mDesc.name; }
+   GFXShaderConstType getType() const { return mDesc.constType; }
+   U32 getArraySize() const { return mDesc.arraySize; }
 
-   void setValid( bool valid ) { mValid = valid; }
-   S32 getSamplerRegister() const;
+   U32 getSize() const { return mDesc.size; }
+   void setValid(bool valid) { mValid = valid; }
+   /// @warning This will always return the value assigned when the shader was
+   /// initialized.  If the value is later changed this method won't reflect that.
+   S32 getSamplerRegister() const { return (!isSampler() || !mValid) ? -1 : mDesc.samplerReg; }
 
    // Returns true if this is a handle to a sampler register.
-   bool isSampler() const 
+   bool isSampler() const
    {
-      return ( mPixelConstant && mPixelHandle.constType >= GFXSCT_Sampler ) || ( mVertexConstant && mVertexHandle.constType >= GFXSCT_Sampler );
+      return (getType() >= GFXSCT_Sampler);
    }
 
    /// Restore to uninitialized state.
    void clear()
    {
       mShader = NULL;
-      mVertexConstant = false;
-      mPixelConstant = false;
       mInstancingConstant = false;
-      mVertexHandle.clear();
-      mPixelHandle.clear();
       mValid = false;
    }
 
-   GFXD3D11ShaderConstHandle();
+   GFXShaderConstDesc mDesc;
+   GFXD3D11Shader* mShader;
+   DescMap mDescMap;
+   U32 mStageFlags;
+   bool mInstancingConstant;
 };
 
 /// The D3D11 implementation of a shader constant buffer.
 class GFXD3D11ShaderConstBuffer : public GFXShaderConstBuffer
 {
-   friend class GFXD3D11Shader;
    // Cache device context
    ID3D11DeviceContext* mDeviceContext;
 
 public:
+   typedef Map<BufferKey, ConstantBuffer> BufferMap;
 
-   GFXD3D11ShaderConstBuffer(GFXD3D11Shader* shader,
-      GFXD3D11ConstBufferLayout* vertexLayout,
-      GFXD3D11ConstBufferLayout* pixelLayout);
+   GFXD3D11ShaderConstBuffer(GFXD3D11Shader* shader);
 
    virtual ~GFXD3D11ShaderConstBuffer();
 
@@ -312,8 +117,7 @@ public:
    /// @param mPrevShaderBuffer The previously active buffer
    void activate(GFXD3D11ShaderConstBuffer *prevShaderBuffer);
 
-   /// Used internally by GXD3D11ShaderConstBuffer to determine if it's dirty.
-   bool isDirty();
+   void addBuffer(const GFXShaderConstDesc desc);
 
    /// Called from GFXD3D11Shader when constants have changed and need
    /// to be the shader this buffer references is reloaded.
@@ -344,33 +148,20 @@ public:
 
    // GFXResource
    virtual const String describeSelf() const;
-   virtual void zombify();
-   virtual void resurrect();
+   virtual void zombify() {}
+   virtual void resurrect() {}
 
 protected:
-
-   void _createBuffers();
-
-   template<class T>
-   inline void SET_CONSTANT(GFXShaderConstHandle* handle,
-      const T& fv,
-      GenericConstBuffer *vBuffer,
-      GenericConstBuffer *pBuffer);
-
-   // Constant buffers, VSSetConstantBuffers1 has issues on win 7. So unfortunately for now we have multiple constant buffers
-   ID3D11Buffer* mConstantBuffersV[CBUFFER_MAX];
-   ID3D11Buffer* mConstantBuffersP[CBUFFER_MAX];
-
-   /// We keep a weak reference to the shader 
+   friend class GFXD3D11Shader;
+   /// We keep a weak reference to the shader
    /// because it will often be deleted.
    WeakRefPtr<GFXD3D11Shader> mShader;
+   BufferMap mBufferMap;
+
+   void setMatrix(const GFXShaderConstDesc& handle, const U32 inSize, const void* data, U8* basePointer);
+   void internalSet(GFXShaderConstHandle* handle, const U32 inSize, const void* data);
 
-   //vertex
-   GFXD3D11ConstBufferLayout* mVertexConstBufferLayout;
-   GenericConstBuffer* mVertexConstBuffer;
-   //pixel
-   GFXD3D11ConstBufferLayout* mPixelConstBufferLayout;
-   GenericConstBuffer* mPixelConstBuffer;
+   ID3D11Buffer* mBoundBuffers[6][16];
 };
 
 class gfxD3D11Include;
@@ -385,17 +176,17 @@ class GFXD3D11Shader : public GFXShader
 
 public:
    typedef Map<String, GFXD3D11ShaderConstHandle*> HandleMap;
+   typedef Map<String, GFXShaderConstDesc> BufferMap;
 
    GFXD3D11Shader();
-   virtual ~GFXD3D11Shader();   
+   virtual ~GFXD3D11Shader();
 
    // GFXShader
    virtual GFXShaderConstBufferRef allocConstBuffer();
    virtual const Vector<GFXShaderConstDesc>& getShaderConstDesc() const;
-   virtual GFXShaderConstHandle* getShaderConstHandle(const String& name); 
+   virtual GFXShaderConstHandle* getShaderConstHandle(const String& name);
    virtual GFXShaderConstHandle* findShaderConstHandle(const String& name);
    virtual U32 getAlignmentValue(const GFXShaderConstType constType) const;
-   virtual bool getDisassembly( String &outStr ) const;
 
    // GFXResource
    virtual void zombify();
@@ -403,71 +194,36 @@ public:
 
 protected:
 
-   virtual bool _init();   
-
-   static const U32 smCompiledShaderTag;
-
-   ConstantTable table;
+   virtual bool _init();
 
    ID3D11VertexShader *mVertShader;
    ID3D11PixelShader *mPixShader;
-
-   GFXD3D11ConstBufferLayout* mVertexConstBufferLayout;
-   GFXD3D11ConstBufferLayout* mPixelConstBufferLayout;   
+   ID3D11GeometryShader *mGeoShader;
 
    static gfxD3DIncludeRef smD3DInclude;
 
    HandleMap mHandles;
-
-   /// The shader disassembly from DX when this shader is compiled.
-   /// We only store this data in non-release builds.
-   String mDissasembly;
-
-   /// Vector of sampler type descriptions consolidated from _compileShader.
-   Vector<GFXShaderConstDesc> mSamplerDescriptions;
+   BufferMap mBuffers;
 
    /// Vector of descriptions (consolidated for the getShaderConstDesc call)
    Vector<GFXShaderConstDesc> mShaderConsts;
-   
+   Vector<GFXShaderConstDesc> mSamplerDescriptions;
+
    // These two functions are used when compiling shaders from hlsl
-   virtual bool _compileShader( const Torque::Path &filePath, 
-                                const String &target, 
-                                const D3D_SHADER_MACRO *defines, 
-                                GenericConstBufferLayout *bufferLayout, 
-                                Vector<GFXShaderConstDesc> &samplerDescriptions );
-
-   void _getShaderConstants( ID3D11ShaderReflection* refTable, 
-	                         GenericConstBufferLayout *bufferLayout,
-                             Vector<GFXShaderConstDesc> &samplerDescriptions );
-
-   bool _convertShaderVariable(const D3D11_SHADER_TYPE_DESC &typeDesc, GFXShaderConstDesc &desc);
-
-
-   bool _saveCompiledOutput( const Torque::Path &filePath, 
-                             ID3DBlob *buffer, 
-                             GenericConstBufferLayout *bufferLayout,
-                             Vector<GFXShaderConstDesc> &samplerDescriptions );
-
-   // Loads precompiled shaders
-   bool _loadCompiledOutput( const Torque::Path &filePath, 
-                             const String &target, 
-                             GenericConstBufferLayout *bufferLayoutF, 
-                             Vector<GFXShaderConstDesc> &samplerDescriptions );
-  
-   // This is used in both cases
-   virtual void _buildShaderConstantHandles(GenericConstBufferLayout *layout, bool vertexConst);
-   
-   virtual void _buildSamplerShaderConstantHandles( Vector<GFXShaderConstDesc> &samplerDescriptions );
+   virtual bool _compileShader( const Torque::Path &filePath,
+                                 GFXShaderStage shaderStage,
+                                const D3D_SHADER_MACRO *defines);
+
+   void _getShaderConstants( ID3D11ShaderReflection* refTable,
+                              GFXShaderStage shaderStage);
 
-   /// Used to build the instancing shader constants from 
-   /// the instancing vertex format.
+   // This is used in both cases
+   virtual void _buildShaderConstantHandles();
    void _buildInstancingShaderConstantHandles();
+
+   GFXShaderConstType convertConstType(D3D11_SHADER_TYPE_DESC typeDesc);
+
 };
 
-inline bool GFXD3D11Shader::getDisassembly(String &outStr) const
-{
-   outStr = mDissasembly;
-   return (outStr.isNotEmpty());
-}
 
 #endif

+ 6 - 4
Engine/source/gfx/bitmap/loaders/bitmapSTB.cpp

@@ -34,6 +34,9 @@
 #define STBIWDEF static inline
 #endif
 
+#pragma warning( push )
+#pragma warning( disable : 4505 ) // unreferenced function removed.
+
 #define STB_IMAGE_IMPLEMENTATION
 #define STB_IMAGE_STATIC
 #include "stb_image.h"
@@ -42,6 +45,8 @@
 #define STB_IMAGE_WRITE_STATIC
 #include "stb_image_write.h"
 
+#pragma warning(pop)
+
 static bool sReadSTB(const Torque::Path& path, GBitmap* bitmap);
 static bool sReadStreamSTB(Stream& stream, GBitmap* bitmap, U32 len);
 
@@ -147,7 +152,7 @@ bool sReadSTB(const Torque::Path& path, GBitmap* bitmap)
          U32 buffSize = readIes->getStreamSize();
          char* buffer = new char[buffSize];
          readIes->read(buffSize, buffer);
-         
+
 
          IESFileInfo info;
          IESLoadHelper IESLoader;
@@ -399,8 +404,6 @@ bool sWriteSTB(const Torque::Path& path, GBitmap* bitmap, U32 compressionLevel)
    String ext = path.getExtension();
 
 
-
-   U32 stride = width * bytes;
    // we always have at least 1
    U32 comp = 1;
 
@@ -554,7 +557,6 @@ void DeferredPNGWriter::append(GBitmap* bitmap, U32 rows)
       mData->channels = bitmap->getBytesPerPixel();
    }
 
-   const U32 height = getMin(bitmap->getHeight(), rows);
    const dsize_t dataChuckSize = bitmap->getByteSize();
 
    const U8* pSrcData = bitmap->getBits();

+ 0 - 289
Engine/source/gfx/genericConstBuffer.cpp

@@ -1,289 +0,0 @@
-//-----------------------------------------------------------------------------
-// Copyright (c) 2012 GarageGames, LLC
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to
-// deal in the Software without restriction, including without limitation the
-// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
-// sell copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
-// IN THE SOFTWARE.
-//-----------------------------------------------------------------------------
-
-#include "platform/platform.h"
-#include "gfx/genericConstBuffer.h"
-
-#include "platform/profiler.h"
-#include "core/stream/stream.h"
-
-
-GenericConstBufferLayout::GenericConstBufferLayout()
-{
-   VECTOR_SET_ASSOCIATION( mParams );
-
-   mBufferSize = 0;
-   mCurrentIndex = 0;
-   mTimesCleared = 0;
-}
-
-void GenericConstBufferLayout::addParameter(const String& name, const GFXShaderConstType constType, const U32 offset, const U32 size, const U32 arraySize, const U32 alignValue)
-{
-#ifdef TORQUE_DEBUG
-   // Make sure we don't have overlapping parameters
-   S32 start = offset;
-   S32 end = offset + size;
-   for (Params::iterator i = mParams.begin(); i != mParams.end(); i++)
-   {
-      const ParamDesc& dp = *i;
-      S32 pstart = dp.offset;
-      S32 pend = pstart + dp.size;
-      pstart -= start;
-      pend -= end;
-      // This is like a minkowski sum for two line segments, if the newly formed line contains
-      // the origin, then they intersect
-      bool intersect = ((pstart >= 0 && 0 >= pend) || ((pend >= 0 && 0 >= pstart)));
-      AssertFatal(!intersect, "Overlapping shader parameter!");
-   }
-#endif
-   ParamDesc desc;
-   desc.name = name;
-   desc.constType = constType;
-   desc.offset = offset;
-   desc.size = size;
-   desc.arraySize = arraySize;
-   desc.alignValue = alignValue;
-   desc.index = mCurrentIndex++;
-   mParams.push_back(desc);
-   mBufferSize = getMax(desc.offset + desc.size, mBufferSize);
-   AssertFatal(mBufferSize, "Empty constant buffer!");
-}
-
-bool GenericConstBufferLayout::set(const ParamDesc& pd, const GFXShaderConstType constType, const U32 size, const void* data, U8* basePointer)
-{
-   PROFILE_SCOPE(GenericConstBufferLayout_set);
-
-   // Shader compilers like to optimize float4x4 uniforms into float3x3s.
-   // So long as the real paramater is a matrix of-some-type and the data
-   // passed in is a MatrixF ( which is will be ), we DO NOT have a
-   // mismatched const type.
-   AssertFatal( pd.constType == constType || 
-               ( 
-                 ( pd.constType == GFXSCT_Float2x2 || 
-                   pd.constType == GFXSCT_Float3x3 || 
-                   pd.constType == GFXSCT_Float3x4 ||  
-                   pd.constType == GFXSCT_Float4x3 || 
-                   pd.constType == GFXSCT_Float4x4 ) && 
-                 ( constType == GFXSCT_Float2x2 || 
-                   constType == GFXSCT_Float3x3 ||  
-                   constType == GFXSCT_Float3x4 ||  
-                   constType == GFXSCT_Float4x3 ||
-                   constType == GFXSCT_Float4x4 )
-               ), "Mismatched const type!" );
-
-   // This "cute" bit of code allows us to support 2x3 and 3x3 matrices in shader constants but use our MatrixF class.  Yes, a hack. -BTR
-   switch (pd.constType)
-   {
-   case GFXSCT_Float2x2 :
-   case GFXSCT_Float3x3 :
-   case GFXSCT_Float4x3 :
-   case GFXSCT_Float4x4 :
-      return setMatrix(pd, constType, size, data, basePointer);
-      break;
-   default :
-      break;
-   }
-
-   AssertFatal(pd.size >= size, "Not enough room in the buffer for this data!");
-
-   // Ok, we only set data if it's different than the data we already have, this maybe more expensive than just setting the data, but 
-   // we'll have to do some timings to see.  For example, the lighting shader constants rarely change, but we can't assume that at the
-   // renderInstMgr level, but we can check down here. -BTR
-   if (dMemcmp(basePointer+pd.offset, data, size) != 0)      
-   {
-      dMemcpy(basePointer+pd.offset, data, size);      
-      return true;
-   }   
-   return false;
-}
-
-bool GenericConstBufferLayout::setMatrix(const ParamDesc& pd, const GFXShaderConstType constType, const U32 size, const void* data, U8* basePointer)
-{
-   PROFILE_SCOPE(GenericConstBufferLayout_setMatrix);
-
-   // We're generic, so just copy the full MatrixF in
-   AssertFatal(pd.size >= size, "Not enough room in the buffer for this data!");
-
-   // Matrices are an annoying case because of the alignment issues.  There are alignment issues in the matrix itself, and then potential inter matrices alignment issues.
-   // So GL and DX will need to derive their own GenericConstBufferLayout classes and override this method to deal with that stuff.  For GenericConstBuffer, copy the whole
-   // 4x4 matrix regardless of the target case.
-
-   if (dMemcmp(basePointer+pd.offset, data, size) != 0)
-   {      
-      dMemcpy(basePointer+pd.offset, data, size);         
-      return true;
-   }
-      
-   return false;
-}
-
-bool GenericConstBufferLayout::getDesc(const String& name, ParamDesc& param) const
-{
-   for (U32 i = 0; i < mParams.size(); i++)
-   {
-      if (mParams[i].name.equal(name))
-      {
-         param = mParams[i];
-         return true;
-      }
-   } 
-   return false;
-}
-
-bool GenericConstBufferLayout::getDesc(const U32 index, ParamDesc& param) const
-{
-   if ( index < mParams.size() )
-   {
-      param = mParams[index];
-      return true;
-   }
-
-   return false;
-}
-
-bool GenericConstBufferLayout::write(Stream* s)
-{
-   // Write out the size of the ParamDesc structure as a sanity check.
-   if (!s->write((U32) sizeof(ParamDesc)))
-      return false;
-   // Next, write out the number of elements we've got.
-   if (!s->write(mParams.size()))
-      return false;
-   for (U32 i = 0; i < mParams.size(); i++)
-   {
-      s->write(mParams[i].name);
-         
-      if (!s->write(mParams[i].offset))
-         return false;
-      if (!s->write(mParams[i].size))
-         return false;
-      U32 t = (U32) mParams[i].constType;
-      if (!s->write(t))
-         return false;
-      if (!s->write(mParams[i].arraySize))
-         return false;
-      if (!s->write(mParams[i].alignValue))
-         return false;
-      if (!s->write(mParams[i].index))
-         return false;
-   }
-   return true;
-}
-
-/// Load this layout from a stream
-bool GenericConstBufferLayout::read(Stream* s)
-{
-   U32 structSize;
-   if (!s->read(&structSize))
-      return false;
-   if (structSize != sizeof(ParamDesc))
-   {
-      AssertFatal(false, "Invalid shader layout structure size!");
-      return false;
-   }
-   U32 numParams;
-   if (!s->read(&numParams))
-      return false;
-   mParams.setSize(numParams);
-   mBufferSize = 0;
-   mCurrentIndex = 0;
-   for (U32 i = 0; i < mParams.size(); i++)
-   {
-      s->read(&mParams[i].name);         
-      if (!s->read(&mParams[i].offset))
-         return false;
-      if (!s->read(&mParams[i].size))
-         return false;
-      U32 t;
-      if (!s->read(&t))
-         return false;
-      mParams[i].constType = (GFXShaderConstType) t;
-      if (!s->read(&mParams[i].arraySize))
-         return false;
-      if (!s->read(&mParams[i].alignValue))
-         return false;
-      if (!s->read(&mParams[i].index))
-         return false;
-      mBufferSize = getMax(mParams[i].offset + mParams[i].size, mBufferSize);
-      mCurrentIndex = getMax(mParams[i].index, mCurrentIndex);
-   }
-   mCurrentIndex++;
-   return true;
-}
-
-void GenericConstBufferLayout::clear()
-{
-   mParams.clear();    
-   mBufferSize = 0;
-   mCurrentIndex = 0;
-   mTimesCleared++;
-}
-
-
-GenericConstBuffer::GenericConstBuffer(GenericConstBufferLayout* layout)
-   :  mLayout( layout ),
-      mBuffer( NULL ),
-      mDirtyStart( U32_MAX ),
-      mDirtyEnd( 0 )
-{
-   if ( layout && layout->getBufferSize() > 0 )
-   {
-      mBuffer = new U8[mLayout->getBufferSize()];   
-
-      // Always set a default value, that way our isEqual checks
-      // will work in release as well.
-      dMemset( mBuffer, 0xFFFF, mLayout->getBufferSize() );
-
-      #ifdef TORQUE_DEBUG
-      
-         // Clear the debug assignment tracking.
-         mWasAssigned.setSize( layout->getParameterCount() );
-         dMemset( mWasAssigned.address(), 0, mWasAssigned.memSize() );
-
-      #endif
-   }
-}
-
-GenericConstBuffer::~GenericConstBuffer() 
-{
-   delete [] mBuffer;
-}
-
-#ifdef TORQUE_DEBUG
-
-void GenericConstBuffer::assertUnassignedConstants( const char *shaderName )
-{
-   for ( U32 i=0; i < mWasAssigned.size(); i++ )
-   {
-      if ( mWasAssigned[i] )
-         continue;
-
-      GenericConstBufferLayout::ParamDesc pd;
-      mLayout->getDesc( i, pd );
-
-      // Assert on the unassigned constant.
-      //AssertFatal( false, avar( "The '%s' shader constant in shader '%s' was unassigned!",
-      //   pd.name.c_str(), shaderName ) );
-   }
-}
-
-#endif

+ 0 - 374
Engine/source/gfx/genericConstBuffer.h

@@ -1,374 +0,0 @@
-//-----------------------------------------------------------------------------
-// Copyright (c) 2012 GarageGames, LLC
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to
-// deal in the Software without restriction, including without limitation the
-// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
-// sell copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
-// IN THE SOFTWARE.
-//-----------------------------------------------------------------------------
-
-#ifndef _GENERICCONSTBUFFER_H_
-#define _GENERICCONSTBUFFER_H_
-
-#ifndef _TORQUE_STRING_H_
-#include "core/util/str.h"
-#endif
-#ifndef _TDICTIONARY_H_
-#include "core/util/tDictionary.h"
-#endif
-#ifndef _TVECTOR_H_
-#include "core/util/tVector.h"
-#endif
-#ifndef _ALIGNEDARRAY_H_
-#include "core/util/tAlignedArray.h"
-#endif
-#ifndef _COLOR_H_
-#include "core/color.h"
-#endif
-#ifndef _MMATRIX_H_
-#include "math/mMatrix.h"
-#endif
-#ifndef _MPOINT2_H_
-#include "math/mPoint2.h"
-#endif
-#ifndef _GFXENUMS_H_
-#include "gfx/gfxEnums.h"
-#endif
-
-class Stream;
-
-
-/// This class defines the memory layout for a GenericConstBuffer.
-class GenericConstBufferLayout 
-{   
-public:
-   /// Describes the parameters we contain
-   struct ParamDesc
-   {
-      ParamDesc()
-         :  name(),
-            offset( 0 ),
-            size( 0 ),
-            constType( GFXSCT_Float ),
-            arraySize( 0 ),
-            alignValue( 0 ),
-            index( 0 )
-      {
-      }
-
-      void clear()
-      {
-         name = String::EmptyString;
-         offset = 0;
-         size = 0;
-         constType = GFXSCT_Float;
-         arraySize = 0;
-         alignValue = 0;
-         index = 0;
-      }
-
-      /// Parameter name
-      String name;
-
-      /// Offset into the memory block
-      U32 offset;
-
-      /// Size of the block
-      U32 size;
-
-      /// Type of data
-      GFXShaderConstType constType;
-
-      // For arrays, how many elements
-      U32 arraySize;
-
-      // Array element alignment value
-      U32 alignValue;
-
-      /// 0 based index of this param, in order of addParameter calls.
-      U32 index;
-   };
-
-   GenericConstBufferLayout();
-   virtual ~GenericConstBufferLayout() {}
-
-   /// Add a parameter to the buffer
-   virtual void addParameter(const String& name, const GFXShaderConstType constType, const U32 offset, const U32 size, const U32 arraySize, const U32 alignValue);
-
-   /// Get the size of the buffer
-   inline U32 getBufferSize() const { return mBufferSize; }
-
-   /// Get the number of parameters
-   inline U32 getParameterCount() const { return mParams.size(); }
-
-   /// Returns the ParamDesc of a parameter 
-   bool getDesc(const String& name, ParamDesc& param) const;
-
-   /// Returns the ParamDesc of a parameter 
-   bool getDesc(const U32 index, ParamDesc& param) const;
-
-   /// Set a parameter, given a base pointer
-   virtual bool set(const ParamDesc& pd, const GFXShaderConstType constType, const U32 size, const void* data, U8* basePointer);
-
-   /// Save this layout to a stream
-   bool write(Stream* s);
-
-   /// Load this layout from a stream
-   bool read(Stream* s);
-
-   /// Restore to initial state.
-   void clear();
-
-protected:
-
-   /// Set a matrix, given a base pointer.
-   virtual bool setMatrix(const ParamDesc& pd, const GFXShaderConstType constType, const U32 size, const void* data, U8* basePointer);
-
-   /// Vector of parameter descriptions.
-   typedef Vector<ParamDesc> Params;
-   
-   /// Vector of parameter descriptions.
-   Params mParams;
-   U32 mBufferSize;
-   U32 mCurrentIndex;
-
-   // This if for debugging shader reloading and can be removed later.
-   U32 mTimesCleared;
-};
-
-
-/// This class manages shader constant data in a system memory buffer.  It is
-/// used by device specific classes for batching together many constant changes 
-/// which are then copied to the device thru a single API call.
-///
-/// @see GenericConstBufferLayout
-///
-class GenericConstBuffer
-{
-public:
-   GenericConstBuffer(GenericConstBufferLayout* layout);
-   ~GenericConstBuffer();
-
-   /// @name Set shader constant values
-   /// @{
-   /// Actually set shader constant values
-   /// @param name Name of the constant, this should be a name contained in the array returned in getShaderConstDesc,
-   /// if an invalid name is used, its ignored, but it's not an error.
-   inline void set(const GenericConstBufferLayout::ParamDesc& pd, const F32 f) { internalSet(pd, GFXSCT_Float, sizeof(F32), &f); }
-   inline void set(const GenericConstBufferLayout::ParamDesc& pd, const Point2F& fv) { internalSet(pd, GFXSCT_Float2, sizeof(Point2F), &fv); }
-   inline void set(const GenericConstBufferLayout::ParamDesc& pd, const Point3F& fv) { internalSet(pd, GFXSCT_Float3, sizeof(Point3F), &fv); }
-   inline void set(const GenericConstBufferLayout::ParamDesc& pd, const Point4F& fv) { internalSet(pd, GFXSCT_Float4, sizeof(Point4F), &fv); }
-   inline void set(const GenericConstBufferLayout::ParamDesc& pd, const PlaneF& fv) { internalSet(pd, GFXSCT_Float4, sizeof(PlaneF), &fv); }
-   inline void set(const GenericConstBufferLayout::ParamDesc& pd, const LinearColorF& fv) { internalSet(pd, GFXSCT_Float4, sizeof(Point4F), &fv); }
-   inline void set(const GenericConstBufferLayout::ParamDesc& pd, const S32 f) { internalSet(pd, GFXSCT_Int, sizeof(S32), &f); }
-   inline void set(const GenericConstBufferLayout::ParamDesc& pd, const Point2I& fv) { internalSet(pd, GFXSCT_Int2, sizeof(Point2I), &fv); }
-   inline void set(const GenericConstBufferLayout::ParamDesc& pd, const Point3I& fv) { internalSet(pd, GFXSCT_Int3, sizeof(Point3I), &fv); }
-   inline void set(const GenericConstBufferLayout::ParamDesc& pd, const Point4I& fv) { internalSet(pd, GFXSCT_Int4, sizeof(Point4I), &fv); }
-   inline void set(const GenericConstBufferLayout::ParamDesc& pd, const AlignedArray<F32>& fv) { internalSet(pd, GFXSCT_Float, fv.getElementSize() * fv.size(), fv.getBuffer()); }
-   inline void set(const GenericConstBufferLayout::ParamDesc& pd, const AlignedArray<Point2F>& fv) { internalSet(pd, GFXSCT_Float2, fv.getElementSize() * fv.size(), fv.getBuffer()); }
-   inline void set(const GenericConstBufferLayout::ParamDesc& pd, const AlignedArray<Point3F>& fv) { internalSet(pd, GFXSCT_Float3, fv.getElementSize() * fv.size(), fv.getBuffer()); }
-   inline void set(const GenericConstBufferLayout::ParamDesc& pd, const AlignedArray<Point4F>& fv) { internalSet(pd, GFXSCT_Float4, fv.getElementSize() * fv.size(), fv.getBuffer()); }
-   inline void set(const GenericConstBufferLayout::ParamDesc& pd, const AlignedArray<S32>& fv) { internalSet(pd, GFXSCT_Int, fv.getElementSize() * fv.size(), fv.getBuffer()); }
-   inline void set(const GenericConstBufferLayout::ParamDesc& pd, const AlignedArray<Point2I>& fv) { internalSet(pd, GFXSCT_Int2, fv.getElementSize() * fv.size(), fv.getBuffer()); }
-   inline void set(const GenericConstBufferLayout::ParamDesc& pd, const AlignedArray<Point3I>& fv) { internalSet(pd, GFXSCT_Int3, fv.getElementSize() * fv.size(), fv.getBuffer()); }
-   inline void set(const GenericConstBufferLayout::ParamDesc& pd, const AlignedArray<Point4I>& fv) { internalSet(pd, GFXSCT_Int4, fv.getElementSize() * fv.size(), fv.getBuffer()); }
-
-   inline void set( const GenericConstBufferLayout::ParamDesc& pd, const MatrixF& mat, const GFXShaderConstType matrixType )
-   {
-      AssertFatal(   matrixType == GFXSCT_Float2x2 || 
-                     matrixType == GFXSCT_Float3x3 || 
-                     matrixType == GFXSCT_Float3x4 || 
-                     matrixType == GFXSCT_Float4x3 || 
-                     matrixType == GFXSCT_Float4x4, 
-         "GenericConstBuffer::set() - Invalid matrix type!" );
-
-      internalSet( pd, matrixType, sizeof(MatrixF), &mat );
-   }
-
-   inline void set( const GenericConstBufferLayout::ParamDesc& pd, const MatrixF* mat, const U32 arraySize, const GFXShaderConstType matrixType )
-   {
-      AssertFatal(   matrixType == GFXSCT_Float2x2 || 
-                     matrixType == GFXSCT_Float3x3 || 
-                     matrixType == GFXSCT_Float3x4 ||
-                     matrixType == GFXSCT_Float4x3 ||  
-                     matrixType == GFXSCT_Float4x4, 
-         "GenericConstBuffer::set() - Invalid matrix type!" );
-
-      internalSet( pd, matrixType, sizeof(MatrixF)*arraySize, mat );
-   }
-
-   /// Gets the dirty buffer range and clears the dirty
-   /// state at the same time.
-   inline const U8* getDirtyBuffer( U32 *start, U32 *size );
-
-   /// Gets the entire buffer ignoring dirty range
-   inline const U8* getEntireBuffer();
-
-   /// Sets the entire buffer as dirty or clears the dirty state.
-   inline void setDirty( bool dirty );
-
-   /// Returns true if the buffer has been modified since the 
-   /// last call to getDirtyBuffer or setDirty.  The buffer is
-   /// not dirty on initial creation.
-   ///
-   /// @see getDirtyBuffer
-   /// @see setDirty
-   inline bool isDirty() const { return mDirtyEnd != 0; }
-
-   /// Returns true if have the same layout and hold the same 
-   /// data as the input buffer.
-   inline bool isEqual( const GenericConstBuffer *buffer ) const;
-
-   /// Returns our layout object.
-   inline GenericConstBufferLayout* getLayout() const { return mLayout; }
-
-   #ifdef TORQUE_DEBUG
-   
-      /// Helper function used to assert on unset constants.
-      void assertUnassignedConstants( const char *shaderName );
-
-   #endif
-
-protected:
-
-   /// Returns a pointer to the raw buffer
-   inline const U8* getBuffer() const { return mBuffer; }
-
-   /// Called by the inlined set functions above to do the
-   /// real dirty work of copying the data to the right location
-   /// within the buffer.
-   inline void internalSet(   const GenericConstBufferLayout::ParamDesc &pd, 
-                              const GFXShaderConstType constType, 
-                              const U32 size, 
-                              const void *data );
-
-   /// The buffer layout.
-   GenericConstBufferLayout *mLayout;
-
-   /// The pointer to the contant store or
-   /// NULL if the layout is empty.
-   U8 *mBuffer;
-
-   /// The byte offset to the start of the dirty
-   /// range within the buffer or U32_MAX if the
-   /// buffer is not dirty.
-   U32 mDirtyStart;
-
-   /// The btye offset to the end of the dirty
-   /// range within the buffer or 0 if the buffer
-   /// is not dirty.
-   U32 mDirtyEnd;
-
-
-   #ifdef TORQUE_DEBUG
-   
-      /// A vector used to keep track if a constant 
-      /// has beed assigned a value or not.
-      ///
-      /// @see assertUnassignedConstants
-      Vector<bool> mWasAssigned;
-
-   #endif
-};
-
-
-// NOTE: These inlines below are here to get the very best possible
-// performance when setting the device shader constants and can be
-// called 4000-8000 times per frame or more.
-//
-// You need a very good reason to consider changing them.
-
-inline void GenericConstBuffer::internalSet( const GenericConstBufferLayout::ParamDesc &pd, 
-                                             const GFXShaderConstType constType, 
-                                             const U32 size, 
-                                             const void *data )
-{   
-   // NOTE: We should have never gotten here if the buffer 
-   // was null as no valid shader constant could have been 
-   // assigned.
-   //
-   // If this happens its a bug in another part of the code.
-   //
-   AssertFatal( mBuffer, "GenericConstBuffer::internalSet - The buffer is NULL!" );
-
-   if ( mLayout->set( pd, constType, size, data, mBuffer ) )
-   {
-      #ifdef TORQUE_DEBUG
-         
-         // Update the debug assignment tracking.
-         mWasAssigned[ pd.index ] = true;
-
-      #endif
-
-      // Keep track of the dirty range so it can be queried
-      // later in GenericConstBuffer::getDirtyBuffer.
-      mDirtyStart = getMin( pd.offset, mDirtyStart );
-      mDirtyEnd = getMax( pd.offset + pd.size, mDirtyEnd );
-   }
-}
-
-inline void GenericConstBuffer::setDirty( bool dirty )
-{ 
-   if ( !mBuffer )
-      return;
-
-   if ( dirty )
-   {
-      mDirtyStart = 0;
-      mDirtyEnd = mLayout->getBufferSize();
-   }
-   else if ( !dirty )
-   {
-      mDirtyStart = U32_MAX;
-      mDirtyEnd = 0;
-   }
-}
-
-inline const U8* GenericConstBuffer::getDirtyBuffer( U32 *start, U32 *size )
-{
-   AssertFatal( isDirty(), "GenericConstBuffer::getDirtyBuffer() - Buffer is not dirty!" );
-   AssertFatal( mDirtyEnd > mDirtyStart, "GenericConstBuffer::getDirtyBuffer() - Dirty range is invalid!" );
-   AssertFatal( mBuffer, "GenericConstBuffer::getDirtyBuffer() - Buffer is empty!" );
-
-   // Use the area we calculated during internalSet.
-   *size = mDirtyEnd - mDirtyStart;
-   *start = mDirtyStart;
-   const U8 *buffer = mBuffer + mDirtyStart;
-
-   // Clear the dirty state while we're here.
-   mDirtyStart = U32_MAX;
-   mDirtyEnd = 0;
-
-   return buffer;
-}
-
-inline const U8* GenericConstBuffer::getEntireBuffer()
-{
-   AssertFatal(mBuffer, "GenericConstBuffer::getDirtyBuffer() - Buffer is empty!");
-
-   return mBuffer;
-}
-
-inline bool GenericConstBuffer::isEqual( const GenericConstBuffer *buffer ) const
-{      
-   U32 bsize = mLayout->getBufferSize();
-   if ( bsize != buffer->mLayout->getBufferSize() )
-      return false;
-
-   return dMemcmp( mBuffer, buffer->getBuffer(), bsize ) == 0;
-}
-
-#endif // _GENERICCONSTBUFFER_H_

+ 269 - 85
Engine/source/gfx/gfxDrawUtil.cpp

@@ -34,7 +34,7 @@
 #include "gfx/gfxPrimitiveBuffer.h"
 #include "gfx/primBuilder.h"
 #include "gfx/gfxDebugEvent.h"
-
+#include "materials/shaderData.h"
 #include "math/mPolyhedron.impl.h"
 
 
@@ -45,7 +45,7 @@ GFXDrawUtil::GFXDrawUtil( GFXDevice * d)
    mTextAnchorColor.set(0xFF, 0xFF, 0xFF, 0xFF);
    mFontRenderBatcher = new FontRenderBatcher();
 
-   _setupStateBlocks();   
+   _setupStateBlocks();
 }
 
 GFXDrawUtil::~GFXDrawUtil()
@@ -90,6 +90,33 @@ void GFXDrawUtil::_setupStateBlocks()
    rectFill.setZReadWrite(false);
    rectFill.setBlend(true, GFXBlendSrcAlpha, GFXBlendInvSrcAlpha);
    mRectFillSB = mDevice->createStateBlock(rectFill);
+
+   // Find ShaderData
+   ShaderData* shaderData;
+   mRoundRectangleShader = Sim::findObject("RoundedRectangleGUI", shaderData) ? shaderData->getShader() : NULL;
+   if (!mRoundRectangleShader)
+   {
+      Con::errorf("GFXDrawUtil - could not find Rounded Rectangle shader");
+   }
+   // Create ShaderConstBuffer and Handles
+   mRoundRectangleShaderConsts = mRoundRectangleShader->allocConstBuffer();
+
+   mCircleShader = Sim::findObject("CircularGUI", shaderData) ? shaderData->getShader() : NULL;
+   if (!mCircleShader)
+   {
+      Con::errorf("GFXDrawUtil - could not find circle shader");
+   }
+   // Create ShaderConstBuffer and Handles
+   mCircleShaderConsts = mCircleShader->allocConstBuffer();
+
+   mThickLineShader = Sim::findObject("ThickLineGUI", shaderData) ? shaderData->getShader() : NULL;
+   if (!mThickLineShader)
+   {
+      Con::errorf("GFXDrawUtil - could not find Thick line shader");
+   }
+   // Create ShaderConstBuffer and Handles
+   mThickLineShaderConsts = mThickLineShader->allocConstBuffer();
+
 }
 
 //-----------------------------------------------------------------------------
@@ -118,13 +145,13 @@ void GFXDrawUtil::setTextAnchorColor( const ColorI &ancColor )
 //-----------------------------------------------------------------------------
 // Draw Text
 //-----------------------------------------------------------------------------
-U32 GFXDrawUtil::drawText( GFont *font, const Point2I &ptDraw, const UTF16 *in_string, 
+U32 GFXDrawUtil::drawText( GFont *font, const Point2I &ptDraw, const UTF16 *in_string,
                           const ColorI *colorTable, const U32 maxColorIndex, F32 rot )
 {
    return drawTextN( font, ptDraw, in_string, dStrlen(in_string), colorTable, maxColorIndex, rot );
 }
 
-U32 GFXDrawUtil::drawText( GFont *font, const Point2I &ptDraw, const UTF8 *in_string, 
+U32 GFXDrawUtil::drawText( GFont *font, const Point2I &ptDraw, const UTF8 *in_string,
                           const ColorI *colorTable, const U32 maxColorIndex, F32 rot )
 {
    return drawTextN( font, ptDraw, in_string, dStrlen(in_string), colorTable, maxColorIndex, rot );
@@ -154,7 +181,7 @@ U32 GFXDrawUtil::drawTextN( GFont *font, const Point2I &ptDraw, const UTF8 *in_s
    return drawTextN( font, ptDraw, ubuf, n, colorTable, maxColorIndex, rot );
 }
 
-U32 GFXDrawUtil::drawTextN( GFont *font, const Point2I &ptDraw, const UTF16 *in_string, 
+U32 GFXDrawUtil::drawTextN( GFont *font, const Point2I &ptDraw, const UTF16 *in_string,
                            U32 n, const ColorI *colorTable, const U32 maxColorIndex, F32 rot )
 {
    // return on zero length strings
@@ -178,11 +205,11 @@ U32 GFXDrawUtil::drawTextN( GFont *font, const Point2I &ptDraw, const UTF16 *in_
 
    S32 ptX = 0;
 
-   // Queue everything for render.   
+   // Queue everything for render.
    mFontRenderBatcher->init(font, n);
 
    U32 i;
-   UTF16 c;   
+   UTF16 c;
    for (i = 0, c = in_string[i]; i < n && in_string[i]; i++, c = in_string[i])
    {
       switch(c)
@@ -193,25 +220,25 @@ U32 GFXDrawUtil::drawTextN( GFont *font, const Point2I &ptDraw, const UTF16 *in_
       case 14:
          {
             // Color code
-            if (colorTable) 
+            if (colorTable)
             {
-               static U8 remap[15] = 
-               { 
+               static U8 remap[15] =
+               {
                   0x0, // 0 special null terminator
                   0x0, // 1 ascii start-of-heading??
-                  0x1, 
-                  0x2, 
-                  0x3, 
-                  0x4, 
-                  0x5, 
-                  0x6, 
+                  0x1,
+                  0x2,
+                  0x3,
+                  0x4,
+                  0x5,
+                  0x6,
                   0x0, // 8 special backspace
                   0x0, // 9 special tab
                   0x0, // a special \n
-                  0x7, 
+                  0x7,
                   0x8,
                   0x0, // a special \r
-                  0x9 
+                  0x9
                };
 
                U8 remapped = remap[c];
@@ -256,7 +283,7 @@ U32 GFXDrawUtil::drawTextN( GFont *font, const Point2I &ptDraw, const UTF16 *in_
          }
 
          // Tab character
-      case dT('\t'): 
+      case dT('\t'):
          {
             if ( tabci == NULL )
                tabci = &(font->getCharInfo( dT(' ') ));
@@ -272,7 +299,7 @@ U32 GFXDrawUtil::drawTextN( GFont *font, const Point2I &ptDraw, const UTF16 *in_
          // Don't draw invalid characters.
       default:
          {
-            if( !font->isValidChar( c ) ) 
+            if( !font->isValidChar( c ) )
                continue;
          }
       }
@@ -354,7 +381,7 @@ void GFXDrawUtil::drawBitmapStretchSR( GFXTextureObject* texture, const RectF &d
 {
    // Sanity if no texture is specified.
    if(!texture)
-      return;   
+      return;
 
    GFXVertexBufferHandle<GFXVertexPCT> verts(mDevice, 4, GFXBufferTypeVolatile );
    verts.lock();
@@ -369,13 +396,13 @@ void GFXDrawUtil::drawBitmapStretchSR( GFXTextureObject* texture, const RectF &d
    F32 screenTop    = dstRect.point.y;
    F32 screenBottom = (dstRect.point.y + dstRect.extent.y);
 
-   if( in_flip & GFXBitmapFlip_X ) 
+   if( in_flip & GFXBitmapFlip_X )
    {
       F32 temp = texLeft;
       texLeft = texRight;
       texRight = temp;
    }
-   if( in_flip & GFXBitmapFlip_Y ) 
+   if( in_flip & GFXBitmapFlip_Y )
    {
       F32 temp = texTop;
       texTop = texBottom;
@@ -435,7 +462,7 @@ void GFXDrawUtil::drawBitmapStretchSR( GFXTextureObject* texture, const RectF &d
       AssertFatal(false, "No GFXDrawUtil state block defined for this filter type!");
       mDevice->setStateBlock(mBitmapStretchSB);
       break;
-   }   
+   }
    mDevice->setTexture( 0, texture );
    mDevice->setupGenericShaders( GFXDevice::GSModColorTexture );
 
@@ -445,7 +472,7 @@ void GFXDrawUtil::drawBitmapStretchSR( GFXTextureObject* texture, const RectF &d
 //-----------------------------------------------------------------------------
 // Draw Rectangle
 //-----------------------------------------------------------------------------
-void GFXDrawUtil::drawRect( const Point2I &upperLeft, const Point2I &lowerRight, const ColorI &color ) 
+void GFXDrawUtil::drawRect( const Point2I &upperLeft, const Point2I &lowerRight, const ColorI &color )
 {
    drawRect( Point2F((F32)upperLeft.x,(F32)upperLeft.y),Point2F((F32)lowerRight.x,(F32)lowerRight.y),color);
 }
@@ -513,57 +540,99 @@ void GFXDrawUtil::drawRect( const Point2F &upperLeft, const Point2F &lowerRight,
 //-----------------------------------------------------------------------------
 // Draw Rectangle Fill
 //-----------------------------------------------------------------------------
-void GFXDrawUtil::drawRectFill( const RectF &rect, const ColorI &color )
+void GFXDrawUtil::drawRectFill(const RectF& rect, const ColorI& color, const F32& borderSize, const ColorI& borderColor)
 {
-   drawRectFill(rect.point, Point2F(rect.extent.x + rect.point.x - 1, rect.extent.y + rect.point.y - 1), color );
+   drawRoundedRect(0.0f, rect.point, Point2F(rect.extent.x + rect.point.x - 1, rect.extent.y + rect.point.y - 1), color, borderSize, borderColor);
 }
 
-void GFXDrawUtil::drawRectFill( const Point2I &upperLeft, const Point2I &lowerRight, const ColorI &color ) 
-{   
-   drawRectFill(Point2F((F32)upperLeft.x, (F32)upperLeft.y), Point2F((F32)lowerRight.x, (F32)lowerRight.y), color);
+void GFXDrawUtil::drawRectFill(const Point2I& upperLeft, const Point2I& lowerRight, const ColorI& color, const F32& borderSize, const ColorI& borderColor)
+{
+   drawRoundedRect(0.0f, Point2F((F32)upperLeft.x, (F32)upperLeft.y), Point2F((F32)lowerRight.x, (F32)lowerRight.y), color, borderSize, borderColor);
 }
 
-void GFXDrawUtil::drawRectFill( const RectI &rect, const ColorI &color )
+void GFXDrawUtil::drawRectFill(const RectI& rect, const ColorI& color, const F32& borderSize, const ColorI& borderColor)
 {
-   drawRectFill(rect.point, Point2I(rect.extent.x + rect.point.x - 1, rect.extent.y + rect.point.y - 1), color );
+   drawRoundedRect(0.0f, rect.point, Point2I(rect.extent.x + rect.point.x - 1, rect.extent.y + rect.point.y - 1), color, borderSize, borderColor);
 }
 
-void GFXDrawUtil::drawRectFill( const Point2F &upperLeft, const Point2F &lowerRight, const ColorI &color )
+void GFXDrawUtil::drawRectFill(const Point2F& upperLeft, const Point2F& lowerRight, const ColorI& color, const F32& borderSize,const ColorI& borderColor)
+{
+   // draw a rounded rect with 0 radiuse.
+   drawRoundedRect(0.0f, upperLeft, lowerRight, color, borderSize, borderColor);
+}
+
+void GFXDrawUtil::drawRoundedRect(const F32& cornerRadius, const RectI& rect, const ColorI& color, const F32& borderSize, const ColorI& borderColor)
+{
+   drawRoundedRect(cornerRadius, rect.point, Point2I(rect.extent.x + rect.point.x - 1, rect.extent.y + rect.point.y - 1), color, borderSize, borderColor);
+}
+
+void GFXDrawUtil::drawRoundedRect(const F32& cornerRadius, const Point2I& upperLeft, const Point2I& lowerRight, const ColorI& color, const F32& borderSize, const ColorI& borderColor)
+{
+   drawRoundedRect(cornerRadius, Point2F((F32)upperLeft.x, (F32)upperLeft.y), Point2F((F32)lowerRight.x, (F32)lowerRight.y), color, borderSize, borderColor);
+}
+
+void GFXDrawUtil::drawRoundedRect(const F32& cornerRadius,
+   const Point2F& upperLeft,
+   const Point2F& lowerRight,
+   const ColorI& color,
+   const F32& borderSize,
+   const ColorI& borderColor)
 {
-   //
-   // Convert Box   a----------x
-   //               |          |
-   //               x----------b
-   // Into Quad
-   //               v0---------v1
-   //               | a       x |
-   //               |           |
-   //               | x       b |
-   //               v2---------v3
-   //
 
    // NorthWest and NorthEast facing offset vectors
-   Point2F nw(-0.5,-0.5); /*  \  */
-   Point2F ne(0.5,-0.5); /*  /  */
+   Point2F nw(-0.5, -0.5); /*  \  */
+   Point2F ne(0.5, -0.5); /*  /  */
 
    GFXVertexBufferHandle<GFXVertexPCT> verts(mDevice, 4, GFXBufferTypeVolatile);
    verts.lock();
 
    F32 ulOffset = 0.5f - mDevice->getFillConventionOffset();
-   
-   verts[0].point.set( upperLeft.x+nw.x + ulOffset, upperLeft.y+nw.y + ulOffset, 0.0f );
-   verts[1].point.set( lowerRight.x + ne.x + ulOffset, upperLeft.y + ne.y + ulOffset, 0.0f);
-   verts[2].point.set( upperLeft.x - ne.x + ulOffset, lowerRight.y - ne.y + ulOffset, 0.0f);
-   verts[3].point.set( lowerRight.x - nw.x + ulOffset, lowerRight.y - nw.y + ulOffset, 0.0f);
+
+   verts[0].point.set(upperLeft.x + nw.x + ulOffset, upperLeft.y + nw.y + ulOffset, 0.0f);
+   verts[1].point.set(lowerRight.x + ne.x + ulOffset, upperLeft.y + ne.y + ulOffset, 0.0f);
+   verts[2].point.set(upperLeft.x - ne.x + ulOffset, lowerRight.y - ne.y + ulOffset, 0.0f);
+   verts[3].point.set(lowerRight.x - nw.x + ulOffset, lowerRight.y - nw.y + ulOffset, 0.0f);
    for (S32 i = 0; i < 4; i++)
       verts[i].color = color;
 
    verts.unlock();
+   mDevice->setVertexBuffer(verts);
 
    mDevice->setStateBlock(mRectFillSB);
-   mDevice->setVertexBuffer( verts );
-   mDevice->setupGenericShaders();
-   mDevice->drawPrimitive( GFXTriangleStrip, 0, 2 );
+
+   Point2F topLeftCorner(upperLeft.x + nw.x + ulOffset, upperLeft.y + nw.y + ulOffset);
+   Point2F bottomRightCorner(lowerRight.x - nw.x + ulOffset, lowerRight.y - nw.y + ulOffset);
+
+   /*mDevice->setupGenericShaders();*/
+   GFX->setShader(mRoundRectangleShader);
+   GFX->setShaderConstBuffer(mRoundRectangleShaderConsts);
+
+   MatrixF tempMatrix = GFX->getProjectionMatrix() * GFX->getViewMatrix() * GFX->getWorldMatrix();
+   Point2F size((F32)(bottomRightCorner.x - topLeftCorner.x), (F32)(bottomRightCorner.y - topLeftCorner.y));
+
+   F32 minExtent = mMin(size.x, size.y);
+
+   F32 radius = cornerRadius;
+   if ((minExtent * 0.5) < radius)
+   {
+      radius = mClampF(radius, 0.0f, (minExtent * 0.5));
+   }
+
+   mRoundRectangleShaderConsts->set(mRoundRectangleShader->getShaderConstHandle("$modelView"), tempMatrix, GFXSCT_Float4x4);
+   mRoundRectangleShaderConsts->setSafe(mRoundRectangleShader->getShaderConstHandle("$radius"), radius);
+   mRoundRectangleShaderConsts->setSafe(mRoundRectangleShader->getShaderConstHandle("$sizeUni"), size);
+   mRoundRectangleShaderConsts->setSafe(mRoundRectangleShader->getShaderConstHandle("$borderSize"), borderSize);
+   mRoundRectangleShaderConsts->setSafe(mRoundRectangleShader->getShaderConstHandle("$borderCol"), borderColor);
+
+   Point2F rectCenter((F32)(topLeftCorner.x + (size.x / 2.0)), (F32)(topLeftCorner.y + (size.y / 2.0)));
+   mRoundRectangleShaderConsts->setSafe(mRoundRectangleShader->getShaderConstHandle("$rectCenter"), rectCenter);
+
+   const Point2I& resolution = GFX->getActiveRenderTarget()->getSize();
+   Point2F TargetSize(1.0 / (F32)resolution.x, 1.0 / (F32)resolution.y);
+
+   mRoundRectangleShaderConsts->setSafe(mRoundRectangleShader->getShaderConstHandle("$oneOverViewport"), TargetSize);
+
+   mDevice->drawPrimitive(GFXTriangleStrip, 0, 2);
 }
 
 void GFXDrawUtil::draw2DSquare( const Point2F &screenPoint, F32 width, F32 spinAngle )
@@ -608,7 +677,73 @@ void GFXDrawUtil::draw2DSquare( const Point2F &screenPoint, F32 width, F32 spinA
 }
 
 //-----------------------------------------------------------------------------
-// Draw Line
+// Draw Circle : FILL
+//-----------------------------------------------------------------------------
+void GFXDrawUtil::drawCircleFill(const RectI& rect, const ColorI& color, F32 radius, const F32& borderSize, const ColorI& borderColor)
+{
+   drawCircleFill(rect.point, Point2I(rect.extent.x + rect.point.x - 1, rect.extent.y + rect.point.y - 1), color, radius, borderSize, borderColor);
+}
+
+void GFXDrawUtil::drawCircleFill(const Point2I& upperLeft, const Point2I& lowerRight, const ColorI& color, F32 radius, const F32& borderSize, const ColorI& borderColor)
+{
+   drawCircleFill(Point2F((F32)upperLeft.x, (F32)upperLeft.y), Point2F((F32)lowerRight.x, (F32)lowerRight.y), color, radius, borderSize, borderColor);
+}
+
+void GFXDrawUtil::drawCircleFill(const Point2F& upperLeft, const Point2F& lowerRight, const ColorI& color, F32 radius, const F32& borderSize, const ColorI& borderColor)
+{
+   // NorthWest and NorthEast facing offset vectors
+   Point2F nw(-0.5, -0.5); /*  \  */
+   Point2F ne(0.5, -0.5); /*  /  */
+
+   GFXVertexBufferHandle<GFXVertexPCT> verts(mDevice, 4, GFXBufferTypeVolatile);
+   verts.lock();
+
+   F32 ulOffset = 0.5f - mDevice->getFillConventionOffset();
+
+   verts[0].point.set(upperLeft.x + nw.x + ulOffset, upperLeft.y + nw.y + ulOffset, 0.0f);
+   verts[1].point.set(lowerRight.x + ne.x + ulOffset, upperLeft.y + ne.y + ulOffset, 0.0f);
+   verts[2].point.set(upperLeft.x - ne.x + ulOffset, lowerRight.y - ne.y + ulOffset, 0.0f);
+   verts[3].point.set(lowerRight.x - nw.x + ulOffset, lowerRight.y - nw.y + ulOffset, 0.0f);
+   for (S32 i = 0; i < 4; i++)
+      verts[i].color = color;
+
+   verts.unlock();
+   mDevice->setVertexBuffer(verts);
+
+   mDevice->setStateBlock(mRectFillSB);
+
+   Point2F topLeftCorner(upperLeft.x + nw.x + ulOffset, upperLeft.y + nw.y + ulOffset);
+   Point2F bottomRightCorner(lowerRight.x - nw.x + ulOffset, lowerRight.y - nw.y + ulOffset);
+
+   /*mDevice->setupGenericShaders();*/
+   GFX->setShader(mCircleShader);
+   GFX->setShaderConstBuffer(mCircleShaderConsts);
+
+   MatrixF tempMatrix = GFX->getProjectionMatrix() * GFX->getViewMatrix() * GFX->getWorldMatrix();
+   Point2F size((F32)(bottomRightCorner.x - topLeftCorner.x), (F32)(bottomRightCorner.y - topLeftCorner.y));
+
+   Point2F rectCenter((F32)(topLeftCorner.x + (size.x / 2.0)), (F32)(topLeftCorner.y + (size.y / 2.0)));
+   mCircleShaderConsts->setSafe(mCircleShader->getShaderConstHandle("$rectCenter"), rectCenter);
+
+   F32 minExtent = mMin(size.x, size.y);
+   F32 shaderRadius = radius;
+
+   if ((minExtent * 0.5) < shaderRadius)
+   {
+      shaderRadius = mClampF(radius, 0.0f, (minExtent * 0.5));
+   }
+
+   mCircleShaderConsts->set(mCircleShader->getShaderConstHandle("$modelView"), tempMatrix, GFXSCT_Float4x4);
+   mCircleShaderConsts->setSafe(mCircleShader->getShaderConstHandle("$radius"), shaderRadius);
+   mCircleShaderConsts->setSafe(mCircleShader->getShaderConstHandle("$sizeUni"), size);
+   mCircleShaderConsts->setSafe(mCircleShader->getShaderConstHandle("$borderSize"), borderSize);
+   mCircleShaderConsts->setSafe(mCircleShader->getShaderConstHandle("$borderCol"), borderColor);
+
+   mDevice->drawPrimitive(GFXTriangleStrip, 0, 2);
+}
+
+//-----------------------------------------------------------------------------
+// Draw Lines : Single Pixel
 //-----------------------------------------------------------------------------
 void GFXDrawUtil::drawLine( const Point3F &startPt, const Point3F &endPt, const ColorI &color )
 {
@@ -648,6 +783,55 @@ void GFXDrawUtil::drawLine( F32 x1, F32 y1, F32 z1, F32 x2, F32 y2, F32 z2, cons
    mDevice->drawPrimitive( GFXLineList, 0, 1 );
 }
 
+//-----------------------------------------------------------------------------
+// Draw Lines : Thick
+//-----------------------------------------------------------------------------
+void GFXDrawUtil::drawThickLine(const Point2I& startPt, const Point2I& endPt, const ColorI& color, const F32& thickness)
+{
+   drawThickLine(startPt.x, startPt.y, 0.0f, endPt.x, endPt.y, 0.0f, color, thickness);
+}
+
+void GFXDrawUtil::drawThickLine(const Point2F& startPt, const Point2F& endPt, const ColorI& color, const F32& thickness)
+{
+   drawThickLine(startPt.x, startPt.y, 0.0f, endPt.x, endPt.y, 0.0f, color, thickness);
+}
+
+void GFXDrawUtil::drawThickLine(F32 x1, F32 y1, F32 z1, F32 x2, F32 y2, F32 z2, const ColorI& color, const F32& thickness)
+{
+   // less than 2 just draw an ordinary line... why you ever here....
+   if (thickness < 2.0f)
+   {
+      drawLine(x1, y1, z1, x2, y2, z2, color);
+      return;
+   }
+
+   GFXVertexBufferHandle<GFXVertexPCT> verts(mDevice, 2, GFXBufferTypeVolatile);
+   verts.lock();
+
+   verts[0].point.set(x1, y1, z1);
+   verts[1].point.set(x2, y2, z2);
+   verts[0].color = color;
+   verts[1].color = color;
+
+   verts.unlock();
+
+   mDevice->setVertexBuffer(verts);
+   mDevice->setStateBlock(mRectFillSB);
+   GFX->setShader(mThickLineShader);
+   GFX->setShaderConstBuffer(mThickLineShaderConsts);
+
+   MatrixF tempMatrix = GFX->getProjectionMatrix() * GFX->getViewMatrix() * GFX->getWorldMatrix();
+   mThickLineShaderConsts->set(mThickLineShader->getShaderConstHandle("$modelView"), tempMatrix, GFXSCT_Float4x4);
+   mThickLineShaderConsts->setSafe(mThickLineShader->getShaderConstHandle("$thickness"), thickness);
+
+   const Point2I& resolution = GFX->getActiveRenderTarget()->getSize();
+   Point2F TargetSize(1.0 / (F32)resolution.x, 1.0 / (F32)resolution.y);
+
+   mThickLineShaderConsts->setSafe(mThickLineShader->getShaderConstHandle("$oneOverViewport"), TargetSize);
+
+   mDevice->drawPrimitive(GFXLineList, 0, 1);
+}
+
 //-----------------------------------------------------------------------------
 // 3D World Draw Misc
 //-----------------------------------------------------------------------------
@@ -713,13 +897,13 @@ void GFXDrawUtil::drawSphere( const GFXStateBlockDesc &desc, F32 radius, const P
 
 //-----------------------------------------------------------------------------
 
-static const Point3F cubePoints[8] = 
+static const Point3F cubePoints[8] =
 {
    Point3F(-1, -1, -1), Point3F(-1, -1,  1), Point3F(-1,  1, -1), Point3F(-1,  1,  1),
    Point3F( 1, -1, -1), Point3F( 1, -1,  1), Point3F( 1,  1, -1), Point3F( 1,  1,  1)
 };
 
-static const U32 cubeFaces[6][4] = 
+static const U32 cubeFaces[6][4] =
 {
    { 0, 4, 6, 2 }, { 0, 2, 3, 1 }, { 0, 1, 5, 4 },
    { 3, 2, 6, 7 }, { 7, 6, 4, 5 }, { 3, 7, 5, 1 }
@@ -812,7 +996,7 @@ void GFXDrawUtil::drawPolygon( const GFXStateBlockDesc& desc, const Point3F* poi
       for( U32 i = 0; i < numPoints; ++ i )
          xfm->mulP( verts[ i ].point );
    }
-   
+
    if( isWireframe )
    {
       verts[ numVerts - 1 ].point = verts[ 0 ].point;
@@ -899,7 +1083,7 @@ void GFXDrawUtil::_drawSolidCube( const GFXStateBlockDesc &desc, const Point3F &
    for(S32 i = 0; i < 6; i++)
    {
       idx = cubeFaces[i][0];
-      verts[vertexIndex].point = cubePoints[idx] * halfSize;      
+      verts[vertexIndex].point = cubePoints[idx] * halfSize;
       verts[vertexIndex].color = color;
       vertexIndex++;
 
@@ -1110,13 +1294,13 @@ void GFXDrawUtil::drawObjectBox( const GFXStateBlockDesc &desc, const Point3F &s
    Point3F cubePts[8];
    for (U32 i = 0; i < 8; i++)
    {
-	   cubePts[i] = cubePoints[i]/2;
+      cubePts[i] = cubePoints[i]/2;
    }
 
-   // 8 corner points of the box   
+   // 8 corner points of the box
    for ( U32 i = 0; i < 8; i++ )
    {
-      //const Point3F &start = cubePoints[i];  
+      //const Point3F &start = cubePoints[i];
 
       // 3 lines per corner point
       for ( U32 j = 0; j < 3; j++ )
@@ -1128,7 +1312,7 @@ void GFXDrawUtil::drawObjectBox( const GFXStateBlockDesc &desc, const Point3F &s
          scaledObjMat.mulP(start);
          PrimBuild::vertex3fv(start);
          scaledObjMat.mulP(end);
-         PrimBuild::vertex3fv(end);            
+         PrimBuild::vertex3fv(end);
       }
    }
 
@@ -1164,10 +1348,10 @@ void GFXDrawUtil::drawCapsule( const GFXStateBlockDesc &desc, const Point3F &cen
 }
 
 void GFXDrawUtil::_drawSolidCapsule( const GFXStateBlockDesc &desc, const Point3F &center, F32 radius, F32 height, const ColorI &color, const MatrixF *xfm )
-{	
+{
    MatrixF mat;
    if ( xfm )
-      mat = *xfm;      
+      mat = *xfm;
    else
       mat = MatrixF::Identity;
 
@@ -1176,7 +1360,7 @@ void GFXDrawUtil::_drawSolidCapsule( const GFXStateBlockDesc &desc, const Point3
    verts.lock();
    for (S32 i=0; i<numPoints + 1; i++)
    {
-      S32 imod = i % numPoints;      
+      S32 imod = i % numPoints;
       verts[2 * i].point = Point3F( circlePoints[imod].x * radius, circlePoints[imod].y * radius, height/2 );
       verts[2 * i].color = color;
       verts[2 * i + 1].point = Point3F( circlePoints[imod].x * radius, circlePoints[imod].y * radius, -height/2 );
@@ -1208,7 +1392,7 @@ void GFXDrawUtil::_drawSolidCapsule( const GFXStateBlockDesc &desc, const Point3
    if ( xfm )
       sphereMat = *xfm;
    else
-      sphereMat = MatrixF::Identity;   
+      sphereMat = MatrixF::Identity;
 
    sphereCenter.set( 0, 0, 0.5f * height );
    mat.mulV( sphereCenter );
@@ -1284,12 +1468,12 @@ void GFXDrawUtil::_drawWireCapsule( const GFXStateBlockDesc &desc, const Point3F
 }
 
 void GFXDrawUtil::drawCone( const GFXStateBlockDesc &desc, const Point3F &basePnt, const Point3F &tipPnt, F32 baseRadius, const ColorI &color )
-{   
+{
    VectorF uvec = tipPnt - basePnt;
    F32 height = uvec.len();
    uvec.normalize();
    MatrixF mat( true );
-   MathUtils::getMatrixFromUpVector( uvec, &mat );   
+   MathUtils::getMatrixFromUpVector( uvec, &mat );
    mat.setPosition(basePnt);
 
    Point3F scale( baseRadius, baseRadius, height );
@@ -1359,7 +1543,7 @@ void GFXDrawUtil::drawCylinder( const GFXStateBlockDesc &desc, const Point3F &ba
    F32 height = uvec.len();
    uvec.normalize();
    MatrixF mat( true );
-   MathUtils::getMatrixFromUpVector( uvec, &mat );   
+   MathUtils::getMatrixFromUpVector( uvec, &mat );
    mat.setPosition(basePnt);
 
    Point3F scale( radius, radius, height * 2 );
@@ -1425,14 +1609,14 @@ void GFXDrawUtil::drawCylinder( const GFXStateBlockDesc &desc, const Point3F &ba
 }
 
 void GFXDrawUtil::drawArrow( const GFXStateBlockDesc &desc, const Point3F &start, const Point3F &end, const ColorI &color, F32 baseRad )
-{   
+{
    GFXTransformSaver saver;
 
    // Direction and length of the arrow.
    VectorF dir = end - start;
    F32 len = dir.len();
-   dir.normalize();   
-   len *= 0.2f;      
+   dir.normalize();
+   len *= 0.2f;
 
    // Base of the cone will be a distance back from the end of the arrow
    // proportional to the total distance of the arrow... 0.3f looks about right.
@@ -1464,11 +1648,11 @@ void GFXDrawUtil::drawFrustum( const Frustum &f, const ColorI &color )
 
    // Draw near and far planes.
    for (U32 offset = 0; offset < 8; offset+=4)
-   {      
+   {
       drawLine(points[offset+0], points[offset+1], color);
       drawLine(points[offset+2], points[offset+3], color);
       drawLine(points[offset+0], points[offset+2], color);
-      drawLine(points[offset+1], points[offset+3], color);            
+      drawLine(points[offset+1], points[offset+3], color);
    }
 
    // connect the near and far planes
@@ -1512,13 +1696,13 @@ void GFXDrawUtil::drawPlaneGrid( const GFXStateBlockDesc &desc, const Point3F &p
    U32 vSteps = 0;
    if( step.y > 0 )
       vSteps = size.y / step.y + 0.5 + 1;
-      
+
    if( uSteps <= 1 || vSteps <= 1 )
       return;
-      
+
    const U32 numVertices = uSteps * 2 + vSteps * 2;
    const U32 numLines = uSteps + vSteps;
-   
+
    Point3F origin;
    switch( plane )
    {
@@ -1552,14 +1736,14 @@ void GFXDrawUtil::drawPlaneGrid( const GFXStateBlockDesc &desc, const Point3F &p
             verts[vertCount].point = Point3F( start + step.x * i, origin.y + size.y, origin.z );
          else
             verts[vertCount].point = Point3F( start + step.x * i, origin.y,  origin.z + size.y );
-            
+
          verts[vertCount].color = color;
          ++vertCount;
       }
    }
 
    if( plane == PlaneXY || plane == PlaneYZ )
-   {      
+   {
       U32 num;
       F32 stp;
       if( plane == PlaneXY )
@@ -1574,7 +1758,7 @@ void GFXDrawUtil::drawPlaneGrid( const GFXStateBlockDesc &desc, const Point3F &p
       }
 
       F32 start = mFloor( origin.y / stp + 0.5f ) * stp;
-         
+
       for ( U32 i = 0; i < num; i++ )
       {
          verts[vertCount].point = Point3F( origin.x, start + stp * i, origin.z );
@@ -1585,7 +1769,7 @@ void GFXDrawUtil::drawPlaneGrid( const GFXStateBlockDesc &desc, const Point3F &p
             verts[vertCount].point = Point3F( origin.x + size.x, start + stp * i, origin.z );
          else
             verts[vertCount].point = Point3F( origin.x, start + stp * i, origin.z + size.x );
-            
+
          verts[vertCount].color = color;
          ++vertCount;
       }
@@ -1604,7 +1788,7 @@ void GFXDrawUtil::drawPlaneGrid( const GFXStateBlockDesc &desc, const Point3F &p
             verts[vertCount].point = Point3F( origin.x + size.x, origin.y, start + step.y * i );
          else
             verts[vertCount].point = Point3F( origin.x, origin.y + size.x, start + step.y * i );
-            
+
          verts[vertCount].color = color;
          ++vertCount;
       }
@@ -1629,7 +1813,7 @@ void GFXDrawUtil::drawTransform( const GFXStateBlockDesc &desc, const MatrixF &m
    GFXVertexBufferHandle<GFXVertexPCT> verts( mDevice, 6, GFXBufferTypeVolatile );
    verts.lock();
 
-   const static ColorI defColors[3] = 
+   const static ColorI defColors[3] =
    {
       ColorI::RED,
       ColorI::GREEN,
@@ -1655,7 +1839,7 @@ void GFXDrawUtil::drawTransform( const GFXStateBlockDesc &desc, const MatrixF &m
    {
       verts[1].point *= *scale;
       verts[3].point *= *scale;
-      verts[5].point *= *scale;      
+      verts[5].point *= *scale;
    }
 
    verts.unlock();

+ 58 - 24
Engine/source/gfx/gfxDrawUtil.h

@@ -31,12 +31,12 @@
 #include "math/mPolyhedron.h"
 #endif
 
-
-
 class FontRenderBatcher;
 class Frustum;
 
 
+
+
 /// Helper class containing utility functions for useful drawing routines
 /// (line, box, rect, billboard, text).
 class GFXDrawUtil
@@ -46,22 +46,36 @@ public:
    ~GFXDrawUtil();
 
    //-----------------------------------------------------------------------------
-   // Draw Rectangles
+   // Draw Rectangles : OUTLINE
+   //-----------------------------------------------------------------------------
+   void drawRect(const Point2F& upperLeft, const Point2F& lowerRight, const ColorI& color);
+   void drawRect(const RectF& rect, const ColorI& color);
+   void drawRect(const Point2I& upperLeft, const Point2I& lowerRight, const ColorI& color);
+   void drawRect(const RectI& rect, const ColorI& color);
+
+   //-----------------------------------------------------------------------------
+   // Draw Rectangles : FILL
    //-----------------------------------------------------------------------------
-   void drawRect( const Point2F &upperLeft, const Point2F &lowerRight, const ColorI &color );
-   void drawRect( const RectF &rect, const ColorI &color );
-   void drawRect( const Point2I &upperLeft, const Point2I &lowerRight, const ColorI &color );
-   void drawRect( const RectI &rect, const ColorI &color );
 
-   void drawRectFill( const Point2F &upperL, const Point2F &lowerR, const ColorI &color );
-   void drawRectFill( const RectF &rect, const ColorI &color );
-   void drawRectFill( const Point2I &upperLeft, const Point2I &lowerRight, const ColorI &color );
-   void drawRectFill( const RectI &rect, const ColorI &color );
+   void drawRectFill(const Point2F& upperL, const Point2F& lowerR, const ColorI& color, const F32& borderSize = 0.0f, const ColorI& borderColor = ColorI(0, 0, 0, 0));
+   void drawRectFill(const RectF& rect, const ColorI& color, const F32& borderSize = 0.0f, const ColorI& borderColor = ColorI(0, 0, 0, 0));
+   void drawRectFill(const Point2I& upperLeft, const Point2I& lowerRight, const ColorI& color, const F32& borderSize = 0.0f, const ColorI& borderColor = ColorI(0, 0, 0, 0));
+   void drawRectFill(const RectI& rect, const ColorI& color, const F32& borderSize = 0.0f, const ColorI& borderColor = ColorI(0, 0, 0, 0));
+   void drawRoundedRect(const F32& cornerRadius, const RectI& rect, const ColorI& color, const F32& borderSize = 0.0f, const ColorI& borderColor = ColorI(0, 0, 0, 0));
+   void drawRoundedRect(const F32& cornerRadius, const Point2I& upperLeft, const Point2I& lowerRight, const ColorI& color, const F32& borderSize = 0.0f, const ColorI& borderColor = ColorI(0, 0, 0, 0));
+   void drawRoundedRect(const F32& cornerRadius, const Point2F& upperLeft, const Point2F& lowerRight, const ColorI& color, const F32& borderSize = 0.0f, const ColorI& borderColor = ColorI(0, 0, 0, 0));
+
+   void draw2DSquare(const Point2F& screenPoint, F32 width, F32 spinAngle = 0.0f);
 
-   void draw2DSquare( const Point2F &screenPoint, F32 width, F32 spinAngle = 0.0f );
+   //-----------------------------------------------------------------------------
+   // Draw Circle : FILL
+   //-----------------------------------------------------------------------------
+   void drawCircleFill(const RectI& rect, const ColorI& color, F32 radius, const F32& borderSize = 0.0f, const ColorI& borderColor = ColorI(0, 0, 0, 0));
+   void drawCircleFill(const Point2I& upperLeft, const Point2I& lowerRight, const ColorI& color, F32 radius, const F32& borderSize = 0.0f, const ColorI& borderColor = ColorI(0, 0, 0, 0));
+   void drawCircleFill(const Point2F& upperLeft, const Point2F& lowerRight, const ColorI& color, F32 radius, const F32& borderSize = 0.0f, const ColorI& borderColor = ColorI(0, 0, 0, 0));
 
    //-----------------------------------------------------------------------------
-   // Draw Lines
+   // Draw Lines : Single Pixel
    //-----------------------------------------------------------------------------
    void drawLine( const Point3F &startPt, const Point3F &endPt, const ColorI &color );
    void drawLine( const Point2F &startPt, const Point2F &endPt, const ColorI &color );
@@ -69,6 +83,13 @@ public:
    void drawLine( F32 x1, F32 y1, F32 x2, F32 y2, const ColorI &color );
    void drawLine( F32 x1, F32 y1, F32 z1, F32 x2, F32 y2, F32 z2, const ColorI &color );
 
+   //-----------------------------------------------------------------------------
+   // Draw Lines : Thick
+   //-----------------------------------------------------------------------------
+   void drawThickLine(const Point2I& startPt, const Point2I& endPt, const ColorI& color, const F32& thickness);
+   void drawThickLine(const Point2F& startPt, const Point2F& endPt, const ColorI& color, const F32& thickness);
+   void drawThickLine(F32 x1, F32 y1, F32 z1, F32 x2, F32 y2, F32 z2, const ColorI& color, const F32& thickness);
+
    //-----------------------------------------------------------------------------
    // Draw Text
    //-----------------------------------------------------------------------------
@@ -92,7 +113,7 @@ public:
 
    //-----------------------------------------------------------------------------
    // Draw Bitmaps
-   //-----------------------------------------------------------------------------  
+   //-----------------------------------------------------------------------------
    void drawBitmap( GFXTextureObject*texture, const Point2F &in_rAt, const GFXBitmapFlip in_flip = GFXBitmapFlip_None, const GFXTextureFilterType filter = GFXTextureFilterPoint , bool in_wrap = true, F32 angle = 0.0f);
    void drawBitmapSR( GFXTextureObject*texture, const Point2F &in_rAt, const RectF &srcRect, const GFXBitmapFlip in_flip = GFXBitmapFlip_None, const GFXTextureFilterType filter = GFXTextureFilterPoint , bool in_wrap = true, F32 angle = 0.0f);
    void drawBitmapStretch( GFXTextureObject*texture, const RectF &dstRect, const GFXBitmapFlip in_flip = GFXBitmapFlip_None, const GFXTextureFilterType filter = GFXTextureFilterPoint , bool in_wrap = true, F32 angle = 0.0f);
@@ -108,15 +129,15 @@ public:
    //-----------------------------------------------------------------------------
    void drawTriangle( const GFXStateBlockDesc &desc, const Point3F &p0, const Point3F &p1, const Point3F &p2, const ColorI &color, const MatrixF *xfm = NULL );
    void drawPolygon( const GFXStateBlockDesc& desc, const Point3F* points, U32 numPoints, const ColorI& color, const MatrixF* xfm = NULL );
-   void drawCube( const GFXStateBlockDesc &desc, const Point3F &size, const Point3F &pos, const ColorI &color, const MatrixF *xfm = NULL );   
-   void drawCube( const GFXStateBlockDesc &desc, const Box3F &box, const ColorI &color, const MatrixF *xfm = NULL );   
-   void drawObjectBox( const GFXStateBlockDesc &desc, const Point3F &size, const Point3F &pos, const MatrixF &objMat, const ColorI &color );   
-   void drawSphere( const GFXStateBlockDesc &desc, F32 radius, const Point3F &pos, const ColorI &color, bool drawTop = true, bool drawBottom = true, const MatrixF *xfm = NULL );      
+   void drawCube( const GFXStateBlockDesc &desc, const Point3F &size, const Point3F &pos, const ColorI &color, const MatrixF *xfm = NULL );
+   void drawCube( const GFXStateBlockDesc &desc, const Box3F &box, const ColorI &color, const MatrixF *xfm = NULL );
+   void drawObjectBox( const GFXStateBlockDesc &desc, const Point3F &size, const Point3F &pos, const MatrixF &objMat, const ColorI &color );
+   void drawSphere( const GFXStateBlockDesc &desc, F32 radius, const Point3F &pos, const ColorI &color, bool drawTop = true, bool drawBottom = true, const MatrixF *xfm = NULL );
    void drawCapsule( const GFXStateBlockDesc &desc, const Point3F &center, F32 radius, F32 height, const ColorI &color, const MatrixF *xfm = NULL );
-   void drawCone( const GFXStateBlockDesc &desc, const Point3F &basePnt, const Point3F &tipPnt, F32 baseRadius, const ColorI &color );      
-   void drawCylinder( const GFXStateBlockDesc &desc, const Point3F &basePnt, const Point3F &tipPnt, F32 baseRadius, const ColorI &color );      
+   void drawCone( const GFXStateBlockDesc &desc, const Point3F &basePnt, const Point3F &tipPnt, F32 baseRadius, const ColorI &color );
+   void drawCylinder( const GFXStateBlockDesc &desc, const Point3F &basePnt, const Point3F &tipPnt, F32 baseRadius, const ColorI &color );
    void drawArrow( const GFXStateBlockDesc &desc, const Point3F &start, const Point3F &end, const ColorI &color, F32 baseRad = 0.0f);
-   void drawFrustum( const Frustum& f, const ColorI &color );   
+   void drawFrustum( const Frustum& f, const ColorI &color );
 
    /// Draw a solid or wireframe (depending on fill mode of @a desc) polyhedron with the given color.
    ///
@@ -128,7 +149,7 @@ public:
 
    /// Draws a solid XY plane centered on the point with the specified dimensions.
    void drawSolidPlane( const GFXStateBlockDesc &desc, const Point3F &pos, const Point2F &size, const ColorI &color );
-   
+
    enum Plane
    {
       PlaneXY,
@@ -142,7 +163,7 @@ public:
    /// Draws axis lines representing the passed matrix.
    /// If scale is NULL axes will be drawn the length they exist within the MatrixF.
    /// If colors is NULL the default colors are RED, GREEEN, BLUE ( x, y, z ).
-   void drawTransform( const GFXStateBlockDesc &desc, const MatrixF &mat, const Point3F *scale = NULL, const ColorI colors[3] = NULL );  
+   void drawTransform( const GFXStateBlockDesc &desc, const MatrixF &mat, const Point3F *scale = NULL, const ColorI colors[3] = NULL );
 
 protected:
 
@@ -174,8 +195,21 @@ protected:
    GFXStateBlockRef mBitmapStretchWrapSB;
    GFXStateBlockRef mBitmapStretchWrapLinearSB;
    GFXStateBlockRef mRectFillSB;
-   
+
    FontRenderBatcher* mFontRenderBatcher;
+
+   // Expanded shaders
+   // rounded rectangle.
+   GFXShaderRef mRoundRectangleShader;
+   GFXShaderConstBufferRef mRoundRectangleShaderConsts;
+
+   // thick line.
+   GFXShaderRef mCircleShader;
+   GFXShaderConstBufferRef mCircleShaderConsts;
+
+   // thick line.
+   GFXShaderRef mThickLineShader;
+   GFXShaderConstBufferRef mThickLineShaderConsts;
 };
 
 #endif // _GFX_GFXDRAWER_H_

+ 43 - 29
Engine/source/gfx/gfxEnums.h

@@ -64,7 +64,7 @@ enum GFXTexCallbackCode
    GFXResurrect,
 };
 
-enum GFXPrimitiveType 
+enum GFXPrimitiveType
 {
    GFXPT_FIRST = 0,
    GFXPointList = 0,
@@ -75,7 +75,7 @@ enum GFXPrimitiveType
    GFXPT_COUNT
 };
 
-enum GFXBitmapFlip 
+enum GFXBitmapFlip
 {
    GFXBitmapFlip_None = 0,
    GFXBitmapFlip_X    = 1 << 0,
@@ -83,7 +83,7 @@ enum GFXBitmapFlip
    GFXBitmapFlip_XY   = GFXBitmapFlip_X | GFXBitmapFlip_Y
 };
 
-enum GFXTextureAddressMode 
+enum GFXTextureAddressMode
 {
    GFXAddress_FIRST = 0,
    GFXAddressWrap = 0,
@@ -94,7 +94,7 @@ enum GFXTextureAddressMode
    GFXAddress_COUNT
 };
 
-enum GFXTextureFilterType 
+enum GFXTextureFilterType
 {
    GFXTextureFilter_FIRST = 0,
    GFXTextureFilterNone = 0,
@@ -104,7 +104,7 @@ enum GFXTextureFilterType
    GFXTextureFilter_COUNT
 };
 
-enum GFXFillMode 
+enum GFXFillMode
 {
    GFXFill_FIRST = 1,
    GFXFillPoint = 1,
@@ -113,7 +113,7 @@ enum GFXFillMode
    GFXFill_COUNT
 };
 
-enum GFXFormat 
+enum GFXFormat
 {
    // when adding formats make sure to place
    // them in the correct group!
@@ -152,7 +152,7 @@ enum GFXFormat
    GFXFormatR11G11B10,
    GFXFormatD32,
    GFXFormatD24X8,
-   GFXFormatD24S8,   
+   GFXFormatD24S8,
    GFXFormatD24FS8,
 
    // Guaranteed RGBA8 (for apis which really dont like bgr)
@@ -172,7 +172,7 @@ enum GFXFormat
    GFXFormatBC3,  //dxt4/5
    GFXFormatBC4,  //3dc+ / ati1
    GFXFormatBC5,  //3dc / ati2
-   // compressed sRGB formats   
+   // compressed sRGB formats
    GFXFormatBC1_SRGB,
    GFXFormatBC2_SRGB,
    GFXFormatBC3_SRGB,
@@ -191,7 +191,7 @@ enum GFXFormat
 /// Returns the byte size of the pixel for non-compressed formats.
 inline U32 GFXFormat_getByteSize( GFXFormat format )
 {
-   AssertFatal( format < GFXFormat_UNKNOWNSIZE, 
+   AssertFatal( format < GFXFormat_UNKNOWNSIZE,
       "GFXDevice::formatByteSize - Cannot size a compressed format!" );
 
    if ( format < GFXFormat_16BIT )
@@ -205,12 +205,12 @@ inline U32 GFXFormat_getByteSize( GFXFormat format )
    else if ( format < GFXFormat_128BIT )
       return 8;// 64 bit...
 
-   // This should be 128bits... else its a DDS and 
+   // This should be 128bits... else its a DDS and
    // the assert should have gone off above.
    return 16;
 }
 
-enum GFXClearFlags 
+enum GFXClearFlags
 {
    GFXClearTarget = 1 << 0,
    GFXClearZBuffer = 1 << 1,
@@ -218,7 +218,7 @@ enum GFXClearFlags
 };
 
 /// The supported blend modes.
-enum GFXBlend 
+enum GFXBlend
 {
    GFXBlend_FIRST = 0,
    GFXBlendZero = 0, /// (0, 0, 0, 0)
@@ -238,7 +238,7 @@ enum GFXBlend
 /// Constants that name each GFXDevice type. Any new GFXDevice subclass must be
 /// added to this enum. A string representing its name must also be added to
 /// GFXInit::getAdapterNameFromType().
-enum GFXAdapterType 
+enum GFXAdapterType
 {
    OpenGL = 0,
    Direct3D11,
@@ -255,7 +255,7 @@ enum GFXCullMode
    GFXCull_COUNT
 };
 
-enum GFXCmpFunc 
+enum GFXCmpFunc
 {
    GFXCmp_FIRST = 0,
    GFXCmpNever = 0,
@@ -269,7 +269,7 @@ enum GFXCmpFunc
    GFXCmp_COUNT
 };
 
-enum GFXStencilOp 
+enum GFXStencilOp
 {
    GFXStencilOp_FIRST = 0,
    GFXStencilOpKeep = 0,
@@ -283,8 +283,8 @@ enum GFXStencilOp
    GFXStencilOp_COUNT
 };
 
-enum GFXBlendOp 
-{ 
+enum GFXBlendOp
+{
    GFXBlendOp_FIRST = 0,
    GFXBlendOpAdd = 0,
    GFXBlendOpSubtract,
@@ -294,7 +294,7 @@ enum GFXBlendOp
    GFXBlendOp_COUNT
 };
 
-enum GFXMatrixType 
+enum GFXMatrixType
 {
    GFXMatrixWorld = 256,
    GFXMatrixView = 2,
@@ -312,25 +312,39 @@ enum GFXMatrixType
 
 enum GFXShaderConstType
 {
+   GFXSCT_Uknown,
    /// GFX"S"hader"C"onstant"T"ype
+   GFXSCT_ConstBuffer,
    // Scalar
-   GFXSCT_Float, 
+   GFXSCT_Float,
    // Vectors
-   GFXSCT_Float2, 
-   GFXSCT_Float3, 
-   GFXSCT_Float4, 
+   GFXSCT_Float2,
+   GFXSCT_Float3,
+   GFXSCT_Float4,
    // Matrices
-   GFXSCT_Float2x2, 
+   GFXSCT_Float2x2,
    GFXSCT_Float3x3,
    GFXSCT_Float3x4,
    GFXSCT_Float4x3,
-   GFXSCT_Float4x4, 
+   GFXSCT_Float4x4,
+   // Scalar
+   GFXSCT_Int,
+   // Vectors
+   GFXSCT_Int2,
+   GFXSCT_Int3,
+   GFXSCT_Int4,
+   // Scalar
+   GFXSCT_UInt,
+   // Vectors
+   GFXSCT_UInt2,
+   GFXSCT_UInt3,
+   GFXSCT_UInt4,
    // Scalar
-   GFXSCT_Int, 
+   GFXSCT_Bool,
    // Vectors
-   GFXSCT_Int2, 
-   GFXSCT_Int3, 
-   GFXSCT_Int4, 
+   GFXSCT_Bool2,
+   GFXSCT_Bool3,
+   GFXSCT_Bool4,
    // Samplers
    GFXSCT_Sampler,
    GFXSCT_SamplerCube,
@@ -352,7 +366,7 @@ enum GFXDeclType
    /// @see Point2F
    GFXDeclType_Float2,
 
-   /// A three-component F32. 
+   /// A three-component F32.
    /// @see Point3F
    GFXDeclType_Float3,
 

+ 40 - 15
Engine/source/gfx/gfxShader.cpp

@@ -49,9 +49,9 @@ GFXShader::~GFXShader()
 }
 
 #ifndef TORQUE_OPENGL
-bool GFXShader::init(   const Torque::Path &vertFile, 
-                        const Torque::Path &pixFile, 
-                        F32 pixVersion, 
+bool GFXShader::init(   const Torque::Path &vertFile,
+                        const Torque::Path &pixFile,
+                        F32 pixVersion,
                         const Vector<GFXShaderMacro> &macros )
 {
    Vector<String> samplerNames;
@@ -59,13 +59,18 @@ bool GFXShader::init(   const Torque::Path &vertFile,
 }
 #endif
 
-bool GFXShader::init(   const Torque::Path &vertFile, 
-                        const Torque::Path &pixFile, 
-                        F32 pixVersion, 
+bool GFXShader::init(   F32 pixVersion,
                         const Vector<GFXShaderMacro> &macros,
                         const Vector<String> &samplerNames,
                         GFXVertexFormat *instanceFormat)
 {
+   // early out.
+   if (mVertexFile.isEmpty() && mPixelFile.isEmpty() && mGeometryFile.isEmpty())
+   {
+      Con::errorf("Shader files empty, please call setShaderStageFile from shaderData");
+      return false;
+   }
+
    // Take care of instancing
    if (instanceFormat)
    {
@@ -74,8 +79,6 @@ bool GFXShader::init(   const Torque::Path &vertFile,
    }
 
    // Store the inputs for use in reloading.
-   mVertexFile = vertFile;
-   mPixelFile = pixFile;
    mPixVersion = pixVersion;
    mMacros = macros;
    mSamplerNamesOrdered = samplerNames;
@@ -91,8 +94,12 @@ bool GFXShader::init(   const Torque::Path &vertFile,
    _updateDesc();
 
    // Add file change notifications for reloads.
-   Torque::FS::AddChangeNotification( mVertexFile, this, &GFXShader::_onFileChanged );
-   Torque::FS::AddChangeNotification( mPixelFile, this, &GFXShader::_onFileChanged );
+   if(!mVertexFile.isEmpty())
+      Torque::FS::AddChangeNotification( mVertexFile, this, &GFXShader::_onFileChanged );
+   if(!mPixelFile.isEmpty())
+      Torque::FS::AddChangeNotification( mPixelFile, this, &GFXShader::_onFileChanged );
+   if(!mGeometryFile.isEmpty())
+      Torque::FS::AddChangeNotification( mGeometryFile, this, &GFXShader::_onFileChanged);
 
    return true;
 }
@@ -119,11 +126,11 @@ bool GFXShader::reload()
 
 void GFXShader::_updateDesc()
 {
-   mDescription = String::ToString( "Files: %s, %s Pix Version: %0.2f\nMacros: ", 
+   mDescription = String::ToString( "Files: %s, %s Pix Version: %0.2f\nMacros: ",
       mVertexFile.getFullPath().c_str(), mPixelFile.getFullPath().c_str(), mPixVersion );
 
    GFXShaderMacro::stringize( smGlobalMacros, &mDescription );
-   GFXShaderMacro::stringize( mMacros, &mDescription );   
+   GFXShaderMacro::stringize( mMacros, &mDescription );
 }
 
 void GFXShader::addGlobalMacro( const String &name, const String &value )
@@ -161,8 +168,26 @@ bool GFXShader::removeGlobalMacro( const String &name )
    return false;
 }
 
+void GFXShader::setShaderStageFile(const GFXShaderStage stage, const Torque::Path& filePath)
+{
+   switch (stage)
+   {
+   case GFXShaderStage::VERTEX_SHADER:
+      mVertexFile = filePath;
+      break;
+   case GFXShaderStage::PIXEL_SHADER:
+      mPixelFile = filePath;
+      break;
+   case GFXShaderStage::GEOMETRY_SHADER:
+      mGeometryFile = filePath;
+      break;
+   default:
+      break;
+   }
+}
+
 void GFXShader::_unlinkBuffer( GFXShaderConstBuffer *buf )
-{   
+{
    Vector<GFXShaderConstBuffer*>::iterator iter = mActiveBuffers.begin();
    for ( ; iter != mActiveBuffers.end(); iter++ )
    {
@@ -177,7 +202,7 @@ void GFXShader::_unlinkBuffer( GFXShaderConstBuffer *buf )
 }
 
 
-DefineEngineFunction( addGlobalShaderMacro, void, 
+DefineEngineFunction( addGlobalShaderMacro, void,
    ( const char *name, const char *value ), ( nullAsType<const char*>() ),
    "Adds a global shader macro which will be merged with the script defined "
    "macros on every shader.  The macro will replace the value of an existing "
@@ -189,7 +214,7 @@ DefineEngineFunction( addGlobalShaderMacro, void,
    GFXShader::addGlobalMacro( name, value );
 }
 
-DefineEngineFunction( removeGlobalShaderMacro, void, ( const char *name ),, 
+DefineEngineFunction( removeGlobalShaderMacro, void, ( const char *name ),,
    "Removes an existing global macro by name.\n"
    "@see addGlobalShaderMacro\n"
    "@ingroup Rendering\n" )

+ 62 - 44
Engine/source/gfx/gfxShader.h

@@ -65,19 +65,34 @@ class GFXShader;
 class GFXVertexFormat;
 
 
+enum GFXShaderStage
+{
+   VERTEX_SHADER     = BIT(0),
+   PIXEL_SHADER      = BIT(1),
+   GEOMETRY_SHADER   = BIT(2),
+   DOMAIN_SHADER     = BIT(3),
+   HULL_SHADER       = BIT(4),
+   COMPUTE_SHADER    = BIT(5)
+};
+
 /// Instances of this struct are returned GFXShaderConstBuffer
-struct GFXShaderConstDesc 
+struct GFXShaderConstDesc
 {
 public:
-   String name;
-   GFXShaderConstType constType;   
-   U32 arraySize; // > 1 means it is an array!
+   String name = String::EmptyString;
+   GFXShaderConstType constType = GFXSCT_Uknown;
+   U32 arraySize = 0;            // > 1 means it is an array!
+   S32 bindPoint = -1;           // bind point used for ubo/cb
+   S32 samplerReg = -1;          // sampler register.
+   U32 offset = 0;               // offset for vars
+   U32 size = 0;                 // size of buffer/type
+   GFXShaderStage shaderStage = VERTEX_SHADER;   // only used dx side.not wasting a bit for an unknown?
 };
 
 /// This is an opaque handle used by GFXShaderConstBuffer clients to set individual shader constants.
 /// Derived classes can put whatever info they need into here, these handles are owned by the shader constant buffer
 /// (or shader).  Client code should not free these.
-class GFXShaderConstHandle 
+class GFXShaderConstHandle
 {
 public:
 
@@ -86,8 +101,8 @@ public:
 
    /// Returns true if this constant is valid and can
    /// be set on the shader.
-   bool isValid() const { return mValid; }   
-   
+   bool isValid() const { return mValid; }
+
    /// Returns the name of the constant handle.
    virtual const String& getName() const = 0;
 
@@ -95,7 +110,7 @@ public:
    virtual GFXShaderConstType getType() const = 0;
 
    virtual U32 getArraySize() const = 0;
-   
+
    /// Returns -1 if this handle does not point to a Sampler.
    virtual S32 getSamplerRegister() const = 0;
 
@@ -104,7 +119,7 @@ protected:
    /// The state of the constant which is
    /// set from the derived class.
    bool mValid;
-   
+
 };
 
 
@@ -128,7 +143,7 @@ protected:
    /// @see wasLost
    bool mWasLost;
 
-   GFXShaderConstBuffer()   
+   GFXShaderConstBuffer()
       :  mWasLost( true ),
          mInstPtr( NULL )
    {
@@ -140,16 +155,16 @@ public:
    virtual GFXShader* getShader() = 0;
 
    /// The content of the buffer is in the lost state when
-   /// first created or when the shader is reloaded.  When 
+   /// first created or when the shader is reloaded.  When
    /// the content is lost you must refill the buffer
    /// with all the constants used by your shader.
    ///
-   /// Use this property to avoid setting constants which do 
+   /// Use this property to avoid setting constants which do
    /// not changefrom one frame to the next.
    ///
    bool wasLost() const { return mWasLost; }
 
-   /// An inline helper which ensures the handle is valid 
+   /// An inline helper which ensures the handle is valid
    /// before the virtual set method is called.
    ///
    /// You should prefer using this method unless your sure the
@@ -168,7 +183,7 @@ public:
    ///
    /// Perfer using setSafe unless you can check the handle
    /// validity yourself and skip a significat amount of work.
-   ///   
+   ///
    /// @see GFXShaderConstHandle::isValid()
    ///
    virtual void set(GFXShaderConstHandle* handle, const F32 f) = 0;
@@ -189,19 +204,19 @@ public:
    virtual void set(GFXShaderConstHandle* handle, const AlignedArray<Point2I>& fv) = 0;
    virtual void set(GFXShaderConstHandle* handle, const AlignedArray<Point3I>& fv) = 0;
    virtual void set(GFXShaderConstHandle* handle, const AlignedArray<Point4I>& fv) = 0;
-   
-   /// Set a variable sized matrix shader constant.   
-   virtual void set( GFXShaderConstHandle* handle, 
-                     const MatrixF& mat, 
+
+   /// Set a variable sized matrix shader constant.
+   virtual void set( GFXShaderConstHandle* handle,
+                     const MatrixF& mat,
                      const GFXShaderConstType matrixType = GFXSCT_Float4x4 ) = 0;
-   
+
    /// Set a variable sized matrix shader constant from
-   /// an array of matricies.   
-   virtual void set( GFXShaderConstHandle* handle, 
-                     const MatrixF* mat, 
-                     const U32 arraySize, 
+   /// an array of matricies.
+   virtual void set( GFXShaderConstHandle* handle,
+                     const MatrixF* mat,
+                     const U32 arraySize,
                      const GFXShaderConstType matrixType = GFXSCT_Float4x4 ) = 0;
-   
+
    // TODO: Make this protected and put a real API around it.
    U8 *mInstPtr;
 };
@@ -217,8 +232,8 @@ class GFXShader : public StrongRefBase, public GFXResource
    friend class GFXShaderConstBuffer;
 
 protected:
-  
-   /// These are system wide shader macros which are 
+
+   /// These are system wide shader macros which are
    /// merged with shader specific macros at creation.
    static Vector<GFXShaderMacro> smGlobalMacros;
 
@@ -229,19 +244,22 @@ protected:
    static bool smLogWarnings;
 
    /// The vertex shader file.
-   Torque::Path mVertexFile;  
+   Torque::Path mVertexFile;
 
    /// The pixel shader file.
-   Torque::Path mPixelFile;  
+   Torque::Path mPixelFile;
 
-   /// The macros to be passed to the shader.      
+   // the geometry shader file.
+   Torque::Path mGeometryFile;
+
+   /// The macros to be passed to the shader.
    Vector<GFXShaderMacro> mMacros;
 
    /// Ordered SamplerNames
    /// We need to store a list of sampler for allow OpenGL to
    /// assign correct location for each sampler.
    /// GLSL 150 not allow explicit uniform location.
-   /// Only used on OpenGL   
+   /// Only used on OpenGL
    Vector<String> mSamplerNamesOrdered;
 
    /// The pixel version this is compiled for.
@@ -256,7 +274,7 @@ protected:
    Signal<void()> mReloadSignal;
 
    /// Vector of buffers that reference this shader.
-   /// It is the responsibility of the derived shader class to populate this 
+   /// It is the responsibility of the derived shader class to populate this
    /// vector and to notify them when this shader is reloaded.  Classes
    /// derived from GFXShaderConstBuffer should call _unlinkBuffer from
    /// their destructor.
@@ -267,7 +285,7 @@ protected:
    /// A protected constructor so it cannot be instantiated.
    GFXShader();
 
-public:  
+public:
 
    /// Adds a global shader macro which will be merged with
    /// the script defined macros on every shader reload.
@@ -288,9 +306,9 @@ public:
 
    /// Toggle logging for shader errors.
    static void setLogging( bool logErrors,
-                           bool logWarning ) 
+                           bool logWarning )
    {
-      smLogErrors = logErrors; 
+      smLogErrors = logErrors;
       smLogWarnings = logWarning;
    }
 
@@ -300,16 +318,14 @@ public:
    ///
    /// Deprecated. Remove on T3D 4.0
 #ifndef TORQUE_OPENGL
-   bool init(  const Torque::Path &vertFile, 
-               const Torque::Path &pixFile, 
-               F32 pixVersion, 
+   bool init(  const Torque::Path &vertFile,
+               const Torque::Path &pixFile,
+               F32 pixVersion,
                const Vector<GFXShaderMacro> &macros );
 #endif
 
    ///
-   bool init(  const Torque::Path &vertFile, 
-               const Torque::Path &pixFile, 
-               F32 pixVersion, 
+   bool init( F32 pixVersion,
                const Vector<GFXShaderMacro> &macros,
                const Vector<String> &samplerNames,
                GFXVertexFormat *instanceFormat = NULL );
@@ -320,23 +336,23 @@ public:
    Signal<void()> getReloadSignal() { return mReloadSignal; }
 
    /// Allocate a constant buffer
-   virtual GFXShaderConstBufferRef allocConstBuffer() = 0;  
+   virtual GFXShaderConstBufferRef allocConstBuffer() = 0;
 
    /// Returns our list of shader constants, the material can get this and just set the constants it knows about
    virtual const Vector<GFXShaderConstDesc>& getShaderConstDesc() const = 0;
 
    /// Returns a shader constant handle for the name constant.
    ///
-   /// Since shaders can reload and later have handles that didn't 
+   /// Since shaders can reload and later have handles that didn't
    /// exist originally this will return a handle in an invalid state
    /// if the constant doesn't exist at this time.
-   virtual GFXShaderConstHandle* getShaderConstHandle( const String& name ) = 0; 
+   virtual GFXShaderConstHandle* getShaderConstHandle( const String& name ) = 0;
 
    /// Returns a shader constant handle for the name constant, if the variable doesn't exist NULL is returned.
    virtual GFXShaderConstHandle* findShaderConstHandle( const String& name ) = 0;
 
    /// Returns the alignment value for constType
-   virtual U32 getAlignmentValue(const GFXShaderConstType constType) const = 0;   
+   virtual U32 getAlignmentValue(const GFXShaderConstType constType) const = 0;
 
    /// Returns the required vertex format for this shader.
    /// Returns the pixel shader version.
@@ -349,6 +365,8 @@ public:
    /// the shader disassembly.
    virtual bool getDisassembly( String &outStr ) const { return false; }
 
+   void setShaderStageFile(const GFXShaderStage stage, const Torque::Path& filePath);
+
    /// Returns the vertex shader file path.
    const String& getVertexShaderFile() const { return mVertexFile.getFullPath(); }
 

+ 121 - 87
Engine/source/gfx/gl/gfxGLDevice.cpp

@@ -57,7 +57,7 @@
 #include "gfx/gl/tGL/tXGL.h"
 #endif
 
-GFXAdapter::CreateDeviceInstanceDelegate GFXGLDevice::mCreateDeviceInstance(GFXGLDevice::createInstance); 
+GFXAdapter::CreateDeviceInstanceDelegate GFXGLDevice::mCreateDeviceInstance(GFXGLDevice::createInstance);
 
 GFXDevice *GFXGLDevice::createInstance( U32 adapterIndex )
 {
@@ -76,7 +76,7 @@ void loadGLCore()
    if(coreLoaded)
       return;
    coreLoaded = true;
-   
+
    // Make sure we've got our GL bindings.
    GL::gglPerformBinds();
 }
@@ -87,11 +87,11 @@ void loadGLExtensions(void *context)
    if(extensionsLoaded)
       return;
    extensionsLoaded = true;
-   
+
    GL::gglPerformExtensionBinds(context);
 }
 
-void STDCALL glDebugCallback(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, 
+void STDCALL glDebugCallback(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length,
 	const GLchar *message, const void *userParam)
 {
     // JTH [11/24/2016]: This is a temporary fix so that we do not get spammed for redundant fbo changes.
@@ -118,24 +118,24 @@ void STDCALL glAmdDebugCallback(GLuint id, GLenum category, GLenum severity, GLs
 }
 
 void GFXGLDevice::initGLState()
-{  
+{
    // We don't currently need to sync device state with a known good place because we are
    // going to set everything in GFXGLStateBlock, but if we change our GFXGLStateBlock strategy, this may
    // need to happen.
-   
+
    // Deal with the card profiler here when we know we have a valid context.
    mCardProfiler = new GFXGLCardProfiler();
-   mCardProfiler->init(); 
+   mCardProfiler->init();
    glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, (GLint*)&mMaxShaderTextures);
    // JTH: Needs removed, ffp
    //glGetIntegerv(GL_MAX_TEXTURE_UNITS, (GLint*)&mMaxFFTextures);
    glGetIntegerv(GL_MAX_COLOR_ATTACHMENTS, (GLint*)&mMaxTRColors);
    mMaxTRColors = getMin( mMaxTRColors, (U32)(GFXTextureTarget::MaxRenderSlotId-1) );
-   
+
    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.   
+   // Setting mPixelShaderVersion to 3.0 will allow Advanced Lighting to run.
    mPixelShaderVersion = 3.0;
 
 	// Set capability extensions.
@@ -150,7 +150,7 @@ void GFXGLDevice::initGLState()
    String vendorStr = (const char*)glGetString( GL_VENDOR );
    if( vendorStr.find("NVIDIA", 0, String::NoCase | String::Left) != String::NPos)
       mUseGlMap = false;
-   
+
    // Workaround for all Mac's, has a problem using glMap* with volatile buffers
 #ifdef TORQUE_OS_MAC
    mUseGlMap = false;
@@ -173,7 +173,7 @@ void GFXGLDevice::initGLState()
    else if(gglHasExtension(AMD_debug_output))
    {
       glEnable(GL_DEBUG_OUTPUT);
-      glDebugMessageCallbackAMD(glAmdDebugCallback, NULL);      
+      glDebugMessageCallbackAMD(glAmdDebugCallback, NULL);
       //glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB);
       GLuint unusedIds = 0;
       glDebugMessageEnableAMD(GL_DONT_CARE, GL_DONT_CARE, 0,&unusedIds, GL_TRUE);
@@ -258,16 +258,17 @@ GFXGLDevice::GFXGLDevice(U32 adapterIndex) :
       mModelViewProjSC[i] = NULL;
 
    mOpenglStateCache = new GFXGLStateCache;
+   mCurrentConstBuffer = NULL;
 }
 
 GFXGLDevice::~GFXGLDevice()
 {
    mCurrentStateBlock = NULL;
 
-   for(int i = 0; i < VERTEX_STREAM_COUNT; ++i)      
+   for(int i = 0; i < VERTEX_STREAM_COUNT; ++i)
       mCurrentVB[i] = NULL;
    mCurrentPB = NULL;
-   
+
    for(U32 i = 0; i < mVolatileVBs.size(); i++)
       mVolatileVBs[i] = NULL;
    for(U32 i = 0; i < mVolatilePBs.size(); i++)
@@ -291,13 +292,18 @@ GFXGLDevice::~GFXGLDevice()
       mTextureManager->kill();
    }
 
+   // Free device buffers
+   DeviceBufferMap::Iterator bufferIter = mDeviceBufferMap.begin();
+   for (; bufferIter != mDeviceBufferMap.end(); ++bufferIter)
+      glDeleteBuffers(1, &bufferIter->value);
+
    GFXResource* walk = mResourceListHead;
    while(walk)
    {
       walk->zombify();
       walk = walk->getNextResource();
    }
-      
+
    if( mCardProfiler )
       SAFE_DELETE( mCardProfiler );
 
@@ -306,16 +312,33 @@ GFXGLDevice::~GFXGLDevice()
    SAFE_DELETE( mOpenglStateCache );
 }
 
+GLuint GFXGLDevice::getDeviceBuffer(const GFXShaderConstDesc desc)
+{
+   String name(desc.name + "_" + String::ToString(desc.size));
+   DeviceBufferMap::Iterator buf = mDeviceBufferMap.find(name);
+   if (buf != mDeviceBufferMap.end())
+   {
+      return mDeviceBufferMap[name];
+   }
+
+   GLuint uboHandle;
+   glGenBuffers(1, &uboHandle);
+
+   mDeviceBufferMap[name] = uboHandle;
+
+   return uboHandle;
+}
+
 void GFXGLDevice::zombify()
 {
    mTextureManager->zombify();
 
-   for(int i = 0; i < VERTEX_STREAM_COUNT; ++i)   
+   for(int i = 0; i < VERTEX_STREAM_COUNT; ++i)
       if(mCurrentVB[i])
          mCurrentVB[i]->finish();
    if(mCurrentPB)
          mCurrentPB->finish();
-   
+
    //mVolatileVBs.clear();
    //mVolatilePBs.clear();
    GFXResource* walk = mResourceListHead;
@@ -334,12 +357,12 @@ void GFXGLDevice::resurrect()
       walk->resurrect();
       walk = walk->getNextResource();
    }
-   for(int i = 0; i < VERTEX_STREAM_COUNT; ++i)   
+   for(int i = 0; i < VERTEX_STREAM_COUNT; ++i)
       if(mCurrentVB[i])
          mCurrentVB[i]->prepare();
    if(mCurrentPB)
       mCurrentPB->prepare();
-   
+
    mTextureManager->resurrect();
 }
 
@@ -366,7 +389,7 @@ GFXPrimitiveBuffer* GFXGLDevice::findVolatilePBO(U32 numIndices, U32 numPrimitiv
    for(U32 i = 0; i < mVolatilePBs.size(); i++)
       if((mVolatilePBs[i]->mIndexCount >= numIndices) && (mVolatilePBs[i]->getRefCount() == 1))
          return mVolatilePBs[i];
-   
+
    // No existing PB, so create one
    StrongRefPtr<GFXGLPrimitiveBuffer> buf(new GFXGLPrimitiveBuffer(GFX, numIndices, numPrimitives, GFXBufferTypeVolatile));
    buf->registerResourceWithDevice(this);
@@ -374,18 +397,18 @@ GFXPrimitiveBuffer* GFXGLDevice::findVolatilePBO(U32 numIndices, U32 numPrimitiv
    return buf.getPointer();
 }
 
-GFXVertexBuffer *GFXGLDevice::allocVertexBuffer(   U32 numVerts, 
-                                                   const GFXVertexFormat *vertexFormat, 
-                                                   U32 vertSize, 
+GFXVertexBuffer *GFXGLDevice::allocVertexBuffer(   U32 numVerts,
+                                                   const GFXVertexFormat *vertexFormat,
+                                                   U32 vertSize,
                                                    GFXBufferType bufferType,
-                                                   void* data )  
+                                                   void* data )
 {
    PROFILE_SCOPE(GFXGLDevice_allocVertexBuffer);
    if(bufferType == GFXBufferTypeVolatile)
       return findVolatileVBO(numVerts, vertexFormat, vertSize);
-         
+
    GFXGLVertexBuffer* buf = new GFXGLVertexBuffer( GFX, numVerts, vertexFormat, vertSize, bufferType );
-   buf->registerResourceWithDevice(this);   
+   buf->registerResourceWithDevice(this);
 
    if(data)
    {
@@ -398,10 +421,10 @@ GFXVertexBuffer *GFXGLDevice::allocVertexBuffer(   U32 numVerts,
    return buf;
 }
 
-GFXPrimitiveBuffer *GFXGLDevice::allocPrimitiveBuffer( U32 numIndices, U32 numPrimitives, GFXBufferType bufferType, void* data ) 
+GFXPrimitiveBuffer *GFXGLDevice::allocPrimitiveBuffer( U32 numIndices, U32 numPrimitives, GFXBufferType bufferType, void* data )
 {
    GFXPrimitiveBuffer* buf;
-   
+
    if(bufferType == GFXBufferTypeVolatile)
    {
       buf = findVolatilePBO(numIndices, numPrimitives);
@@ -411,7 +434,7 @@ GFXPrimitiveBuffer *GFXGLDevice::allocPrimitiveBuffer( U32 numIndices, U32 numPr
       buf = new GFXGLPrimitiveBuffer(GFX, numIndices, numPrimitives, bufferType);
       buf->registerResourceWithDevice(this);
    }
-   
+
    if(data)
    {
       void* dest;
@@ -430,7 +453,7 @@ void GFXGLDevice::setVertexStream( U32 stream, GFXVertexBuffer *buffer )
    {
       // Reset the state the old VB required, then set the state the new VB requires.
       if( mCurrentVB[stream] )
-      {     
+      {
          mCurrentVB[stream]->finish();
       }
 
@@ -460,10 +483,10 @@ void GFXGLDevice::setVertexStreamFrequency( U32 stream, U32 frequency )
 }
 
 GFXCubemap* GFXGLDevice::createCubemap()
-{ 
+{
    GFXGLCubemap* cube = new GFXGLCubemap();
    cube->registerResourceWithDevice(this);
-   return cube; 
+   return cube;
 };
 
 GFXCubemapArray *GFXGLDevice::createCubemapArray()
@@ -480,7 +503,7 @@ GFXTextureArray* GFXGLDevice::createTextureArray()
    return textureArray;
 }
 
-void GFXGLDevice::endSceneInternal() 
+void GFXGLDevice::endSceneInternal()
 {
    // nothing to do for opengl
    mCanCurrentlyRender = false;
@@ -556,9 +579,9 @@ void GFXGLDevice::clear(U32 flags, const LinearColorF& color, F32 z, U32 stencil
 {
    // Make sure we have flushed our render target state.
    _updateRenderTargets();
-   
+
    bool writeAllColors = true;
-   bool zwrite = true;   
+   bool zwrite = true;
    bool writeAllStencil = true;
    const GFXStateBlockDesc *desc = NULL;
    if (mCurrentGLStateBlock)
@@ -568,7 +591,7 @@ void GFXGLDevice::clear(U32 flags, const LinearColorF& color, F32 z, U32 stencil
       writeAllColors = desc->colorWriteRed && desc->colorWriteGreen && desc->colorWriteBlue && desc->colorWriteAlpha;
       writeAllStencil = desc->stencilWriteMask == 0xFFFFFFFF;
    }
-   
+
    glColorMask(true, true, true, true);
    glDepthMask(true);
    glStencilMask(0xFFFFFFFF);
@@ -585,7 +608,7 @@ void GFXGLDevice::clear(U32 flags, const LinearColorF& color, F32 z, U32 stencil
 
    if(!writeAllColors)
       glColorMask(desc->colorWriteRed, desc->colorWriteGreen, desc->colorWriteBlue, desc->colorWriteAlpha);
-   
+
    if(!zwrite)
       glDepthMask(false);
 
@@ -623,20 +646,20 @@ inline GLsizei GFXGLDevice::primCountToIndexCount(GFXPrimitiveType primType, U32
          AssertFatal(false, "GFXGLDevice::primCountToIndexCount - unrecognized prim type");
          break;
    }
-   
+
    return 0;
 }
 
-GFXVertexDecl* GFXGLDevice::allocVertexDecl( const GFXVertexFormat *vertexFormat ) 
+GFXVertexDecl* GFXGLDevice::allocVertexDecl( const GFXVertexFormat *vertexFormat )
 {
    PROFILE_SCOPE(GFXGLDevice_allocVertexDecl);
    typedef Map<void*, GFXGLVertexDecl> GFXGLVertexDeclMap;
-   static GFXGLVertexDeclMap declMap;   
+   static GFXGLVertexDeclMap declMap;
    GFXGLVertexDeclMap::Iterator itr = declMap.find( (void*)vertexFormat->getDescription().c_str() ); // description string are interned, safe to use c_str()
    if(itr != declMap.end())
       return &itr->value;
 
-   GFXGLVertexDecl &decl = declMap[(void*)vertexFormat->getDescription().c_str()];   
+   GFXGLVertexDecl &decl = declMap[(void*)vertexFormat->getDescription().c_str()];
    decl.init(vertexFormat);
    return &decl;
 }
@@ -652,7 +675,7 @@ inline void GFXGLDevice::preDrawPrimitive()
    {
       updateStates();
    }
-   
+
    if(mCurrentShaderConstBuffer)
       setShaderConstBufferInternal(mCurrentShaderConstBuffer);
 
@@ -660,18 +683,18 @@ inline void GFXGLDevice::preDrawPrimitive()
    {
       AssertFatal(mCurrVertexDecl, "");
       const GFXGLVertexDecl* decl = static_cast<const GFXGLVertexDecl*>(mCurrVertexDecl);
-      
+
       for(int i = 0; i < getNumVertexStreams(); ++i)
       {
          if(mCurrentVB[i])
          {
-            mCurrentVB[i]->prepare(i, mCurrentVB_Divisor[i]);    // GL_ARB_vertex_attrib_binding  
+            mCurrentVB[i]->prepare(i, mCurrentVB_Divisor[i]);    // GL_ARB_vertex_attrib_binding
             decl->prepareBuffer_old( i, mCurrentVB[i]->mBuffer, mCurrentVB_Divisor[i] ); // old vertex buffer/format
          }
       }
 
-      decl->updateActiveVertexAttrib( GFXGL->getOpenglCache()->getCacheVertexAttribActive() );         
-   }   
+      decl->updateActiveVertexAttrib( GFXGL->getOpenglCache()->getCacheVertexAttribActive() );
+   }
 
    mNeedUpdateVertexAttrib = false;
 }
@@ -682,26 +705,26 @@ inline void GFXGLDevice::postDrawPrimitive(U32 primitiveCount)
    mDeviceStatistics.mPolyCount += primitiveCount;
 }
 
-void GFXGLDevice::drawPrimitive( GFXPrimitiveType primType, U32 vertexStart, U32 primitiveCount ) 
+void GFXGLDevice::drawPrimitive( GFXPrimitiveType primType, U32 vertexStart, U32 primitiveCount )
 {
    preDrawPrimitive();
-  
+
    if(mCurrentVB[0])
       vertexStart += mCurrentVB[0]->mBufferVertexOffset;
 
    if(mDrawInstancesCount)
       glDrawArraysInstanced(GFXGLPrimType[primType], vertexStart, primCountToIndexCount(primType, primitiveCount), mDrawInstancesCount);
    else
-      glDrawArrays(GFXGLPrimType[primType], vertexStart, primCountToIndexCount(primType, primitiveCount));   
+      glDrawArrays(GFXGLPrimType[primType], vertexStart, primCountToIndexCount(primType, primitiveCount));
 
    postDrawPrimitive(primitiveCount);
 }
 
-void GFXGLDevice::drawIndexedPrimitive(   GFXPrimitiveType primType, 
-                                          U32 startVertex, 
-                                          U32 minIndex, 
-                                          U32 numVerts, 
-                                          U32 startIndex, 
+void GFXGLDevice::drawIndexedPrimitive(   GFXPrimitiveType primType,
+                                          U32 startVertex,
+                                          U32 minIndex,
+                                          U32 numVerts,
+                                          U32 startIndex,
                                           U32 primitiveCount )
 {
    preDrawPrimitive();
@@ -732,7 +755,7 @@ void GFXGLDevice::setTextureInternal(U32 textureUnit, const GFXTextureObject*tex
    {
       mActiveTextureType[textureUnit] = tex->getBinding();
       tex->bind(textureUnit);
-   } 
+   }
    else if(mActiveTextureType[textureUnit] != GL_ZERO)
    {
       glActiveTexture(GL_TEXTURE0 + textureUnit);
@@ -805,21 +828,21 @@ void GFXGLDevice::setClipRect( const RectI &inRect )
    F32 r = F32(mClip.point.x + mClip.extent.x);
    F32 b = F32(mClip.point.y + mClip.extent.y);
    F32 t = F32(mClip.point.y);
-   
-   // Set up projection matrix, 
+
+   // Set up projection matrix,
    //static Point4F pt;
    pt.set(2.0f / (r - l), 0.0f, 0.0f, 0.0f);
    mProjectionMatrix.setColumn(0, pt);
-   
+
    pt.set(0.0f, 2.0f / (t - b), 0.0f, 0.0f);
    mProjectionMatrix.setColumn(1, pt);
-   
+
    pt.set(0.0f, 0.0f, 1.0f, 0.0f);
    mProjectionMatrix.setColumn(2, pt);
-   
+
    pt.set((l + r) / (l - r), (t + b) / (b - t), 1.0f, 1.0f);
    mProjectionMatrix.setColumn(3, pt);
-   
+
    MatrixF mTempMatrix(true);
    setViewMatrix( mTempMatrix );
    setWorldMatrix( mTempMatrix );
@@ -844,7 +867,7 @@ void GFXGLDevice::setStateBlockInternal(GFXStateBlock* block, bool force)
    GFXGLStateBlock* glCurrent = static_cast<GFXGLStateBlock*>(mCurrentStateBlock.getPointer());
    if (force)
       glCurrent = NULL;
-      
+
    glBlock->activate(glCurrent); // Doesn't use current yet.
    mCurrentGLStateBlock = glBlock;
 }
@@ -863,19 +886,19 @@ GFXFence * GFXGLDevice::createFence()
    GFXFence* fence = _createPlatformSpecificFence();
    if(!fence)
       fence = new GFXGeneralFence( this );
-      
+
    fence->registerResourceWithDevice(this);
    return fence;
 }
 
 GFXOcclusionQuery* GFXGLDevice::createOcclusionQuery()
-{   
+{
    GFXOcclusionQuery *query = new GFXGLOcclusionQuery( this );
    query->registerResourceWithDevice(this);
    return query;
 }
 
-void GFXGLDevice::setupGenericShaders( GenericShaderType type ) 
+void GFXGLDevice::setupGenericShaders( GenericShaderType type )
 {
    AssertFatal(type != GSTargetRestore, "");
 
@@ -927,7 +950,7 @@ void GFXGLDevice::setupGenericShaders( GenericShaderType type )
       Sim::getRootGroup()->addObject(shaderData);
    }
 
-   MatrixF tempMatrix =  mProjectionMatrix * mViewMatrix * mWorldMatrix[mWorldStackSize];  
+   MatrixF tempMatrix =  mProjectionMatrix * mViewMatrix * mWorldMatrix[mWorldStackSize];
    mGenericShaderBuffer[type]->setSafe(mModelViewProjSC[type], tempMatrix);
 
    setShader( mGenericShader[type] );
@@ -959,8 +982,19 @@ void GFXGLDevice::setShader(GFXShader *shader, bool force)
 
 void GFXGLDevice::setShaderConstBufferInternal(GFXShaderConstBuffer* buffer)
 {
-   PROFILE_SCOPE(GFXGLDevice_setShaderConstBufferInternal);
-   static_cast<GFXGLShaderConstBuffer*>(buffer)->activate();
+   if (buffer)
+   {
+      PROFILE_SCOPE(GFXGLDevice_setShaderConstBufferInternal);
+      AssertFatal(static_cast<GFXGLShaderConstBuffer*>(buffer), "Incorrect shader const buffer type for this device!");
+      GFXGLShaderConstBuffer* oglBuffer = static_cast<GFXGLShaderConstBuffer*>(buffer);
+
+      oglBuffer->activate(mCurrentConstBuffer);
+      mCurrentConstBuffer = oglBuffer;
+   }
+   else
+   {
+      mCurrentConstBuffer = NULL;
+   }
 }
 
 U32 GFXGLDevice::getNumSamplers() const
@@ -968,7 +1002,7 @@ U32 GFXGLDevice::getNumSamplers() const
    return getMin((U32)GFX_TEXTURE_STAGE_COUNT,mPixelShaderVersion > 0.001f ? mMaxShaderTextures : mMaxFFTextures);
 }
 
-GFXTextureObject* GFXGLDevice::getDefaultDepthTex() const 
+GFXTextureObject* GFXGLDevice::getDefaultDepthTex() const
 {
    if(mWindowRT && mWindowRT->getPointer())
       return static_cast<GFXGLWindowTarget*>( mWindowRT->getPointer() )->mBackBufferDepthTex.getPointer();
@@ -976,9 +1010,9 @@ GFXTextureObject* GFXGLDevice::getDefaultDepthTex() const
    return NULL;
 }
 
-U32 GFXGLDevice::getNumRenderTargets() const 
-{ 
-   return mMaxTRColors; 
+U32 GFXGLDevice::getNumRenderTargets() const
+{
+   return mMaxTRColors;
 }
 
 void GFXGLDevice::_updateRenderTargets()
@@ -988,9 +1022,9 @@ void GFXGLDevice::_updateRenderTargets()
       if ( mRTDeactivate )
       {
          mRTDeactivate->deactivate();
-         mRTDeactivate = NULL;   
+         mRTDeactivate = NULL;
       }
-      
+
       // NOTE: The render target changes is not really accurate
       // as the GFXTextureTarget supports MRT internally.  So when
       // we activate a GFXTarget it could result in multiple calls
@@ -1006,31 +1040,31 @@ void GFXGLDevice::_updateRenderTargets()
       else
       {
          GFXGLWindowTarget *win = dynamic_cast<GFXGLWindowTarget*>( mCurrentRT.getPointer() );
-         AssertFatal( win != NULL, 
+         AssertFatal( win != NULL,
                      "GFXGLDevice::_updateRenderTargets() - invalid target subclass passed!" );
-         
+
          win->makeActive();
-         
+
          if( win->mContext != static_cast<GFXGLDevice*>(GFX)->mContext )
          {
             mRTDirty = false;
             GFX->updateStates(true);
          }
       }
-      
+
       mRTDirty = false;
    }
-   
+
    if ( mViewportDirty )
    {
-      glViewport( mViewport.point.x, mViewport.point.y, mViewport.extent.x, mViewport.extent.y ); 
+      glViewport( mViewport.point.x, mViewport.point.y, mViewport.extent.x, mViewport.extent.y );
       mViewportDirty = false;
    }
 }
 
-GFXFormat GFXGLDevice::selectSupportedFormat(   GFXTextureProfile* profile, 
-                                                const Vector<GFXFormat>& formats, 
-                                                bool texture, 
+GFXFormat GFXGLDevice::selectSupportedFormat(   GFXTextureProfile* profile,
+                                                const Vector<GFXFormat>& formats,
+                                                bool texture,
                                                 bool mustblend,
                                                 bool mustfilter )
 {
@@ -1041,10 +1075,10 @@ GFXFormat GFXGLDevice::selectSupportedFormat(   GFXTextureProfile* profile,
          continue;
       if(GFXGLTextureInternalFormat[formats[i]] == GL_ZERO)
          continue;
-      
+
       return formats[i];
    }
-   
+
    return GFXFormatR8G8B8A8;
 }
 
@@ -1055,7 +1089,7 @@ U32 GFXGLDevice::getTotalVideoMemory_GL_EXT()
    {
       GLint mem[4] = {0};
       glGetIntegerv(GL_TEXTURE_FREE_MEMORY_ATI, mem);  // Retrieve the texture pool
-      
+
       /* With mem[0] i get only the total memory free in the pool in KB
       *
       * mem[0] - total memory free in the pool
@@ -1066,7 +1100,7 @@ U32 GFXGLDevice::getTotalVideoMemory_GL_EXT()
 
       return  mem[0] / 1024;
    }
-   
+
    //source http://www.opengl.org/registry/specs/NVX/gpu_memory_info.txt
    else if( gglHasExtension(NVX_gpu_memory_info) )
    {

+ 42 - 33
Engine/source/gfx/gl/gfxGLDevice.h

@@ -43,9 +43,11 @@ class GFXGLCubemap;
 class GFXGLCubemapArray;
 class GFXGLStateCache;
 class GFXGLVertexDecl;
+class GFXGLShaderConstBuffer;
 
 class GFXGLDevice : public GFXDevice
 {
+
 public:
    struct GLCapabilities
    {
@@ -59,6 +61,11 @@ public:
    };
    GLCapabilities mCapabilities;
 
+   // UBO map
+   typedef Map<String, GLuint> DeviceBufferMap;
+   // grab device buffer.
+   GLuint getDeviceBuffer(const GFXShaderConstDesc desc);
+
    void zombify();
    void resurrect();
    GFXGLDevice(U32 adapterIndex);
@@ -105,13 +112,13 @@ public:
    /// @{
    virtual F32 getPixelShaderVersion() const { return mPixelShaderVersion; }
    virtual void  setPixelShaderVersion( F32 version ) { mPixelShaderVersion = version; }
-   
+
    virtual void setShader(GFXShader *shader, bool force = false);
-   
+
    /// @attention GL cannot check if the given format supports blending or filtering!
    virtual GFXFormat selectSupportedFormat(GFXTextureProfile *profile,
 	   const Vector<GFXFormat> &formats, bool texture, bool mustblend, bool mustfilter);
-      
+
    /// Returns the number of texture samplers that can be used in a shader rendering pass
    virtual U32 getNumSamplers() const;
 
@@ -128,11 +135,11 @@ public:
 
    virtual void drawPrimitive( GFXPrimitiveType primType, U32 vertexStart, U32 primitiveCount );
 
-   virtual void drawIndexedPrimitive(  GFXPrimitiveType primType, 
-                                       U32 startVertex, 
-                                       U32 minIndex, 
-                                       U32 numVerts, 
-                                       U32 startIndex, 
+   virtual void drawIndexedPrimitive(  GFXPrimitiveType primType,
+                                       U32 startVertex,
+                                       U32 minIndex,
+                                       U32 numVerts,
+                                       U32 startIndex,
                                        U32 primitiveCount );
 
    virtual void setClipRect( const RectI &rect );
@@ -142,15 +149,15 @@ public:
 
    virtual U32 getMaxDynamicVerts() { return GFX_MAX_DYNAMIC_VERTS; }
    virtual U32 getMaxDynamicIndices() { return GFX_MAX_DYNAMIC_INDICES; }
-   
+
    GFXFence *createFence();
-   
+
    GFXOcclusionQuery* createOcclusionQuery();
 
    GFXGLStateBlockRef getCurrentStateBlock() { return mCurrentGLStateBlock; }
-   
+
    virtual void setupGenericShaders( GenericShaderType type = GSColor );
-   
+
    ///
    bool supportsAnisotropic() const { return mCapabilities.anisotropicFiltering; }
 
@@ -158,16 +165,16 @@ public:
 
    GFXTextureObject* getDefaultDepthTex() const;
 
-   /// Returns the number of vertex streams supported by the device.	
+   /// Returns the number of vertex streams supported by the device.
    const U32 getNumVertexStreams() const { return mNumVertexStream; }
 
-   bool glUseMap() const { return mUseGlMap; }   
+   bool glUseMap() const { return mUseGlMap; }
    const char* interpretDebugResult(long result) { return "Not Implemented"; };
-protected:   
+protected:
    /// Called by GFXDevice to create a device specific stateblock
    virtual GFXStateBlockRef createStateBlockInternal(const GFXStateBlockDesc& desc);
    /// Called by GFXDevice to actually set a stateblock.
-   virtual void setStateBlockInternal(GFXStateBlock* block, bool force);   
+   virtual void setStateBlockInternal(GFXStateBlock* block, bool force);
 
    /// Called by base GFXDevice to actually set a const buffer
    virtual void setShaderConstBufferInternal(GFXShaderConstBuffer* buffer);
@@ -184,13 +191,13 @@ protected:
    /// is created.
    virtual void initStates() { }
 
-   virtual GFXVertexBuffer *allocVertexBuffer(  U32 numVerts, 
+   virtual GFXVertexBuffer *allocVertexBuffer(  U32 numVerts,
                                                 const GFXVertexFormat *vertexFormat,
-                                                U32 vertSize, 
+                                                U32 vertSize,
                                                 GFXBufferType bufferType,
                                                 void* data = NULL);
    virtual GFXPrimitiveBuffer *allocPrimitiveBuffer( U32 numIndices, U32 numPrimitives, GFXBufferType bufferType, void* data = NULL );
-   
+
    // NOTE: The GL device doesn't need a vertex declaration at
    // this time, but we need to return something to keep the system
    // from retrying to allocate one on every call.
@@ -199,11 +206,13 @@ protected:
    virtual void setVertexDecl( const GFXVertexDecl *decl );
 
    virtual void setVertexStream( U32 stream, GFXVertexBuffer *buffer );
-   virtual void setVertexStreamFrequency( U32 stream, U32 frequency );   
+   virtual void setVertexStreamFrequency( U32 stream, U32 frequency );
+   StrongRefPtr<GFXGLShaderConstBuffer> mCurrentConstBuffer;
+   DeviceBufferMap mDeviceBufferMap;
 
 private:
    typedef GFXDevice Parent;
-   
+
    friend class GFXGLTextureObject;
    friend class GFXGLCubemap;
    friend class GFXGLCubemapArray;
@@ -215,18 +224,18 @@ private:
    static GFXAdapter::CreateDeviceInstanceDelegate mCreateDeviceInstance;
 
    U32 mAdapterIndex;
-   
+
    StrongRefPtr<GFXGLVertexBuffer> mCurrentVB[VERTEX_STREAM_COUNT];
    U32 mCurrentVB_Divisor[VERTEX_STREAM_COUNT];
    bool mNeedUpdateVertexAttrib;
    StrongRefPtr<GFXGLPrimitiveBuffer> mCurrentPB;
    U32 mDrawInstancesCount;
-   
+
    GFXShader* mCurrentShader;
    GFXShaderRef mGenericShader[GS_COUNT];
    GFXShaderConstBufferRef mGenericShaderBuffer[GS_COUNT];
    GFXShaderConstHandle *mModelViewProjSC[GS_COUNT];
-   
+
    /// Since GL does not have separate world and view matrices we need to track them
    MatrixF m_mCurrentWorld;
    MatrixF m_mCurrentView;
@@ -237,34 +246,34 @@ private:
    F32 mPixelShaderVersion;
 
    U32 mNumVertexStream;
-   
+
    U32 mMaxShaderTextures;
    U32 mMaxFFTextures;
 
    U32 mMaxTRColors;
 
    RectI mClip;
-   
+
    GFXGLStateBlockRef mCurrentGLStateBlock;
-   
+
    GLenum mActiveTextureType[GFX_TEXTURE_STAGE_COUNT];
-   
+
    Vector< StrongRefPtr<GFXGLVertexBuffer> > mVolatileVBs; ///< Pool of existing volatile VBs so we can reuse previously created ones
    Vector< StrongRefPtr<GFXGLPrimitiveBuffer> > mVolatilePBs; ///< Pool of existing volatile PBs so we can reuse previously created ones
 
    GLsizei primCountToIndexCount(GFXPrimitiveType primType, U32 primitiveCount);
    void preDrawPrimitive();
-   void postDrawPrimitive(U32 primitiveCount);  
-   
+   void postDrawPrimitive(U32 primitiveCount);
+
    GFXVertexBuffer* findVolatileVBO(U32 numVerts, const GFXVertexFormat *vertexFormat, U32 vertSize); ///< Returns an existing volatile VB which has >= numVerts and the same vert flags/size, or creates a new VB if necessary
    GFXPrimitiveBuffer* findVolatilePBO(U32 numIndices, U32 numPrimitives); ///< Returns an existing volatile PB which has >= numIndices, or creates a new PB if necessary
 
    void vsyncCallback(); ///< Vsync callback
-   
+
    void initGLState(); ///< Guaranteed to be called after all extensions have been loaded, use to init card profiler, shader version, max samplers, etc.
-   
+
    GFXFence* _createPlatformSpecificFence(); ///< If our platform (e.g. OS X) supports a fence extenstion (e.g. GL_APPLE_fence) this will create one, otherwise returns NULL
-   
+
    void setPB(GFXGLPrimitiveBuffer* pb); ///< Sets mCurrentPB
 
    GFXGLStateCache *mOpenglStateCache;

文件差異過大導致無法顯示
+ 517 - 292
Engine/source/gfx/gl/gfxGLShader.cpp


+ 153 - 76
Engine/source/gfx/gl/gfxGLShader.h

@@ -29,101 +29,101 @@
 #include "core/util/tSignal.h"
 #include "core/util/tDictionary.h"
 
-class GFXGLShaderConstHandle;
 class FileStream;
-class GFXGLShaderConstBuffer;
 class GFXGLDevice;
+class GFXGLShader;
 
-class GFXGLShader : public GFXShader
+struct BufferRange
 {
-   typedef Map<String, GFXGLShaderConstHandle*> HandleMap;
-public:
-   GFXGLShader(GFXGLDevice* device);
-   virtual ~GFXGLShader();
-
-   /// @name GFXShader interface
-   /// @{
-   virtual GFXShaderConstHandle* getShaderConstHandle(const String& name);
-   virtual GFXShaderConstHandle* findShaderConstHandle(const String& name);
-
-   /// Returns our list of shader constants, the material can get this and just set the constants it knows about
-   virtual const Vector<GFXShaderConstDesc>& getShaderConstDesc() const;
-
-   /// Returns the alignment value for constType
-   virtual U32 getAlignmentValue(const GFXShaderConstType constType) const; 
-
-   virtual GFXShaderConstBufferRef allocConstBuffer();
-
-   /// @}
-   
-   /// @name GFXResource interface
-   /// @{
-   virtual void zombify();
-   virtual void resurrect() { reload(); }
-   virtual const String describeSelf() const;
-   /// @}      
-
-   /// Activates this shader in the GL context.
-   void useProgram();
-   
-protected:
+   U32 mBufMin = U32_MAX;
+   U32 mBufMax = 0;
 
-   friend class GFXGLShaderConstBuffer;
-   friend class GFXGLShaderConstHandle;
-   
-   virtual bool _init();   
+   inline void addSlot(U32 slot)
+   {
+      mBufMin = getMin(mBufMin, slot);
+      mBufMax = getMax(mBufMax, slot);
+   }
 
-   bool initShader(  const Torque::Path &file, 
-                     bool isVertex, 
-                     const Vector<GFXShaderMacro> &macros );
+   inline bool isValid() const { return mBufMin <= mBufMax; }
+};
 
-   void clearShaders();
-   void initConstantDescs();
-   void initHandles();
-   void setConstantsFromBuffer(GFXGLShaderConstBuffer* buffer);
-   
-   static char* _handleIncludes( const Torque::Path &path, FileStream *s );
+struct ConstantBuffer
+{
+   GLuint bufHandle;
+   U8* data;
+   U32 size;
+   bool isDirty;
+};
 
-   static bool _loadShaderFromStream(  GLuint shader, 
-                                       const Torque::Path& path, 
-                                       FileStream* s, 
-                                       const Vector<GFXShaderMacro>& macros );
+class GFXGLShaderConstHandle : public GFXShaderConstHandle
+{
+   friend class GFXGLShader;
 
-   /// @name Internal GL handles
-   /// @{
-   GLuint mVertexShader;
-   GLuint mPixelShader;
-   GLuint mProgram;
-   /// @}
-    
-   Vector<GFXShaderConstDesc> mConstants;
-   U32 mConstBufferSize;
-   U8* mConstBuffer;
-   HandleMap mHandles;
-   GFXGLDevice* mDevice;
-   Vector<GFXGLShaderConstHandle*> mValidHandles;
+public:
+   // DX side needs the description map as the same uniform can exist across stages. for gl it is program wide.
+   GFXGLShaderConstHandle(GFXGLShader* shader);
+   GFXGLShaderConstHandle(GFXGLShader* shader,
+      const GFXShaderConstDesc& desc);
+
+   void reinit(const GFXShaderConstDesc& desc);
+
+   virtual ~GFXGLShaderConstHandle();
+   const GFXShaderConstDesc getDesc();
+   const String& getName() const { return mDesc.name; }
+   GFXShaderConstType getType() const { return mDesc.constType; }
+   U32 getArraySize() const { return mDesc.arraySize; }
+
+   U32 getSize() const { return mDesc.size; }
+   void setValid(bool valid) { mValid = valid; }
+   /// @warning This will always return the value assigned when the shader was
+   /// initialized.  If the value is later changed this method won't reflect that.
+   S32 getSamplerRegister() const { return (!isSampler() || !mValid) ? -1 : mDesc.samplerReg; }
+
+   // Returns true if this is a handle to a sampler register.
+   bool isSampler() const
+   {
+      return (getType() >= GFXSCT_Sampler);
+   }
+
+   /// Restore to uninitialized state.
+   void clear()
+   {
+      mShader = NULL;
+      mInstancingConstant = false;
+      mValid = false;
+   }
+
+   GFXShaderConstDesc mDesc;
+   GFXGLShader* mShader;
+   bool mUBOUniform;
+   bool mInstancingConstant;
 };
 
 class GFXGLShaderConstBuffer : public GFXShaderConstBuffer
 {
 public:
-   GFXGLShaderConstBuffer(GFXGLShader* shader, U32 bufSize, U8* existingConstants);
+   // -1 is the global buffer.
+   typedef Map<S32, ConstantBuffer> BufferMap;
+
+   GFXGLShaderConstBuffer(GFXGLShader* shader);
    ~GFXGLShaderConstBuffer();
-   
+
    /// Called by GFXGLDevice to activate this buffer.
-   void activate();
+   void activate(GFXGLShaderConstBuffer* prevShaderBuffer);
+
+   void addBuffer(const GFXShaderConstDesc desc);
 
    /// Called when the shader this buffer references is reloaded.
-   void onShaderReload( GFXGLShader *shader );
+   void onShaderReload(GFXGLShader* shader);
 
    // GFXShaderConstBuffer
-   virtual GFXShader* getShader() { return mShader; }
+   virtual GFXShader* getShader();
    virtual void set(GFXShaderConstHandle* handle, const F32 fv);
    virtual void set(GFXShaderConstHandle* handle, const Point2F& fv);
    virtual void set(GFXShaderConstHandle* handle, const Point3F& fv);
    virtual void set(GFXShaderConstHandle* handle, const Point4F& fv);
    virtual void set(GFXShaderConstHandle* handle, const PlaneF& fv);
-   virtual void set(GFXShaderConstHandle* handle, const LinearColorF& fv);   
+   virtual void set(GFXShaderConstHandle* handle, const LinearColorF& fv);
    virtual void set(GFXShaderConstHandle* handle, const S32 f);
    virtual void set(GFXShaderConstHandle* handle, const Point2I& fv);
    virtual void set(GFXShaderConstHandle* handle, const Point3I& fv);
@@ -131,13 +131,13 @@ public:
    virtual void set(GFXShaderConstHandle* handle, const AlignedArray<F32>& fv);
    virtual void set(GFXShaderConstHandle* handle, const AlignedArray<Point2F>& fv);
    virtual void set(GFXShaderConstHandle* handle, const AlignedArray<Point3F>& fv);
-   virtual void set(GFXShaderConstHandle* handle, const AlignedArray<Point4F>& fv);   
+   virtual void set(GFXShaderConstHandle* handle, const AlignedArray<Point4F>& fv);
    virtual void set(GFXShaderConstHandle* handle, const AlignedArray<S32>& fv);
    virtual void set(GFXShaderConstHandle* handle, const AlignedArray<Point2I>& fv);
    virtual void set(GFXShaderConstHandle* handle, const AlignedArray<Point3I>& fv);
    virtual void set(GFXShaderConstHandle* handle, const AlignedArray<Point4I>& fv);
    virtual void set(GFXShaderConstHandle* handle, const MatrixF& mat, const GFXShaderConstType matType = GFXSCT_Float4x4);
-   virtual void set(GFXShaderConstHandle* handle, const MatrixF* mat, const U32 arraySize, const GFXShaderConstType matrixType = GFXSCT_Float4x4);   
+   virtual void set(GFXShaderConstHandle* handle, const MatrixF* mat, const U32 arraySize, const GFXShaderConstType matrixType = GFXSCT_Float4x4);
 
    // GFXResource
    virtual const String describeSelf() const;
@@ -147,14 +147,91 @@ public:
 private:
 
    friend class GFXGLShader;
-   U8* mBuffer;
+
    WeakRefPtr<GFXGLShader> mShader;
-   
+   BufferMap mBufferMap;
+
    template<typename ConstType>
    void internalSet(GFXShaderConstHandle* handle, const ConstType& param);
-   
+
    template<typename ConstType>
    void internalSet(GFXShaderConstHandle* handle, const AlignedArray<ConstType>& fv);
 };
 
-#endif // _GFXGLSHADER_H_
+class GFXGLShader : public GFXShader
+{
+   friend class GFXGLShaderConstBuffer;
+   friend class GFXGLShaderConstHandle;
+public:
+   typedef Map<String, GFXGLShaderConstHandle*> HandleMap;
+   typedef Map<String, GFXShaderConstDesc> BufferMap;
+
+   GFXGLShader(GFXGLDevice* device);
+   virtual ~GFXGLShader();
+
+   /// @name GFXShader interface
+   /// @{
+   virtual GFXShaderConstHandle* getShaderConstHandle(const String& name);
+   virtual GFXShaderConstHandle* findShaderConstHandle(const String& name);
+
+   /// Returns our list of shader constants, the material can get this and just set the constants it knows about
+   virtual const Vector<GFXShaderConstDesc>& getShaderConstDesc() const;
+
+   /// Returns the alignment value for constType
+   virtual U32 getAlignmentValue(const GFXShaderConstType constType) const;
+
+   virtual GFXShaderConstBufferRef allocConstBuffer();
+
+   /// @}
+
+   /// @name GFXResource interface
+   /// @{
+   virtual void zombify();
+   virtual void resurrect() { reload(); }
+   virtual const String describeSelf() const;
+   /// @}
+
+   /// Activates this shader in the GL context.
+   void useProgram();
+
+protected:
+   virtual bool _init();
+
+   bool initShader(const Torque::Path& file,
+      GFXShaderStage stage,
+      const Vector<GFXShaderMacro>& macros);
+
+   void clearShaders();
+
+   void initConstantDescs();
+   void initHandles();
+   void setConstantsFromBuffer(U8* buffer);
+
+   static char* _handleIncludes(const Torque::Path& path, FileStream* s);
+
+   static bool _loadShaderFromStream(GLuint shader,
+      const Torque::Path& path,
+      FileStream* s,
+      const Vector<GFXShaderMacro>& macros);
+
+   /// @name Internal GL handles
+   /// @{
+   GLuint mVertexShader;
+   GLuint mPixelShader;
+   GLuint mGeometryShader;
+   GLuint mProgram;
+   /// @}
+
+   U8* mGlobalConstBuffer;
+
+   Vector<GFXShaderConstDesc> mShaderConsts;
+
+   HandleMap mHandles;
+   BufferMap mBuffers;
+
+   GFXGLDevice* mDevice;
+
+   GFXShaderConstType convertConstType(GLenum constType);
+};
+
+#endif // _GFXGLSHADER_H_

+ 1003 - 0
Engine/source/gui/shaderEditor/guiShaderEditor.cpp

@@ -0,0 +1,1003 @@
+//-----------------------------------------------------------------------------
+// Copyright (c) 2012 GarageGames, LLC
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to
+// deal in the Software without restriction, including without limitation the
+// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+// sell copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+// IN THE SOFTWARE.
+//-----------------------------------------------------------------------------
+
+#include "platform/platform.h"
+#include "gui/shaderEditor/guiShaderEditor.h"
+#include "gui/shaderEditor/nodes/materialOutputNode.h"
+#include "gui/shaderEditor/nodes/mathNode.h"
+
+#include "core/frameAllocator.h"
+#include "core/stream/fileStream.h"
+#include "core/stream/memStream.h"
+#include "console/consoleTypes.h"
+#include "gui/core/guiCanvas.h"
+#include "console/engineAPI.h"
+#include "console/script.h"
+#include "console/typeValidators.h"
+#include "gfx/primBuilder.h"
+
+IMPLEMENT_CONOBJECT(GuiShaderEditor);
+
+ConsoleDocClass(GuiShaderEditor,
+   "@brief Implementation of a shader node editor.\n\n"
+   "Editor use only.\n\n"
+   "@internal"
+);
+
+GuiShaderEditor::GuiShaderEditor()
+   : mDragBeginPoint(-1, -1),
+   mViewOffset(0,0),
+   mZoomScale(1.0f),
+   mFullBoxSelection(false),
+   mDragAddSelection(false),
+   mDragMoveUndo(false)
+{
+   VECTOR_SET_ASSOCIATION(mCurrNodes);
+   VECTOR_SET_ASSOCIATION(mSelectedNodes);
+   VECTOR_SET_ASSOCIATION(mDragBeginPoints);
+   VECTOR_SET_ASSOCIATION(mCurrConnections);
+
+   mActive = true;
+   mMouseDownMode = GuiShaderEditor::Selecting;
+
+   mTrash = NULL;
+   mTempConnection = NULL;
+   mNodeSize = 10;
+   // test
+   addNode(new BRDFOutputNode());
+   addNode(new MathAddNode());
+   addNode(new GuiShaderNode());
+}
+
+bool GuiShaderEditor::onWake()
+{
+   if (!Parent::onWake())
+      return false;
+
+   return true;
+}
+
+void GuiShaderEditor::onSleep()
+{
+   Parent::onSleep();
+}
+
+// anything smaller than 4 is way too small....
+IRangeValidator nodeSizeRange(4, 30);
+
+void GuiShaderEditor::initPersistFields()
+{
+   docsURL;
+   addGroup("Node Settings");
+      addFieldV("nodeSize", TypeS32, Offset(mNodeSize, GuiShaderEditor),&nodeSizeRange,
+         "Size of nodes.");
+   endGroup("Node Settings");
+
+   addGroup("Selection");
+      addField("fullBoxSelection", TypeBool, Offset(mFullBoxSelection, GuiShaderEditor),
+         "If true, rectangle selection will only select controls fully inside the drag rectangle.");
+   endGroup("Selection");
+   Parent::initPersistFields();
+}
+
+bool GuiShaderEditor::onAdd()
+{
+   if (!Parent::onAdd())
+      return false;
+
+   mTrash = new SimGroup();
+
+   if (!mTrash->registerObject())
+      return false;
+
+
+   return true;
+}
+
+void GuiShaderEditor::onRemove()
+{
+   Parent::onRemove();
+
+   mTrash->deleteObject();
+
+   mTrash = NULL;
+
+  /* for (GuiShaderNode* node : mCurrNodes)
+   {
+      SAFE_DELETE(node);
+   }*/
+
+   for (GuiShaderNode* node : mSelectedNodes)
+   {
+      SAFE_DELETE(node);
+   }
+}
+
+void GuiShaderEditor::onPreRender()
+{
+   setUpdate();
+}
+
+void GuiShaderEditor::renderNodes(Point2I offset, const RectI& updateRect)
+{
+   // Save the current clip rect
+   // so we can restore it at the end of this method.
+   RectI savedClipRect = GFX->getClipRect();
+
+   // offset is the upper-left corner of this control in screen coordinates
+   // updateRect is the intersection rectangle in screen coords of the control
+   // hierarchy.  This can be set as the clip rectangle in most cases.
+   RectI clipRect = updateRect;
+   clipRect.inset(2, 2);
+
+   GFXDrawUtil* drawer = GFX->getDrawUtil();
+
+   // render nodes in reverse order.
+   for (ShaderNodeVector::iterator i = mCurrNodes.end(); i-- != mCurrNodes.begin(); )
+   {
+      GuiShaderNode* node = *i;
+      // this is useful for sub node graphs.
+      if (node->isVisible())
+      {
+         Point2I childPos = offset + node->getPosition();
+         RectI childClip(childPos, node->getExtent() );
+
+         if (selectionContains(node))
+         {
+            node->mSelected = true;
+         }
+         else
+         {
+            node->mSelected = false;
+         }
+
+         if (childClip.intersect(clipRect))
+         {
+            GFX->setClipRect(childClip);
+            GFX->setStateBlock(mDefaultGuiSB);
+            node->renderNode(childPos, childClip, mNodeSize);
+         }
+
+         GFX->setClipRect(clipRect);
+         GFX->setStateBlock(mDefaultGuiSB);
+         for (NodeInput* input : node->mInputNodes)
+         {
+            Point2I pos = node->localToGlobalCoord(input->pos) + offset;
+
+            ColorI border = input->col;
+
+            ColorI fill = mProfile->mFillColor;
+            if (hasConnection(input))
+            {
+               fill = input->col;
+            }
+
+            RectI socketRect(pos, Point2I(mNodeSize, mNodeSize));
+            drawer->drawCircleFill(socketRect, fill, mNodeSize / 2, 1.0f, border);
+         }
+
+         for (NodeOutput* output : node->mOutputNodes)
+         {
+            Point2I pos = node->localToGlobalCoord(output->pos) + offset;
+
+            ColorI border = output->col;
+
+            ColorI fill = mProfile->mFillColor;
+            if (hasConnection(output))
+            {
+               fill = output->col;
+            }
+
+            RectI socketRect(pos, Point2I(mNodeSize, mNodeSize));
+            drawer->drawCircleFill(socketRect, fill, mNodeSize / 2, 1.0f, border);
+         }
+      }
+   }
+
+   // Restore the clip rect to what it was at the start
+   // of this method.
+   GFX->setClipRect(savedClipRect);
+}
+
+void GuiShaderEditor::renderConnections(Point2I offset, const RectI& updateRect)
+{
+   // Save the current clip rect
+   // so we can restore it at the end of this method.
+   RectI savedClipRect = GFX->getClipRect();
+
+   // offset is the upper-left corner of this control in screen coordinates
+   // updateRect is the intersection rectangle in screen coords of the control
+   // hierarchy.  This can be set as the clip rectangle in most cases.
+   RectI clipRect = updateRect;
+   clipRect.inset(2, 2);
+
+   GFXDrawUtil* drawer = GFX->getDrawUtil();
+
+   for (NodeConnection* conn : mCurrConnections)
+   {
+      // for temp connetion, nodeA is always the first node selected.
+      Point2I start(Point2I::Zero);
+      Point2I end(Point2I::Zero);
+
+      start = conn->nodeA->localToGlobalCoord(conn->inSocket->pos) + offset;
+      end = conn->nodeB->localToGlobalCoord(conn->outSocket->pos) + offset;
+
+      start += Point2I(mNodeSize / 2, mNodeSize / 2);
+      end += Point2I(mNodeSize / 2, mNodeSize / 2);
+
+      drawer->drawThickLine(start, end,ColorI(255,255,255,255), 2.0f);
+   }
+
+   // Restore the clip rect to what it was at the start
+   // of this method.
+   GFX->setClipRect(savedClipRect);
+}
+
+void GuiShaderEditor::onRender(Point2I offset, const RectI& updateRect)
+{
+   offset += mViewOffset;
+
+   GFXDrawUtil* drawer = GFX->getDrawUtil();
+
+   // render our nodes.
+   renderConnections(offset, updateRect);
+   renderNodes(offset, updateRect);
+
+   if (mActive)
+   {
+      if (mMouseDownMode == DragConnection)
+      {
+         // something went wrong.... fix it fix it fix it.
+         if (mTempConnection == NULL)
+            return;
+         else
+         {
+            // for temp connetion, nodeA is always the first node selected.
+            Point2I start(Point2I::Zero);
+            ColorI color(ColorI::WHITE);
+            if (mTempConnection->inSocket != NULL)
+            {
+               start = mTempConnection->nodeA->localToGlobalCoord(mTempConnection->inSocket->pos) + offset;
+               color = mTempConnection->inSocket->col;
+            }
+            else if (mTempConnection->outSocket != NULL)
+            {
+               start = mTempConnection->nodeA->localToGlobalCoord(mTempConnection->outSocket->pos) + offset;
+               color = mTempConnection->outSocket->col;
+            }
+
+            RectI sockActive(start, Point2I(mNodeSize, mNodeSize));
+            start += Point2I(mNodeSize / 2, mNodeSize / 2);
+
+            drawer->drawThickLine(start, mLastMousePos + offset, color, 2.0f);
+
+            // draw socket overlay over the top of the line.
+            drawer->drawCircleFill(sockActive, color, mNodeSize / 2);
+         }
+      }
+      // Draw selection rectangle last so it is rendered on top.
+      if (mMouseDownMode == DragSelecting)
+      {
+         RectI b;
+         getDragRect(b);
+         b.point += offset;
+
+         // Draw outline.
+         drawer->drawRect(b, ColorI(100, 100, 100, 128));
+
+         // Draw fill.
+         b.inset(1, 1);
+         drawer->drawRectFill(b, ColorI(150, 150, 150, 128));
+      }
+   }
+}
+
+bool GuiShaderEditor::onKeyDown(const GuiEvent& event)
+{
+   if (!mActive)
+      return Parent::onKeyDown(event);
+
+   if (!(event.modifier & SI_PRIMARY_CTRL))
+   {
+      switch (event.keyCode)
+      {
+      case KEY_BACKSPACE:
+      case KEY_DELETE:
+         deleteSelection();
+         return true;
+      default:
+         break;
+      }
+   }
+
+   return false;
+}
+
+void GuiShaderEditor::onMouseDown(const GuiEvent& event)
+{
+   if (!mActive)
+   {
+      Parent::onMouseDown(event);
+      return;
+   }
+
+   setFirstResponder();
+
+   // lock mouse
+   mouseLock();
+
+   // get mouse pos with our view offset and scale.
+   mLastMousePos = globalToLocalCoord(event.mousePoint) - mViewOffset;
+
+   GuiShaderNode* hitNode = findHitNode(mLastMousePos);
+
+   if(findHitSocket(mLastMousePos))
+   {
+      // handled in hit socket.
+      return;
+   }
+   else
+   {
+      if (event.modifier & SI_SHIFT)
+      {
+         startDragRectangle(mLastMousePos);
+         mDragAddSelection = true;
+      }
+      else if (selectionContains(hitNode))
+      {
+         if (event.modifier & SI_MULTISELECT)
+         {
+            removeSelection(hitNode);
+            setMouseMode(Selecting);
+         }
+         else if (event.modifier & SI_PRIMARY_ALT)
+         {
+            startDragClone(mLastMousePos);
+         }
+         else
+         {
+            startDragMove(mLastMousePos);
+         }
+      }
+      else
+      {
+         if (hitNode == NULL)
+         {
+            startDragRectangle(mLastMousePos);
+            mDragAddSelection = false;
+         }
+         else if (event.modifier & SI_PRIMARY_ALT && hitNode != NULL)
+         {
+            // Alt is down.  Start a drag clone.
+            clearSelection();
+            addSelection(hitNode);
+            startDragClone(mLastMousePos);
+         }
+         else if (event.modifier & SI_MULTISELECT)
+         {
+            addSelection(hitNode);
+         }
+         else
+         {
+            // Clicked on node.  Start move.
+            clearSelection();
+            addSelection(hitNode);
+            startDragMove(mLastMousePos);
+         }
+      }
+   }
+
+}
+
+void GuiShaderEditor::onMouseUp(const GuiEvent& event)
+{
+   if (!mActive)
+   {
+      Parent::onMouseUp(event);
+      return;
+   }
+
+   //unlock the mouse
+   mouseUnlock();
+
+   // Reset Drag Axis Alignment Information
+   mDragBeginPoint.set(-1, -1);
+   mDragBeginPoints.clear();
+
+   // get mouse pos with our view offset and scale.
+   mLastMousePos = globalToLocalCoord(event.mousePoint) - mViewOffset;
+
+   if (mMouseDownMode == DragConnection)
+   {
+      U32 ret = finishConnection(mLastMousePos);
+
+      if (ret == 1) // we set the input on mouse up, nodeB is the inputSocket, swap order.
+      {
+         NodeConnection* conn = new NodeConnection();
+         conn->nodeA = mTempConnection->nodeB;
+         conn->nodeB = mTempConnection->nodeA;
+         conn->inSocket = mTempConnection->inSocket;
+         conn->outSocket = mTempConnection->outSocket;
+
+         mCurrConnections.push_back(conn);
+      }
+
+      if (ret == 2) // we set the output on mouse up, nodeB is the outputSocket
+      {
+         NodeConnection* conn = new NodeConnection();
+         conn->nodeA = mTempConnection->nodeA;
+         conn->nodeB = mTempConnection->nodeB;
+         conn->inSocket = mTempConnection->inSocket;
+         conn->outSocket = mTempConnection->outSocket;
+
+         mCurrConnections.push_back(conn);
+      }
+
+      mTempConnection = NULL;
+   }
+
+   if (mMouseDownMode == DragSelecting)
+   {
+      if (!(event.modifier & SI_MULTISELECT) && !mDragAddSelection)
+         clearSelection();
+
+      RectI rect;
+      getDragRect(rect);
+
+      if (rect.extent.x <= 2 && rect.extent.y <= 2)
+      {
+         addSelectionAtPoint(rect.point);
+      }
+      else
+      {
+         Vector< GuiShaderNode* > hits;
+         findNodesInRect(rect, hits);
+
+         for (GuiShaderNode* node : hits)
+         {
+            addSelection(node);
+         }
+      }
+   }
+
+   //reset the mouse mode
+   setFirstResponder();
+   setMouseMode(Selecting);
+}
+
+void GuiShaderEditor::onMouseDragged(const GuiEvent& event)
+{
+   if (!mActive)
+   {
+      Parent::onMouseDragged(event);
+      return;
+   }
+
+   // get mouse pos with our view offset and scale.
+   Point2I mousePoint = globalToLocalCoord(event.mousePoint) - mViewOffset;
+
+   if (mMouseDownMode == DragClone)
+   {
+      // If we haven't yet crossed the mouse delta to actually start the
+      // clone, check if we have now.
+
+      S32 delta = mAbs((mousePoint - mDragBeginPoint).len());
+      if (delta >= 4)
+      {
+         cloneSelection();
+         mLastMousePos = mDragBeginPoint;
+         mDragMoveUndo = false;
+
+         setMouseMode(MovingSelection);
+      }
+   }
+
+   if (mMouseDownMode == MovingSelection && mSelectedNodes.size())
+   {
+      Point2I delta = mousePoint - mLastMousePos;
+      RectI selBounds = getSelectionBounds();
+
+      if (delta.x || delta.y)
+         moveSelection(delta, mDragMoveUndo);
+
+      mLastMousePos += delta;
+   }
+   else
+      mLastMousePos = mousePoint;
+}
+
+void GuiShaderEditor::onMiddleMouseDown(const GuiEvent& event)
+{
+   if (!mActive)
+   {
+      Parent::onMiddleMouseDown(event);
+      return;
+   }
+
+   setFirstResponder();
+
+   // lock mouse
+   mouseLock();
+
+   // get mouse pos with our view offset and scale.
+   mLastMousePos = globalToLocalCoord(event.mousePoint);
+
+   setMouseMode(DragPanning);
+   getRoot()->showCursor(false);
+}
+
+void GuiShaderEditor::onMiddleMouseUp(const GuiEvent& event)
+{
+   if (!mActive)
+   {
+      Parent::onMiddleMouseUp(event);
+      return;
+   }
+
+   getRoot()->showCursor(true);
+
+   //unlock the mouse
+   mouseUnlock();
+
+   // Reset Drag Axis Alignment Information
+   mDragBeginPoint.set(-1, -1);
+   mDragBeginPoints.clear();
+
+   // get mouse pos with our view offset and scale.
+   mLastMousePos = globalToLocalCoord(event.mousePoint);
+
+   setFirstResponder();
+   setMouseMode(Selecting);
+}
+
+void GuiShaderEditor::onMiddleMouseDragged(const GuiEvent& event)
+{
+   if (!mActive)
+   {
+      Parent::onMiddleMouseDragged(event);
+      return;
+   }
+
+   // get mouse pos with our view offset and scale.
+   Point2I mousePoint = globalToLocalCoord(event.mousePoint);
+
+   if (mMouseDownMode == DragPanning)
+   {
+      Point2I delta = mousePoint - mLastMousePos;
+      // invert it
+      if (delta.x || delta.y)
+         mViewOffset += -delta;
+
+      mLastMousePos += delta;
+   }
+   else
+      mLastMousePos = mousePoint;
+}
+
+bool GuiShaderEditor::onMouseWheelUp(const GuiEvent& event)
+{
+   if (!mActive || !mAwake || !mVisible)
+      return Parent::onMouseWheelUp(event);
+
+   mZoomScale *= 1.1f;
+
+   return true;
+}
+
+bool GuiShaderEditor::onMouseWheelDown(const GuiEvent& event)
+{
+   if (!mActive || !mAwake || !mVisible)
+      return Parent::onMouseWheelDown(event);
+
+   mZoomScale *= 0.9f;
+
+   return true;
+}
+
+RectI GuiShaderEditor::getSelectionBounds()
+{
+
+   Vector<GuiShaderNode*>::const_iterator i = mSelectedNodes.begin();
+
+   Point2I minPos = (*i)->localToGlobalCoord(Point2I(0, 0));
+   Point2I maxPos = minPos;
+
+   for (; i != mSelectedNodes.end(); i++)
+   {
+      Point2I iPos = (**i).localToGlobalCoord(Point2I(0, 0));
+
+      minPos.x = getMin(iPos.x, minPos.x);
+      minPos.y = getMin(iPos.y, minPos.y);
+
+      Point2I iExt = (**i).getExtent();
+
+      iPos.x += iExt.x;
+      iPos.y += iExt.y;
+
+      maxPos.x = getMax(iPos.x, maxPos.x);
+      maxPos.y = getMax(iPos.y, maxPos.y);
+   }
+
+   minPos = globalToLocalCoord(minPos);
+   maxPos = globalToLocalCoord(maxPos);
+
+   return RectI(minPos.x, minPos.y, (maxPos.x - minPos.x), (maxPos.y - minPos.y));
+}
+
+void GuiShaderEditor::deleteSelection()
+{
+   for (GuiShaderNode* node : mSelectedNodes)
+   {
+      mTrash->addObject(node);
+
+      Vector<NodeConnection*> connVec;
+      for (NodeInput* input : node->mInputNodes)
+      {
+         hasConnection(input, connVec);
+      }
+
+      for (NodeOutput* output : node->mOutputNodes)
+      {
+         hasConnection(output, connVec);
+      }
+
+      for (NodeConnection* conn : connVec)
+      {
+         Vector< NodeConnection* >::iterator i = T3D::find(mCurrConnections.begin(), mCurrConnections.end(), conn);
+         if (i != mCurrConnections.end())
+         {
+            mCurrConnections.erase(i);
+         }
+      }
+
+      Vector< GuiShaderNode* >::iterator i = T3D::find(mCurrNodes.begin(), mCurrNodes.end(), node);
+      if (i != mCurrNodes.end())
+         mCurrNodes.erase(i);
+   }
+
+   clearSelection();
+}
+
+void GuiShaderEditor::moveSelection(const Point2I& delta, bool callback)
+{
+   for (GuiShaderNode* node : mSelectedNodes)
+   {
+      node->setPosition(node->getPosition() + delta);
+   }
+}
+
+void GuiShaderEditor::clearSelection()
+{
+   mSelectedNodes.clear();
+}
+
+void GuiShaderEditor::cloneSelection()
+{
+   Vector<GuiShaderNode*> newSelection;
+
+   for (GuiShaderNode* node : mSelectedNodes)
+   {
+      GuiShaderNode* clone = dynamic_cast<GuiShaderNode*>(node->deepClone());
+      if (clone)
+         newSelection.push_back(clone);
+   }
+
+   clearSelection();
+
+   for (GuiShaderNode* cloneNode : newSelection)
+   {
+      mCurrNodes.push_back(cloneNode);
+      addSelection(cloneNode);
+   }
+}
+
+void GuiShaderEditor::addSelectionAtPoint(const Point2I& pos)
+{
+   // turn hit off on already selected nodes.
+   canHitSelectedNodes(false);
+
+   GuiShaderNode* node = findHitNode(pos);
+
+   // reset hit status.
+   canHitSelectedNodes();
+
+   if (node)
+      addSelection(node);
+}
+
+void GuiShaderEditor::addSelection(GuiShaderNode* inNode)
+{
+   if (inNode != NULL && !selectionContains(inNode))
+   {
+      mSelectedNodes.push_back(inNode);
+   }
+}
+
+bool GuiShaderEditor::selectionContains(GuiShaderNode* inNode)
+{
+   for (GuiShaderNode* node : mSelectedNodes)
+   {
+      if (node == inNode)
+         return true;
+   }
+
+   return false;
+}
+
+void GuiShaderEditor::removeSelection(GuiShaderNode* inNode)
+{
+   if (selectionContains(inNode))
+   {
+      Vector< GuiShaderNode* >::iterator i = T3D::find(mSelectedNodes.begin(), mSelectedNodes.end(), inNode);
+      if (i != mSelectedNodes.end())
+         mSelectedNodes.erase(i);
+   }
+}
+
+void GuiShaderEditor::canHitSelectedNodes(bool state)
+{
+   for (GuiShaderNode* node : mSelectedNodes)
+      node->setCanHit(state);
+}
+
+//-----------------------------------------------------------------------------
+// Input handling
+//-----------------------------------------------------------------------------
+
+GuiShaderNode* GuiShaderEditor::findHitNode(const Point2I& pt)
+{
+   for (GuiShaderNode* node : mCurrNodes)
+   {
+      if (node->pointInControl(pt))
+      {
+         // selecting one node, push it to the front of the mcurrnodes stack so its rendered on top.
+         Vector< GuiShaderNode* >::iterator i = T3D::find(mCurrNodes.begin(), mCurrNodes.end(), node);
+         if (i != mCurrNodes.end())
+         {
+            mCurrNodes.erase(i);
+            mCurrNodes.insert(mCurrNodes.begin(), node);
+         }
+
+         return node;
+      }
+   }
+
+   return nullptr;
+}
+
+bool GuiShaderEditor::findHitSocket(const Point2I& pt)
+{
+   Point2I parentOffset = localToGlobalCoord(getPosition()) + mViewOffset;
+   Point2I offsetPoint = pt + localToGlobalCoord(getPosition());
+
+   for (GuiShaderNode* node : mCurrNodes)
+   {
+      for (NodeInput* inNode : node->mInputNodes)
+      {
+         Point2I offSet = node->localToGlobalCoord(inNode->pos) + parentOffset;
+         RectI box(offSet.x, offSet.y, mNodeSize, mNodeSize);
+
+         S32 xt = offsetPoint.x - box.point.x;
+         S32 yt = offsetPoint.y - box.point.y;
+         if (xt >= 0 && yt >= 0 && xt < box.extent.x && yt < box.extent.y)
+         {
+            mTempConnection = new NodeConnection();
+            mTempConnection->nodeA = node;
+            mTempConnection->inSocket = inNode;
+            setMouseMode(DragConnection);
+            return true;
+         }
+      }
+
+      for (NodeOutput* outNode : node->mOutputNodes)
+      {
+         Point2I offSet = node->localToGlobalCoord(outNode->pos) + parentOffset;
+         RectI box(offSet.x, offSet.y, mNodeSize, mNodeSize);
+
+         S32 xt = offsetPoint.x - box.point.x;
+         S32 yt = offsetPoint.y - box.point.y;
+         if (xt >= 0 && yt >= 0 && xt < box.extent.x && yt < box.extent.y)
+         {
+            mTempConnection = new NodeConnection();
+            mTempConnection->nodeA = node;
+            mTempConnection->outSocket = outNode;
+            setMouseMode(DragConnection);
+            return true;
+         }
+      }
+   }
+   return false;
+}
+
+U32 GuiShaderEditor::finishConnection(const Point2I& pt)
+{
+   Point2I parentOffset = localToGlobalCoord(getPosition()) + mViewOffset;
+   Point2I offsetPoint = pt + localToGlobalCoord(getPosition());
+
+   for (GuiShaderNode* node : mCurrNodes)
+   {
+      for (NodeInput* inNode : node->mInputNodes)
+      {
+         Point2I offSet = node->localToGlobalCoord(inNode->pos) + parentOffset;
+         RectI box(offSet.x, offSet.y, mNodeSize, mNodeSize);
+
+         S32 xt = offsetPoint.x - box.point.x;
+         S32 yt = offsetPoint.y - box.point.y;
+         if (xt >= 0 && yt >= 0 && xt < box.extent.x && yt < box.extent.y)
+         {
+            if (mTempConnection->nodeA == node || mTempConnection->inSocket != NULL)
+               return false;
+
+            NodeConnection* conn;
+            if(hasConnection(inNode, conn))
+            {
+               Vector< NodeConnection* >::iterator i = T3D::find(mCurrConnections.begin(), mCurrConnections.end(), conn);
+               if (i != mCurrConnections.end())
+               {
+                  mCurrConnections.erase(i);
+               }
+            }
+
+            mTempConnection->nodeB = node;
+            mTempConnection->inSocket = inNode;
+            return 1;
+         }
+      }
+
+      for (NodeOutput* outNode : node->mOutputNodes)
+      {
+         Point2I offSet = node->localToGlobalCoord(outNode->pos) + parentOffset;
+         RectI box(offSet.x, offSet.y, mNodeSize, mNodeSize);
+
+         S32 xt = offsetPoint.x - box.point.x;
+         S32 yt = offsetPoint.y - box.point.y;
+         if (xt >= 0 && yt >= 0 && xt < box.extent.x && yt < box.extent.y)
+         {
+            if (mTempConnection->nodeA == node || mTempConnection->outSocket != NULL)
+               return false;
+
+            NodeConnection* conn;
+            if (hasConnection(mTempConnection->inSocket, conn))
+            {
+               Vector< NodeConnection* >::iterator i = T3D::find(mCurrConnections.begin(), mCurrConnections.end(), conn);
+               if (i != mCurrConnections.end())
+               {
+                  mCurrConnections.erase(i);
+               }
+            }
+
+            mTempConnection->nodeB = node;
+            mTempConnection->outSocket = outNode;
+            return 2;
+         }
+      }
+   }
+   return 0;
+}
+
+bool GuiShaderEditor::hasConnection(NodeSocket* inSocket)
+{
+   for (NodeConnection* con : mCurrConnections)
+   {
+      if (con->inSocket == dynamic_cast<NodeInput*>(inSocket) || con->outSocket == dynamic_cast<NodeOutput*>(inSocket))
+      {
+         return true;
+      }
+   }
+
+   return false;
+}
+
+bool GuiShaderEditor::hasConnection(NodeSocket* inSocket, Vector<NodeConnection*>& conn)
+{
+   bool ret = false;
+
+   for (NodeConnection* con : mCurrConnections)
+   {
+      if (con->inSocket == dynamic_cast<NodeInput*>(inSocket) || con->outSocket == dynamic_cast<NodeOutput*>(inSocket))
+      {
+         conn.push_back(con);
+         ret = true;
+      }
+   }
+
+   return ret;
+}
+
+bool GuiShaderEditor::hasConnection(NodeSocket* inSocket, NodeConnection*& conn)
+{
+   for (NodeConnection* con : mCurrConnections)
+   {
+      if (con->inSocket == dynamic_cast<NodeInput*>(inSocket) || con->outSocket == dynamic_cast<NodeOutput*>(inSocket))
+      {
+         if (conn != nullptr)
+            conn = con;
+         return true;
+      }
+   }
+   return false;
+}
+
+void GuiShaderEditor::findNodesInRect(const RectI& rect, Vector<GuiShaderNode*>& outResult)
+{
+   canHitSelectedNodes(false);
+   for (GuiShaderNode* node : mCurrNodes)
+   {
+      if (node->getBounds().overlaps(rect))
+      {
+         outResult.push_back(node);
+      }
+   }
+
+   canHitSelectedNodes();
+}
+
+void GuiShaderEditor::getDragRect(RectI& box)
+{
+   box.point.x = getMin(mLastMousePos.x, mSelectionAnchor.x);
+   box.extent.x = getMax(mLastMousePos.x, mSelectionAnchor.x) - box.point.x + 1;
+   box.point.y = getMin(mLastMousePos.y, mSelectionAnchor.y);
+   box.extent.y = getMax(mLastMousePos.y, mSelectionAnchor.y) - box.point.y + 1;
+}
+
+void GuiShaderEditor::startDragMove(const Point2I& startPoint)
+{
+   mDragMoveUndo = true;
+
+   mDragBeginPoint = startPoint;
+
+   mDragBeginPoints.reserve(mSelectedNodes.size());
+
+   for (GuiShaderNode* node : mSelectedNodes)
+   {
+      mDragBeginPoints.push_back(node->getPosition());
+   }
+
+   setMouseMode(MovingSelection);
+
+}
+
+void GuiShaderEditor::startDragRectangle(const Point2I& startPoint)
+{
+   mSelectionAnchor = startPoint;
+   setMouseMode(DragSelecting);
+}
+
+void GuiShaderEditor::startDragClone(const Point2I& startPoint)
+{
+   mDragBeginPoint = startPoint;
+   setMouseMode(DragClone);
+}
+
+void GuiShaderEditor::setMouseMode(mouseModes mode)
+{
+   if (mMouseDownMode != mode)
+   {
+      mMouseDownMode = mode;
+   }
+}
+
+void GuiShaderEditor::addNode(GuiShaderNode* newNode)
+{
+   mCurrNodes.push_back(newNode);
+}
+

+ 147 - 0
Engine/source/gui/shaderEditor/guiShaderEditor.h

@@ -0,0 +1,147 @@
+//-----------------------------------------------------------------------------
+// Copyright (c) 2012 GarageGames, LLC
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to
+// deal in the Software without restriction, including without limitation the
+// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+// sell copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+// IN THE SOFTWARE.
+//-----------------------------------------------------------------------------
+
+#ifndef _GUISHADEREDITOR_H_
+#define _GUISHADEREDITOR_H_
+
+#ifndef _GUICONTROL_H_
+#include "gui/core/guiControl.h"
+#endif
+#ifndef _UNDO_H_
+#include "util/undo.h"
+#endif
+#ifndef _GFX_GFXDRAWER_H_
+#include "gfx/gfxDrawUtil.h"
+#endif
+
+#ifndef _SHADERNODE_H_
+#include "gui/shaderEditor/guiShaderNode.h"
+#endif // !_SHADERNODE_H_
+
+struct NodeConnection
+{
+   // keep track of the nodes hit.
+   GuiShaderNode* nodeA = NULL;
+   GuiShaderNode* nodeB = NULL;
+
+   // keep track of the sockets.
+   NodeInput* inSocket = NULL;
+   NodeOutput* outSocket = NULL;
+};
+
+class GuiShaderEditor : public GuiControl
+{
+public:
+
+   typedef GuiControl Parent;
+
+   enum mouseModes { Selecting, MovingSelection, DragPanning, DragConnection, DragSelecting, DragClone };
+
+protected:
+
+   // list
+   typedef Vector<GuiShaderNode*> ShaderNodeVector;
+   typedef Vector<NodeConnection*> ShderNodeConnections;
+   // all nodes in this graph.
+   ShaderNodeVector mCurrNodes;
+   ShderNodeConnections mCurrConnections;
+   NodeConnection* mTempConnection;
+   // Undo
+   SimGroup* mTrash;
+
+   // view controls
+   Point2I mViewOffset;
+   F32 mZoomScale;
+   // mouse interaction
+   mouseModes mMouseDownMode;
+   Point2I mLastMousePos;
+   Point2I mLastDragPos;
+   Point2I mSelectionAnchor;
+   Point2I mDragBeginPoint;
+   Vector<Point2I> mDragBeginPoints;
+   bool mDragAddSelection;
+   bool mDragMoveUndo;
+   bool mFullBoxSelection;
+   S32 mNodeSize;
+   ShaderNodeVector mSelectedNodes;
+
+   void renderNodes(Point2I offset, const RectI& updateRect);
+   void renderConnections(Point2I offset, const RectI& updateRect);
+
+   // functions for handling mouse events.
+   GuiShaderNode* findHitNode(const Point2I& pt);
+   bool findHitSocket(const Point2I& pt);
+   U32 finishConnection(const Point2I& pt);
+   bool hasConnection(NodeSocket* inSocket);
+   bool hasConnection(NodeSocket* inSocket, Vector<NodeConnection*>& conn);
+   bool hasConnection(NodeSocket* inSocket, NodeConnection*& conn);
+
+   void findNodesInRect(const RectI& rect, Vector<GuiShaderNode*>& outResult);
+
+   void getDragRect(RectI& box);
+   void startDragMove(const Point2I& startPoint);
+   void startDragRectangle(const Point2I& startPoint);
+   void startDragClone(const Point2I& startPoint);
+   void setMouseMode(mouseModes mode);
+   void addNode(GuiShaderNode* newNode);
+
+public:
+   GuiShaderEditor();
+
+   DECLARE_CONOBJECT(GuiShaderEditor);
+   DECLARE_CATEGORY("Shader Editor");
+   DECLARE_DESCRIPTION("Implements a shader node based editor.");
+
+   bool onWake();
+   void onSleep();
+   static void initPersistFields();
+   virtual bool onAdd() override;
+   virtual void onRemove() override;
+
+   virtual void onPreRender() override;
+   void drawThickLine(const Point2I& pt1, const Point2I& pt2, U32 thickness = 2, ColorI col1 = ColorI(255, 255, 255), ColorI col2 = ColorI(255, 255, 255));
+   virtual void onRender(Point2I offset, const RectI& updateRect) override;
+
+   // interaction
+   virtual bool onKeyDown(const GuiEvent& event) override;
+   virtual void onMouseDown(const GuiEvent& event) override;
+   virtual void onMouseUp(const GuiEvent& event) override;
+   virtual void onMouseDragged(const GuiEvent& event) override;
+   virtual void onMiddleMouseDown(const GuiEvent& event) override;
+   virtual void onMiddleMouseUp(const GuiEvent& event) override;
+   virtual void onMiddleMouseDragged(const GuiEvent& event) override;
+   virtual bool onMouseWheelUp(const GuiEvent& event) override;
+   virtual bool onMouseWheelDown(const GuiEvent& event) override;
+
+   RectI getSelectionBounds();
+   void deleteSelection();
+   void moveSelection(const Point2I& delta, bool callback = true);
+   void clearSelection();
+   void cloneSelection();
+   void addSelectionAtPoint(const Point2I& pos);
+   void addSelection(GuiShaderNode* inNode);
+   bool selectionContains(GuiShaderNode* inNode);
+   void removeSelection(GuiShaderNode* inNode);
+   void canHitSelectedNodes(bool state = true);
+};
+
+#endif _GUISHADEREDITOR_H_

+ 203 - 0
Engine/source/gui/shaderEditor/guiShaderNode.cpp

@@ -0,0 +1,203 @@
+//-----------------------------------------------------------------------------
+// Copyright (c) 2012 GarageGames, LLC
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to
+// deal in the Software without restriction, including without limitation the
+// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+// sell copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+// IN THE SOFTWARE.
+//-----------------------------------------------------------------------------
+
+#include "platform/platform.h"
+#include "gui/shaderEditor/guiShaderNode.h"
+
+#include "gui/core/guiCanvas.h"
+
+IMPLEMENT_CONOBJECT(GuiShaderNode);
+
+ConsoleDocClass(GuiShaderNode,
+   "@brief Base class for all nodes to derive from.\n\n"
+   "Editor use only.\n\n"
+   "@internal"
+);
+
+
+GuiShaderNode::GuiShaderNode()
+{
+   VECTOR_SET_ASSOCIATION(mInputNodes);
+   VECTOR_SET_ASSOCIATION(mOutputNodes);
+
+   mTitle = "Default Node";
+   mSelected = false;
+   mNodeType = NodeTypes::Default;
+
+
+   GuiControlProfile* profile = NULL;
+   if (Sim::findObject("GuiShaderEditorProfile", profile))
+      setControlProfile(profile);
+
+   // fixed extent for all nodes, only height should be changed
+   setExtent(180, 35);
+
+   mPrevNodeSize = -1;
+}
+
+bool GuiShaderNode::onWake()
+{
+   if (!Parent::onWake())
+      return false;
+
+   return true;
+}
+
+void GuiShaderNode::onSleep()
+{
+   Parent::onSleep();
+}
+
+void GuiShaderNode::initPersistFields()
+{
+   docsURL;
+   Parent::initPersistFields();
+}
+
+bool GuiShaderNode::onAdd()
+{
+   if (!Parent::onAdd())
+      return false;
+
+   return true;
+}
+
+void GuiShaderNode::onRemove()
+{
+   Parent::onRemove();
+}
+
+void GuiShaderNode::renderNode(Point2I offset, const RectI& updateRect, const S32 nodeSize)
+{
+   if (!mProfile)
+      return Parent::onRender(offset, updateRect);
+
+   GFXDrawUtil* drawer = GFX->getDrawUtil();
+
+   // draw background.
+   // Get our rect.
+   RectI winRect;
+   winRect.point = offset;
+   winRect.extent = getExtent();
+
+   ColorI border = mProfile->mBorderColor;
+
+   if (mSelected)
+      border = mProfile->mBorderColorSEL;
+
+   drawer->drawRoundedRect(15.0f, winRect, mProfile->mFillColor, 5.0f, border);
+
+   // draw header
+   ColorI header(50, 50, 50, 128);
+
+   switch (mNodeType)
+   {
+   case NodeTypes::Default:
+      header = ColorI(128, 50, 128, 128);
+      break;
+   case NodeTypes::Uniform:
+      header = ColorI(50, 100, 128, 128);
+      break;
+   case NodeTypes::Input:
+      header = ColorI(128, 100, 50, 128);
+      break;
+   case NodeTypes::Output:
+      header = ColorI(50, 100, 50, 128);
+      break;
+   case NodeTypes::TextureSampler:
+      header = ColorI(50, 50, 128, 128);
+      break;
+   case NodeTypes::MathOperation:
+      header = ColorI(128, 0, 128, 128);
+      break;
+   case NodeTypes::Procedural:
+      header = ColorI(128, 100, 0, 128);
+      break;
+   case NodeTypes::Generator:
+      header = ColorI(0, 100, 128, 128);
+      break;
+   default:
+      header = ColorI(128, 0, 0, 128);
+      break;
+   }
+
+   RectI headRect;
+   U32 headerSize = 30;
+   headRect.point = offset;
+   headRect.extent = Point2I(getExtent().x, headerSize);
+   drawer->drawRoundedRect(15.0f, headRect, header);
+
+   // draw header text.
+   U32 strWidth = mProfile->mFont->getStrWidth(mTitle.c_str());
+   Point2I headerPos = Point2I((getExtent().x / 2) - (strWidth / 2), (headerSize / 2) - (mProfile->mFont->getFontSize() / 2));
+   drawer->setBitmapModulation(mProfile->mFontColor);
+   drawer->drawText(mProfile->mFont, headerPos + offset, mTitle);
+   drawer->clearBitmapModulation();
+
+   if (mInputNodes.size() > 0 || mOutputNodes.size() > 0)
+   {
+      U32 textPadX = nodeSize, textPadY = mProfile->mFont->getFontSize() + (nodeSize / 2);
+      Point2I slotPos(textPadX, headerSize + (nodeSize / 2));
+      drawer->setBitmapModulation(mProfile->mFontColor);
+      for (NodeInput* input : mInputNodes)
+      {
+         drawer->drawText(mProfile->mFont, slotPos + offset, input->name);
+
+         if (input->pos == Point2I::Zero || mPrevNodeSize != nodeSize)
+            input->pos = Point2I(-(nodeSize / 2) + 1, slotPos.y + ((mProfile->mFont->getFontSize() / 2) - (nodeSize / 2)));
+
+         slotPos.y += textPadY;
+      }
+
+      U32 inputY = slotPos.y;
+
+      slotPos = Point2I(getExtent().x, headerSize + (nodeSize / 2));
+      for (NodeOutput* output : mOutputNodes)
+      {
+         strWidth = mProfile->mFont->getStrWidth(output->name.c_str());
+         slotPos.x = getExtent().x - strWidth - textPadX;
+
+         drawer->drawText(mProfile->mFont, slotPos + offset, output->name);
+
+         if (output->pos == Point2I::Zero || mPrevNodeSize != nodeSize)
+            output->pos = Point2I(getExtent().x - (nodeSize / 2) - 1 , slotPos.y + ((mProfile->mFont->getFontSize() / 2) - (nodeSize / 2)));
+
+         slotPos.y += textPadY;
+      }
+      drawer->clearBitmapModulation();
+
+      U32 outputY = slotPos.y;
+
+      if (getExtent().y < slotPos.y || mPrevNodeSize != nodeSize)
+         setExtent(Point2I(getExtent().x, mMax(inputY, outputY)));
+
+      mPrevNodeSize = nodeSize;
+   }
+}
+
+void GuiShaderNode::write(Stream& stream, U32 tabStop, U32 flags)
+{
+}
+
+void GuiShaderNode::read(Stream& stream)
+{
+}

+ 159 - 0
Engine/source/gui/shaderEditor/guiShaderNode.h

@@ -0,0 +1,159 @@
+//-----------------------------------------------------------------------------
+// Copyright (c) 2012 GarageGames, LLC
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to
+// deal in the Software without restriction, including without limitation the
+// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+// sell copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+// IN THE SOFTWARE.
+//-----------------------------------------------------------------------------
+
+#ifndef _SHADERNODE_H_
+#define _SHADERNODE_H_
+
+#ifndef _GUICONTROL_H_
+#include "gui/core/guiControl.h"
+#endif
+
+#ifndef _SIMBASE_H_
+#include "console/simBase.h"
+#endif
+
+#ifndef _GFX_GFXDRAWER_H_
+#include "gfx/gfxDrawUtil.h"
+#endif
+
+
+enum class NodeTypes
+{
+   Default,
+   Uniform,
+   Input,
+   Output,
+   TextureSampler,
+   MathOperation,
+   Procedural,
+   Generator
+};
+
+enum class DataDimensions
+{
+   Dynamic, // can be any dimension, usually defined by what was connected to it.
+   Scalar,
+   Vector2,
+   Vector3,
+   Vector4,
+   Mat4x4,
+};
+
+// parent class for sockets detection in shaderEditor.
+struct NodeSocket
+{
+   String name;
+   DataDimensions dimensions;
+   ColorI col = ColorI::WHITE;
+   NodeSocket()
+      :name(String::EmptyString), dimensions(DataDimensions::Dynamic)
+   {}
+   NodeSocket(String inName, DataDimensions inDim)
+      :name(inName), dimensions(inDim)
+   {
+      switch (inDim)
+      {
+      case DataDimensions::Dynamic:
+         col = ColorI(200, 200, 200, 128);
+         break;
+      case DataDimensions::Scalar:
+         col = ColorI(210, 105, 30, 128);
+         break;
+      case DataDimensions::Vector2:
+         col = ColorI(152, 251,152, 128);
+         break;
+      case DataDimensions::Vector3:
+         col = ColorI(127, 255, 212, 128);
+         break;
+      case DataDimensions::Vector4:
+         col = ColorI(100, 149, 237, 128);
+         break;
+      case DataDimensions::Mat4x4:
+         col = ColorI(153, 50, 204, 128);
+         break;
+      default:
+         break;
+      }
+   }
+
+public:
+   virtual ~NodeSocket() {}
+};
+
+struct NodeInput : NodeSocket
+{
+   Point2I pos = Point2I::Zero;
+
+   NodeInput()
+      :NodeSocket()
+   {}
+   NodeInput(String inName , DataDimensions inDim)
+      :NodeSocket(inName , inDim)
+   {}
+};
+
+struct NodeOutput : NodeSocket
+{
+   Point2I pos = Point2I::Zero;
+
+   NodeOutput()
+      :NodeSocket()
+   {}
+   NodeOutput(String inName, DataDimensions inDim)
+      :NodeSocket(inName, inDim)
+   {}
+};
+
+class GuiShaderNode : public GuiControl
+{
+private:
+   typedef GuiControl Parent;
+
+protected:
+   String mTitle;
+   NodeTypes mNodeType;
+   S32 mPrevNodeSize;
+public:
+   Vector<NodeInput*> mInputNodes;
+   Vector<NodeOutput*> mOutputNodes;
+
+   GuiShaderNode();
+
+   bool onWake();
+   void onSleep();
+   static void initPersistFields();
+   virtual bool onAdd() override;
+   virtual void onRemove() override;
+
+   void renderNode(Point2I offset, const RectI& updateRect, const S32 nodeSize);
+   // Serialization functions
+   void write(Stream& stream, U32 tabStop = 0, U32 flags = 0);
+   void read(Stream& stream);
+
+   // is the parent that all other nodes are derived from.
+   DECLARE_CONOBJECT(GuiShaderNode);
+   DECLARE_CATEGORY("Shader Core");
+   DECLARE_DESCRIPTION("Base class for all shader nodes.");
+
+   bool mSelected;
+};
+#endif // !_SHADERNODE_H_

+ 51 - 0
Engine/source/gui/shaderEditor/nodes/materialOutputNode.cpp

@@ -0,0 +1,51 @@
+//-----------------------------------------------------------------------------
+// Copyright (c) 2012 GarageGames, LLC
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to
+// deal in the Software without restriction, including without limitation the
+// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+// sell copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+// IN THE SOFTWARE.
+//-----------------------------------------------------------------------------
+#include "platform/platform.h"
+#include "gui/shaderEditor/nodes/materialOutputNode.h"
+
+//-----------------------------------------------------------------
+// BRDF Output Node.
+//-----------------------------------------------------------------
+
+IMPLEMENT_CONOBJECT(BRDFOutputNode);
+
+ConsoleDocClass(BRDFOutputNode,
+   "@brief Deferred Material output.\n\n"
+   "Editor use only.\n\n"
+   "@internal"
+);
+
+BRDFOutputNode::BRDFOutputNode()
+   : GuiShaderNode()
+{
+   mNodeType = NodeTypes::Output;
+
+   mInputNodes.push_back(new NodeInput("Albedo", DataDimensions::Vector3));
+   mInputNodes.push_back(new NodeInput("Normal", DataDimensions::Vector3));
+   mInputNodes.push_back(new NodeInput("Ambient Occlusion", DataDimensions::Scalar));
+   mInputNodes.push_back(new NodeInput("Metallic", DataDimensions::Scalar));
+   mInputNodes.push_back(new NodeInput("Roughness", DataDimensions::Scalar));
+   mInputNodes.push_back(new NodeInput("Emissive Color", DataDimensions::Vector3));
+   mInputNodes.push_back(new NodeInput("Opacity", DataDimensions::Scalar));
+
+   mTitle = "Standard BRDF";
+}

+ 39 - 0
Engine/source/gui/shaderEditor/nodes/materialOutputNode.h

@@ -0,0 +1,39 @@
+//-----------------------------------------------------------------------------
+// Copyright (c) 2012 GarageGames, LLC
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to
+// deal in the Software without restriction, including without limitation the
+// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+// sell copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+// IN THE SOFTWARE.
+//-----------------------------------------------------------------------------
+
+#include "gui/shaderEditor/guiShaderNode.h"
+
+//-----------------------------------------------------------------
+// Put all material output nodes here.
+//-----------------------------------------------------------------
+
+class BRDFOutputNode : public GuiShaderNode
+{
+   typedef GuiShaderNode Parent;
+public:
+   BRDFOutputNode();
+
+   // is the parent that all other nodes are derived from.
+   DECLARE_CONOBJECT(BRDFOutputNode);
+   DECLARE_CATEGORY("Shader Output");
+   DECLARE_DESCRIPTION("Deferred Material output.");
+};

+ 49 - 0
Engine/source/gui/shaderEditor/nodes/mathNode.cpp

@@ -0,0 +1,49 @@
+//-----------------------------------------------------------------------------
+// Copyright (c) 2012 GarageGames, LLC
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to
+// deal in the Software without restriction, including without limitation the
+// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+// sell copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+// IN THE SOFTWARE.
+//-----------------------------------------------------------------------------
+#include "platform/platform.h"
+
+#include "gui/shaderEditor/nodes/mathNode.h"
+
+//-----------------------------------------------------------------
+// Math addition Node.
+//-----------------------------------------------------------------
+
+IMPLEMENT_CONOBJECT(MathAddNode);
+
+ConsoleDocClass(MathAddNode,
+   "@brief Math addition node.\n\n"
+   "Editor use only.\n\n"
+   "@internal"
+);
+
+MathAddNode::MathAddNode()
+   : GuiShaderNode()
+{
+   mNodeType = NodeTypes::MathOperation;
+
+   mInputNodes.push_back(new NodeInput("A", DataDimensions::Dynamic));
+   mInputNodes.push_back(new NodeInput("B", DataDimensions::Dynamic));
+
+   mOutputNodes.push_back(new NodeOutput("Result", DataDimensions::Dynamic));
+
+   mTitle = "Math Node";
+}

+ 39 - 0
Engine/source/gui/shaderEditor/nodes/mathNode.h

@@ -0,0 +1,39 @@
+//-----------------------------------------------------------------------------
+// Copyright (c) 2012 GarageGames, LLC
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to
+// deal in the Software without restriction, including without limitation the
+// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+// sell copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+// IN THE SOFTWARE.
+//-----------------------------------------------------------------------------
+
+#include "gui/shaderEditor/guiShaderNode.h"
+
+//-----------------------------------------------------------------
+// Put all Math nodes here.
+//-----------------------------------------------------------------
+
+class MathAddNode : public GuiShaderNode
+{
+   typedef GuiShaderNode Parent;
+public:
+   MathAddNode();
+
+   // is the parent that all other nodes are derived from.
+   DECLARE_CONOBJECT(MathAddNode);
+   DECLARE_CATEGORY("Shader Math");
+   DECLARE_DESCRIPTION("Math addition node.");
+};

+ 0 - 1
Engine/source/materials/processedCustomMaterial.cpp

@@ -35,7 +35,6 @@
 #include "materials/materialParameters.h"
 #include "gfx/sim/gfxStateBlockData.h"
 #include "core/util/safeDelete.h"
-#include "gfx/genericConstBuffer.h"
 #include "console/simFieldDictionary.h"
 #include "console/propertyParsing.h"
 #include "gfx/util/screenspace.h"

+ 0 - 1
Engine/source/materials/processedShaderMaterial.cpp

@@ -26,7 +26,6 @@
 #include "core/util/safeDelete.h"
 #include "gfx/sim/cubemapData.h"
 #include "gfx/gfxShader.h"
-#include "gfx/genericConstBuffer.h"
 #include "gfx/gfxPrimitiveBuffer.h"
 #include "scene/sceneRenderState.h"
 #include "shaderGen/shaderFeature.h"

+ 100 - 72
Engine/source/materials/shaderData.cpp

@@ -48,10 +48,12 @@ ConsoleDocClass( ShaderData,
 	"// Used for the procedural clould system\n"
 	"singleton ShaderData( CloudLayerShader )\n"
 	"{\n"
-   "	DXVertexShaderFile   = $Core::CommonShaderPath @ \"/cloudLayerV.hlsl\";\n"
-   "	DXPixelShaderFile    = $Core::CommonShaderPath @ \"/cloudLayerP.hlsl\";\n"
-   "	OGLVertexShaderFile = $Core::CommonShaderPath @ \"/gl/cloudLayerV.glsl\";\n"
-   "	OGLPixelShaderFile = $Core::CommonShaderPath @ \"/gl/cloudLayerP.glsl\";\n"
+   "	DXVertexShaderFile      = $Core::CommonShaderPath @ \"/cloudLayerV.hlsl\";\n"
+   "	DXPixelShaderFile       = $Core::CommonShaderPath @ \"/cloudLayerP.hlsl\";\n"
+   "	DXGeometryShaderFile    = $Core::CommonShaderPath @ \"/cloudLayerG.hlsl\";\n"
+   "	OGLVertexShaderFile     = $Core::CommonShaderPath @ \"/gl/cloudLayerV.glsl\";\n"
+   "	OGLPixelShaderFile      = $Core::CommonShaderPath @ \"/gl/cloudLayerP.glsl\";\n"
+   "	OGLGeometryShaderFile   = $Core::CommonShaderPath @ \"/gl/cloudLayerG.glsl\";\n"
 	"	pixVersion = 2.0;\n"
 	"};\n"
 	"@endtsexample\n\n"
@@ -67,70 +69,87 @@ ShaderData::ShaderData()
 
    for( int i = 0; i < NumTextures; ++i)
       mRTParams[i] = false;
+
+   mDXVertexShaderName = StringTable->EmptyString();
+   mDXPixelShaderName = StringTable->EmptyString();
+   mDXGeometryShaderName = StringTable->EmptyString();
+
+   mOGLVertexShaderName = StringTable->EmptyString();
+   mOGLPixelShaderName = StringTable->EmptyString();
+   mOGLGeometryShaderName = StringTable->EmptyString();
 }
 
 void ShaderData::initPersistFields()
 {
    docsURL;
-   addField("DXVertexShaderFile",   TypeStringFilename,  Offset(mDXVertexShaderName,   ShaderData),
-	   "@brief %Path to the DirectX vertex shader file to use for this ShaderData.\n\n"
-	   "It must contain only one program and no pixel shader, just the vertex shader."
-	   "It can be either an HLSL or assembly level shader. HLSL's must have a "
-	   "filename extension of .hlsl, otherwise its assumed to be an assembly file.");
-
-   addField("DXPixelShaderFile",    TypeStringFilename,  Offset(mDXPixelShaderName,  ShaderData),
-	   "@brief %Path to the DirectX pixel shader file to use for this ShaderData.\n\n"
-	   "It must contain only one program and no vertex shader, just the pixel "
-	   "shader. It can be either an HLSL or assembly level shader. HLSL's "
-	   "must have a filename extension of .hlsl, otherwise its assumed to be an assembly file.");
-
-   addField("OGLVertexShaderFile",  TypeStringFilename,  Offset(mOGLVertexShaderName,   ShaderData),
-	   "@brief %Path to an OpenGL vertex shader file to use for this ShaderData.\n\n"
-	   "It must contain only one program and no pixel shader, just the vertex shader.");
-
-   addField("OGLPixelShaderFile",   TypeStringFilename,  Offset(mOGLPixelShaderName,  ShaderData),
-	   "@brief %Path to an OpenGL pixel shader file to use for this ShaderData.\n\n"
-	   "It must contain only one program and no vertex shader, just the pixel "
-	   "shader.");
-
-   addField("useDevicePixVersion",  TypeBool,            Offset(mUseDevicePixVersion,   ShaderData),
-	   "@brief If true, the maximum pixel shader version offered by the graphics card will be used.\n\n"
-	   "Otherwise, the script-defined pixel shader version will be used.\n\n");
-
-   addField("pixVersion",           TypeF32,             Offset(mPixVersion,   ShaderData),
-	   "@brief Indicates target level the shader should be compiled.\n\n"
-	   "Valid numbers at the time of this writing are 1.1, 1.4, 2.0, and 3.0. "
-	   "The shader will not run properly if the hardware does not support the "
-	   "level of shader compiled.");
-   
-   addField("defines",              TypeRealString,      Offset(mDefines,   ShaderData), 
-	   "@brief String of case-sensitive defines passed to the shader compiler.\n\n"
+   addField("DXVertexShaderFile", TypeStringFilename, Offset(mDXVertexShaderName, ShaderData),
+      "@brief %Path to the DirectX vertex shader file to use for this ShaderData.\n\n"
+      "It must contain only one program and no pixel shader, just the vertex shader."
+      "It can be either an HLSL or assembly level shader. HLSL's must have a "
+      "filename extension of .hlsl, otherwise its assumed to be an assembly file.");
+
+   addField("DXPixelShaderFile", TypeStringFilename, Offset(mDXPixelShaderName, ShaderData),
+      "@brief %Path to the DirectX pixel shader file to use for this ShaderData.\n\n"
+      "It must contain only one program and no vertex shader, just the pixel "
+      "shader. It can be either an HLSL or assembly level shader. HLSL's "
+      "must have a filename extension of .hlsl, otherwise its assumed to be an assembly file.");
+
+   addField("DXGeometryShaderFile", TypeStringFilename, Offset(mDXGeometryShaderName, ShaderData),
+      "@brief %Path to the DirectX geometry shader file to use for this ShaderData.\n\n"
+      "It can be either an HLSL or assembly level shader. HLSL's must have a "
+      "filename extension of .hlsl, otherwise its assumed to be an assembly file.");
+
+   addField("OGLVertexShaderFile", TypeStringFilename, Offset(mOGLVertexShaderName, ShaderData),
+      "@brief %Path to an OpenGL vertex shader file to use for this ShaderData.\n\n"
+      "It must contain only one program and no pixel shader, just the vertex shader.");
+
+   addField("OGLPixelShaderFile", TypeStringFilename, Offset(mOGLPixelShaderName, ShaderData),
+      "@brief %Path to an OpenGL pixel shader file to use for this ShaderData.\n\n"
+      "It must contain only one program and no vertex shader, just the pixel "
+      "shader.");
+
+   addField("OGLGeometryShaderFile", TypeStringFilename, Offset(mOGLGeometryShaderName, ShaderData),
+      "@brief %Path to the OpenGL Geometry shader file to use for this ShaderData.\n\n");
+
+   addField("useDevicePixVersion", TypeBool, Offset(mUseDevicePixVersion, ShaderData),
+      "@brief If true, the maximum pixel shader version offered by the graphics card will be used.\n\n"
+      "Otherwise, the script-defined pixel shader version will be used.\n\n");
+
+   addField("pixVersion", TypeF32, Offset(mPixVersion, ShaderData),
+      "@brief Indicates target level the shader should be compiled.\n\n"
+      "Valid numbers at the time of this writing are 1.1, 1.4, 2.0, and 3.0. "
+      "The shader will not run properly if the hardware does not support the "
+      "level of shader compiled.");
+
+   addField("defines", TypeRealString, Offset(mDefines, ShaderData),
+      "@brief String of case-sensitive defines passed to the shader compiler.\n\n"
       "The string should be delimited by a semicolon, tab, or newline character."
-      
+
       "@tsexample\n"
-       "singleton ShaderData( FlashShader )\n"
-          "{\n"
-              "DXVertexShaderFile 	= $shaderGen::cachePath @ \"/postFx/flashV.hlsl\";\n"
-              "DXPixelShaderFile 	= $shaderGen::cachePath @ \"/postFx/flashP.hlsl\";\n\n"
-              " //Define setting the color of WHITE_COLOR.\n"
-              "defines = \"WHITE_COLOR=float4(1.0,1.0,1.0,0.0)\";\n\n"
-              "pixVersion = 2.0\n"
-          "}\n"
+      "singleton ShaderData( FlashShader )\n"
+      "{\n"
+      "DXVertexShaderFile 	   = $shaderGen::cachePath @ \"/postFx/flashV.hlsl\";\n"
+      "DXPixelShaderFile 	   = $shaderGen::cachePath @ \"/postFx/flashP.hlsl\";\n\n"
+      "DXGeometryShaderFile   = $shaderGen::cachePath @ \"/postFx/flashG.hlsl\";\n\n"
+      " //Define setting the color of WHITE_COLOR.\n"
+      "defines = \"WHITE_COLOR=float4(1.0,1.0,1.0,0.0)\";\n\n"
+      "pixVersion = 2.0\n"
+      "}\n"
       "@endtsexample\n\n"
-      );
+   );
 
-   addField("samplerNames",              TypeRealString,      Offset(mSamplerNames,   ShaderData), NumTextures, 
+   addField("samplerNames", TypeRealString, Offset(mSamplerNames, ShaderData), NumTextures,
       "@brief Indicates names of samplers present in shader. Order is important.\n\n"
-	   "Order of sampler names are used to assert correct sampler register/location"
+      "Order of sampler names are used to assert correct sampler register/location"
       "Other objects (GFXStateBlockData, PostEffect...) use index number to link samplers."
-      );
+   );
 
-   addField("rtParams",              TypeBool,      Offset(mRTParams,   ShaderData), NumTextures, "");
+   addField("rtParams", TypeBool, Offset(mRTParams, ShaderData), NumTextures, "");
 
    Parent::initPersistFields();
 
    // Make sure we get activation signals.
-   LightManager::smActivateSignal.notify( &ShaderData::_onLMActivate );
+   LightManager::smActivateSignal.notify(&ShaderData::_onLMActivate);
 }
 
 bool ShaderData::onAdd()
@@ -147,8 +166,8 @@ bool ShaderData::onAdd()
 
    for(int i = 0; i < NumTextures; ++i)
    {
-      if( mSamplerNames[i].isNotEmpty() && !mSamplerNames[i].startsWith("$") )      
-         mSamplerNames[i].insert(0, "$");      
+      if( mSamplerNames[i].isNotEmpty() && !mSamplerNames[i].startsWith("$") )
+         mSamplerNames[i].insert(0, "$");
    }
 
    return true;
@@ -164,12 +183,12 @@ void ShaderData::onRemove()
 
 const Vector<GFXShaderMacro>& ShaderData::_getMacros()
 {
-   // If they have already been processed then 
+   // If they have already been processed then
    // return the cached result.
    if ( mShaderMacros.size() != 0 || mDefines.isEmpty() )
       return mShaderMacros;
 
-   mShaderMacros.clear();  
+   mShaderMacros.clear();
    GFXShaderMacro macro;
    const U32 defineCount = StringUnit::getUnitCount( mDefines, ";\n\t" );
    for ( U32 i=0; i < defineCount; i++ )
@@ -195,7 +214,7 @@ GFXShader* ShaderData::getShader( const Vector<GFXShaderMacro> &macros )
 
    // Convert the final macro list to a string.
    String cacheKey;
-   GFXShaderMacro::stringize( macros, &cacheKey );   
+   GFXShaderMacro::stringize( macros, &cacheKey );
 
    // Lookup the shader for this instance.
    ShaderCache::Iterator iter = mShaders.find( cacheKey );
@@ -237,9 +256,13 @@ GFXShader* ShaderData::_createShader( const Vector<GFXShaderMacro> &macros )
    {
       case Direct3D11:
       {
-         success = shader->init( mDXVertexShaderName, 
-                                 mDXPixelShaderName, 
-                                 pixver,
+         if (mDXVertexShaderName != String::EmptyString)
+            shader->setShaderStageFile(GFXShaderStage::VERTEX_SHADER, mDXVertexShaderName);
+         if (mDXPixelShaderName != String::EmptyString)
+            shader->setShaderStageFile(GFXShaderStage::PIXEL_SHADER, mDXPixelShaderName);
+         if (mDXGeometryShaderName != String::EmptyString)
+            shader->setShaderStageFile(GFXShaderStage::GEOMETRY_SHADER, mDXGeometryShaderName);
+         success = shader->init( pixver,
                                  macros,
                                  samplers);
          break;
@@ -247,14 +270,19 @@ GFXShader* ShaderData::_createShader( const Vector<GFXShaderMacro> &macros )
 
       case OpenGL:
       {
-         success = shader->init( mOGLVertexShaderName,
-                                 mOGLPixelShaderName,
-                                 pixver,
+         if(mOGLVertexShaderName != String::EmptyString)
+            shader->setShaderStageFile(GFXShaderStage::VERTEX_SHADER, mOGLVertexShaderName);
+         if (mOGLPixelShaderName != String::EmptyString)
+            shader->setShaderStageFile(GFXShaderStage::PIXEL_SHADER, mOGLPixelShaderName);
+         if (mOGLGeometryShaderName != String::EmptyString)
+            shader->setShaderStageFile(GFXShaderStage::GEOMETRY_SHADER, mOGLGeometryShaderName);
+
+         success = shader->init( pixver,
                                  macros,
                                  samplers);
          break;
       }
-         
+
       default:
          // Other device types are assumed to not support shaders.
          success = false;
@@ -268,7 +296,7 @@ GFXShader* ShaderData::_createShader( const Vector<GFXShaderMacro> &macros )
    {
       if(descs[i].constType != GFXSCT_Sampler && descs[i].constType != GFXSCT_SamplerCube)
          continue;
-      
+
       GFXShaderConstHandle *handle = shader->findShaderConstHandle(descs[i].name);
       if(!handle || !handle->isValid())
          continue;
@@ -321,7 +349,7 @@ void ShaderData::_onLMActivate( const char *lm, bool activate )
 
 bool ShaderData::hasSamplerDef(const String &_samplerName, int &pos) const
 {
-   String samplerName = _samplerName.startsWith("$") ? _samplerName : "$"+_samplerName;   
+   String samplerName = _samplerName.startsWith("$") ? _samplerName : "$"+_samplerName;
    for(int i = 0; i < NumTextures; ++i)
    {
       if( mSamplerNames[i].equal(samplerName, String::NoCase ) )
@@ -342,9 +370,9 @@ bool ShaderData::_checkDefinition(GFXShader *shader)
    samplers.reserve(NumTextures);
    bool rtParams[NumTextures];
    for(int i = 0; i < NumTextures; ++i)
-      rtParams[i] = false;   
+      rtParams[i] = false;
 
-   const Vector<GFXShaderConstDesc> &shaderConstDesc = shader->getShaderConstDesc(); 
+   const Vector<GFXShaderConstDesc> &shaderConstDesc = shader->getShaderConstDesc();
 
    for(int i = 0; i < shaderConstDesc.size(); ++i)
    {
@@ -352,7 +380,7 @@ bool ShaderData::_checkDefinition(GFXShader *shader)
       if(desc.constType == GFXSCT_Sampler)
       {
          samplers.push_back(desc.name );
-      }      
+      }
    }
 
    for(int i = 0; i < samplers.size(); ++i)
@@ -361,14 +389,14 @@ bool ShaderData::_checkDefinition(GFXShader *shader)
       bool find = hasSamplerDef(samplers[i], pos);
 
       if(find && pos >= 0 && mRTParams[pos])
-      {              
+      {
          if( !shader->findShaderConstHandle( String::ToString("$rtParams%d", pos)) )
          {
             String errStr = String::ToString("ShaderData(%s) sampler[%d] used but rtParams%d not used in shader compilation. Possible error", shader->getPixelShaderFile().c_str(), pos, pos);
             Con::errorf(errStr);
             error = true;
          }
-      }     
+      }
 
       if(!find)
       {
@@ -377,7 +405,7 @@ bool ShaderData::_checkDefinition(GFXShader *shader)
          GFXAssertFatal(0, errStr);
          error = true;
       }
-   }  
+   }
 
    return !error;
 }

+ 15 - 15
Engine/source/materials/shaderData.h

@@ -47,7 +47,7 @@ protected:
    ///
    static Vector<ShaderData*> smAllShaderData;
 
-   typedef HashTable<String,GFXShaderRef> ShaderCache;
+   typedef HashTable<String, GFXShaderRef> ShaderCache;
 
    ShaderCache mShaders;
 
@@ -56,12 +56,12 @@ protected:
    F32 mPixVersion;
 
    StringTableEntry mDXVertexShaderName;
-
    StringTableEntry mDXPixelShaderName;
+   StringTableEntry mDXGeometryShaderName;
 
    StringTableEntry mOGLVertexShaderName;
-
    StringTableEntry mOGLPixelShaderName;
+   StringTableEntry mOGLGeometryShaderName;
 
    /// A semicolon, tab, or newline delimited string of case
    /// sensitive defines that are passed to the shader compiler.
@@ -80,40 +80,40 @@ protected:
    /// them if the content has changed.
    const Vector<GFXShaderMacro>& _getMacros();
 
-   /// Helper for converting an array of macros 
+   /// Helper for converting an array of macros
    /// into a formatted string.
-   void _stringizeMacros(  const Vector<GFXShaderMacro> &macros, 
-                           String *outString );
+   void _stringizeMacros(const Vector<GFXShaderMacro>& macros,
+      String* outString);
 
    /// Creates a new shader returning NULL on error.
-   GFXShader* _createShader( const Vector<GFXShaderMacro> &macros );
+   GFXShader* _createShader(const Vector<GFXShaderMacro>& macros);
 
    /// @see LightManager::smActivateSignal
-   static void _onLMActivate( const char *lm, bool activate );
+   static void _onLMActivate(const char* lm, bool activate);
 
    enum
    {
       NumTextures = 16
    };
 
-   String mSamplerNames[NumTextures]; 
+   String mSamplerNames[NumTextures];
    bool mRTParams[NumTextures];
 
-   bool _checkDefinition(GFXShader *shader);   
+   bool _checkDefinition(GFXShader* shader);
 
 public:
 
-   void setSamplerName(const String &name, int idx) { mSamplerNames[idx] = name; }
+   void setSamplerName(const String& name, int idx) { mSamplerNames[idx] = name; }
    String getSamplerName(int idx) const { return mSamplerNames[idx]; }
 
-   bool hasSamplerDef(const String &samplerName, int &pos) const;
+   bool hasSamplerDef(const String& samplerName, int& pos) const;
    bool hasRTParamsDef(const int pos) const { return mRTParams[pos]; }
 
    ShaderData();
 
-   /// Returns an initialized shader instance or NULL 
+   /// Returns an initialized shader instance or NULL
    /// if the shader failed to be created.
-   GFXShader* getShader( const Vector<GFXShaderMacro> &macros = Vector<GFXShaderMacro>() );
+   GFXShader* getShader(const Vector<GFXShaderMacro>& macros = Vector<GFXShaderMacro>());
 
    /// Forces a reinitialization of all the instanced shaders.
    void reloadShaders();
@@ -124,7 +124,7 @@ public:
 
    /// Returns the required pixel shader version for this shader.
    F32 getPixVersion() const { return mPixVersion; }
-   
+
    // SimObject
    virtual bool onAdd();
    virtual void onRemove();

+ 14 - 14
Engine/source/platformWin32/winPlatformCPUCount.cpp

@@ -1,19 +1,19 @@
 // Original code is:
-// Copyright (c) 2005 Intel Corporation 
+// Copyright (c) 2005 Intel Corporation
 // All Rights Reserved
 //
 // CPUCount.cpp : Detects three forms of hardware multi-threading support across IA-32 platform
-//					The three forms of HW multithreading are: Multi-processor, Multi-core, and 
+//					The three forms of HW multithreading are: Multi-processor, Multi-core, and
 //					HyperThreading Technology.
 //					This application enumerates all the logical processors enabled by OS and BIOS,
-//					determine the HW topology of these enabled logical processors in the system 
+//					determine the HW topology of these enabled logical processors in the system
 //					using information provided by CPUID instruction.
 //					A multi-processing system can support any combination of the three forms of HW
-//					multi-threading support. The relevant topology can be identified using a 
-//					three level decomposition of the "initial APIC ID" into 
-//					Package_id, core_id, and SMT_id. Such decomposition provides a three-level map of 
+//					multi-threading support. The relevant topology can be identified using a
+//					three level decomposition of the "initial APIC ID" into
+//					Package_id, core_id, and SMT_id. Such decomposition provides a three-level map of
 //					the topology of hardware resources and
-//					allow multi-threaded software to manage shared hardware resources in 
+//					allow multi-threaded software to manage shared hardware resources in
 //					the platform to reduce resource contention
 
 //					Multicore detection algorithm for processor and cache topology requires
@@ -60,25 +60,25 @@ namespace CPUInfo {
 
       PSYSTEM_LOGICAL_PROCESSOR_INFORMATION buffer = NULL;
       DWORD returnLength = 0;
-      
+
       // get buffer length
       DWORD rc = GetLogicalProcessorInformation( buffer, &returnLength );
       buffer = (PSYSTEM_LOGICAL_PROCESSOR_INFORMATION)malloc( returnLength );
 
-      rc = GetLogicalProcessorInformation( buffer, &returnLength );      
+      rc = GetLogicalProcessorInformation( buffer, &returnLength );
 
       // if we fail, assume single threaded
       if( FALSE == rc )
-      {           
+      {
          free( buffer );
          Con::errorf("Unable to determine CPU Count, assuming 1 core");
          TotAvailCore = 1;
          TotAvailLogical = 1;
          return CONFIG_SingleCoreAndHTNotCapable;
-      }      
+      }
 
-#pragma push
-#pragma warning (disable: 6011)
+#pragma warning( push )
+#pragma warning( disable: 6011 )
       PSYSTEM_LOGICAL_PROCESSOR_INFORMATION ptr = buffer;
 
       DWORD byteOffset = 0;
@@ -95,7 +95,7 @@ namespace CPUInfo {
       }
 
       free( buffer );
-#pragma pop
+#pragma warning( pop )
 
       EConfig StatusFlag = CONFIG_SingleCoreAndHTNotCapable;
 

+ 3 - 3
Engine/source/scene/sceneQueryUtil.h

@@ -5,7 +5,7 @@
 /// allows it to return the appropriate geometry.
 enum PolyListContext
 {
-   /// A hint that the polyist is intended 
+   /// A hint that the polyist is intended
    /// for collision testing.
    PLC_Collision,
 
@@ -24,7 +24,7 @@ enum PolyListContext
 
    /// A hint that the polyist will be used
    /// to export geometry and would like to have
-   /// texture coords and materials.   
+   /// texture coords and materials.
    PLC_Export
 };
 
@@ -71,7 +71,7 @@ struct SceneBinRange
    inline bool isGlobal() const
    {
       return minCoord[0] == 0 &&
-         minCoord[0] == 0 &&
+         minCoord[1] == 0 &&
          maxCoord[0] == 0xFFFF &&
          maxCoord[1] == 0xFFFF;
    }

+ 9 - 9
Engine/source/shaderGen/HLSL/debugVizFeatureHLSL.cpp

@@ -122,13 +122,13 @@ void DebugVizHLSL::processPix(Vector<ShaderComponent*>& componentList,
       if (fd.features[MFT_LightMap] || fd.features[MFT_ToneMap] || fd.features[MFT_VertLit])
          return;
 
-      MultiLine* meta = new MultiLine;
+      MultiLine* newMeta = new MultiLine;
 
       // Now the wsPosition and wsView.
       Var* worldToTangent = getInWorldToTangent(componentList);
       Var* wsNormal = getInWorldNormal(componentList);
       Var* wsPosition = getInWsPosition(componentList);
-      Var* wsView = getWsView(wsPosition, meta);
+      Var* wsView = getWsView(wsPosition, newMeta);
 
       //Reflection Probe WIP
       U32 MAX_FORWARD_PROBES = 4;
@@ -153,32 +153,32 @@ void DebugVizHLSL::processPix(Vector<ShaderComponent*>& componentList,
       Var* showAttenVar = new Var("showAttenVar", "int");
       char buf[64];
       dSprintf(buf, sizeof(buf), "   @ = %s;\r\n", showAtten);
-      meta->addStatement(new GenOp(buf, new DecOp(showAttenVar)));
+      newMeta->addStatement(new GenOp(buf, new DecOp(showAttenVar)));
 
       Var* showContribVar = new Var("showContribVar", "int");
       dSprintf(buf, sizeof(buf), "   @ = %s;\r\n", showContrib);
-      meta->addStatement(new GenOp(buf, new DecOp(showContribVar)));
+      newMeta->addStatement(new GenOp(buf, new DecOp(showContribVar)));
 
       Var* showSpecVar = new Var("showSpecVar", "int");
       dSprintf(buf, sizeof(buf), "   @ = %s;\r\n", showSpec);
-      meta->addStatement(new GenOp(buf, new DecOp(showSpecVar)));
+      newMeta->addStatement(new GenOp(buf, new DecOp(showSpecVar)));
 
       Var* showDiffVar = new Var("showDiffVar", "int");
       dSprintf(buf, sizeof(buf), "   @ = %s;\r\n", showDiff);
-      meta->addStatement(new GenOp(buf, new DecOp(showDiffVar)));
+      newMeta->addStatement(new GenOp(buf, new DecOp(showDiffVar)));
 
       String computeForwardProbes = String("   @ = debugVizForwardProbes(@,@,@,@,@,@,@,@,\r\n\t\t");
       computeForwardProbes += String("@,TORQUE_SAMPLER2D_MAKEARG(@),\r\n\t\t");
       computeForwardProbes += String("TORQUE_SAMPLERCUBEARRAY_MAKEARG(@),TORQUE_SAMPLERCUBEARRAY_MAKEARG(@), @, @, @, @).rgb; \r\n");
 
-      meta->addStatement(new GenOp(computeForwardProbes.c_str(), ibl, surface, cubeMips, numProbes, worldToObjArray, probeConfigData, inProbePosArray, refScaleArray, inRefPosArray,
+      newMeta->addStatement(new GenOp(computeForwardProbes.c_str(), ibl, surface, cubeMips, numProbes, worldToObjArray, probeConfigData, inProbePosArray, refScaleArray, inRefPosArray,
          skylightCubemapIdx, BRDFTexture,
          irradianceCubemapAR, specularCubemapAR,
          showAttenVar, showContribVar, showSpecVar, showDiffVar));
 
-      meta->addStatement(new GenOp("   @.rgb = @.rgb;\r\n", color, ibl));
+      newMeta->addStatement(new GenOp("   @.rgb = @.rgb;\r\n", color, ibl));
 
-      output = meta;
+      output = newMeta;
       return;
    }
 }

+ 22 - 19
Engine/source/shaderGen/shaderGen.cpp

@@ -47,7 +47,7 @@ MODULE_BEGIN( ShaderGen )
    {
       ManagedSingleton< ShaderGen >::createSingleton();
    }
-   
+
    MODULE_SHUTDOWN
    {
       ManagedSingleton< ShaderGen >::deleteSingleton();
@@ -94,7 +94,7 @@ bool ShaderGen::_handleGFXEvent(GFXDevice::GFXDeviceEventType event)
 }
 
 void ShaderGen::initShaderGen()
-{   
+{
    if (mInit)
       return;
 
@@ -125,7 +125,7 @@ void ShaderGen::initShaderGen()
    {
       // If we didn't get a path then we're gonna cache the shaders to
       // a virtualized memory file system.
-      mMemFS = new Torque::Mem::MemFileSystem( "shadergen:/" ); 
+      mMemFS = new Torque::Mem::MemFileSystem( "shadergen:/" );
       Torque::FS::Mount( "shadergen", mMemFS );
    }
    else
@@ -136,8 +136,8 @@ void ShaderGen::initShaderGen()
 }
 
 void ShaderGen::generateShader( const MaterialFeatureData &featureData,
-                                char *vertFile, 
-                                char *pixFile, 
+                                char *vertFile,
+                                char *pixFile,
                                 F32 *pixVersion,
                                 const GFXVertexFormat *vertexFormat,
                                 const char* cacheName,
@@ -155,23 +155,23 @@ void ShaderGen::generateShader( const MaterialFeatureData &featureData,
    char pixShaderName[256];
 
    // Note:  We use a postfix of _V/_P here so that it sorts the matching
-   // vert and pixel shaders together when listed alphabetically.   
+   // vert and pixel shaders together when listed alphabetically.
    dSprintf( vertShaderName, sizeof(vertShaderName), "shadergen:/%s_V.%s", cacheName, mFileEnding.c_str() );
    dSprintf( pixShaderName, sizeof(pixShaderName), "shadergen:/%s_P.%s", cacheName, mFileEnding.c_str() );
-   
+
    dStrcpy( vertFile, vertShaderName, 256 );
    dStrcpy( pixFile, pixShaderName, 256 );
-   
+
    // this needs to change - need to optimize down to ps v.1.1
    *pixVersion = GFX->getPixelShaderVersion();
-   
+
    if ( !Con::getBoolVariable( "ShaderGen::GenNewShaders", true ) )
    {
       // If we are not regenerating the shader we will return here.
       // But we must fill in the shader macros first!
 
       _processVertFeatures( macros, true );
-      _processPixFeatures( macros, true );      
+      _processPixFeatures( macros, true );
 
       return;
    }
@@ -190,7 +190,7 @@ void ShaderGen::generateShader( const MaterialFeatureData &featureData,
    _processVertFeatures(macros);
    _printVertShader( *s );
    delete s;
-   
+
    ((ShaderConnector*)mComponents[C_CONNECTOR])->reset();
    LangElement::deleteElements();
 
@@ -202,7 +202,7 @@ void ShaderGen::generateShader( const MaterialFeatureData &featureData,
       AssertFatal(false, "Failed to open Shader Stream" );
       delete s;
       return;
-   }   
+   }
 
    mOutput = new MultiLine;
    _processPixFeatures(macros);
@@ -284,7 +284,7 @@ void ShaderGen::_processVertFeatures( Vector<GFXShaderMacro> &macros, bool macro
             mOutput->addStatement( feature->getOutput() );
 
          feature->reset();
-         mOutput->addStatement( new GenOp( "   \r\n" ) );         
+         mOutput->addStatement( new GenOp( "   \r\n" ) );
       }
    }
 
@@ -327,7 +327,7 @@ void ShaderGen::_processPixFeatures( Vector<GFXShaderMacro> &macros, bool macros
          mOutput->addStatement( new GenOp( "   \r\n" ) );
       }
    }
-   
+
    ShaderConnector *connect = dynamic_cast<ShaderConnector *>( mComponents[C_CONNECTOR] );
    connect->sortVars();
 }
@@ -335,7 +335,7 @@ void ShaderGen::_processPixFeatures( Vector<GFXShaderMacro> &macros, bool macros
 void ShaderGen::_printFeatureList(Stream &stream)
 {
    mPrinter->printLine(stream, "// Features:");
-      
+
    const FeatureSet &features = mFeatureData.features;
 
    for( U32 i=0; i < features.getCount(); i++ )
@@ -376,7 +376,7 @@ void ShaderGen::_printDependencies(Stream &stream)
 
       for( U32 j=0; j < dependencies.size(); j++ )
       {
-         if (  j != i && 
+         if (  j != i &&
                *dependencies[i] == *dependencies[j] )
          {
             dup = true;
@@ -386,7 +386,7 @@ void ShaderGen::_printDependencies(Stream &stream)
 
       if ( dup )
          dependencies.erase( i );
-      else        
+      else
          i++;
    }
 
@@ -493,7 +493,10 @@ GFXShader* ShaderGen::getShader( const MaterialFeatureData &featureData, const G
    generateShader( featureData, vertFile, pixFile, &pixVersion, vertexFormat, cacheKey, shaderMacros );
 
    GFXShader *shader = GFX->createShader();
-   if (!shader->init(vertFile, pixFile, pixVersion, shaderMacros, samplers, &mInstancingFormat))
+   shader->setShaderStageFile(GFXShaderStage::VERTEX_SHADER, vertFile);
+   shader->setShaderStageFile(GFXShaderStage::PIXEL_SHADER, pixFile);
+
+   if (!shader->init(pixVersion, shaderMacros, samplers, &mInstancingFormat))
    {
       delete shader;
       return NULL;
@@ -508,5 +511,5 @@ void ShaderGen::flushProceduralShaders()
 {
    // The shaders are reference counted, so we
    // just need to clear the map.
-   mProcShaders.clear();  
+   mProcShaders.clear();
 }

+ 38 - 0
Templates/BaseGame/game/core/rendering/scripts/gfxData/shaders.tscript

@@ -149,4 +149,42 @@ singleton ShaderData( CubemapSaveShader )
    samplerNames[0] = "$cubemapTex";
 	
    pixVersion = 3.0;
+};
+
+//-----------------------------------------------------------------------------
+// GUI shaders
+//-----------------------------------------------------------------------------
+singleton ShaderData( RoundedRectangleGUI )
+{
+   DXVertexShaderFile   = $Core::CommonShaderPath @ "/fixedFunction/colorV.hlsl";
+   DXPixelShaderFile    = $Core::CommonShaderPath @ "/fixedFunction/roundedRectangleP.hlsl";
+
+   OGLVertexShaderFile  = $Core::CommonShaderPath @ "/fixedFunction/gl/colorV.glsl";
+   OGLPixelShaderFile   = $Core::CommonShaderPath @ "/fixedFunction/gl/roundedRectangleP.glsl";
+      
+   pixVersion = 3.0;   
+};
+
+singleton ShaderData( CircularGUI )
+{
+   DXVertexShaderFile   = $Core::CommonShaderPath @ "/fixedFunction/colorV.hlsl";
+   DXPixelShaderFile    = $Core::CommonShaderPath @ "/fixedFunction/circleP.hlsl";
+
+   OGLVertexShaderFile  = $Core::CommonShaderPath @ "/fixedFunction/gl/colorV.glsl";
+   OGLPixelShaderFile   = $Core::CommonShaderPath @ "/fixedFunction/gl/circleP.glsl";
+      
+   pixVersion = 3.0;   
+};
+
+singleton ShaderData( ThickLineGUI )
+{
+   DXVertexShaderFile   = $Core::CommonShaderPath @ "/fixedFunction/colorV.hlsl";
+   DXGeometryShaderFile = $Core::CommonShaderPath @ "/fixedFunction/thickLineG.hlsl";
+   DXPixelShaderFile    = $Core::CommonShaderPath @ "/fixedFunction/thickLineP.hlsl";
+
+   OGLVertexShaderFile   = $Core::CommonShaderPath @ "/fixedFunction/gl/colorV.glsl";
+   OGLGeometryShaderFile = $Core::CommonShaderPath @ "/fixedFunction/gl/thickLineG.glsl";
+   OGLPixelShaderFile    = $Core::CommonShaderPath @ "/fixedFunction/gl/thickLineP.glsl";
+      
+   pixVersion = 3.0;   
 };

+ 66 - 0
Templates/BaseGame/game/core/rendering/shaders/fixedFunction/circleP.hlsl

@@ -0,0 +1,66 @@
+//-----------------------------------------------------------------------------
+// Copyright (c) 2012 GarageGames, LLC
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to
+// deal in the Software without restriction, including without limitation the
+// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+// sell copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+// IN THE SOFTWARE.
+//-----------------------------------------------------------------------------
+
+#include "../shaderModel.hlsl"
+
+struct Conn
+{
+   float4 HPOS             : TORQUE_POSITION;
+   float4 color            : COLOR;
+};
+
+uniform float2 sizeUni;
+uniform float radius;
+uniform float2 rectCenter;
+uniform float borderSize;
+uniform float4 borderCol;
+
+float circle(float2 p, float2 center, float r)
+{
+    return length(p - center);
+}
+ 
+float4 main(Conn IN) : TORQUE_TARGET0
+{   
+    float distance = circle(IN.HPOS.xy, rectCenter, radius);
+    
+    float4 fromColor = borderCol;
+    float4 toColor = float4(0.0, 0.0, 0.0, 0.0);
+
+    if(distance < radius)
+    {
+        distance = abs(distance) - radius;
+        
+        if(distance < (radius - (borderSize)))
+        {
+            toColor = IN.color;
+            distance = abs(distance) - (borderSize);
+        }
+
+        float blend = smoothstep(0.0, 1.0, distance);
+        return lerp(fromColor, toColor, blend);
+    }
+    
+    distance = abs(distance) - radius; 
+    float blend = smoothstep(0.0, 1.0, distance);
+    return lerp(fromColor, toColor, blend);
+}

+ 62 - 0
Templates/BaseGame/game/core/rendering/shaders/fixedFunction/gl/circleP.glsl

@@ -0,0 +1,62 @@
+//-----------------------------------------------------------------------------
+// Copyright (c) 2012 GarageGames, LLC
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to
+// deal in the Software without restriction, including without limitation the
+// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+// sell copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+// IN THE SOFTWARE.
+//-----------------------------------------------------------------------------
+
+in vec4 color;
+
+out vec4 OUT_col;
+
+uniform vec2 sizeUni;
+uniform float radius;
+uniform vec2 rectCenter;
+uniform float borderSize;
+uniform vec4 borderCol;
+
+float circle(vec2 p, vec2 center, float r)
+{
+    return length(p - center);
+}
+ 
+void main()
+{   
+    float dist = circle(gl_FragCoord.xy, rectCenter, radius);
+    
+    vec4 fromColor = borderCol;
+    vec4 toColor = vec4(0.0, 0.0, 0.0, 0.0);
+
+    if(dist < radius)
+    {
+        dist = abs(dist) - radius;
+        
+        if(dist < (radius - (borderSize)))
+        {
+            toColor = color;
+            dist = abs(dist) - (borderSize);
+        }
+
+        float blend = smoothstep(0.0, 1.0, dist);
+        OUT_col = mix(fromColor, toColor, blend);
+    }
+    
+    dist = abs(dist) - radius; 
+    float blend = smoothstep(0.0, 1.0, dist);
+    OUT_col = mix(fromColor, toColor, blend);
+}

+ 98 - 0
Templates/BaseGame/game/core/rendering/shaders/fixedFunction/gl/roundedRectangleP.glsl

@@ -0,0 +1,98 @@
+//-----------------------------------------------------------------------------
+// Copyright (c) 2012 GarageGames, LLC
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to
+// deal in the Software without restriction, including without limitation the
+// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+// sell copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+// IN THE SOFTWARE.
+//-----------------------------------------------------------------------------
+in vec4 color;
+
+out vec4 OUT_col;
+
+uniform vec2 sizeUni;
+uniform vec2 rectCenter;
+uniform vec2 oneOverViewport;
+uniform float radius;
+uniform float borderSize;
+uniform vec4 borderCol;
+
+float RoundedRectSDF(vec2 p, vec2 size, float radius)
+{
+    // Calculate distance to each side of the rectangle
+    vec2 dist = abs(p) - size + vec2(radius, radius);
+
+    // Compute the distance to the rounded corners
+    float cornerDist = length(max(dist, 0.0));
+
+    // Return the minimum distance (negative inside, positive outside)
+    return min(max(dist.x, dist.y), 0.0) + cornerDist - radius; 
+}
+ 
+void main()
+{  
+    vec2 p = gl_FragCoord.xy;
+    
+    float halfBorder = borderSize * 0.5; 
+    vec2 halfSize = sizeUni * 0.5;
+    p -= rectCenter; 
+
+    // Calculate signed distance field for rounded rectangle 
+    vec4 fromColor = borderCol;
+    // alpha
+    vec4 toColor = vec4(0.0, 0.0, 0.0, 0.0);
+
+    float cornerRadius = radius;
+
+    // if ((p.y < 0.0 && p.x < 0.0) || // top left corner
+    //     (p.y < 0.0 && p.x > 0.0) || // top right corner
+    //     (p.y > 0.0 && p.x > 0.0) || // bottom right corner.  
+    //     (p.y > 0.0 && p.x < 0.0))  // bottom left corner
+    // {
+    //     cornerRadius = radius;   
+    // } 
+
+    if(cornerRadius > 0.0 || halfBorder > 0.0)
+    {
+        float sdf = RoundedRectSDF(p, halfSize, cornerRadius - halfBorder);
+
+        if(halfBorder > 0.0)
+        {
+            if(sdf < 0.0)
+            {
+                // if ((p.y >= -halfSize.y - radius + halfBorder && p.y <= -halfSize.y + radius - halfBorder)  ||  // top border
+                //     (p.y >= halfSize.y - radius + halfBorder && p.y <= halfSize.y + radius - halfBorder)    ||  // bottom border
+                //     (p.x >= -halfSize.x - radius + halfBorder && p.x <= -halfSize.x + radius - halfBorder)  ||  // left border
+                //     (p.x >= halfSize.x - radius + halfBorder && p.x <= halfSize.x + radius - halfBorder) ) {    // right border
+                    
+                // }
+                toColor = color;
+                sdf = abs(sdf) / borderSize;
+            } 
+            
+        } 
+        else{
+            fromColor = color; 
+        }  
+
+        float alpha = smoothstep(-1.0, 1.0, sdf); 
+        OUT_col = mix(fromColor, toColor, alpha);
+    }
+    else
+    {
+        OUT_col = color;
+    }
+}

+ 67 - 0
Templates/BaseGame/game/core/rendering/shaders/fixedFunction/gl/thickLineG.glsl

@@ -0,0 +1,67 @@
+//-----------------------------------------------------------------------------
+// Copyright (c) 2012 GarageGames, LLC
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to
+// deal in the Software without restriction, including without limitation the
+// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+// sell copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+// IN THE SOFTWARE.
+//-----------------------------------------------------------------------------
+
+layout (lines) in; 
+layout (triangle_strip, max_vertices = 4) out;
+
+in VS_OUT {
+    vec4 color;
+} gs_in[];
+
+
+out vec4 fragColor;
+
+uniform float thickness;
+uniform vec2 oneOverViewport;
+
+void main()
+{
+    // Calculate the direction of the line segment
+    vec2 direction = normalize(gl_in[1].gl_Position.xy - gl_in[0].gl_Position.xy);
+
+    // Calculate perpendicular direction
+    vec2 perpendicular = normalize(vec2(-direction.y, direction.x));
+
+    // Calculate offset for thickness 
+    vec2 offset = vec2(thickness * oneOverViewport.x, thickness *  oneOverViewport.y) * perpendicular;
+ 
+    // Calculate vertices for the line with thickness
+    vec2 p0 = gl_in[0].gl_Position.xy + offset;
+    vec2 p1 = gl_in[0].gl_Position.xy - offset;
+    vec2 p2 = gl_in[1].gl_Position.xy + offset;
+    vec2 p3 = gl_in[1].gl_Position.xy - offset;
+
+    fragColor = gs_in[0].color;
+    gl_Position = vec4(p0, 0.0f, 1.0f);
+    EmitVertex();
+
+    gl_Position = vec4(p1, 0.0f, 1.0f);
+    EmitVertex();
+
+    gl_Position = vec4(p2, 0.0f, 1.0f);
+    EmitVertex();
+
+    gl_Position = vec4(p3, 0.0f, 1.0f);
+    EmitVertex();
+
+    EndPrimitive();
+}

+ 30 - 0
Templates/BaseGame/game/core/rendering/shaders/fixedFunction/gl/thickLineP.glsl

@@ -0,0 +1,30 @@
+//-----------------------------------------------------------------------------
+// Copyright (c) 2012 GarageGames, LLC
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to
+// deal in the Software without restriction, including without limitation the
+// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+// sell copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+// IN THE SOFTWARE.
+//-----------------------------------------------------------------------------
+
+in vec4 fragColor;
+
+out vec4 OUT_col;
+
+void main()
+{
+   OUT_col = fragColor;
+}

+ 103 - 0
Templates/BaseGame/game/core/rendering/shaders/fixedFunction/roundedRectangleP.hlsl

@@ -0,0 +1,103 @@
+//-----------------------------------------------------------------------------
+// Copyright (c) 2012 GarageGames, LLC
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to
+// deal in the Software without restriction, including without limitation the
+// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+// sell copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+// IN THE SOFTWARE.
+//-----------------------------------------------------------------------------
+
+#include "../shaderModel.hlsl"
+
+struct Conn
+{
+   float4 HPOS             : TORQUE_POSITION;
+   float4 color            : COLOR;
+};
+
+uniform float2 sizeUni;
+uniform float2 rectCenter;
+uniform float2 oneOverViewport;
+uniform float radius;
+uniform float borderSize;
+uniform float4 borderCol;
+
+float RoundedRectSDF(float2 p, float2 size, float radius)
+{
+    // Calculate distance to each side of the rectangle
+    float2 dist = abs(p) - size + float2(radius, radius);
+
+    // Compute the distance to the rounded corners
+    float cornerDist = length(max(dist, 0.0));
+
+    // Return the minimum distance (negative inside, positive outside)
+    return min(max(dist.x, dist.y), 0.0) + cornerDist - radius; 
+}
+ 
+float4 main(Conn IN) : TORQUE_TARGET0
+{  
+    float2 p = IN.HPOS.xy;
+    
+    float halfBorder = borderSize * 0.5; 
+    float2 halfSize = sizeUni * 0.5;
+    p -= rectCenter; 
+
+    // Calculate signed distance field for rounded rectangle 
+    float4 fromColor = borderCol;
+    // alpha
+    float4 toColor = float4(0.0, 0.0, 0.0, 0.0);
+
+    float cornerRadius = radius;
+
+    // if ((p.y < 0.0 && p.x < 0.0) || // top left corner
+    //     (p.y < 0.0 && p.x > 0.0) || // top right corner
+    //     (p.y > 0.0 && p.x > 0.0) || // bottom right corner.  
+    //     (p.y > 0.0 && p.x < 0.0))  // bottom left corner
+    // {
+    //     cornerRadius = radius;   
+    // } 
+
+    if(cornerRadius > 0.0 || halfBorder > 0.0)
+    {
+        float sdf = RoundedRectSDF(p, halfSize, cornerRadius - halfBorder);
+
+        if(halfBorder > 0.0)
+        {
+            if(sdf < 0.0)
+            {
+                // if ((p.y >= -halfSize.y - radius + halfBorder && p.y <= -halfSize.y + radius - halfBorder)  ||  // top border
+                //     (p.y >= halfSize.y - radius + halfBorder && p.y <= halfSize.y + radius - halfBorder)    ||  // bottom border
+                //     (p.x >= -halfSize.x - radius + halfBorder && p.x <= -halfSize.x + radius - halfBorder)  ||  // left border
+                //     (p.x >= halfSize.x - radius + halfBorder && p.x <= halfSize.x + radius - halfBorder) ) {    // right border
+                    
+                // }
+                toColor = IN.color;
+                sdf = abs(sdf) / borderSize;
+            } 
+            
+        } 
+        else{
+            fromColor = IN.color; 
+        }  
+
+        float alpha = smoothstep(-1.0, 1.0, sdf); 
+        return lerp(fromColor, toColor, alpha);
+    }
+    else
+    {
+        return IN.color;
+    }
+}

+ 77 - 0
Templates/BaseGame/game/core/rendering/shaders/fixedFunction/thickLineG.hlsl

@@ -0,0 +1,77 @@
+//-----------------------------------------------------------------------------
+// Copyright (c) 2012 GarageGames, LLC
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to
+// deal in the Software without restriction, including without limitation the
+// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+// sell copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+// IN THE SOFTWARE.
+//-----------------------------------------------------------------------------
+
+#include "../shaderModel.hlsl"
+
+struct Conn
+{
+   float4 HPOS             : TORQUE_POSITION;
+   float4 color            : COLOR;
+};
+
+struct PSConn
+{
+   float4 HPOS             : TORQUE_POSITION;
+   float4 color            : COLOR;
+};
+
+uniform float thickness;
+uniform float2 oneOverViewport;
+
+[maxvertexcount(4)]
+void main(line Conn lineSegment[2], inout TriangleStream<PSConn> outstream)
+{
+    // Calculate the direction of the line segment
+    float2 direction = normalize(lineSegment[1].HPOS.xy - lineSegment[0].HPOS.xy);
+
+    // Calculate perpendicular direction
+    float2 perpendicular = normalize(float2(-direction.y, direction.x));
+
+    // Calculate offset for thickness 
+    float2 offset = float2(thickness * oneOverViewport.x, thickness *  oneOverViewport.y) * perpendicular;
+ 
+    // Calculate vertices for the line with thickness
+    float2 p0 = lineSegment[0].HPOS.xy + offset;
+    float2 p1 = lineSegment[0].HPOS.xy - offset;
+    float2 p2 = lineSegment[1].HPOS.xy + offset;
+    float2 p3 = lineSegment[1].HPOS.xy - offset;
+
+    PSConn output;
+
+    output.HPOS = float4(p0, 0.0f, 1.0f);
+    output.color = lineSegment[0].color;
+    outstream.Append(output);
+
+    output.HPOS = float4(p1, 0.0f, 1.0f);
+    output.color = lineSegment[0].color;
+    outstream.Append(output);
+
+    output.HPOS = float4(p2, 0.0f, 1.0f);
+    output.color = lineSegment[1].color;
+    outstream.Append(output);
+
+    output.HPOS = float4(p3, 0.0f, 1.0f);
+    output.color = lineSegment[1].color;
+    outstream.Append(output);
+
+    outstream.RestartStrip();
+}

+ 34 - 0
Templates/BaseGame/game/core/rendering/shaders/fixedFunction/thickLineP.hlsl

@@ -0,0 +1,34 @@
+//-----------------------------------------------------------------------------
+// Copyright (c) 2012 GarageGames, LLC
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to
+// deal in the Software without restriction, including without limitation the
+// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+// sell copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+// IN THE SOFTWARE.
+//-----------------------------------------------------------------------------
+
+#include "../shaderModel.hlsl"
+
+struct PSConn
+{
+   float4 HPOS             : TORQUE_POSITION;
+   float4 color            : COLOR;
+};
+
+float4 main(PSConn IN) : TORQUE_TARGET0
+{
+   return IN.color;
+}

+ 10 - 0
Templates/BaseGame/game/tools/gui/profiles.ed.tscript

@@ -943,6 +943,16 @@ singleton GuiControlProfile( GuiBackFillProfile )
    category = "Editor";
 };
 
+singleton GuiControlProfile(GuiShaderEditorProfile : ToolsGuiDefaultProfile)
+{
+   opaque = true;
+   canKeyFocus = true;
+   border = true;
+   borderColor = "128 128 128 128";
+   borderColorHL = "128 128 0";
+   borderColorSEL = "128 0 128 128";
+};
+
 singleton GuiControlProfile( GuiControlListPopupProfile )
 {
    opaque = true;

+ 7 - 0
Templates/BaseGame/game/tools/shaderEditor/gui/shaderEditorGui.asset.taml

@@ -0,0 +1,7 @@
+<GUIAsset
+    canSave="true"
+    canSaveDynamicFields="true"
+    AssetName="ShaderEditorGui, EditorGuiGroup"
+    scriptFile="@assetFile=shaderEditorGui.ed.gui"
+    GUIFile="@assetFile=shaderEditorGui.ed.gui"
+    VersionId="1"/>

+ 122 - 0
Templates/BaseGame/game/tools/shaderEditor/gui/shaderEditorGui.ed.gui

@@ -0,0 +1,122 @@
+//--- OBJECT WRITE BEGIN ---
+$guiContent = new GuiControl(ShaderEditorGui) {
+   extent = "1280 720";
+   profile = "GuiDefaultProfile";
+   tooltipProfile = "ToolsGuiToolTipProfile";
+   isContainer = "1";
+   canSaveDynamicFields = "1";
+
+   new GuiFrameSetCtrl() {
+      columns = "0 320 1000";
+      borderWidth = "2";
+      borderColor = "10 10 10 0";
+      autoBalance = "1";
+      extent = "1280 720";
+      horizSizing = "width";
+      vertSizing = "height";
+      profile = "ToolsGuiFrameSetProfile";
+      tooltipProfile = "ToolsGuiToolTipProfile";
+
+      new GuiControl() {
+         extent = "318 720";
+         horizSizing = "width";
+         vertSizing = "height";
+         profile = "ToolsGuiDefaultProfile";
+         tooltipProfile = "ToolsGuiToolTipProfile";
+         isContainer = "1";
+
+         new GuiSplitContainer() {
+            orientation = "Horizontal";
+            splitPoint = "0 200";
+            extent = "317 720";
+            horizSizing = "width";
+            vertSizing = "height";
+            profile = "ToolsGuiDefaultProfile";
+            tooltipProfile = "ToolsGuiToolTipProfile";
+
+            new GuiPanel(ShaderEditorPreview) {
+               docking = "Client";
+               extent = "317 198";
+               profile = "ToolsGuiButtonProfile";
+               tooltipProfile = "ToolsGuiToolTipProfile";
+               internalName = "Panel1";
+            };
+            new GuiPanel(ShaderEditorInspector) {
+               docking = "Client";
+               position = "0 202";
+               extent = "317 518";
+               profile = "ToolsGuiButtonProfile";
+               tooltipProfile = "ToolsGuiToolTipProfile";
+               internalName = "panel2";
+            };
+         };
+      };
+      new GuiControl() {
+         position = "320 0";
+         extent = "678 720";
+         horizSizing = "width";
+         vertSizing = "height";
+         profile = "ToolsGuiButtonProfile";
+         tooltipProfile = "ToolsGuiToolTipProfile";
+         isContainer = "1";
+
+         new GuiShaderEditor(ShaderNodeGraph) {
+            extent = "678 720";
+            horizSizing = "width";
+            vertSizing = "height";
+            profile = "GuiShaderEditorProfile";
+            tooltipProfile = "GuiToolTipProfile";
+         };
+      };
+      new GuiControl(ShaderEditorSidebar) {
+         position = "1000 0";
+         extent = "280 720";
+         horizSizing = "width";
+         vertSizing = "height";
+         profile = "ToolsGuiDefaultProfile";
+         tooltipProfile = "ToolsGuiButtonProfile";
+         isContainer = "1";
+
+         new GuiTabBookCtrl(ShaderEditorTabBook) {
+            tabHeight = "20";
+            allowReorder = "1";
+            selectedPage = "0";
+            position = "3 5";
+            extent = "271 520";
+            horizSizing = "width";
+            vertSizing = "height";
+            profile = "ToolsGuiTabBookProfile";
+            tooltipProfile = "ToolsGuiToolTipProfile";
+
+            new GuiTabPageCtrl() {
+               fitBook = "1";
+               text = "Library";
+               position = "0 20";
+               extent = "271 500";
+               horizSizing = "width";
+               vertSizing = "height";
+               profile = "ToolsGuiTabPageProfile";
+               tooltipProfile = "ToolsGuiToolTipProfile";
+
+               new GuiScrollCtrl() {
+                  hScrollBar = "dynamic";
+                  childMargin = "0 2";
+                  extent = "271 490";
+                  horizSizing = "width";
+                  vertSizing = "height";
+                  profile = "ToolsGuiScrollProfile";
+                  tooltipProfile = "ToolsGuiToolTipProfile";
+
+                  new GuiStackControl(ShaderToolbox) {
+                     extent = "591 1000";
+                     horizSizing = "width";
+                     profile = "ToolsGuiDefaultProfile";
+                     tooltipProfile = "ToolsGuiToolTipProfile";
+                  };
+               };
+            };
+         };
+      };
+   };
+};
+//--- OBJECT WRITE END ---

+ 2 - 1
Tools/CMake/modules/tools.cmake

@@ -4,7 +4,8 @@ option(TORQUE_TOOLS "Enable Torque Tools" ON)
 if(TORQUE_TOOLS)
   message("Enabling Torque Tools Module")
 
-  file(GLOB_RECURSE TORQUE_TOOLS_SOURCES "gui/editor/*.cpp" "gui/editor/*.h" "gui/worldEditor/*.cpp" "gui/worldEditor/*.h")
+  file(GLOB_RECURSE TORQUE_TOOLS_SOURCES  "gui/editor/*.cpp" "gui/editor/*.h" "gui/worldEditor/*.cpp" "gui/worldEditor/*.h" "gui/shaderEditor/*.cpp" "gui/shaderEditor/*.h"
+                                          "gui/shaderEditor/nodes/*.cpp" "gui/shaderEditor/nodes/*.h")
   file(GLOB_RECURSE TORQUE_TOOLS_SOURCES2 "environment/editors/*.cpp" "environment/editors/*.h")
   file(GLOB_RECURSE TORQUE_TOOLS_SOURCES3 "forest/editor/*.cpp" "forest/editor/*.h")
                                          

部分文件因文件數量過多而無法顯示