Browse Source

Updating BaseGame to work with PBR, and a PBR example module

Areloch 6 years ago
parent
commit
cedbd387d9
98 changed files with 6627 additions and 2806 deletions
  1. 10 0
      Engine/source/gfx/gfxTextureManager.cpp
  2. 6 0
      Engine/source/gfx/gfxTextureManager.h
  3. 15 10
      Engine/source/renderInstance/renderProbeMgr.cpp
  4. 4 4
      Engine/source/ts/assimp/assimpAppMaterial.cpp
  5. 3 0
      Templates/BaseGame/game/core/clientServer/scripts/client/levelDownload.cs
  6. BIN
      Templates/BaseGame/game/core/gui/scripts/fonts/Arial 12 (ansi).uft
  7. BIN
      Templates/BaseGame/game/core/gui/scripts/fonts/Arial 14 (ansi).uft
  8. BIN
      Templates/BaseGame/game/core/gui/scripts/fonts/Arial Bold 16 (ansi).uft
  9. BIN
      Templates/BaseGame/game/core/gui/scripts/fonts/Arial Bold 18 (ansi).uft
  10. BIN
      Templates/BaseGame/game/core/gui/scripts/fonts/ArialItalic 14 (ansi).uft
  11. 103 21
      Templates/BaseGame/game/core/lighting/scripts/advancedLighting_Shaders.cs
  12. 1 1
      Templates/BaseGame/game/core/lighting/scripts/basicLighting_Init.cs
  13. 22 33
      Templates/BaseGame/game/core/lighting/scripts/deferredShading.cs
  14. 2 3
      Templates/BaseGame/game/core/postFX/scripts/hdr.cs
  15. 19 0
      Templates/BaseGame/game/core/postFX/scripts/pbr.cs
  16. 2 0
      Templates/BaseGame/game/core/rendering/Core_Rendering.cs
  17. BIN
      Templates/BaseGame/game/core/rendering/images/brdfTexture.dds
  18. BIN
      Templates/BaseGame/game/core/rendering/images/default_irradiance.dds
  19. BIN
      Templates/BaseGame/game/core/rendering/images/default_prefilter.dds
  20. 5 3
      Templates/BaseGame/game/core/rendering/scripts/renderManager.cs
  21. 1 1
      Templates/BaseGame/game/core/rendering/shaders/basicCloudsV.hlsl
  22. 98 0
      Templates/BaseGame/game/core/rendering/shaders/brdf.hlsl
  23. 1 0
      Templates/BaseGame/game/core/rendering/shaders/cloudLayerV.hlsl
  24. 1 0
      Templates/BaseGame/game/core/rendering/shaders/gl/basicCloudsV.glsl
  25. 98 0
      Templates/BaseGame/game/core/rendering/shaders/gl/brdf.glsl
  26. 1 0
      Templates/BaseGame/game/core/rendering/shaders/gl/cloudLayerV.glsl
  27. 52 0
      Templates/BaseGame/game/core/rendering/shaders/gl/cubemapSaveP.glsl
  28. 51 0
      Templates/BaseGame/game/core/rendering/shaders/gl/cubemapSaveV.glsl
  29. 379 186
      Templates/BaseGame/game/core/rendering/shaders/gl/lighting.glsl
  30. 50 1
      Templates/BaseGame/game/core/rendering/shaders/gl/torque.glsl
  31. 346 186
      Templates/BaseGame/game/core/rendering/shaders/lighting.hlsl
  32. 6 5
      Templates/BaseGame/game/core/rendering/shaders/lighting/advanced/convexGeometryV.hlsl
  33. 37 0
      Templates/BaseGame/game/core/rendering/shaders/lighting/advanced/cubemapV.hlsl
  34. 2 2
      Templates/BaseGame/game/core/rendering/shaders/lighting/advanced/farFrustumQuadV.hlsl
  35. 136 0
      Templates/BaseGame/game/core/rendering/shaders/lighting/advanced/gl/brdfLookupP.glsl
  36. 33 0
      Templates/BaseGame/game/core/rendering/shaders/lighting/advanced/gl/cubemapV.glsl
  37. 20 13
      Templates/BaseGame/game/core/rendering/shaders/lighting/advanced/gl/deferredShadingP.glsl
  38. 60 0
      Templates/BaseGame/game/core/rendering/shaders/lighting/advanced/gl/irradianceP.glsl
  39. 0 28
      Templates/BaseGame/game/core/rendering/shaders/lighting/advanced/gl/lightingUtils.glsl
  40. 46 110
      Templates/BaseGame/game/core/rendering/shaders/lighting/advanced/gl/pointLightP.glsl
  41. 130 0
      Templates/BaseGame/game/core/rendering/shaders/lighting/advanced/gl/prefilterP.glsl
  42. 68 0
      Templates/BaseGame/game/core/rendering/shaders/lighting/advanced/gl/probeShadingP.glsl
  43. 209 0
      Templates/BaseGame/game/core/rendering/shaders/lighting/advanced/gl/reflectionProbeArrayP.glsl
  44. 162 0
      Templates/BaseGame/game/core/rendering/shaders/lighting/advanced/gl/reflectionProbeP.glsl
  45. 32 0
      Templates/BaseGame/game/core/rendering/shaders/lighting/advanced/gl/reflectionProbeV.glsl
  46. 82 0
      Templates/BaseGame/game/core/rendering/shaders/lighting/advanced/gl/skylightP.glsl
  47. 51 120
      Templates/BaseGame/game/core/rendering/shaders/lighting/advanced/gl/spotLightP.glsl
  48. 74 144
      Templates/BaseGame/game/core/rendering/shaders/lighting/advanced/gl/vectorLightP.glsl
  49. 63 0
      Templates/BaseGame/game/core/rendering/shaders/lighting/advanced/irradianceP.hlsl
  50. 56 122
      Templates/BaseGame/game/core/rendering/shaders/lighting/advanced/pointLightP.hlsl
  51. 130 0
      Templates/BaseGame/game/core/rendering/shaders/lighting/advanced/prefilterP.hlsl
  52. 203 0
      Templates/BaseGame/game/core/rendering/shaders/lighting/advanced/reflectionProbeArrayP.hlsl
  53. 65 128
      Templates/BaseGame/game/core/rendering/shaders/lighting/advanced/spotLightP.hlsl
  54. 45 127
      Templates/BaseGame/game/core/rendering/shaders/lighting/advanced/vectorLightP.hlsl
  55. 5 5
      Templates/BaseGame/game/core/rendering/shaders/lighting/shadowMap/shadowMapIO_GLSL.h
  56. 1 2
      Templates/BaseGame/game/core/rendering/shaders/postFX/fogP.hlsl
  57. 3 7
      Templates/BaseGame/game/core/rendering/shaders/postFX/fxaa/fxaaP.hlsl
  58. 3 3
      Templates/BaseGame/game/core/rendering/shaders/postFX/gammaP.hlsl
  59. 36 11
      Templates/BaseGame/game/core/rendering/shaders/postFX/hdr/finalPassCombineP.hlsl
  60. 35 11
      Templates/BaseGame/game/core/rendering/shaders/postFX/hdr/gl/finalPassCombineP.glsl
  61. 42 66
      Templates/BaseGame/game/core/rendering/shaders/shaderModel.hlsl
  62. 3 5
      Templates/BaseGame/game/core/rendering/shaders/shaderModelAutoGen.hlsl
  63. 54 47
      Templates/BaseGame/game/core/rendering/shaders/torque.hlsl
  64. BIN
      Templates/BaseGame/game/data/StaticShapeTest/Images/Grid_512_orange.png
  65. 9 0
      Templates/BaseGame/game/data/StaticShapeTest/Images/Grid_512_orange_ALBEDO.asset.taml
  66. 9 0
      Templates/BaseGame/game/data/StaticShapeTest/Shapes/Cube.asset.taml
  67. 5 0
      Templates/BaseGame/game/data/StaticShapeTest/Shapes/Cube.cs
  68. BIN
      Templates/BaseGame/game/data/StaticShapeTest/Shapes/Cube.fbx
  69. 8 0
      Templates/BaseGame/game/data/StaticShapeTest/Shapes/Cylinder.asset.taml
  70. 5 0
      Templates/BaseGame/game/data/StaticShapeTest/Shapes/Cylinder.cs
  71. BIN
      Templates/BaseGame/game/data/StaticShapeTest/Shapes/Cylinder.fbx
  72. 11 0
      Templates/BaseGame/game/data/StaticShapeTest/Shapes/materials.cs
  73. 10 0
      Templates/BaseGame/game/data/StaticShapeTest/StaticShapeTest.cs
  74. 25 0
      Templates/BaseGame/game/data/StaticShapeTest/StaticShapeTest.module
  75. 9 0
      Templates/BaseGame/game/data/StaticShapeTest/materials/Grid_512_orange.asset.taml
  76. 7 0
      Templates/BaseGame/game/data/StaticShapeTest/materials/Grid_512_orange.cs
  77. 20 25
      Templates/BaseGame/game/data/shaderCache/8625023c97ea6cf9_P.hlsl
  78. 6 14
      Templates/BaseGame/game/data/shaderCache/8625023c97ea6cf9_V.hlsl
  79. 0 22
      Templates/BaseGame/game/data/shaderCache/autogenConditioners.h
  80. BIN
      Templates/BaseGame/game/data/ui/art/BackgroundImage.png
  81. 915 52
      Templates/BaseGame/game/tools/materialEditor/gui/guiMaterialPropertiesWindow.ed.gui
  82. 2 0
      Templates/BaseGame/game/tools/materialEditor/main.cs
  83. 230 17
      Templates/BaseGame/game/tools/materialEditor/scripts/materialEditor.ed.cs
  84. 61 0
      Templates/BaseGame/game/tools/resources/ReflectProbeSphere.dae
  85. 8 0
      Templates/BaseGame/game/tools/resources/materials.cs
  86. 49 0
      Templates/BaseGame/game/tools/resources/reflectionProbePreviewP.hlsl
  87. 58 0
      Templates/BaseGame/game/tools/resources/reflectionProbePreviewV.hlsl
  88. 47 47
      Templates/BaseGame/game/tools/settings.xml
  89. 1559 1206
      Templates/BaseGame/game/tools/worldEditor/gui/guiTerrainMaterialDlg.ed.gui
  90. 18 0
      Templates/BaseGame/game/tools/worldEditor/gui/objectBuilderGui.ed.gui
  91. 192 0
      Templates/BaseGame/game/tools/worldEditor/gui/probeBakeDlg.gui
  92. 13 3
      Templates/BaseGame/game/tools/worldEditor/main.cs
  93. 5 0
      Templates/BaseGame/game/tools/worldEditor/scripts/editors/creator.ed.cs
  94. 38 2
      Templates/BaseGame/game/tools/worldEditor/scripts/interfaces/terrainMaterialDlg.ed.cs
  95. 83 13
      Templates/BaseGame/game/tools/worldEditor/scripts/lightViz.cs
  96. 5 0
      Templates/BaseGame/game/tools/worldEditor/scripts/lighting.ed.cs
  97. 2 0
      Templates/BaseGame/game/tools/worldEditor/scripts/menus.ed.cs
  98. 56 0
      Templates/BaseGame/game/tools/worldEditor/scripts/probeBake.ed.cs

+ 10 - 0
Engine/source/gfx/gfxTextureManager.cpp

@@ -45,6 +45,8 @@ S32 GFXTextureManager::smTextureReductionLevel = 0;
 String GFXTextureManager::smMissingTexturePath(Con::getVariable("$Core::MissingTexturePath"));
 String GFXTextureManager::smMissingTexturePath(Con::getVariable("$Core::MissingTexturePath"));
 String GFXTextureManager::smUnavailableTexturePath(Con::getVariable("$Core::UnAvailableTexturePath"));
 String GFXTextureManager::smUnavailableTexturePath(Con::getVariable("$Core::UnAvailableTexturePath"));
 String GFXTextureManager::smWarningTexturePath(Con::getVariable("$Core::WarningTexturePath"));
 String GFXTextureManager::smWarningTexturePath(Con::getVariable("$Core::WarningTexturePath"));
+String GFXTextureManager::smDefaultIrradianceCubemapPath(Con::getVariable("$Core::DefaultIrradianceCubemap"));
+String GFXTextureManager::smDefaultPrefilterCubemapPath(Con::getVariable("$Core::DefaultPrefilterCubemap"));
 
 
 GFXTextureManager::EventSignal GFXTextureManager::smEventSignal;
 GFXTextureManager::EventSignal GFXTextureManager::smEventSignal;
 
 
@@ -70,6 +72,14 @@ void GFXTextureManager::init()
    Con::addVariable( "$pref::Video::warningTexturePath", TypeRealString, &smWarningTexturePath,
    Con::addVariable( "$pref::Video::warningTexturePath", TypeRealString, &smWarningTexturePath,
       "The file path of the texture used to warn the developer.\n"
       "The file path of the texture used to warn the developer.\n"
       "@ingroup GFX\n" );
       "@ingroup GFX\n" );
+
+   Con::addVariable("$Core::DefaultIrradianceCubemap", TypeRealString, &smDefaultIrradianceCubemapPath,
+      "The file path of the texture used as the default irradiance cubemap for PBR.\n"
+      "@ingroup GFX\n");
+
+   Con::addVariable("$Core::DefaultPrefilterCubemap", TypeRealString, &smDefaultPrefilterCubemapPath,
+      "The file path of the texture used as the default specular cubemap for PBR.\n"
+      "@ingroup GFX\n");
 }
 }
 
 
 GFXTextureManager::GFXTextureManager()
 GFXTextureManager::GFXTextureManager()

+ 6 - 0
Engine/source/gfx/gfxTextureManager.h

@@ -74,6 +74,9 @@ public:
    /// Provide the path to the texture used to warn the developer
    /// Provide the path to the texture used to warn the developer
    static const String& getWarningTexturePath() { return smWarningTexturePath; }
    static const String& getWarningTexturePath() { return smWarningTexturePath; }
 
 
+   static const String& getDefaultIrradianceCubemapPath() { return smDefaultIrradianceCubemapPath; }
+   static const String& getDefaultPrefilterCubemapPath() { return smDefaultPrefilterCubemapPath; }
+
    /// Update width and height based on available resources.
    /// Update width and height based on available resources.
    ///
    ///
    /// We provide a simple interface for managing texture memory usage. Specifically,
    /// We provide a simple interface for managing texture memory usage. Specifically,
@@ -210,6 +213,9 @@ protected:
    /// File path to the warning texture
    /// File path to the warning texture
    static String smWarningTexturePath;
    static String smWarningTexturePath;
 
 
+   static String smDefaultIrradianceCubemapPath;
+   static String smDefaultPrefilterCubemapPath;
+
    GFXTextureObject *mListHead;
    GFXTextureObject *mListHead;
    GFXTextureObject *mListTail;
    GFXTextureObject *mListTail;
 
 

+ 15 - 10
Engine/source/renderInstance/renderProbeMgr.cpp

@@ -199,7 +199,8 @@ RenderProbeMgr::RenderProbeMgr()
 : RenderBinManager(RenderPassManager::RIT_Probes, 1.0f, 1.0f),
 : RenderBinManager(RenderPassManager::RIT_Probes, 1.0f, 1.0f),
    mLastShader(nullptr),
    mLastShader(nullptr),
    mLastConstants(nullptr),
    mLastConstants(nullptr),
-	mProbesDirty(false)
+	mProbesDirty(false),
+   hasSkylight(false)
 {
 {
    mEffectiveProbeCount = 0;
    mEffectiveProbeCount = 0;
    mMipCount = 0;
    mMipCount = 0;
@@ -250,13 +251,17 @@ bool RenderProbeMgr::onAdd()
    //create our own default default skylight
    //create our own default default skylight
    mDefaultSkyLight = new ProbeRenderInst;
    mDefaultSkyLight = new ProbeRenderInst;
    mDefaultSkyLight->mProbeShapeType = ProbeRenderInst::Skylight;
    mDefaultSkyLight->mProbeShapeType = ProbeRenderInst::Skylight;
-   if (!mDefaultSkyLight->mIrradianceCubemap.set("core/art/pbr/default_irradiance.dds"))
+   mDefaultSkyLight->mIsEnabled = false;
+
+   String defaultIrradMapPath = GFXTextureManager::getDefaultIrradianceCubemapPath();
+   if (!mDefaultSkyLight->mIrradianceCubemap.set(defaultIrradMapPath))
    {
    {
       Con::errorf("RenderProbeMgr::onAdd: Failed to load default irradiance cubemap");
       Con::errorf("RenderProbeMgr::onAdd: Failed to load default irradiance cubemap");
       return false;
       return false;
    }
    }
 
 
-   if (!mDefaultSkyLight->mPrefilterCubemap.set("core/art/pbr/default_prefilter.dds"))
+   String defaultPrefilterPath = GFXTextureManager::getDefaultPrefilterCubemapPath();
+   if (!mDefaultSkyLight->mPrefilterCubemap.set(defaultPrefilterPath))
    {
    {
       Con::errorf("RenderProbeMgr::onAdd: Failed to load default prefilter cubemap");
       Con::errorf("RenderProbeMgr::onAdd: Failed to load default prefilter cubemap");
       return false;
       return false;
@@ -825,15 +830,15 @@ void RenderProbeMgr::render( SceneRenderState *state )
 
 
          mProbeArrayEffect->setShaderConst("$probeContribColors", contribColors);
          mProbeArrayEffect->setShaderConst("$probeContribColors", contribColors);
       }
       }
-      
-      mProbeArrayEffect->setShaderConst("$inProbePosArray", probePositionsData);
-      mProbeArrayEffect->setShaderConst("$inRefPosArray", probeRefPositionsData);
-      mProbeArrayEffect->setShaderConst("$worldToObjArray", probeWorldToObjData);
-      mProbeArrayEffect->setShaderConst("$bbMinArray", probeBBMinData);
-      mProbeArrayEffect->setShaderConst("$bbMaxArray", probeBBMaxData);
-      mProbeArrayEffect->setShaderConst("$probeConfigData", probeConfigData);
    }
    }
 
 
+   mProbeArrayEffect->setShaderConst("$inProbePosArray", probePositionsData);
+   mProbeArrayEffect->setShaderConst("$inRefPosArray", probeRefPositionsData);
+   mProbeArrayEffect->setShaderConst("$worldToObjArray", probeWorldToObjData);
+   mProbeArrayEffect->setShaderConst("$bbMinArray", probeBBMinData);
+   mProbeArrayEffect->setShaderConst("$bbMaxArray", probeBBMaxData);
+   mProbeArrayEffect->setShaderConst("$probeConfigData", probeConfigData);
+
    // Make sure the effect is gonna render.
    // Make sure the effect is gonna render.
    getProbeArrayEffect()->setSkip(false);
    getProbeArrayEffect()->setSkip(false);
 
 

+ 4 - 4
Engine/source/ts/assimp/assimpAppMaterial.cpp

@@ -210,10 +210,10 @@ void AssimpAppMaterial::initMaterial(const Torque::Path& path, Material* mat) co
          mat->mSpecularMapFilename[0] = cleanTextureName(torquePath, cleanFile);
          mat->mSpecularMapFilename[0] = cleanTextureName(torquePath, cleanFile);
    }
    }
 
 
-   LinearColorF specularColor(1.0f, 1.0f, 1.0f, 1.0f);
+   /*LinearColorF specularColor(1.0f, 1.0f, 1.0f, 1.0f);
    if (AI_SUCCESS == mAIMat->Get(AI_MATKEY_COLOR_SPECULAR, read_color))
    if (AI_SUCCESS == mAIMat->Get(AI_MATKEY_COLOR_SPECULAR, read_color))
       specularColor.set(read_color.r, read_color.g, read_color.b, opacity);
       specularColor.set(read_color.r, read_color.g, read_color.b, opacity);
-   mat->mSpecular[0] = specularColor;
+   mat->mMetalness[0] = specularColor;
 
 
    // Specular Power
    // Specular Power
    F32 specularPower = 1.0f;
    F32 specularPower = 1.0f;
@@ -223,7 +223,7 @@ void AssimpAppMaterial::initMaterial(const Torque::Path& path, Material* mat) co
    // Specular
    // Specular
    F32 specularStrength = 0.0f;
    F32 specularStrength = 0.0f;
    if (AI_SUCCESS == mAIMat->Get(AI_MATKEY_SHININESS, specularStrength))
    if (AI_SUCCESS == mAIMat->Get(AI_MATKEY_SHININESS, specularStrength))
-      mat->mSpecularStrength[0] = specularStrength;
+      mat->mSpecularStrength[0] = specularStrength;*/
 #endif
 #endif
 
 
    // Double-Sided
    // Double-Sided
@@ -343,4 +343,4 @@ void AssimpAppMaterial::enumerateMaterialProperties(aiMaterial* mtl)
       }
       }
    }
    }
 }
 }
-#endif
+#endif

+ 3 - 0
Templates/BaseGame/game/core/clientServer/scripts/client/levelDownload.cs

@@ -44,6 +44,9 @@ function clientCmdMissionStartPhase1(%seq, %missionName)
    echo ("*** New Mission: " @ %missionName);
    echo ("*** New Mission: " @ %missionName);
    echo ("*** Phase 1: Download Datablocks & Targets");
    echo ("*** Phase 1: Download Datablocks & Targets");
    
    
+   $Client::MissionFile = %missionName;
+   $pref::ReflectionProbes::CurrentLevelPath = filePath($Client::MissionFile) @ "/" @ fileBase($Client::MissionFile) @ "/probes/";
+   
    //Prep the postFX stuff
    //Prep the postFX stuff
    // Load the post effect presets for this mission.
    // Load the post effect presets for this mission.
    %path = filePath( %missionName ) @ "/" @ fileBase( %missionName ) @ $PostFXManager::fileExtension;
    %path = filePath( %missionName ) @ "/" @ fileBase( %missionName ) @ $PostFXManager::fileExtension;

BIN
Templates/BaseGame/game/core/gui/scripts/fonts/Arial 12 (ansi).uft


BIN
Templates/BaseGame/game/core/gui/scripts/fonts/Arial 14 (ansi).uft


BIN
Templates/BaseGame/game/core/gui/scripts/fonts/Arial Bold 16 (ansi).uft


BIN
Templates/BaseGame/game/core/gui/scripts/fonts/Arial Bold 18 (ansi).uft


BIN
Templates/BaseGame/game/core/gui/scripts/fonts/ArialItalic 14 (ansi).uft


+ 103 - 21
Templates/BaseGame/game/core/lighting/scripts/advancedLighting_Shaders.cs

@@ -30,9 +30,16 @@ new GFXStateBlockData( AL_VectorLightState )
    blendDest = GFXBlendOne;
    blendDest = GFXBlendOne;
    blendOp = GFXBlendOpAdd;
    blendOp = GFXBlendOpAdd;
    
    
+   colorWriteDefined = true;
+   colorWriteRed = true;
+   colorWriteBlue = true;
+   colorWriteGreen = true;
+   colorWriteAlpha = false; //disable alpha write
+   
    zDefined = true;
    zDefined = true;
    zEnable = false;
    zEnable = false;
-   zWriteEnable = false;
+   zWriteEnable = true;
+   zFunc = GFXCmpGreater;
 
 
    samplersDefined = true;
    samplersDefined = true;
    samplerStates[0] = SamplerClampPoint;  // G-buffer
    samplerStates[0] = SamplerClampPoint;  // G-buffer
@@ -49,12 +56,8 @@ new GFXStateBlockData( AL_VectorLightState )
    cullMode = GFXCullNone;
    cullMode = GFXCullNone;
    
    
    stencilDefined = true;
    stencilDefined = true;
-   stencilEnable = true;
-   stencilFailOp = GFXStencilOpKeep;
-   stencilZFailOp = GFXStencilOpKeep;
-   stencilPassOp = GFXStencilOpKeep;
-   stencilFunc = GFXCmpLess;
-   stencilRef = 0;
+   stencilEnable = false;
+
 };
 };
 
 
 // Vector Light Material
 // Vector Light Material
@@ -87,11 +90,11 @@ new CustomMaterial( AL_VectorLightMaterial )
    sampler["shadowMap"] = "$dynamiclight";
    sampler["shadowMap"] = "$dynamiclight";
    sampler["dynamicShadowMap"] = "$dynamicShadowMap";
    sampler["dynamicShadowMap"] = "$dynamicShadowMap";
    sampler["ssaoMask"] = "#ssaoMask";  
    sampler["ssaoMask"] = "#ssaoMask";  
-   sampler["lightBuffer"] = "#lightinfo";
+   sampler["lightBuffer"] = "#specularLighting";
    sampler["colorBuffer"] = "#color";
    sampler["colorBuffer"] = "#color";
    sampler["matInfoBuffer"] = "#matinfo";
    sampler["matInfoBuffer"] = "#matinfo";
    
    
-   target = "lightinfo";
+   target = "AL_FormatToken";
    
    
    pixVersion = 3.0;
    pixVersion = 3.0;
 };
 };
@@ -107,10 +110,16 @@ new GFXStateBlockData( AL_ConvexLightState )
    blendDest = GFXBlendOne;
    blendDest = GFXBlendOne;
    blendOp = GFXBlendOpAdd;
    blendOp = GFXBlendOpAdd;
    
    
+   colorWriteDefined = true;
+   colorWriteRed = true;
+   colorWriteBlue = true;
+   colorWriteGreen = true;
+   colorWriteAlpha = false; //disable alpha write
+   
    zDefined = true;
    zDefined = true;
    zEnable = true;
    zEnable = true;
    zWriteEnable = false;
    zWriteEnable = false;
-   zFunc = GFXCmpGreaterEqual;
+   zFunc = GFXCmpGreater;
 
 
    samplersDefined = true;
    samplersDefined = true;
    samplerStates[0] = SamplerClampPoint;  // G-buffer
    samplerStates[0] = SamplerClampPoint;  // G-buffer
@@ -126,12 +135,8 @@ new GFXStateBlockData( AL_ConvexLightState )
    cullMode = GFXCullCW;
    cullMode = GFXCullCW;
    
    
    stencilDefined = true;
    stencilDefined = true;
-   stencilEnable = true;
-   stencilFailOp = GFXStencilOpKeep;
-   stencilZFailOp = GFXStencilOpKeep;
-   stencilPassOp = GFXStencilOpKeep;
-   stencilFunc = GFXCmpLess;
-   stencilRef = 0;
+   stencilEnable = false;
+
 };
 };
 
 
 // Point Light Material
 // Point Light Material
@@ -164,11 +169,11 @@ new CustomMaterial( AL_PointLightMaterial )
    sampler["shadowMap"] = "$dynamiclight";
    sampler["shadowMap"] = "$dynamiclight";
    sampler["dynamicShadowMap"] = "$dynamicShadowMap";
    sampler["dynamicShadowMap"] = "$dynamicShadowMap";
    sampler["cookieMap"] = "$dynamiclightmask";
    sampler["cookieMap"] = "$dynamiclightmask";
-   sampler["lightBuffer"] = "#lightinfo";
+   sampler["lightBuffer"] = "#specularLighting";
    sampler["colorBuffer"] = "#color";
    sampler["colorBuffer"] = "#color";
    sampler["matInfoBuffer"] = "#matinfo";
    sampler["matInfoBuffer"] = "#matinfo";
    
    
-   target = "lightinfo";
+   target = "AL_FormatToken";
    
    
    pixVersion = 3.0;
    pixVersion = 3.0;
 };
 };
@@ -203,11 +208,11 @@ new CustomMaterial( AL_SpotLightMaterial )
    sampler["shadowMap"] = "$dynamiclight";
    sampler["shadowMap"] = "$dynamiclight";
    sampler["dynamicShadowMap"] = "$dynamicShadowMap";
    sampler["dynamicShadowMap"] = "$dynamicShadowMap";
    sampler["cookieMap"] = "$dynamiclightmask";
    sampler["cookieMap"] = "$dynamiclightmask";
-   sampler["lightBuffer"] = "#lightinfo";
+   sampler["lightBuffer"] = "#specularLighting";
    sampler["colorBuffer"] = "#color";
    sampler["colorBuffer"] = "#color";
    sampler["matInfoBuffer"] = "#matinfo";
    sampler["matInfoBuffer"] = "#matinfo";
    
    
-   target = "lightinfo";
+   target = "AL_FormatToken";
    
    
    pixVersion = 3.0;
    pixVersion = 3.0;
 };
 };
@@ -270,7 +275,84 @@ new CustomMaterial( AL_ParticlePointLightMaterial )
    stateBlock = AL_ConvexLightState;
    stateBlock = AL_ConvexLightState;
    
    
    sampler["deferredBuffer"] = "#deferred";
    sampler["deferredBuffer"] = "#deferred";
-   target = "lightinfo";
+   target = "diffuseLighting";
+   
+   pixVersion = 3.0;
+};
+
+//Probe Processing
+new ShaderData( IrradianceShader )
+{
+   DXVertexShaderFile = $Core::CommonShaderPath @ "/lighting/advanced/cubemapV.hlsl";
+   DXPixelShaderFile  = $Core::CommonShaderPath @ "/lighting/advanced/irradianceP.hlsl";
+
+   OGLVertexShaderFile = $Core::CommonShaderPath @ "/lighting/advanced/gl/cubemapV.glsl";
+   OGLPixelShaderFile  = $Core::CommonShaderPath @ "/lighting/advanced/gl/irradianceP.glsl";
+   
+   samplerNames[0] = "$environmentMap";
+   
+   pixVersion = 3.0;
+};
+
+new ShaderData( PrefiterCubemapShader )
+{
+   DXVertexShaderFile = $Core::CommonShaderPath @ "/lighting/advanced/cubemapV.hlsl";
+   DXPixelShaderFile  = $Core::CommonShaderPath @ "/lighting/advanced/prefilterP.hlsl";
+
+   OGLVertexShaderFile = $Core::CommonShaderPath @ "/lighting/advanced/gl/cubemapV.glsl";
+   OGLPixelShaderFile  = $Core::CommonShaderPath @ "/lighting/advanced/gl/prefilterP.glsl";
+   
+   samplerNames[0] = "$environmentMap";
    
    
    pixVersion = 3.0;
    pixVersion = 3.0;
 };
 };
+
+//
+singleton ShaderData( PFX_ReflectionProbeArray )
+{
+   DXVertexShaderFile   = $Core::CommonShaderPath @ "/postFx/postFxV.hlsl";
+   DXPixelShaderFile    = $Core::CommonShaderPath @ "/lighting/advanced/reflectionProbeArrayP.hlsl";
+
+   OGLVertexShaderFile  = $Core::CommonShaderPath @ "/postFx/gl/postFxV.glsl";
+   OGLPixelShaderFile   = $Core::CommonShaderPath @ "/lighting/advanced/gl/reflectionProbeArrayP.glsl";
+   
+   samplerNames[0] = "$deferredBuffer";
+   samplerNames[1] = "$colorBuffer";
+   samplerNames[2] = "$matInfoBuffer";
+   samplerNames[3] = "$BRDFTexture";
+   samplerNames[4] = "$specularCubemapAR";
+   samplerNames[5] = "$irradianceCubemapAR";
+   samplerNames[6] = "$skylightSpecularMap";
+   samplerNames[7] = "$skylightIrradMap";
+
+   pixVersion = 2.0;
+};  
+
+singleton GFXStateBlockData( PFX_ReflectionProbeArrayStateBlock )
+{  
+   alphaDefined = true;
+   alphaTestEnable = true;
+   alphaTestRef = 1;
+   alphaTestFunc = GFXCmpGreaterEqual;
+         
+   // Do a one to one blend.
+   blendDefined = true;
+   blendEnable = true;
+   blendSrc = GFXBlendOne;
+   blendDest = GFXBlendOne;
+   
+   zDefined = true;
+   zEnable = false;
+   zWriteEnable = false;
+   
+   
+   samplersDefined = true;
+   samplerStates[0] = SamplerClampPoint;
+   samplerStates[1] = SamplerClampPoint;
+   samplerStates[2] = SamplerClampPoint;
+   samplerStates[3] = SamplerClampPoint;
+   samplerStates[4] = SamplerClampLinear;
+   samplerStates[5] = SamplerClampLinear;
+   samplerStates[6] = SamplerClampLinear;
+   samplerStates[7] = SamplerClampLinear;
+};

+ 1 - 1
Templates/BaseGame/game/core/lighting/scripts/basicLighting_Init.cs

@@ -64,7 +64,7 @@ singleton CustomMaterial( BL_ProjectedShadowMaterial )
 function onActivateBasicLM()
 function onActivateBasicLM()
 {
 {
    // If HDR is enabled... enable the special format token.
    // If HDR is enabled... enable the special format token.
-   if ( $platform !$= "macos" && HDRPostFx.isEnabled )
+   if ( HDRPostFx.isEnabled )
       AL_FormatToken.enable();
       AL_FormatToken.enable();
       
       
    // Create render pass for projected shadow.
    // Create render pass for projected shadow.

+ 22 - 33
Templates/BaseGame/game/core/lighting/scripts/deferredShading.cs

@@ -1,14 +1,3 @@
-singleton ShaderData( ClearGBufferShader )
-{
-   DXVertexShaderFile = $Core::CommonShaderPath @ "/lighting/advanced/deferredClearGBufferV.hlsl";
-   DXPixelShaderFile  = $Core::CommonShaderPath @ "/lighting/advanced/deferredClearGBufferP.hlsl";
-
-   OGLVertexShaderFile = $Core::CommonShaderPath @ "/postFX/gl/postFxV.glsl";
-   OGLPixelShaderFile  = $Core::CommonShaderPath @ "/lighting/advanced/gl/deferredClearGBufferP.glsl";
-
-   pixVersion = 2.0;   
-};
-
 singleton ShaderData( DeferredColorShader )
 singleton ShaderData( DeferredColorShader )
 {
 {
    DXVertexShaderFile = $Core::CommonShaderPath @ "/postFx/postFxV.hlsl";
    DXVertexShaderFile = $Core::CommonShaderPath @ "/postFx/postFxV.hlsl";
@@ -20,15 +9,15 @@ singleton ShaderData( DeferredColorShader )
    pixVersion = 2.0;   
    pixVersion = 2.0;   
 };
 };
 
 
-// Primary Deferred Shader
-new GFXStateBlockData( AL_DeferredShadingState : PFX_DefaultStateBlock )
-{  
-   cullMode = GFXCullNone;
+new GFXStateBlockData( AL_DeferredCaptureState : PFX_DefaultStateBlock )
+{        
+   blendEnable = false; 
    
    
-   blendDefined = true;
-   blendEnable = true; 
-   blendSrc = GFXBlendSrcAlpha;
-   blendDest = GFXBlendInvSrcAlpha;
+   separateAlphaBlendDefined = true;
+   separateAlphaBlendEnable = true;
+   separateAlphaBlendSrc = GFXBlendSrcAlpha;
+   separateAlphaBlendDest = GFXBlendDestAlpha;
+   separateAlphaBlendOp = GFXBlendOpMin;
    
    
    samplersDefined = true;
    samplersDefined = true;
    samplerStates[0] = SamplerWrapLinear;
    samplerStates[0] = SamplerWrapLinear;
@@ -38,33 +27,33 @@ new GFXStateBlockData( AL_DeferredShadingState : PFX_DefaultStateBlock )
    samplerStates[4] = SamplerWrapLinear;
    samplerStates[4] = SamplerWrapLinear;
 };
 };
 
 
-new ShaderData( AL_DeferredShader )
+new ShaderData( AL_ProbeShader )
 {
 {
    DXVertexShaderFile = $Core::CommonShaderPath @ "/postFX/postFxV.hlsl";
    DXVertexShaderFile = $Core::CommonShaderPath @ "/postFX/postFxV.hlsl";
-   DXPixelShaderFile  = $Core::CommonShaderPath @ "/lighting/advanced/deferredShadingP.hlsl";
+   DXPixelShaderFile  = $Core::CommonShaderPath @ "/lighting/advanced/probeShadingP.hlsl";
    
    
    OGLVertexShaderFile = $Core::CommonShaderPath @ "/postFX/gl/postFxV.glsl";
    OGLVertexShaderFile = $Core::CommonShaderPath @ "/postFX/gl/postFxV.glsl";
-   OGLPixelShaderFile  = $Core::CommonShaderPath @ "/lighting/advanced/gl/deferredShadingP.glsl";
+   OGLPixelShaderFile  = $Core::CommonShaderPath @ "/lighting/advanced/gl/probeShadingP.glsl";
 
 
    samplerNames[0] = "colorBufferTex";
    samplerNames[0] = "colorBufferTex";
-   samplerNames[1] = "lightDeferredTex";
+   samplerNames[1] = "diffuseLightingBuffer";
    samplerNames[2] = "matInfoTex";
    samplerNames[2] = "matInfoTex";
-   samplerNames[3] = "deferredTex";
-   
+   samplerNames[3] = "specularLightingBuffer";
+   samplerNames[4] = "deferredTex";
    pixVersion = 2.0;
    pixVersion = 2.0;
 };
 };
 
 
-singleton PostEffect( AL_DeferredShading )
+singleton PostEffect( AL_PreCapture )
 {
 {
-   renderTime = "PFXAfterBin";
-   renderBin = "SkyBin";
-   shader = AL_DeferredShader;
-   stateBlock = AL_DeferredShadingState;
+   renderTime = "PFXBeforeBin";
+   renderBin = "EditorBin";
+   shader = AL_ProbeShader;
+   stateBlock = AL_DeferredCaptureState;
    texture[0] = "#color";
    texture[0] = "#color";
-   texture[1] = "#lightinfo";
+   texture[1] = "#diffuseLighting";
    texture[2] = "#matinfo";
    texture[2] = "#matinfo";
-   texture[3] = "#deferred";
-   
+   texture[3] = "#specularLighting";
+   texture[4] = "#deferred";
    target = "$backBuffer";
    target = "$backBuffer";
    renderPriority = 10000;
    renderPriority = 10000;
    allowReflectPass = true;
    allowReflectPass = true;

+ 2 - 3
Templates/BaseGame/game/core/postFX/scripts/hdr.cs

@@ -170,7 +170,6 @@ singleton ShaderData( HDR_CombineShader )
    samplerNames[1] = "$luminanceTex";
    samplerNames[1] = "$luminanceTex";
    samplerNames[2] = "$bloomTex";
    samplerNames[2] = "$bloomTex";
    samplerNames[3] = "$colorCorrectionTex";
    samplerNames[3] = "$colorCorrectionTex";
-   samplerNames[4] = "deferredTex";
    
    
    pixVersion = 3.0;
    pixVersion = 3.0;
 };
 };
@@ -295,7 +294,7 @@ function HDRPostFX::onEnabled( %this )
    
    
    // Change the format of the offscreen surface
    // Change the format of the offscreen surface
    // to an HDR compatible format.
    // to an HDR compatible format.
-   AL_FormatToken.format = %format;
+   %this.previousFormat = AL_FormatToken.format;
    setReflectFormat( %format );
    setReflectFormat( %format );
    
    
    // Reset the light manager which will ensure the new
    // Reset the light manager which will ensure the new
@@ -312,7 +311,7 @@ function HDRPostFX::onDisabled( %this )
    GammaPostFX.enable();
    GammaPostFX.enable();
    
    
    // Restore the non-HDR offscreen surface format.
    // Restore the non-HDR offscreen surface format.
-   %format = getBestHDRFormat();
+   %format = %this.previousFormat;
    AL_FormatToken.format = %format;
    AL_FormatToken.format = %format;
    setReflectFormat( %format );
    setReflectFormat( %format );
    
    

+ 19 - 0
Templates/BaseGame/game/core/postFX/scripts/pbr.cs

@@ -0,0 +1,19 @@
+singleton PostEffect( reflectionProbeArrayPostFX )
+{
+   // Do not allow the selection effect to work in reflection 
+   // passes by default so we don't do the extra drawing.
+   //allowReflectPass = false;
+                  
+   renderTime = "PFXAfterBin";
+   renderBin = "ProbeBin";
+   renderPriority = 9999;
+   isEnabled = true;
+
+   shader = PFX_ReflectionProbeArray;
+   stateBlock = PFX_ReflectionProbeArrayStateBlock;
+
+   texture[0] = "#deferred";
+   texture[1] = "#color";
+   texture[2] = "#matinfo";
+   texture[3] = "core/rendering/images/brdfTexture.dds";   
+};

+ 2 - 0
Templates/BaseGame/game/core/rendering/Core_Rendering.cs

@@ -5,6 +5,8 @@ function Core_Rendering::onCreate(%this)
    $Core::UnAvailableTexturePath = "core/rendering/images/unavailable";
    $Core::UnAvailableTexturePath = "core/rendering/images/unavailable";
    $Core::WarningTexturePath = "core/rendering/images/warnMat";
    $Core::WarningTexturePath = "core/rendering/images/warnMat";
    $Core::CommonShaderPath = "core/rendering/shaders";
    $Core::CommonShaderPath = "core/rendering/shaders";
+   $Core::DefaultIrradianceCubemap = "core/rendering/images/default_irradiance.dds";
+   $Core::DefaultPrefilterCubemap = "core/rendering/images/default_prefilter.dds";
    
    
    exec("./scripts/renderManager.cs");
    exec("./scripts/renderManager.cs");
    exec("./scripts/gfxData/clouds.cs");
    exec("./scripts/gfxData/clouds.cs");

BIN
Templates/BaseGame/game/core/rendering/images/brdfTexture.dds


BIN
Templates/BaseGame/game/core/rendering/images/default_irradiance.dds


BIN
Templates/BaseGame/game/core/rendering/images/default_prefilter.dds


+ 5 - 3
Templates/BaseGame/game/core/rendering/scripts/renderManager.cs

@@ -48,9 +48,7 @@ function initRenderManager()
    };
    };
    DiffuseRenderPassManager.addManager( new RenderPassStateBin() { renderOrder = 0.001; stateToken = AL_FormatToken; } );
    DiffuseRenderPassManager.addManager( new RenderPassStateBin() { renderOrder = 0.001; stateToken = AL_FormatToken; } );
      
      
-   // We really need to fix the sky to render after all the 
-   // meshes... but that causes issues in reflections.
-   DiffuseRenderPassManager.addManager( new RenderObjectMgr(SkyBin) { bintype = "Sky"; renderOrder = 0.1; processAddOrder = 0.1; } );
+   DiffuseRenderPassManager.addManager( new RenderProbeMgr(ProbeBin)       { bintype = "Probes"; renderOrder = 0.019; processAddOrder = 0.019; } );
    
    
    //DiffuseRenderPassManager.addManager( new RenderVistaMgr()               { bintype = "Vista"; renderOrder = 0.15; processAddOrder = 0.15; } );
    //DiffuseRenderPassManager.addManager( new RenderVistaMgr()               { bintype = "Vista"; renderOrder = 0.15; processAddOrder = 0.15; } );
    
    
@@ -65,6 +63,10 @@ function initRenderManager()
    DiffuseRenderPassManager.addManager( new RenderMeshMgr(DecalRoadBin)    { bintype = "DecalRoad"; renderOrder = 0.8; processAddOrder = 0.8; } );
    DiffuseRenderPassManager.addManager( new RenderMeshMgr(DecalRoadBin)    { bintype = "DecalRoad"; renderOrder = 0.8; processAddOrder = 0.8; } );
    DiffuseRenderPassManager.addManager( new RenderMeshMgr(DecalBin)        { bintype = "Decal"; renderOrder = 0.81; processAddOrder = 0.81; } );
    DiffuseRenderPassManager.addManager( new RenderMeshMgr(DecalBin)        { bintype = "Decal"; renderOrder = 0.81; processAddOrder = 0.81; } );
    DiffuseRenderPassManager.addManager( new RenderOcclusionMgr(OccluderBin){ bintype = "Occluder"; renderOrder = 0.9; processAddOrder = 0.9; } );
    DiffuseRenderPassManager.addManager( new RenderOcclusionMgr(OccluderBin){ bintype = "Occluder"; renderOrder = 0.9; processAddOrder = 0.9; } );
+
+   // Render the sky last
+   DiffuseRenderPassManager.addManager( new RenderObjectMgr(SkyBin) { bintype = "Sky"; renderOrder = 0.95; processAddOrder = 0.95; } );
+
      
      
    // We now render translucent objects that should handle
    // We now render translucent objects that should handle
    // their own fogging and lighting.
    // their own fogging and lighting.

+ 1 - 1
Templates/BaseGame/game/core/rendering/shaders/basicCloudsV.hlsl

@@ -46,7 +46,7 @@ ConnectData main( CloudVert IN )
    ConnectData OUT;
    ConnectData OUT;
 
 
    OUT.hpos = mul(modelview, float4(IN.pos,1.0));
    OUT.hpos = mul(modelview, float4(IN.pos,1.0));
-
+   OUT.hpos.z = OUT.hpos.w;
    float2 uv = IN.uv0;
    float2 uv = IN.uv0;
    uv += texOffset;
    uv += texOffset;
    uv *= texScale;
    uv *= texScale;

+ 98 - 0
Templates/BaseGame/game/core/rendering/shaders/brdf.hlsl

@@ -0,0 +1,98 @@
+//-----------------------------------------------------------------------------
+// Copyright (c) 2018 GarageGames, LLC
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to
+// deal in the Software without restriction, including without limitation the
+// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+// sell copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION 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 BRDF_HLSL
+#define BRDF_HLSL
+
+#include "./torque.hlsl"
+
+// BRDF from Frostbite presentation:
+// Moving Frostbite to Physically Based Rendering
+// S´ebastien Lagarde - Electronic Arts Frostbite
+// Charles de Rousiers - Electronic Arts Frostbite
+// SIGGRAPH 2014
+
+float3 F_Schlick(in float3 f0, in float f90, in float u)
+{
+	return f0 + (f90 - f0) * pow(1.f - u, 5.f);
+}
+
+float3 F_Fresnel(float3 SpecularColor, float VoH)
+{
+	float3 SpecularColorSqrt = sqrt(min(SpecularColor, float3(0.99, 0.99, 0.99)));
+	float3 n = (1 + SpecularColorSqrt) / (1 - SpecularColorSqrt);
+	float3 g = sqrt(n*n + VoH*VoH - 1);
+	return 0.5 * sqr((g - VoH) / (g + VoH)) * (1 + sqr(((g + VoH)*VoH - 1) / ((g - VoH)*VoH + 1)));
+}
+
+float3 FresnelSchlickRoughness(float cosTheta, float3 F0, float roughness)
+{
+	float3 ret = float3(0.0, 0.0, 0.0);
+	float powTheta = pow(1.0 - cosTheta, 5.0);
+	float invRough = float(1.0 - roughness);
+
+	ret.x = F0.x + (max(invRough, F0.x) - F0.x) * powTheta;
+	ret.y = F0.y + (max(invRough, F0.y) - F0.y) * powTheta;
+	ret.z = F0.z + (max(invRough, F0.z) - F0.z) * powTheta;
+
+	return ret;
+}
+
+float Fr_DisneyDiffuse(float NdotV, float NdotL, float LdotH, float linearRoughness)
+{
+	float energyBias = lerp(0, 0.5, linearRoughness);
+	float energyFactor = lerp(1.0, 1.0 / 1.51, linearRoughness);
+	float fd90 = energyBias + 2.0 * LdotH*LdotH * linearRoughness;
+	float3 f0 = float3(1.0f, 1.0f, 1.0f);
+	float lightScatter = F_Schlick(f0, fd90, NdotL).r;
+	float viewScatter = F_Schlick(f0, fd90, NdotV).r;
+
+	return lightScatter * viewScatter * energyFactor;
+}
+
+float V_SmithGGXCorrelated(float NdotL, float NdotV, float alphaG2)
+{
+	// Original formulation of G_SmithGGX Correlated 
+	// lambda_v = (-1 + sqrt(alphaG2 * (1 - NdotL2) / NdotL2 + 1)) * 0.5f; 
+	// lambda_l = (-1 + sqrt(alphaG2 * (1 - NdotV2) / NdotV2 + 1)) * 0.5f; 
+	// G_SmithGGXCorrelated = 1 / (1 + lambda_v + lambda_l); 
+	// V_SmithGGXCorrelated = G_SmithGGXCorrelated / (4.0f * NdotL * NdotV); 
+
+
+	// This is the optimized version 
+	//float alphaG2 = alphaG * alphaG;
+
+	// Caution: the "NdotL *" and "NdotV *" are explicitely inversed , this is not a mistake. 
+	float Lambda_GGXV = NdotL * sqrt((-NdotV * alphaG2 + NdotV) * NdotV + alphaG2);
+	float Lambda_GGXL = NdotV * sqrt((-NdotL * alphaG2 + NdotL) * NdotL + alphaG2);
+
+	return 0.5f / (Lambda_GGXV + Lambda_GGXL);
+}
+
+float D_GGX(float NdotH, float m2)
+{
+	// Divide by PI is apply later 
+	//float m2 = m * m;
+	float f = (NdotH * m2 - NdotH) * NdotH + 1;
+	return m2 / (f * f);
+}
+
+#endif

+ 1 - 0
Templates/BaseGame/game/core/rendering/shaders/cloudLayerV.hlsl

@@ -63,6 +63,7 @@ ConnectData main( CloudVert IN )
    ConnectData OUT;
    ConnectData OUT;
 
 
    OUT.hpos = mul(modelview, float4(IN.pos,1.0));
    OUT.hpos = mul(modelview, float4(IN.pos,1.0));
+   OUT.hpos.z = OUT.hpos.w;
    // Offset the uv so we don't have a seam directly over our head.
    // Offset the uv so we don't have a seam directly over our head.
    float2 uv = IN.uv0 + float2( 0.5, 0.5 );
    float2 uv = IN.uv0 + float2( 0.5, 0.5 );
    
    

+ 1 - 0
Templates/BaseGame/game/core/rendering/shaders/gl/basicCloudsV.glsl

@@ -41,6 +41,7 @@ out vec2 texCoord;
 void main()
 void main()
 {  
 {  
    gl_Position = tMul(modelview, IN_pos);
    gl_Position = tMul(modelview, IN_pos);
+   gl_Position.z = gl_Position.w;
    
    
    vec2 uv = IN_uv0;
    vec2 uv = IN_uv0;
    uv += texOffset;
    uv += texOffset;

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

@@ -0,0 +1,98 @@
+//-----------------------------------------------------------------------------
+// Copyright (c) 2018 GarageGames, LLC
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to
+// deal in the Software without restriction, including without limitation the
+// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+// sell copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION 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 BRDF_HLSL
+#define BRDF_HLSL
+
+#include "./torque.glsl"
+
+// BRDF from Frostbite presentation:
+// Moving Frostbite to Physically Based Rendering
+// S´ebastien Lagarde - Electronic Arts Frostbite
+// Charles de Rousiers - Electronic Arts Frostbite
+// SIGGRAPH 2014
+
+vec3 F_Schlick(in vec3 f0, in float f90, in float u)
+{
+	return f0 + (f90 - f0) * pow(1.f - u, 5.f);
+}
+
+vec3 F_Fresnel(vec3 SpecularColor, float VoH)
+{
+	vec3 SpecularColorSqrt = sqrt(min(SpecularColor, vec3(0.99, 0.99, 0.99)));
+	vec3 n = (1 + SpecularColorSqrt) / (1 - SpecularColorSqrt);
+	vec3 g = sqrt(n*n + VoH*VoH - 1);
+	return 0.5 * sqr((g - VoH) / (g + VoH)) * (1 + sqr(((g + VoH)*VoH - 1) / ((g - VoH)*VoH + 1)));
+}
+
+vec3 FresnelSchlickRoughness(float cosTheta, vec3 F0, float roughness)
+{
+	vec3 ret = vec3(0.0, 0.0, 0.0);
+	float powTheta = pow(1.0 - cosTheta, 5.0);
+	float invRough = float(1.0 - roughness);
+
+	ret.x = F0.x + (max(invRough, F0.x) - F0.x) * powTheta;
+	ret.y = F0.y + (max(invRough, F0.y) - F0.y) * powTheta;
+	ret.z = F0.z + (max(invRough, F0.z) - F0.z) * powTheta;
+
+	return ret;
+}
+
+float Fr_DisneyDiffuse(float NdotV, float NdotL, float LdotH, float linearRoughness)
+{
+	float energyBias = lerp(0, 0.5, linearRoughness);
+	float energyFactor = lerp(1.0, 1.0 / 1.51, linearRoughness);
+	float fd90 = energyBias + 2.0 * LdotH*LdotH * linearRoughness;
+	vec3 f0 = vec3(1.0f, 1.0f, 1.0f);
+	float lightScatter = F_Schlick(f0, fd90, NdotL).r;
+	float viewScatter = F_Schlick(f0, fd90, NdotV).r;
+
+	return lightScatter * viewScatter * energyFactor;
+}
+
+float V_SmithGGXCorrelated(float NdotL, float NdotV, float alphaG2)
+{
+	// Original formulation of G_SmithGGX Correlated 
+	// lambda_v = (-1 + sqrt(alphaG2 * (1 - NdotL2) / NdotL2 + 1)) * 0.5f; 
+	// lambda_l = (-1 + sqrt(alphaG2 * (1 - NdotV2) / NdotV2 + 1)) * 0.5f; 
+	// G_SmithGGXCorrelated = 1 / (1 + lambda_v + lambda_l); 
+	// V_SmithGGXCorrelated = G_SmithGGXCorrelated / (4.0f * NdotL * NdotV); 
+
+
+	// This is the optimized version 
+	//float alphaG2 = alphaG * alphaG;
+
+	// Caution: the "NdotL *" and "NdotV *" are explicitely inversed , this is not a mistake. 
+	float Lambda_GGXV = NdotL * sqrt((-NdotV * alphaG2 + NdotV) * NdotV + alphaG2);
+	float Lambda_GGXL = NdotV * sqrt((-NdotL * alphaG2 + NdotL) * NdotL + alphaG2);
+
+	return 0.5f / (Lambda_GGXV + Lambda_GGXL);
+}
+
+float D_GGX(float NdotH, float m2)
+{
+	// Divide by PI is apply later 
+	//float m2 = m * m;
+	float f = (NdotH * m2 - NdotH) * NdotH + 1;
+	return m2 / (f * f);
+}
+
+#endif

+ 1 - 0
Templates/BaseGame/game/core/rendering/shaders/gl/cloudLayerV.glsl

@@ -62,6 +62,7 @@ void main()
    vec2 IN_uv0 = vTexCoord0.st;
    vec2 IN_uv0 = vTexCoord0.st;
 
 
    gl_Position = modelview * IN_pos;
    gl_Position = modelview * IN_pos;
+   gl_Position.z = gl_Position.w;
    
    
    // Offset the uv so we don't have a seam directly over our head.
    // Offset the uv so we don't have a seam directly over our head.
    vec2 uv = IN_uv0 + vec2( 0.5, 0.5 );
    vec2 uv = IN_uv0 + vec2( 0.5, 0.5 );

+ 52 - 0
Templates/BaseGame/game/core/rendering/shaders/gl/cubemapSaveP.glsl

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

+ 51 - 0
Templates/BaseGame/game/core/rendering/shaders/gl/cubemapSaveV.glsl

@@ -0,0 +1,51 @@
+//-----------------------------------------------------------------------------
+// Copyright (c) 2016 GarageGames, LLC
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to
+// deal in the Software without restriction, including without limitation the
+// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+// sell copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+// IN THE SOFTWARE.
+//-----------------------------------------------------------------------------
+
+#include "hlslCompat.glsl"
+#include "torque.glsl"
+
+uniform float4x4 matrix0;
+uniform float4x4 matrix1;
+uniform float4x4 matrix2;
+uniform float4x4 matrix3;
+uniform float4x4 matrix4;
+uniform float4x4 matrix5;
+
+out float3 face_pos_x;
+out float3 face_neg_x;
+out float3 face_pos_y;
+out float3 face_neg_y;
+out float3 face_pos_z;
+out float3 face_neg_z;
+
+void main()
+{
+   float4 vertex = float4(float2((gl_VertexID << 1) & 2, gl_VertexID & 2) * float2(2, -2) + float2(-1, 1), 0, 1);
+   gl_Position = vertex;
+   correctSSP(gl_Position);
+   face_pos_x = tMul(matrix0, vertex).xyz;
+   face_neg_x = tMul(matrix1, vertex).xyz;
+   face_pos_y = tMul(matrix2, vertex).xyz;
+   face_neg_y = tMul(matrix3, vertex).xyz;
+   face_pos_z = tMul(matrix4, vertex).xyz;
+   face_neg_z = tMul(matrix5, vertex).xyz;
+}

+ 379 - 186
Templates/BaseGame/game/core/rendering/shaders/gl/lighting.glsl

@@ -1,6 +1,6 @@
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 // Copyright (c) 2012 GarageGames, LLC
 // Copyright (c) 2012 GarageGames, LLC
-//
+// Portions Copyright Zefiros
 // Permission is hereby granted, free of charge, to any person obtaining a copy
 // Permission is hereby granted, free of charge, to any person obtaining a copy
 // of this software and associated documentation files (the "Software"), to
 // of this software and associated documentation files (the "Software"), to
 // deal in the Software without restriction, including without limitation the
 // deal in the Software without restriction, including without limitation the
@@ -21,9 +21,9 @@
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 
 
 #include "./torque.glsl"
 #include "./torque.glsl"
-
+#include "./brdf.glsl"
 #ifndef TORQUE_SHADERGEN
 #ifndef TORQUE_SHADERGEN
-
+#line 26
 // These are the uniforms used by most lighting shaders.
 // These are the uniforms used by most lighting shaders.
 
 
 uniform vec4 inLightPos[3];
 uniform vec4 inLightPos[3];
@@ -38,11 +38,31 @@ uniform vec4 inLightColor[4];
 
 
 uniform vec4 ambient;
 uniform vec4 ambient;
 #define ambientCameraFactor 0.3
 #define ambientCameraFactor 0.3
-uniform float specularPower;
-uniform vec4 specularColor;
+uniform float smoothness;
+uniform float metalness;
+uniform vec4 albedo;
 
 
 #endif // !TORQUE_SHADERGEN
 #endif // !TORQUE_SHADERGEN
 
 
+#define MAX_PROBES 50
+#define MAX_FORWARD_PROBES 4
+
+vec3 getDistanceVectorToPlane( vec3 origin, vec3 direction, vec4 plane )
+{
+   float denum = dot( plane.xyz, direction.xyz );
+   float num = dot( plane, vec4( origin, 1.0 ) );
+   float t = -num / denum;
+
+   return direction.xyz * t;
+}
+
+vec3 getDistanceVectorToPlane( float negFarPlaneDotEye, vec3 direction, vec4 plane )
+{
+   float denum = dot( plane.xyz, direction.xyz );
+   float t = negFarPlaneDotEye / denum;
+
+   return direction.xyz * t;
+}
 
 
 void compute4Lights( vec3 wsView, 
 void compute4Lights( vec3 wsView, 
                      vec3 wsPosition, 
                      vec3 wsPosition, 
@@ -57,193 +77,366 @@ void compute4Lights( vec3 wsView,
                         vec4 inLightSpotDir[3],
                         vec4 inLightSpotDir[3],
                         vec4 inLightSpotAngle,
                         vec4 inLightSpotAngle,
                         vec4 inLightSpotFalloff,
                         vec4 inLightSpotFalloff,
-                        float specularPower,
-                        vec4 specularColor,
+                        float smoothness,
+                        float metalness,
+                        vec4 albedo,
 
 
                      #endif // TORQUE_SHADERGEN
                      #endif // TORQUE_SHADERGEN
                      
                      
                      out vec4 outDiffuse,
                      out vec4 outDiffuse,
                      out vec4 outSpecular )
                      out vec4 outSpecular )
 {
 {
-   // NOTE: The light positions and spotlight directions
-   // are stored in SoA order, so inLightPos[0] is the
-   // x coord for all 4 lights... inLightPos[1] is y... etc.
-   //
-   // This is the key to fully utilizing the vector units and
-   // saving a huge amount of instructions.
-   //
-   // For example this change saved more than 10 instructions 
-   // over a simple for loop for each light.
-   
-   int i;
-
-   vec4 lightVectors[3];
-   for ( i = 0; i < 3; i++ )
-      lightVectors[i] = wsPosition[i] - inLightPos[i];
-
-   vec4 squareDists = vec4(0);
-   for ( i = 0; i < 3; i++ )
-      squareDists += lightVectors[i] * lightVectors[i];
-
-   // Accumulate the dot product between the light 
-   // vector and the normal.
-   //
-   // The normal is negated because it faces away from
-   // the surface and the light faces towards the
-   // surface... this keeps us from needing to flip
-   // the light vector direction which complicates
-   // the spot light calculations.
-   //
-   // We normalize the result a little later.
-   //
-   vec4 nDotL = vec4(0);
-   for ( i = 0; i < 3; i++ )
-      nDotL += lightVectors[i] * -wsNormal[i];
-
-   vec4 rDotL = vec4(0);
-   #ifndef TORQUE_BL_NOSPECULAR
-
-      // We're using the Phong specular reflection model
-      // here where traditionally Torque has used Blinn-Phong
-      // which has proven to be more accurate to real materials.
-      //
-      // We do so because its cheaper as do not need to 
-      // calculate the half angle for all 4 lights.
-      //   
-      // Advanced Lighting still uses Blinn-Phong, but the
-      // specular reconstruction it does looks fairly similar
-      // to this.
-      //
-      vec3 R = reflect( wsView, -wsNormal );
-
-      for ( i = 0; i < 3; i++ )
-         rDotL += lightVectors[i] * R[i];
-
-   #endif
- 
-   // Normalize the dots.
-   //
-   // Notice we're using the half type here to get a
-   // much faster sqrt via the rsq_pp instruction at 
-   // the loss of some precision.
-   //
-   // Unless we have some extremely large point lights
-   // i don't believe the precision loss will matter.
-   //
-   half4 correction = half4(inversesqrt( squareDists ));
-   nDotL = saturate( nDotL * correction );
-   rDotL = clamp( rDotL * correction, 0.00001, 1.0 );
-
-   // First calculate a simple point light linear 
-   // attenuation factor.
-   //
-   // If this is a directional light the inverse
-   // radius should be greater than the distance
-   // causing the attenuation to have no affect.
-   //
-   vec4 atten = saturate( 1.0 - ( squareDists * inLightInvRadiusSq ) );
-
-   #ifndef TORQUE_BL_NOSPOTLIGHT
-
-      // The spotlight attenuation factor.  This is really
-      // fast for what it does... 6 instructions for 4 spots.
-
-      vec4 spotAtten = vec4(0);
-      for ( i = 0; i < 3; i++ )
-         spotAtten += lightVectors[i] * inLightSpotDir[i];
-
-      vec4 cosAngle = ( spotAtten * correction ) - inLightSpotAngle;
-      atten *= saturate( cosAngle * inLightSpotFalloff );
-
-   #endif
-
-   // Finally apply the shadow masking on the attenuation.
-   atten *= shadowMask;
-
-   // Get the final light intensity.
-   vec4 intensity = nDotL * atten;
-
-   // Combine the light colors for output.
-   outDiffuse = vec4(0);
-   for ( i = 0; i < 4; i++ )
-      outDiffuse += intensity[i] * inLightColor[i];
-
-   // Output the specular power.
-   vec4 specularIntensity = pow( rDotL, vec4(specularPower) ) * atten;
-   
-   // Apply the per-light specular attenuation.
-   vec4 specular = vec4(0,0,0,1);
-   for ( i = 0; i < 4; i++ )
-      specular += vec4( inLightColor[i].rgb * inLightColor[i].a * specularIntensity[i], 1 );
-
-   // Add the final specular intensity values together
-   // using a single dot product operation then get the
-   // final specular lighting color.
-   outSpecular = specularColor * specular;
-}
-
-
-// This value is used in AL as a constant power to raise specular values
-// to, before storing them into the light info buffer. The per-material 
-// specular value is then computer by using the integer identity of 
-// exponentiation: 
-//
-//    (a^m)^n = a^(m*n)
-//
-//       or
-//
-//    (specular^constSpecular)^(matSpecular/constSpecular) = specular^(matSpecular*constSpecular)   
-//
-#define AL_ConstantSpecularPower 12.0f
-
-/// The specular calculation used in Advanced Lighting.
-///
-///   @param toLight    Normalized vector representing direction from the pixel 
-///                     being lit, to the light source, in world space.
-///
-///   @param normal  Normalized surface normal.
-///   
-///   @param toEye   The normalized vector representing direction from the pixel 
-///                  being lit to the camera.
-///
-float AL_CalcSpecular( vec3 toLight, vec3 normal, vec3 toEye )
-{
-   // (R.V)^c
-   float specVal = dot( normalize( -reflect( toLight, normal ) ), toEye );
-
-   // Return the specular factor.
-   return pow( max( specVal, 0.00001f ), AL_ConstantSpecularPower );
-}
-
-/// The output for Deferred Lighting
-///
-///   @param toLight    Normalized vector representing direction from the pixel 
-///                     being lit, to the light source, in world space.
-///
-///   @param normal  Normalized surface normal.
-///   
-///   @param toEye   The normalized vector representing direction from the pixel 
-///                  being lit to the camera.
-///
-vec4 AL_DeferredOutput(
-      vec3   lightColor,
-      vec3   diffuseColor,
-      vec4   matInfo,
-      vec4   ambient,
-      float specular,
-      float shadowAttenuation)
-{
-   vec3 specularColor = vec3(specular);
-   bool metalness = getFlag(matInfo.r, 3);
-   if ( metalness )
+   outDiffuse = vec4(0,0,0,0);
+   outSpecular = vec4(0,0,0,0);
+}
+
+struct Surface
+{
+	vec3 P;				// world space position
+	vec3 N;				// world space normal
+	vec3 V;				// world space view vector
+	vec4 baseColor;		// base color [0 -> 1] (rgba)
+	float metalness;		// metalness [0:dielectric -> 1:metal]
+	float roughness;		// roughness: [0:smooth -> 1:rough] (linear)
+	float roughness_brdf; // roughness remapped from linear to BRDF
+	float depth;         // depth: [0:near -> 1:far] (linear)
+	float ao;            // ambient occlusion [0 -> 1]
+	float matFlag;       // material flag - use getFlag to retreive 
+
+	float NdotV;			// cos(angle between normal and view vector)
+	vec3 f0;				// fresnel value (rgb)
+	vec3 albedo;			// diffuse light absorbtion value (rgb)
+	vec3 R;				// reflection vector
+	vec3 F;				// fresnel term computed from f0, N and V
+	void Update();
+};
+
+void Surface::Update()
+{
+	NdotV = abs(dot(N, V)) + 1e-5f; // avoid artifact
+
+	albedo = baseColor.rgb * (1.0 - metalness);
+	f0 = lerp(vec3(0.04), baseColor.rgb, metalness);
+	R = -reflect(V, N);
+	float f90 = saturate(50.0 * dot(f0, vec3(0.33,0.33,0.33)));
+	F = F_Schlick(f0, f90, NdotV);
+}
+	
+Surface createSurface(vec4 normDepth, sampler2D colorBuffer, sampler2D matInfoBuffer, in vec2 uv, in vec3 wsEyePos, in vec3 wsEyeRay, in mat4 invView)
+{
+	Surface surface;// = Surface();
+
+	vec4 gbuffer1 = texture(colorBuffer, uv);
+	vec4 gbuffer2 = texture(matInfoBuffer, uv);
+	surface.depth = normDepth.a;
+	surface.P = wsEyePos + wsEyeRay * surface.depth;
+	surface.N = tMul(invView, vec4(normDepth.xyz,0)).xyz; //TODO move t3d to use WS normals
+	surface.V = normalize(wsEyePos - surface.P);
+	surface.baseColor = gbuffer1;
+	const float minRoughness=1e-4;
+	surface.roughness = clamp(1.0 - gbuffer2.b, minRoughness, 1.0); //t3d uses smoothness, so we convert to roughness.
+	surface.roughness_brdf = surface.roughness * surface.roughness;
+	surface.metalness = gbuffer2.a;
+	surface.ao = gbuffer2.g;
+	surface.matFlag = gbuffer2.r;
+	surface.Update();
+	return surface;
+}
+
+Surface createForwardSurface(vec4 baseColor, vec4 normal, vec4 pbrProperties, in vec2 uv, in vec3 wsPosition, in vec3 wsEyePos, in vec3 wsEyeRay, in mat4x4 invView)
+{
+	Surface surface;// = Surface();
+
+  surface.depth = 0;
+	surface.P = wsPosition;
+	surface.N = tMul(invView, vec4(normal.xyz,0)).xyz; //TODO move t3d to use WS normals
+	surface.V = normalize(wsEyePos - surface.P);
+	surface.baseColor = baseColor;
+  const float minRoughness=1e-4;
+	surface.roughness = clamp(1.0 - pbrProperties.b, minRoughness, 1.0); //t3d uses smoothness, so we convert to roughness.
+	surface.roughness_brdf = surface.roughness * surface.roughness;
+	surface.metalness = pbrProperties.a;
+  surface.ao = pbrProperties.g;
+  surface.matFlag = pbrProperties.r;
+
+	surface.Update();
+	return surface;
+}
+
+struct SurfaceToLight
+{
+	vec3 L;				// surface to light vector
+	vec3 Lu;				// un-normalized surface to light vector
+	vec3 H;				// half-vector between view vector and light vector
+	float NdotL;			// cos(angle between N and L)
+	float HdotV;			// cos(angle between H and V) = HdotL = cos(angle between H and L)
+	float NdotH;			// cos(angle between N and H)
+
+};
+
+SurfaceToLight createSurfaceToLight(in Surface surface, in vec3 L)
+{
+	SurfaceToLight surfaceToLight;// = SurfaceToLight();
+	surfaceToLight.Lu = L;
+	surfaceToLight.L = normalize(L);
+	surfaceToLight.H = normalize(surface.V + surfaceToLight.L);
+	surfaceToLight.NdotL = saturate(dot(surfaceToLight.L, surface.N));
+	surfaceToLight.HdotV = saturate(dot(surfaceToLight.H, surface.V));
+	surfaceToLight.NdotH = saturate(dot(surfaceToLight.H, surface.N));
+	return surfaceToLight;
+}
+
+vec3 BRDF_GetSpecular(in Surface surface, in SurfaceToLight surfaceToLight)
+{
+	float f90 = saturate(50.0 * dot(surface.f0, vec3(0.33,0.33,0.33)));
+	vec3 F = F_Schlick(surface.f0, f90, surfaceToLight.HdotV);
+	float Vis = V_SmithGGXCorrelated(surface.NdotV, surfaceToLight.NdotL, surface.roughness_brdf);
+	float D = D_GGX(surfaceToLight.NdotH, surface.roughness_brdf);
+	vec3 Fr = D * F * Vis / M_PI_F;
+	return Fr;
+}
+
+vec3 BRDF_GetDiffuse(in Surface surface, in SurfaceToLight surfaceToLight)
+{
+   //getting some banding with disney method, using lambert instead - todo futher testing
+	float Fd = 1.0 / M_PI_F;
+   //energy conservation - remove this if reverting back to disney method
+   vec3 kD = vec3(1.0) - surface.F;
+	kD *= 1.0 - surface.metalness;
+   vec3 diffuse = kD * surface.baseColor.rgb * Fd;
+	return diffuse;
+}
+
+//attenuations functions from "moving frostbite to pbr paper"
+//https://seblagarde.files.wordpress.com/2015/07/course_notes_moving_frostbite_to_pbr_v32.pdf
+float smoothDistanceAtt ( float squaredDistance , float invSqrAttRadius )
+{
+   float factor = squaredDistance * invSqrAttRadius ;
+   float smoothFactor = saturate (1.0f - factor * factor );
+   return sqr(smoothFactor);
+}
+
+float getDistanceAtt( vec3 unormalizedLightVector , float invSqrAttRadius )
+{
+   float sqrDist = dot ( unormalizedLightVector , unormalizedLightVector );
+   float attenuation = 1.0 / (max ( sqrDist , 0.01*0.01) );
+   attenuation *= smoothDistanceAtt ( sqrDist , invSqrAttRadius );
+   return attenuation;
+}
+
+ float getSpotAngleAtt( vec3 normalizedLightVector , vec3 lightDir , vec2 lightSpotParams )
+ {
+   float cd = dot ( lightDir , normalizedLightVector );
+   float attenuation = saturate ( ( cd - lightSpotParams.x ) / lightSpotParams.y );
+   // smooth the transition
+   return sqr(attenuation);
+}
+
+vec3 getDirectionalLight(in Surface surface, in SurfaceToLight surfaceToLight, vec3 lightColor, float lightIntensity, float shadow)
+{
+   vec3 factor = lightColor * max(surfaceToLight.NdotL, 0) * shadow * lightIntensity;
+   vec3 diffuse = BRDF_GetDiffuse(surface,surfaceToLight) * factor;
+   vec3 spec = BRDF_GetSpecular(surface,surfaceToLight) * factor;
+
+   vec3 final = max(vec3(0.0f), diffuse + spec * surface.ao);
+   return final;
+}
+
+vec3 getPunctualLight(in Surface surface, in SurfaceToLight surfaceToLight, vec3 lightColor, float lightIntensity, float radius, float shadow)
+{
+   float attenuation = getDistanceAtt(surfaceToLight.Lu, radius);
+   vec3 factor = lightColor * max(surfaceToLight.NdotL, 0) * shadow * lightIntensity * attenuation;
+
+   vec3 diffuse = BRDF_GetDiffuse(surface,surfaceToLight) * factor;
+   vec3 spec = BRDF_GetSpecular(surface,surfaceToLight) * factor;
+
+   vec3 final = max(vec3(0.0f), diffuse + spec * surface.ao * surface.F);
+   return final;
+}
+
+float G1V(float dotNV, float k)
+{
+	return 1.0f/(dotNV*(1.0f-k)+k);
+}
+
+vec3 directSpecular(vec3 N, vec3 V, vec3 L, float roughness, float F0)
+{
+	float alpha = roughness*roughness;
+
+	//TODO don't need to calculate all this again timmy!!!!!!
+    vec3 H = normalize(V + L);
+    float dotNL = clamp(dot(N,L), 0.0, 1.0);
+    float dotNV = clamp(dot(N,V), 0.0, 1.0);
+    float dotNH = clamp(dot(N,H), 0.0, 1.0);
+	float dotHV = clamp(dot(H,V), 0.0, 1.0);
+	float dotLH = clamp(dot(L,H), 0.0, 1.0);
+
+	float F, D, vis;
+
+	// D
+	float alphaSqr = alpha*alpha;
+	float pi = 3.14159f;
+	float denom = dotNH * dotNH *(alphaSqr-1.0) + 1.0f;
+	D = alphaSqr/(pi * denom * denom);
+
+	// F
+	float dotLH5 = pow(1.0f-dotLH,5);
+	F = F0 + (1.0-F0)*(dotLH5);
+
+	// V
+	float k = alpha/2.0f;
+	vis = G1V(dotNL,k)*G1V(dotNV,k);
+
+	float specular = dotNL * D * F * vis;
+	return vec3(specular,specular,specular);
+}
+
+//Probe IBL stuff
+float defineSphereSpaceInfluence(vec3 wsPosition, vec3 wsProbePosition, float radius)
+{
+   vec3 L = wsProbePosition.xyz - wsPosition;
+   float contribution = 1.0 - length(L) / radius;
+   return contribution;
+}
+
+float getDistBoxToPoint(vec3 pt, vec3 extents)
+{
+   vec3 d = max(max(-extents - pt, 0), pt - extents);
+   return max(max(d.x, d.y), d.z);
+}
+
+float defineBoxSpaceInfluence(vec3 wsPosition, mat4 worldToObj, float attenuation)
+{
+   vec3 surfPosLS = tMul(worldToObj, vec4(wsPosition, 1.0)).xyz;
+   float atten = 1.0 - attenuation;
+   float baseVal = 0.25;
+   float dist = getDistBoxToPoint(surfPosLS, vec3(baseVal, baseVal, baseVal));
+   return saturate(smoothstep(baseVal + 0.0001, atten*baseVal, dist));
+}
+
+// Box Projected IBL Lighting
+// Based on: http://www.gamedev.net/topic/568829-box-projected-cubemap-environment-mapping/
+// and https://seblagarde.wordpress.com/2012/09/29/image-based-lighting-approaches-and-parallax-corrected-cubemap/
+vec3 boxProject(vec3 wsPosition, vec3 wsReflectVec, mat4 worldToObj, vec3 bbMin, vec3 bbMax, vec3 refPosition)
+{
+   vec3 RayLS = tMul(worldToObj, vec4(wsReflectVec, 0.0)).xyz;
+   vec3 PositionLS = tMul(worldToObj, vec4(wsPosition, 1.0)).xyz;
+
+   vec3 unit = bbMax.xyz - bbMin.xyz;
+   vec3 plane1vec = (unit / 2 - PositionLS) / RayLS;
+   vec3 plane2vec = (-unit / 2 - PositionLS) / RayLS;
+   vec3 furthestPlane = max(plane1vec, plane2vec);
+   float dist = min(min(furthestPlane.x, furthestPlane.y), furthestPlane.z);
+   vec3 posonbox = wsPosition + wsReflectVec * dist;
+
+   return posonbox - refPosition.xyz;
+}
+
+vec4 computeForwardProbes(Surface surface,
+    float cubeMips, float numProbes, mat4x4 worldToObjArray[MAX_FORWARD_PROBES], vec4 probeConfigData[MAX_FORWARD_PROBES], 
+    vec4 inProbePosArray[MAX_FORWARD_PROBES], vec4 bbMinArray[MAX_FORWARD_PROBES], vec4 bbMaxArray[MAX_FORWARD_PROBES], vec4 inRefPosArray[MAX_FORWARD_PROBES],
+    float hasSkylight, sampler2D BRDFTexture, 
+	samplerCube skylightIrradMap, samplerCube skylightSpecularMap,
+	samplerCubeArray irradianceCubemapAR, samplerCubeArray specularCubemapAR)
+{
+  int i = 0;
+   float blendFactor[MAX_FORWARD_PROBES];
+   float blendSum = 0;
+   float blendFacSum = 0;
+   float invBlendSum = 0;
+   float probehits = 0;
+   //Set up our struct data
+   float contribution[MAX_FORWARD_PROBES];
+  for (i = 0; i < numProbes; ++i)
+  {
+      contribution[i] = 0;
+
+      if (probeConfigData[i].r == 0) //box
+      {
+         contribution[i] = defineBoxSpaceInfluence(surface.P, worldToObjArray[i], probeConfigData[i].b);
+         if (contribution[i] > 0.0)
+            probehits++;
+      }
+      else if (probeConfigData[i].r == 1) //sphere
+      {
+         contribution[i] = defineSphereSpaceInfluence(surface.P, inProbePosArray[i].xyz, probeConfigData[i].g);
+         if (contribution[i] > 0.0)
+            probehits++;
+      }
+
+      contribution[i] = max(contribution[i], 0);
+
+      blendSum += contribution[i];
+      invBlendSum += (1.0f - contribution[i]);
+   }
+
+   if (probehits > 1.0)
    {
    {
-       specularColor = 0.04 * (1 - specular) + diffuseColor * specular;
+      for (i = 0; i < numProbes; i++)
+      {
+         blendFactor[i] = ((contribution[i] / blendSum)) / probehits;
+         blendFactor[i] *= ((contribution[i]) / invBlendSum);
+         blendFactor[i] = saturate(blendFactor[i]);
+         blendFacSum += blendFactor[i];
+      }
+
+      // Normalize blendVal
+      if (blendFacSum == 0.0f) // Possible with custom weight
+      {
+         blendFacSum = 1.0f;
+      }
+
+      float invBlendSumWeighted = 1.0f / blendFacSum;
+      for (i = 0; i < numProbes; ++i)
+      {
+         blendFactor[i] *= invBlendSumWeighted;
+         contribution[i] *= blendFactor[i];
+      }
    }
    }
 
 
-   //specular = color * map * spec^gloss
-   float specularOut = (specularColor * matInfo.b * min(pow(max(specular,1.0f), max((matInfo.a / AL_ConstantSpecularPower),1.0f)),matInfo.a)).r;
-      
-   lightColor *= vec3(shadowAttenuation);
-   lightColor += ambient.rgb;
-   return vec4(lightColor.rgb, specularOut); 
-}
+   vec3 irradiance = vec3(0, 0, 0);
+   vec3 specular = vec3(0, 0, 0);
+
+   // Radiance (Specular)
+   float lod = surface.roughness*cubeMips;
+
+//1
+   float alpha = 1.0f;
+   for (i = 0; i < numProbes; ++i)
+   {
+      float contrib = contribution[i];
+      if (contrib != 0)
+      {
+         int cubemapIdx = int(probeConfigData[i].a);
+         vec3 dir = boxProject(surface.P, surface.R, worldToObjArray[i], bbMinArray[i].xyz, bbMaxArray[i].xyz, inRefPosArray[i].xyz);
+
+         irradiance += textureLod(irradianceCubemapAR, vec4(dir, cubemapIdx), 0).xyz * contrib;
+         specular += textureLod(specularCubemapAR, vec4(dir, cubemapIdx), lod).xyz * contrib;
+         alpha -= contrib;
+      }
+   }
+
+   if (hasSkylight == 1 && alpha > 0.001)
+   {
+      irradiance += textureLod(skylightIrradMap, surface.R, 0).xyz * alpha;
+      specular += textureLod(skylightSpecularMap, surface.R, lod).xyz * alpha;
+   }
+
+   vec3 F = FresnelSchlickRoughness(surface.NdotV, surface.f0, surface.roughness);
+
+   //energy conservation
+   vec3 kD = vec3(1.0,1.0,1.0) - F;
+   kD *= 1.0 - surface.metalness;
+
+   //apply brdf
+   //Do it once to save on texture samples
+   vec2 brdf = textureLod(BRDFTexture, vec2(surface.roughness, surface.NdotV),0).xy;
+   specular *= brdf.x * F + brdf.y;
+
+   //final diffuse color
+   vec3 diffuse = kD * irradiance * surface.baseColor.rgb;
+   vec4 finalColor = vec4(diffuse + specular * surface.ao, 1.0);
+
+   finalColor = vec4(irradiance.rgb,1);
+   return finalColor;
+}

+ 50 - 1
Templates/BaseGame/game/core/rendering/shaders/gl/torque.glsl

@@ -22,7 +22,7 @@
 
 
 #ifndef _TORQUE_GLSL_
 #ifndef _TORQUE_GLSL_
 #define _TORQUE_GLSL_
 #define _TORQUE_GLSL_
-
+#line 25
 
 
 float M_HALFPI_F   = 1.57079632679489661923;
 float M_HALFPI_F   = 1.57079632679489661923;
 float M_PI_F       = 3.14159265358979323846;
 float M_PI_F       = 3.14159265358979323846;
@@ -336,4 +336,53 @@ vec3 toGamma(vec3 tex)
 }
 }
 #endif //
 #endif //
 
 
+vec3 PBRFresnel(vec3 albedo, vec3 indirect, float metalness, float fresnel)
+{
+   vec3 diffuseColor = albedo - (albedo * metalness);
+   vec3 reflectColor = mix(indirect*albedo, indirect, fresnel);
+
+   return diffuseColor + reflectColor;
+}
+
+vec3 simpleFresnel(vec3 diffuseColor, vec3 reflectColor, float metalness, float angle, float bias, float power)
+{
+   float fresnelTerm = bias + (1.0 - bias) * pow(abs(1.0 - max(angle, 0)), power);
+
+   fresnelTerm *= metalness;
+
+   return mix(diffuseColor, reflectColor, fresnelTerm);
+}
+
+//get direction for a cube face
+vec3 getCubeDir(int face, vec2 uv)
+{
+	vec2 debiased = uv * 2.0f - 1.0f;
+
+	vec3 dir = vec3(0);
+
+	switch (face)
+	{
+		case 0: dir = vec3(1, -debiased.y, -debiased.x); 
+			break;
+
+		case 1: dir = vec3(-1, -debiased.y, debiased.x); 
+			break;
+
+		case 2: dir = vec3(debiased.x, 1, debiased.y); 
+			break;
+
+		case 3: dir = vec3(debiased.x, -1, -debiased.y); 
+			break;
+
+		case 4: dir = vec3(debiased.x, -debiased.y, 1); 
+			break;
+
+		case 5: dir = vec3(-debiased.x, -debiased.y, -1); 
+			break;
+	};
+
+	return normalize(dir);
+}
+
+#define sqr(a)		((a)*(a))
 #endif // _TORQUE_GLSL_
 #endif // _TORQUE_GLSL_

+ 346 - 186
Templates/BaseGame/game/core/rendering/shaders/lighting.hlsl

@@ -1,6 +1,6 @@
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 // Copyright (c) 2012 GarageGames, LLC
 // Copyright (c) 2012 GarageGames, LLC
-//
+// Portions Copyright Zefiros
 // Permission is hereby granted, free of charge, to any person obtaining a copy
 // Permission is hereby granted, free of charge, to any person obtaining a copy
 // of this software and associated documentation files (the "Software"), to
 // of this software and associated documentation files (the "Software"), to
 // deal in the Software without restriction, including without limitation the
 // deal in the Software without restriction, including without limitation the
@@ -21,6 +21,8 @@
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 
 
 #include "./torque.hlsl"
 #include "./torque.hlsl"
+#include "./brdf.hlsl"
+#include "./shaderModelAutoGen.hlsl"
 
 
 #ifndef TORQUE_SHADERGEN
 #ifndef TORQUE_SHADERGEN
 
 
@@ -37,13 +39,33 @@ uniform float4 inLightColor[4];
 #endif
 #endif
 
 
 uniform float4 ambient;
 uniform float4 ambient;
-#define ambientCameraFactor 0.3
-uniform float specularPower;
-uniform float4 specularColor;
+uniform float smoothness;
+uniform float metalness;
+uniform float4 albedo;
 
 
 #endif // !TORQUE_SHADERGEN
 #endif // !TORQUE_SHADERGEN
 
 
+#define MAX_PROBES 50
+#define MAX_FORWARD_PROBES 4
+
+inline float3 getDistanceVectorToPlane( float3 origin, float3 direction, float4 plane )
+{
+   float denum = dot( plane.xyz, direction.xyz );
+   float num = dot( plane, float4( origin, 1.0 ) );
+   float t = -num / denum;
+
+   return direction.xyz * t;
+}
+
+inline float3 getDistanceVectorToPlane( float negFarPlaneDotEye, float3 direction, float4 plane )
+{
+   float denum = dot( plane.xyz, direction.xyz );
+   float t = negFarPlaneDotEye / denum;
 
 
+   return direction.xyz * t;
+}
+
+//TODO fix compute 4 lights
 void compute4Lights( float3 wsView, 
 void compute4Lights( float3 wsView, 
                      float3 wsPosition, 
                      float3 wsPosition, 
                      float3 wsNormal,
                      float3 wsNormal,
@@ -57,193 +79,331 @@ void compute4Lights( float3 wsView,
                         float4 inLightSpotDir[3],
                         float4 inLightSpotDir[3],
                         float4 inLightSpotAngle,
                         float4 inLightSpotAngle,
                         float4 inLightSpotFalloff,
                         float4 inLightSpotFalloff,
-                        float specularPower,
-                        float4 specularColor,
+                        float smoothness,
+                        float metalness,
+                        float4 albedo,
 
 
                      #endif // TORQUE_SHADERGEN
                      #endif // TORQUE_SHADERGEN
                      
                      
                      out float4 outDiffuse,
                      out float4 outDiffuse,
                      out float4 outSpecular )
                      out float4 outSpecular )
 {
 {
-   // NOTE: The light positions and spotlight directions
-   // are stored in SoA order, so inLightPos[0] is the
-   // x coord for all 4 lights... inLightPos[1] is y... etc.
-   //
-   // This is the key to fully utilizing the vector units and
-   // saving a huge amount of instructions.
-   //
-   // For example this change saved more than 10 instructions 
-   // over a simple for loop for each light.
-   
-   int i;
-
-   float4 lightVectors[3];
-   for ( i = 0; i < 3; i++ )
-      lightVectors[i] = wsPosition[i] - inLightPos[i];
-
-   float4 squareDists = 0;
-   for ( i = 0; i < 3; i++ )
-      squareDists += lightVectors[i] * lightVectors[i];
-
-   // Accumulate the dot product between the light 
-   // vector and the normal.
-   //
-   // The normal is negated because it faces away from
-   // the surface and the light faces towards the
-   // surface... this keeps us from needing to flip
-   // the light vector direction which complicates
-   // the spot light calculations.
-   //
-   // We normalize the result a little later.
-   //
-   float4 nDotL = 0;
-   for ( i = 0; i < 3; i++ )
-      nDotL += lightVectors[i] * -wsNormal[i];
-
-   float4 rDotL = 0;
-   #ifndef TORQUE_BL_NOSPECULAR
-
-      // We're using the Phong specular reflection model
-      // here where traditionally Torque has used Blinn-Phong
-      // which has proven to be more accurate to real materials.
-      //
-      // We do so because its cheaper as do not need to 
-      // calculate the half angle for all 4 lights.
-      //   
-      // Advanced Lighting still uses Blinn-Phong, but the
-      // specular reconstruction it does looks fairly similar
-      // to this.
-      //
-      float3 R = reflect( wsView, -wsNormal );
-
-      for ( i = 0; i < 3; i++ )
-         rDotL += lightVectors[i] * R[i];
-
-   #endif
- 
-   // Normalize the dots.
-   //
-   // Notice we're using the half type here to get a
-   // much faster sqrt via the rsq_pp instruction at 
-   // the loss of some precision.
-   //
-   // Unless we have some extremely large point lights
-   // i don't believe the precision loss will matter.
-   //
-   half4 correction = (half4)rsqrt( squareDists );
-   nDotL = saturate( nDotL * correction );
-   rDotL = clamp( rDotL * correction, 0.00001, 1.0 );
-
-   // First calculate a simple point light linear 
-   // attenuation factor.
-   //
-   // If this is a directional light the inverse
-   // radius should be greater than the distance
-   // causing the attenuation to have no affect.
-   //
-   float4 atten = saturate( 1.0 - ( squareDists * inLightInvRadiusSq ) );
-
-   #ifndef TORQUE_BL_NOSPOTLIGHT
-
-      // The spotlight attenuation factor.  This is really
-      // fast for what it does... 6 instructions for 4 spots.
-
-      float4 spotAtten = 0;
-      for ( i = 0; i < 3; i++ )
-         spotAtten += lightVectors[i] * inLightSpotDir[i];
-
-      float4 cosAngle = ( spotAtten * correction ) - inLightSpotAngle;
-      atten *= saturate( cosAngle * inLightSpotFalloff );
-
-   #endif
-
-   // Finally apply the shadow masking on the attenuation.
-   atten *= shadowMask;
-
-   // Get the final light intensity.
-   float4 intensity = nDotL * atten;
-
-   // Combine the light colors for output.
-   outDiffuse = 0;
-   for ( i = 0; i < 4; i++ )
-      outDiffuse += intensity[i] * inLightColor[i];
-
-   // Output the specular power.
-   float4 specularIntensity = pow( rDotL, specularPower.xxxx ) * atten;
-   
-   // Apply the per-light specular attenuation.
-   float4 specular = float4(0,0,0,1);
-   for ( i = 0; i < 4; i++ )
-      specular += float4( inLightColor[i].rgb * inLightColor[i].a * specularIntensity[i], 1 );
-
-   // Add the final specular intensity values together
-   // using a single dot product operation then get the
-   // final specular lighting color.
-   outSpecular = specularColor * specular;
-}
-
-
-// This value is used in AL as a constant power to raise specular values
-// to, before storing them into the light info buffer. The per-material 
-// specular value is then computer by using the integer identity of 
-// exponentiation: 
-//
-//    (a^m)^n = a^(m*n)
-//
-//       or
-//
-//    (specular^constSpecular)^(matSpecular/constSpecular) = specular^(matSpecular*constSpecular)   
-//
-#define AL_ConstantSpecularPower 12.0f
-
-/// The specular calculation used in Advanced Lighting.
-///
-///   @param toLight    Normalized vector representing direction from the pixel 
-///                     being lit, to the light source, in world space.
-///
-///   @param normal  Normalized surface normal.
-///   
-///   @param toEye   The normalized vector representing direction from the pixel 
-///                  being lit to the camera.
-///
-float AL_CalcSpecular( float3 toLight, float3 normal, float3 toEye )
-{
-   // (R.V)^c
-   float specVal = dot( normalize( -reflect( toLight, normal ) ), toEye );
-
-   // Return the specular factor.
-   return pow( max( specVal, 0.00001f ), AL_ConstantSpecularPower );
-}
-
-/// The output for Deferred Lighting
-///
-///   @param toLight    Normalized vector representing direction from the pixel 
-///                     being lit, to the light source, in world space.
-///
-///   @param normal  Normalized surface normal.
-///   
-///   @param toEye   The normalized vector representing direction from the pixel 
-///                  being lit to the camera.
-///
-float4 AL_DeferredOutput(
-      float3   lightColor,
-      float3   diffuseColor,
-      float4   matInfo,
-      float4   ambient,
-      float    specular,
-      float    shadowAttenuation)
-{
-   float3 specularColor = float3(specular, specular, specular);
-   bool metalness = getFlag(matInfo.r, 3);
-   if ( metalness )
+
+   outDiffuse = float4(0,0,0,0);
+   outSpecular = float4(0,0,0,0);
+}
+
+struct Surface
+{
+	float3 P;				// world space position
+	float3 N;				// world space normal
+	float3 V;				// world space view vector
+	float4 baseColor;		// base color [0 -> 1] (rgba)
+	float metalness;		// metalness [0:dielectric -> 1:metal]
+	float roughness;		// roughness: [0:smooth -> 1:rough] (linear)
+	float roughness_brdf; // roughness remapped from linear to BRDF
+   float depth;         // depth: [0:near -> 1:far] (linear)
+   float ao;            // ambient occlusion [0 -> 1]
+   float matFlag;       // material flag - use getFlag to retreive 
+
+	float NdotV;			// cos(angle between normal and view vector)
+	float3 f0;				// fresnel value (rgb)
+	float3 albedo;			// diffuse light absorbtion value (rgb)
+	float3 R;				// reflection vector
+	float3 F;				// fresnel term computed from f0, N and V
+
+	inline void Update()
+	{
+		NdotV = abs(dot(N, V)) + 1e-5f; // avoid artifact
+
+		albedo = baseColor.rgb * (1.0 - metalness);
+		f0 = lerp(0.04.xxx, baseColor.rgb, metalness);
+
+		R = -reflect(V, N);
+		float f90 = saturate(50.0 * dot(f0, 0.33));
+		F = F_Schlick(f0, f90, NdotV);
+	}
+};
+
+inline Surface createSurface(float4 gbuffer0, TORQUE_SAMPLER2D(gbufferTex1), TORQUE_SAMPLER2D(gbufferTex2), in float2 uv, in float3 wsEyePos, in float3 wsEyeRay, in float4x4 invView)
+{
+	Surface surface = (Surface)0;
+
+   float4 gbuffer1 = TORQUE_TEX2DLOD(gbufferTex1, float4(uv,0,0));
+   float4 gbuffer2 = TORQUE_TEX2DLOD(gbufferTex2, float4(uv,0,0));
+
+   surface.depth = gbuffer0.a;
+	surface.P = wsEyePos + wsEyeRay * surface.depth;
+	surface.N = mul(invView, float4(gbuffer0.xyz,0)).xyz; //TODO move t3d to use WS normals
+	surface.V = normalize(wsEyePos - surface.P);
+	surface.baseColor = gbuffer1;
+   const float minRoughness=1e-4;
+	surface.roughness = clamp(1.0 - gbuffer2.b, minRoughness, 1.0); //t3d uses smoothness, so we convert to roughness.
+	surface.roughness_brdf = surface.roughness * surface.roughness;
+	surface.metalness = gbuffer2.a;
+   surface.ao = gbuffer2.g;
+   surface.matFlag = gbuffer2.r;
+
+	surface.Update();
+	return surface;
+}
+
+inline Surface createForwardSurface(float4 baseColor, float3 normal, float4 pbrProperties, in float2 uv, 
+                            in float3 wsPosition, in float3 wsEyePos, in float3 wsEyeRay)
+{
+	Surface surface = (Surface)0;
+
+  surface.depth = 0;
+	surface.P = wsPosition;
+	surface.N = normal;
+	surface.V = normalize(wsEyePos - surface.P);
+	surface.baseColor = baseColor;
+  const float minRoughness=1e-4;
+	surface.roughness = clamp(1.0 - pbrProperties.b, minRoughness, 1); //t3d uses smoothness, so we convert to roughness.
+	surface.roughness_brdf = surface.roughness * surface.roughness;
+	surface.metalness = pbrProperties.a;
+  surface.ao = pbrProperties.g;
+  surface.matFlag = pbrProperties.r;
+
+	surface.Update();
+	return surface;
+}
+
+struct SurfaceToLight
+{
+	float3 L;				// surface to light vector
+   float3 Lu;				// un-normalized surface to light vector
+	float3 H;				// half-vector between view vector and light vector
+	float NdotL;			// cos(angle between N and L)
+	float HdotV;			// cos(angle between H and V) = HdotL = cos(angle between H and L)
+	float NdotH;			// cos(angle between N and H)
+};
+
+inline SurfaceToLight createSurfaceToLight(in Surface surface, in float3 L)
+{
+	SurfaceToLight surfaceToLight = (SurfaceToLight)0;
+   surfaceToLight.Lu = L;
+	surfaceToLight.L = normalize(L);
+	surfaceToLight.H = normalize(surface.V + surfaceToLight.L);
+	surfaceToLight.NdotL = saturate(dot(surfaceToLight.L, surface.N));
+	surfaceToLight.HdotV = saturate(dot(surfaceToLight.H, surface.V));
+	surfaceToLight.NdotH = saturate(dot(surfaceToLight.H, surface.N));
+
+	return surfaceToLight;
+}
+
+float3 BRDF_GetSpecular(in Surface surface, in SurfaceToLight surfaceToLight)
+{
+	float f90 = saturate(50.0 * dot(surface.f0, 0.33));
+	float3 F = F_Schlick(surface.f0, f90, surfaceToLight.HdotV);
+	float Vis = V_SmithGGXCorrelated(surface.NdotV, surfaceToLight.NdotL, surface.roughness_brdf);
+	float D = D_GGX(surfaceToLight.NdotH, surface.roughness_brdf);
+	float3 Fr = D * F * Vis / M_PI_F;
+	return Fr;
+}
+
+float3 BRDF_GetDiffuse(in Surface surface, in SurfaceToLight surfaceToLight)
+{
+   //getting some banding with disney method, using lambert instead - todo futher testing
+	float Fd = 1.0 / M_PI_F;
+   //energy conservation - remove this if reverting back to disney method
+   float3 kD = 1.0.xxx - surface.F;
+	kD *= 1.0 - surface.metalness;
+   float3 diffuse = kD * surface.baseColor.rgb * Fd;
+	return diffuse;
+}
+
+//attenuations functions from "moving frostbite to pbr paper"
+//https://seblagarde.files.wordpress.com/2015/07/course_notes_moving_frostbite_to_pbr_v32.pdf
+float smoothDistanceAtt ( float squaredDistance , float invSqrAttRadius )
+{
+   float factor = squaredDistance * invSqrAttRadius ;
+   float smoothFactor = saturate (1.0f - factor * factor );
+   return sqr(smoothFactor);
+}
+
+float getDistanceAtt( float3 unormalizedLightVector , float invSqrAttRadius )
+{
+   float sqrDist = dot ( unormalizedLightVector , unormalizedLightVector );
+   float attenuation = 1.0 / (max ( sqrDist , 0.01*0.01) );
+   attenuation *= smoothDistanceAtt ( sqrDist , invSqrAttRadius );
+   return attenuation;
+}
+
+ float getSpotAngleAtt( float3 normalizedLightVector , float3 lightDir , float2 lightSpotParams )
+ {
+   float cd = dot ( lightDir , normalizedLightVector );
+   float attenuation = saturate ( ( cd - lightSpotParams.x ) / lightSpotParams.y );
+   // smooth the transition
+   return sqr(attenuation);
+}
+
+inline float3 getDirectionalLight(in Surface surface, in SurfaceToLight surfaceToLight, float3 lightColor, float lightIntensity, float shadow)
+{
+   float3 factor = lightColor * max(surfaceToLight.NdotL, 0) * shadow * lightIntensity;
+   float3 diffuse = BRDF_GetDiffuse(surface,surfaceToLight) * factor;
+   float3 spec = BRDF_GetSpecular(surface,surfaceToLight) * factor;
+
+   float3 final = max(0.0f, diffuse + spec * surface.ao);
+   return final;
+}
+
+inline float3 getPunctualLight(in Surface surface, in SurfaceToLight surfaceToLight, float3 lightColor, float lightIntensity, float radius, float shadow)
+{
+   float attenuation = getDistanceAtt(surfaceToLight.Lu, radius);
+   float3 factor = lightColor * max(surfaceToLight.NdotL, 0) * shadow * lightIntensity * attenuation;
+
+   float3 diffuse = BRDF_GetDiffuse(surface,surfaceToLight) * factor;
+   float3 spec = BRDF_GetSpecular(surface,surfaceToLight) * factor;
+
+   float3 final = max(0.0f, diffuse + spec * surface.ao * surface.F);
+   return final;
+}
+
+//Probe IBL stuff
+float defineSphereSpaceInfluence(float3 wsPosition, float3 wsProbePosition, float radius)
+{
+   float3 L = wsProbePosition.xyz - wsPosition;
+   float contribution = 1.0 - length(L) / radius;
+   return contribution;
+}
+
+float getDistBoxToPoint(float3 pt, float3 extents)
+{
+   float3 d = max(max(-extents - pt, 0), pt - extents);
+   return max(max(d.x, d.y), d.z);
+}
+
+float defineBoxSpaceInfluence(float3 wsPosition, float4x4 worldToObj, float attenuation)
+{
+   float3 surfPosLS = mul(worldToObj, float4(wsPosition, 1.0)).xyz;
+   float atten = 1.0 - attenuation;
+   float baseVal = 0.25;
+   float dist = getDistBoxToPoint(surfPosLS, float3(baseVal, baseVal, baseVal));
+   return saturate(smoothstep(baseVal + 0.0001, atten*baseVal, dist));
+}
+
+// Box Projected IBL Lighting
+// Based on: http://www.gamedev.net/topic/568829-box-projected-cubemap-environment-mapping/
+// and https://seblagarde.wordpress.com/2012/09/29/image-based-lighting-approaches-and-parallax-corrected-cubemap/
+float3 boxProject(float3 wsPosition, float3 wsReflectVec, float4x4 worldToObj, float3 bbMin, float3 bbMax, float3 refPosition)
+{
+   float3 RayLS = mul(worldToObj, float4(wsReflectVec, 0.0)).xyz;
+   float3 PositionLS = mul(worldToObj, float4(wsPosition, 1.0)).xyz;
+
+   float3 unit = bbMax.xyz - bbMin.xyz;
+   float3 plane1vec = (unit / 2 - PositionLS) / RayLS;
+   float3 plane2vec = (-unit / 2 - PositionLS) / RayLS;
+   float3 furthestPlane = max(plane1vec, plane2vec);
+   float dist = min(min(furthestPlane.x, furthestPlane.y), furthestPlane.z);
+   float3 posonbox = wsPosition + wsReflectVec * dist;
+
+   return posonbox - refPosition.xyz;
+}
+
+float4 computeForwardProbes(Surface surface,
+    float cubeMips, float numProbes, float4x4 worldToObjArray[MAX_FORWARD_PROBES], float4 probeConfigData[MAX_FORWARD_PROBES], 
+    float4 inProbePosArray[MAX_FORWARD_PROBES], float4 bbMinArray[MAX_FORWARD_PROBES], float4 bbMaxArray[MAX_FORWARD_PROBES], float4 inRefPosArray[MAX_FORWARD_PROBES],
+    float hasSkylight, TORQUE_SAMPLER2D(BRDFTexture), 
+	TORQUE_SAMPLERCUBE(skylightIrradMap), TORQUE_SAMPLERCUBE(skylightSpecularMap),
+	TORQUE_SAMPLERCUBEARRAY(irradianceCubemapAR), TORQUE_SAMPLERCUBEARRAY(specularCubemapAR))
+{
+  int i = 0;
+   float blendFactor[MAX_FORWARD_PROBES];
+   float blendSum = 0;
+   float blendFacSum = 0;
+   float invBlendSum = 0;
+   float probehits = 0;
+   //Set up our struct data
+   float contribution[MAX_FORWARD_PROBES];
+  for (i = 0; i < numProbes; ++i)
+  {
+      contribution[i] = 0;
+
+      if (probeConfigData[i].r == 0) //box
+      {
+         contribution[i] = defineBoxSpaceInfluence(surface.P, worldToObjArray[i], probeConfigData[i].b);
+         if (contribution[i] > 0.0)
+            probehits++;
+      }
+      else if (probeConfigData[i].r == 1) //sphere
+      {
+         contribution[i] = defineSphereSpaceInfluence(surface.P, inProbePosArray[i].xyz, probeConfigData[i].g);
+         if (contribution[i] > 0.0)
+            probehits++;
+      }
+
+      contribution[i] = max(contribution[i], 0);
+
+      blendSum += contribution[i];
+      invBlendSum += (1.0f - contribution[i]);
+   }
+
+   if (probehits > 1.0)
    {
    {
-       specularColor = 0.04 * (1 - specular) + diffuseColor * specular;
+      for (i = 0; i < numProbes; i++)
+      {
+         blendFactor[i] = ((contribution[i] / blendSum)) / probehits;
+         blendFactor[i] *= ((contribution[i]) / invBlendSum);
+         blendFactor[i] = saturate(blendFactor[i]);
+         blendFacSum += blendFactor[i];
+      }
+
+      // Normalize blendVal
+      if (blendFacSum == 0.0f) // Possible with custom weight
+      {
+         blendFacSum = 1.0f;
+      }
+
+      float invBlendSumWeighted = 1.0f / blendFacSum;
+      for (i = 0; i < numProbes; ++i)
+      {
+         blendFactor[i] *= invBlendSumWeighted;
+         contribution[i] *= blendFactor[i];
+      }
    }
    }
-   
-   //specular = color * map * spec^gloss
-   float specularOut = (specularColor * matInfo.b * min(pow(abs(specular), max(( matInfo.a/ AL_ConstantSpecularPower),1.0f)),matInfo.a)).r;
-   
-   lightColor *= shadowAttenuation;
-   lightColor += ambient.rgb;
-   return float4(lightColor.rgb, specularOut); 
-}
+
+   float3 irradiance = float3(0, 0, 0);
+   float3 specular = float3(0, 0, 0);
+
+   // Radiance (Specular)
+   float lod = surface.roughness*cubeMips;
+
+   float alpha = 1;
+   for (i = 0; i < numProbes; ++i)
+   {
+      float contrib = contribution[i];
+      if (contrib != 0)
+      {
+         int cubemapIdx = probeConfigData[i].a;
+         float3 dir = boxProject(surface.P, surface.R, worldToObjArray[i], bbMinArray[i].xyz, bbMaxArray[i].xyz, inRefPosArray[i].xyz);
+
+         irradiance += TORQUE_TEXCUBEARRAYLOD(irradianceCubemapAR, dir, cubemapIdx, 0).xyz * contrib;
+         specular += TORQUE_TEXCUBEARRAYLOD(specularCubemapAR, dir, cubemapIdx, lod).xyz * contrib;
+         alpha -= contrib;
+      }
+   }
+
+   if (hasSkylight && alpha > 0.001)
+   {
+      irradiance += TORQUE_TEXCUBELOD(skylightIrradMap, float4(surface.R, 0)).xyz;
+      specular = TORQUE_TEXCUBELOD(skylightSpecularMap, float4(surface.R, lod)).xyz;
+   }
+
+   float3 F = FresnelSchlickRoughness(surface.NdotV, surface.f0, surface.roughness);
+
+   //energy conservation
+   float3 kD = 1.0.xxx - F;
+   kD *= 1.0 - surface.metalness;
+
+   //apply brdf
+   //Do it once to save on texture samples
+   float2 brdf = TORQUE_TEX2DLOD(BRDFTexture,float4(surface.roughness, 1.0-surface.NdotV, 0.0, 0.0)).xy;
+   specular *= brdf.x * F + brdf.y;
+
+   //final diffuse color
+   float3 diffuse = kD * irradiance * surface.baseColor.rgb;
+   float4 finalColor = float4(diffuse + specular, 1); 
+//finalColor.rgb += abs(surface.N);
+   return finalColor;
+}

+ 6 - 5
Templates/BaseGame/game/core/rendering/shaders/lighting/advanced/convexGeometryV.hlsl

@@ -37,11 +37,12 @@ struct ConvexConnectV
    float4 vsEyeDir : TEXCOORD2;
    float4 vsEyeDir : TEXCOORD2;
 };
 };
 
 
-ConvexConnectV main( VertData IN,
-                     uniform float4x4 modelview,
-                     uniform float4x4 objTrans,
-                     uniform float4x4 worldViewOnly,
-                     uniform float3 eyePosWorld )
+uniform float4x4 modelview;
+uniform float4x4 objTrans;
+uniform float4x4 worldViewOnly;
+uniform float3 eyePosWorld;
+
+ConvexConnectV main( VertData IN )
 {
 {
    ConvexConnectV OUT;
    ConvexConnectV OUT;
 
 

+ 37 - 0
Templates/BaseGame/game/core/rendering/shaders/lighting/advanced/cubemapV.hlsl

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

+ 2 - 2
Templates/BaseGame/game/core/rendering/shaders/lighting/advanced/farFrustumQuadV.hlsl

@@ -23,9 +23,9 @@
 #include "../../hlslStructs.hlsl"
 #include "../../hlslStructs.hlsl"
 #include "farFrustumQuad.hlsl"
 #include "farFrustumQuad.hlsl"
 
 
+uniform float4 rtParams0;
 
 
-FarFrustumQuadConnectV main( VertexIn_PNTT IN,
-                             uniform float4 rtParams0 )
+FarFrustumQuadConnectV main( VertexIn_PNTT IN )
 {
 {
    FarFrustumQuadConnectV OUT;
    FarFrustumQuadConnectV OUT;
 
 

+ 136 - 0
Templates/BaseGame/game/core/rendering/shaders/lighting/advanced/gl/brdfLookupP.glsl

@@ -0,0 +1,136 @@
+//-----------------------------------------------------------------------------
+// Copyright (c) 2012 GarageGames, LLC
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to
+// deal in the Software without restriction, including without limitation the
+// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+// sell copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+// IN THE SOFTWARE.
+//-----------------------------------------------------------------------------
+
+#include "../../../torque.glsl"
+#line 24
+in vec4 hpos;
+in vec2 uv0;
+
+// ----------------------------------------------------------------------------
+// http://holger.dammertz.org/stuff/notes_HammersleyOnHemisphere.html
+// efficient VanDerCorpus calculation.
+float RadicalInverse_VdC(uint bits) 
+{
+     bits = (bits << 16u) | (bits >> 16u);
+     bits = ((bits & 0x55555555u) << 1u) | ((bits & 0xAAAAAAAAu) >> 1u);
+     bits = ((bits & 0x33333333u) << 2u) | ((bits & 0xCCCCCCCCu) >> 2u);
+     bits = ((bits & 0x0F0F0F0Fu) << 4u) | ((bits & 0xF0F0F0F0u) >> 4u);
+     bits = ((bits & 0x00FF00FFu) << 8u) | ((bits & 0xFF00FF00u) >> 8u);
+     return float(bits) * 2.3283064365386963e-10; // / 0x100000000
+}
+// ----------------------------------------------------------------------------
+vec2 Hammersley(uint i, uint N)
+{
+	return vec2(float(i)/float(N), RadicalInverse_VdC(i));
+}
+// ----------------------------------------------------------------------------
+vec3 ImportanceSampleGGX(vec2 Xi, vec3 N, float roughness)
+{
+	float a = roughness*roughness;
+	
+	float phi = 2.0 * M_PI_F * Xi.x;
+	float cosTheta = sqrt((1.0 - Xi.y) / (1.0 + (a*a - 1.0) * Xi.y));
+	float sinTheta = sqrt(1.0 - cosTheta*cosTheta);
+	
+	// from spherical coordinates to cartesian coordinates - halfway vector
+	vec3 H;
+	H.x = cos(phi) * sinTheta;
+	H.y = sin(phi) * sinTheta;
+	H.z = cosTheta;
+	
+	// from tangent-space H vector to world-space sample vector
+	vec3 up          = abs(N.z) < 0.999 ? vec3(0.0, 0.0, 1.0) : vec3(1.0, 0.0, 0.0);
+	vec3 tangent   = normalize(cross(up, N));
+	vec3 bitangent = cross(N, tangent);
+	
+	vec3 sampleVec = tangent * H.x + bitangent * H.y + N * H.z;
+	return normalize(sampleVec);
+}
+// ----------------------------------------------------------------------------
+float GeometrySchlickGGX(float NdotV, float roughness)
+{
+    // note that we use a different k for IBL
+    float a = roughness;
+    float k = (a * a) / 2.0;
+
+    float nom   = NdotV;
+    float denom = NdotV * (1.0 - k) + k;
+
+    return nom / denom;
+}
+// ----------------------------------------------------------------------------
+float GeometrySmith(vec3 N, vec3 V, vec3 L, float roughness)
+{
+    float NdotV = max(dot(N, V), 0.0);
+    float NdotL = max(dot(N, L), 0.0);
+    float ggx2 = GeometrySchlickGGX(NdotV, roughness);
+    float ggx1 = GeometrySchlickGGX(NdotL, roughness);
+
+    return ggx1 * ggx2;
+}
+// ----------------------------------------------------------------------------
+vec2 IntegrateBRDF(float NdotV, float roughness)
+{
+    vec3 V;
+    V.x = sqrt(1.0 - NdotV*NdotV);
+    V.y = 0.0;
+    V.z = NdotV;
+
+    float A = 0.0;
+    float B = 0.0; 
+
+    vec3 N = vec3(0.0, 0.0, 1.0);
+    
+    const uint SAMPLE_COUNT = 1024u;
+    for(uint i = 0u; i < SAMPLE_COUNT; ++i)
+    {
+        // generates a sample vector that's biased towards the
+        // preferred alignment direction (importance sampling).
+        vec2 Xi = Hammersley(i, SAMPLE_COUNT);
+        vec3 H = ImportanceSampleGGX(Xi, N, roughness);
+        vec3 L = normalize(2.0 * dot(V, H) * H - V);
+
+        float NdotL = max(L.z, 0.0);
+        float NdotH = max(H.z, 0.0);
+        float VdotH = max(dot(V, H), 0.0);
+
+        if(NdotL > 0.0)
+        {
+            float G = GeometrySmith(N, V, L, roughness);
+            float G_Vis = (G * VdotH) / (NdotH * NdotV);
+            float Fc = pow(1.0 - VdotH, 5.0);
+
+            A += (1.0 - Fc) * G_Vis;
+            B += Fc * G_Vis;
+        }
+    }
+    A /= float(SAMPLE_COUNT);
+    B /= float(SAMPLE_COUNT);
+    return vec2(A, B);
+}
+
+out vec4 OUT_col;
+
+void main()
+{
+   OUT_col = vec4(IntegrateBRDF(uv0.x, uv0.y).rg,0,1);
+}

+ 33 - 0
Templates/BaseGame/game/core/rendering/shaders/lighting/advanced/gl/cubemapV.glsl

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

+ 20 - 13
Templates/BaseGame/game/core/rendering/shaders/lighting/advanced/gl/deferredShadingP.glsl

@@ -26,8 +26,9 @@
 #include "../../../gl/torque.glsl"
 #include "../../../gl/torque.glsl"
 
 
 uniform sampler2D colorBufferTex;
 uniform sampler2D colorBufferTex;
-uniform sampler2D lightDeferredTex;
+uniform sampler2D diffuseLightingBuffer;
 uniform sampler2D matInfoTex;
 uniform sampler2D matInfoTex;
+uniform sampler2D specularLightingBuffer;
 uniform sampler2D deferredTex;
 uniform sampler2D deferredTex;
 
 
 out vec4 OUT_col;
 out vec4 OUT_col;
@@ -40,20 +41,26 @@ void main()
       OUT_col = vec4(0.0);
       OUT_col = vec4(0.0);
       return;
       return;
    }
    }
-   vec4 lightBuffer = texture( lightDeferredTex, uv0 );
-   vec4 colorBuffer = texture( colorBufferTex, uv0 );
-   vec4 matInfo = texture( matInfoTex, uv0 );
-   float specular = clamp(lightBuffer.a,0.0,1.0);
-
-   // Diffuse Color Altered by Metalness
-   bool metalness = getFlag(matInfo.r, 3);
-   if ( metalness )
+   
+   vec3 albedo = texture( colorBufferTex, uv0 ).rgb; //albedo
+   vec4 matInfo = texture( matInfoTex, uv0 ); //flags|smoothness|ao|metallic
+
+   bool emissive = getFlag(matInfo.r, 0);
+   if (emissive)
    {
    {
-      colorBuffer *= (1.0 - colorBuffer.a);
+      OUT_col = float4(albedo, 1.0);
+	  return;
    }
    }
+   
+   vec4 diffuse = texture( diffuseLightingBuffer, uv0 ); //shadowmap*specular
+   vec4 specular = texture( specularLightingBuffer, uv0 ); //environment mapping*lightmaps
+
+   float metalness = matInfo.a;
+   
+   vec3 diffuseColor = albedo - (albedo * metalness);
+   vec3 specularColor = lerp(float3(0.04,0.04,0.04), albedo, metalness);
 
 
-   colorBuffer += vec4(specular, specular, specular, 1.0);
-   colorBuffer *= vec4(lightBuffer.rgb, 1.0);
+   vec3 light = (diffuseColor * diffuse.rgb) + (specularColor * specular.rgb);
 
 
-   OUT_col = hdrEncode( vec4(colorBuffer.rgb, 1.0) );
+   OUT_col = hdrEncode(vec4(light, 1.0));
 }
 }

+ 60 - 0
Templates/BaseGame/game/core/rendering/shaders/lighting/advanced/gl/irradianceP.glsl

@@ -0,0 +1,60 @@
+//-----------------------------------------------------------------------------
+// Copyright (c) 2012 GarageGames, LLC
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to
+// deal in the Software without restriction, including without limitation the
+// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+// sell copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+// IN THE SOFTWARE.
+//-----------------------------------------------------------------------------
+
+#include "../../../gl/torque.glsl"
+
+in vec2 uv0;
+uniform int face;
+
+uniform samplerCube environmentMap;
+
+out vec4 OUT_col;
+
+void main()
+{
+    vec3 N = getCubeDir(face, uv0);
+    vec3 irradiance = vec3(0.0);
+    
+    // tangent space calculation from origin point
+    vec3 up    = vec3(0.0, 0.0, 1.0);
+    vec3 right = cross(up, N);
+    up         = cross(N, right);
+       
+    float sampleDelta = 0.025;
+    int nrSamples = 0;
+    for(float phi = 0.0; phi < M_2PI_F; phi += sampleDelta)
+    {
+        for(float theta = 0.0; theta < M_HALFPI_F; theta += sampleDelta)
+        {
+            // spherical to cartesian (in tangent space)
+            vec3 tangentSample = vec3(sin(theta) * cos(phi),  sin(theta) * sin(phi), cos(theta));
+            // tangent space to world
+            vec3 sampleVec = tangentSample.x * right + tangentSample.y * up + tangentSample.z * N; 
+
+            irradiance += texture(environmentMap, sampleVec).rgb * cos(theta) * sin(theta);
+            nrSamples++;
+        }
+    }
+    irradiance = M_PI_F * irradiance * (1.0 / float(nrSamples));
+    
+    OUT_col =  vec4(irradiance, 1.0);
+}

+ 0 - 28
Templates/BaseGame/game/core/rendering/shaders/lighting/advanced/gl/lightingUtils.glsl

@@ -33,34 +33,6 @@ float attenuate( vec4 lightColor, vec2 attParams, float dist )
 	#endif
 	#endif
 }
 }
 
 
-// Calculate the specular coefficent
-//
-//	pxlToLight - Normalized vector representing direction from the pixel being lit, to the light source, in world space
-//	normal - Normalized surface normal
-//	pxlToEye - Normalized vector representing direction from pixel being lit, to the camera, in world space
-//	specPwr - Specular exponent
-//	specularScale - A scalar on the specular output used in RGB accumulation.
-//
-float calcSpecular( vec3 pxlToLight, vec3 normal, vec3 pxlToEye, float specPwr, float specularScale )
-{
-#ifdef PHONG_SPECULAR 
-   // (R.V)^c
-   float specVal = dot( normalize( -reflect( pxlToLight, normal ) ), pxlToEye );
-#else
-   // (N.H)^c   [Blinn-Phong, TGEA style, default]
-   float specVal = dot( normal, normalize( pxlToLight + pxlToEye ) );
-#endif
-
-#ifdef ACCUMULATE_LUV
-   return pow( max( specVal, 0.00001f ), specPwr );
-#else
-   // If this is RGB accumulation, than there is no facility for the luminance
-   // of the light to play in to the specular intensity. In LUV, the luminance
-   // of the light color gets rolled into N.L * Attenuation
-   return specularScale * pow( max( specVal, 0.00001f ), specPwr );
-#endif
-}
-
 vec3 getDistanceVectorToPlane( vec3 origin, vec3 direction, vec4 plane )
 vec3 getDistanceVectorToPlane( vec3 origin, vec3 direction, vec4 plane )
 {
 {
    float denum = dot( plane.xyz, direction.xyz );
    float denum = dot( plane.xyz, direction.xyz );

+ 46 - 110
Templates/BaseGame/game/core/rendering/shaders/lighting/advanced/gl/pointLightP.glsl

@@ -24,11 +24,11 @@
 #include "shadergen:/autogenConditioners.h"
 #include "shadergen:/autogenConditioners.h"
 
 
 #include "farFrustumQuad.glsl"
 #include "farFrustumQuad.glsl"
-#include "lightingUtils.glsl"
 #include "../../../gl/lighting.glsl"
 #include "../../../gl/lighting.glsl"
 #include "../../shadowMap/shadowMapIO_GLSL.h"
 #include "../../shadowMap/shadowMapIO_GLSL.h"
 #include "softShadow.glsl"
 #include "softShadow.glsl"
 #include "../../../gl/torque.glsl"
 #include "../../../gl/torque.glsl"
+#line 31
 
 
 in vec4 wsEyeDir;
 in vec4 wsEyeDir;
 in vec4 ssPos;
 in vec4 ssPos;
@@ -38,7 +38,7 @@ in vec4 color;
 #ifdef USE_COOKIE_TEX
 #ifdef USE_COOKIE_TEX
 
 
 /// The texture for cookie rendering.
 /// The texture for cookie rendering.
-uniform samplerCube cookieMap ;
+uniform samplerCube cookieMap;
 
 
 #endif
 #endif
 
 
@@ -85,7 +85,9 @@ uniform samplerCube cookieMap ;
       // this value was found via experementation
       // this value was found via experementation
       // NOTE: this is wrong, it only biases in one direction, not towards the uv 
       // NOTE: this is wrong, it only biases in one direction, not towards the uv 
       // center ( 0.5 0.5 ).
       // center ( 0.5 0.5 ).
-      //shadowCoord.xy *= 0.997;
+      float offsetVal = 0.95;
+      shadowCoord.xy *= offsetVal;
+      shadowCoord.xy += vec2(1.0-offsetVal) / 2.0;
 
 
       #ifndef SHADOW_PARABOLOID
       #ifndef SHADOW_PARABOLOID
 
 
@@ -122,152 +124,86 @@ uniform vec3 lightPosition;
 uniform vec4 lightColor;
 uniform vec4 lightColor;
 uniform float  lightBrightness;
 uniform float  lightBrightness;
 uniform float  lightRange;
 uniform float  lightRange;
-uniform vec2 lightAttenuation;
 uniform vec4 lightMapParams;
 uniform vec4 lightMapParams;
 uniform vec4 vsFarPlane;
 uniform vec4 vsFarPlane;
-uniform mat3 viewToLightProj;
-uniform mat3 dynamicViewToLightProj;
 uniform vec4 lightParams;
 uniform vec4 lightParams;
+
+uniform float lightInvSqrRange;
 uniform float shadowSoftness;
 uniform float shadowSoftness;
+uniform mat3 worldToLightProj;
+uniform mat3 dynamicWorldToLightProj;
 
 
-out vec4 OUT_col;
+uniform vec3 eyePosWorld;
+uniform mat4 cameraToWorld;
 
 
+out vec4 OUT_col;
 void main()               
 void main()               
 {   
 {   
    // Compute scene UV
    // Compute scene UV
-   vec3 ssPos = ssPos.xyz / ssPos.w;
-   vec2 uvScene = getUVFromSSPos( ssPos, rtParams0 );
+   vec2 uvScene = getUVFromSSPos(ssPos.xyz/ssPos.w, rtParams0);
+
+   //unpack normal and linear depth 
+   vec4 normDepth = deferredUncondition(deferredBuffer, uvScene);
+      
+   //eye ray WS/VS
+   vec3 vsEyeRay = getDistanceVectorToPlane( -vsFarPlane.w, vsEyeDir.xyz, vsFarPlane );
+   vec3 wsEyeRay = tMul(cameraToWorld, vec4(vsEyeRay, 0)).xyz;
+
+   //create surface
+   Surface surface = createSurface( normDepth, colorBuffer, matInfoBuffer,
+                                    uvScene, eyePosWorld, wsEyeRay, cameraToWorld);
    
    
-   // Emissive.
-   vec4 matInfo = texture( matInfoBuffer, uvScene );   
-   bool emissive = getFlag( matInfo.r, 0 );
-   if ( emissive )
+   //early out if emissive
+   if (getFlag(surface.matFlag, 0))
    {
    {
-       OUT_col = vec4(0.0, 0.0, 0.0, 0.0);
-	   return;
+      OUT_col = vec4(0.0);
+	  return;
    }
    }
 
 
-   vec4 colorSample = texture( colorBuffer, uvScene );
-   vec3 subsurface = vec3(0.0,0.0,0.0); 
-   if (getFlag( matInfo.r, 1 ))
+   vec3 L = lightPosition - surface.P;
+   float dist = length(L);
+   vec3 lighting = vec3(0.0);
+   if(dist < lightRange)
    {
    {
-      subsurface = colorSample.rgb;
-      if (colorSample.r>colorSample.g)
-         subsurface = vec3(0.772549, 0.337255, 0.262745);
-	  else
-         subsurface = vec3(0.337255, 0.772549, 0.262745);
-	}
-	
-   // Sample/unpack the normal/z data
-   vec4 deferredSample = deferredUncondition( deferredBuffer, uvScene );
-   vec3 normal = deferredSample.rgb;
-   float depth = deferredSample.a;
-   
-   // Eye ray - Eye -> Pixel
-   vec3 eyeRay = getDistanceVectorToPlane( -vsFarPlane.w, vsEyeDir.xyz, vsFarPlane );
-   vec3 viewSpacePos = eyeRay * depth;
-      
-   // Build light vec, get length, clip pixel if needed
-   vec3 lightVec = lightPosition - viewSpacePos;
-   float lenLightV = length( lightVec );
-   clip( lightRange - lenLightV );
-
-   // Get the attenuated falloff.
-   float atten = attenuate( lightColor, lightAttenuation, lenLightV );
-   clip( atten - 1e-6 );
-
-   // Normalize lightVec
-   lightVec /= lenLightV;
-   
-   // If we can do dynamic branching then avoid wasting
-   // fillrate on pixels that are backfacing to the light.
-   float nDotL = dot( lightVec, normal );
-   //DB_CLIP( nDotL < 0 );
+      float distToLight = dist / lightRange;
+      SurfaceToLight surfaceToLight = createSurfaceToLight(surface, L);
 
 
    #ifdef NO_SHADOW
    #ifdef NO_SHADOW
-   
       float shadowed = 1.0;
       float shadowed = 1.0;
-      	
    #else
    #else
 
 
-      // Get a linear depth from the light source.
-      float distToLight = lenLightV / lightRange;      
-
       #ifdef SHADOW_CUBE
       #ifdef SHADOW_CUBE
               
               
          // TODO: We need to fix shadow cube to handle soft shadows!
          // TODO: We need to fix shadow cube to handle soft shadows!
-         float occ = texture( shadowMap, tMul( viewToLightProj, -lightVec ) ).r;
+         float occ = texture( shadowMap, ttMul( worldToLightProj, -surfaceToLight.L ) ).r;
          float shadowed = saturate( exp( lightParams.y * ( occ - distToLight ) ) );
          float shadowed = saturate( exp( lightParams.y * ( occ - distToLight ) ) );
          
          
       #else
       #else
-
-         vec2 shadowCoord = decodeShadowCoord( tMul( viewToLightProj, -lightVec ) ).xy;
-         
-         float static_shadowed = softShadow_filter( shadowMap,
-                                             ssPos.xy,
-                                             shadowCoord,
-                                             shadowSoftness,
-                                             distToLight,
-                                             nDotL,
-                                             lightParams.y );
-
-         vec2 dynamicShadowCoord = decodeShadowCoord( tMul( dynamicViewToLightProj, -lightVec ) ).xy;
-         float dynamic_shadowed = softShadow_filter( dynamicShadowMap,
-                                             ssPos.xy,
-                                             dynamicShadowCoord,
-                                             shadowSoftness,
-                                             distToLight,
-                                             nDotL,
-                                             lightParams.y );
-
+      vec2 shadowCoord = decodeShadowCoord( tMul( worldToLightProj, -surfaceToLight.L ) ).xy;
+      vec2 dynShadowCoord = decodeShadowCoord( tMul( dynamicWorldToLightProj, -surfaceToLight.L ) ).xy;
+      float static_shadowed = softShadow_filter(shadowMap, ssPos.xy/ssPos.w, shadowCoord, shadowSoftness, distToLight, surfaceToLight.NdotL, lightParams.y);
+      float dynamic_shadowed = softShadow_filter(dynamicShadowMap, ssPos.xy/ssPos.w, dynShadowCoord, shadowSoftness, distToLight, surfaceToLight.NdotL, lightParams.y);
          float shadowed = min(static_shadowed, dynamic_shadowed);
          float shadowed = min(static_shadowed, dynamic_shadowed);
       #endif
       #endif
 
 
    #endif // !NO_SHADOW
    #endif // !NO_SHADOW
    
    
-   vec3 lightcol = lightColor.rgb;
+      vec3 lightCol = lightColor.rgb;
    #ifdef USE_COOKIE_TEX
    #ifdef USE_COOKIE_TEX
 
 
       // Lookup the cookie sample.
       // Lookup the cookie sample.
-      vec4 cookie = texture( cookieMap, tMul( viewToLightProj, -lightVec ) );
-
+      vec4 cookie = texture(cookieMap, ttMul(worldToLightProj, -surfaceToLight.L));
       // Multiply the light with the cookie tex.
       // Multiply the light with the cookie tex.
-      lightcol *= cookie.rgb;
-
+      lightCol *= cookie.rgb;
       // Use a maximum channel luminance to attenuate 
       // Use a maximum channel luminance to attenuate 
       // the lighting else we get specular in the dark
       // the lighting else we get specular in the dark
       // regions of the cookie texture.
       // regions of the cookie texture.
-      atten *= max( cookie.r, max( cookie.g, cookie.b ) );
-
+      lightCol *= max(cookie.r, max(cookie.g, cookie.b));
    #endif
    #endif
 
 
-   // NOTE: Do not clip on fully shadowed pixels as it would
-   // cause the hardware occlusion query to disable the shadow.
-
-   // Specular term
-   float specular = AL_CalcSpecular(   lightVec, 
-                                       normal, 
-                                       normalize( -eyeRay ) ) * lightBrightness * atten * shadowed;
-
-   float Sat_NL_Att = saturate( nDotL * atten * shadowed ) * lightBrightness;
-   vec3 lightColorOut = lightMapParams.rgb * lightcol;
-   vec4 addToResult = vec4(0.0);
-    
-   // TODO: This needs to be removed when lightmapping is disabled
-   // as its extra work per-pixel on dynamic lit scenes.
-   //
-   // Special lightmapping pass.
-   if ( lightMapParams.a < 0.0 )
-   {
-      // This disables shadows on the backsides of objects.
-      shadowed = nDotL < 0.0f ? 1.0f : shadowed;
-
-      Sat_NL_Att = 1.0f;
-      shadowed = mix( 1.0f, shadowed, atten );
-      lightColorOut = vec3(shadowed);
-      specular *= lightBrightness;
-      addToResult = ( 1.0 - shadowed ) * abs(lightMapParams);
+      //get punctual light contribution   
+      lighting = getPunctualLight(surface, surfaceToLight, lightCol, lightBrightness, lightInvSqrRange, shadowed);
    }
    }
 
 
-   OUT_col = AL_DeferredOutput(lightColorOut+subsurface*(1.0-Sat_NL_Att), colorSample.rgb, matInfo, addToResult, specular, Sat_NL_Att);
+   OUT_col = vec4(lighting, 0);
 }
 }

+ 130 - 0
Templates/BaseGame/game/core/rendering/shaders/lighting/advanced/gl/prefilterP.glsl

@@ -0,0 +1,130 @@
+//-----------------------------------------------------------------------------
+// Copyright (c) 2012 GarageGames, LLC
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to
+// deal in the Software without restriction, including without limitation the
+// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+// sell copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+// IN THE SOFTWARE.
+//-----------------------------------------------------------------------------
+
+#include "../../../gl/torque.glsl"
+
+in vec4 hpos;
+in vec2 uv0;
+
+uniform samplerCube environmentMap;
+
+uniform float roughness;
+uniform int face;
+uniform int mipSize;
+uniform int resolution;
+float RadicalInverse_VdC(uint bits)
+{
+	bits = (bits << 16u) | (bits >> 16u);
+	bits = ((bits & 0x55555555u) << 1u) | ((bits & 0xAAAAAAAAu) >> 1u);
+	bits = ((bits & 0x33333333u) << 2u) | ((bits & 0xCCCCCCCCu) >> 2u);
+	bits = ((bits & 0x0F0F0F0Fu) << 4u) | ((bits & 0xF0F0F0F0u) >> 4u);
+	bits = ((bits & 0x00FF00FFu) << 8u) | ((bits & 0xFF00FF00u) >> 8u);
+	return float(bits) * 2.3283064365386963e-10; // / 0x100000000
+}
+
+vec2 Hammersley(uint i, uint N)
+{
+	return vec2(float(i) / float(N), RadicalInverse_VdC(i));
+}
+
+float DistributionGGX(vec3 N, vec3 H, float roughness)
+{
+	float a = roughness * roughness;
+	float a2 = a * a;
+	float NdotH = max(dot(N, H), 0.0);
+	float NdotH2 = NdotH * NdotH;
+
+	float nom = a2;
+	float denom = (NdotH2 * (a2 - 1.0) + 1.0);
+	denom = M_PI_F * denom * denom;
+
+	return nom / denom;
+}
+
+vec3 ImportanceSampleGGX(vec2 Xi, vec3 N)
+{
+	float a = roughness * roughness;
+
+	float phi = 2.0 * M_PI_F * Xi.x;
+	float cosTheta = sqrt((1.0 - Xi.y) / (1.0 + (a*a - 1.0) * Xi.y));
+	float sinTheta = sqrt(1.0 - cosTheta * cosTheta);
+
+	// from spherical coordinates to cartesian coordinates
+	vec3 H;
+	H.x = cos(phi) * sinTheta;
+	H.y = sin(phi) * sinTheta;
+	H.z = cosTheta;
+
+	// from tangent-space vector to world-space sample vector
+	vec3 up = abs(N.z) < 0.999 ? vec3(0.0, 0.0, 1.0) : vec3(1.0, 0.0, 0.0);
+	vec3 tangent = normalize(cross(up, N));
+	vec3 bitangent = cross(N, tangent);
+
+	vec3 sampleVec = tangent * H.x + bitangent * H.y + N * H.z;
+	return normalize(sampleVec);
+}
+
+vec4 prefilterEnvMap(vec3 R)
+{
+    int sampleCount = resolution*2;
+	vec3 N = R;
+	vec3 V = R;
+	float totalWeight = 0.0;
+	vec4 prefilteredColor = vec4(0.0, 0.0, 0.0, 0.0);
+
+	for (int i = 0; i < sampleCount; ++i)
+	{
+			vec2 Xi = Hammersley(i, sampleCount);
+			vec3 H = ImportanceSampleGGX(Xi, N);
+			vec3 L = normalize(2.0 * dot(V, H) * H - V);
+
+			float NdotL = max(dot(N, L), 0.0);
+			if (NdotL > 0.0)
+			{
+				// sample from the environment's mip level based on roughness/pdf
+				float D = DistributionGGX(N, H, roughness);
+				float NdotH = max(dot(N, H), 0.0);
+				float HdotV = max(dot(H, V), 0.0);
+				float pdf = D * NdotH / (4.0 * HdotV) + 0.0001;
+
+				float saTexel = 4.0 * M_PI_F / float(6.0 * sampleCount * sampleCount);
+				float saSample = 1.0 / (float(sampleCount) * pdf + 0.0001);
+
+				float mipLevel = roughness == 0.0 ? 0.0 : 0.5 * log2(saSample / saTexel);
+
+				prefilteredColor += texture(environmentMap, L, mipLevel) * NdotL;				
+
+				totalWeight += NdotL;
+			}
+	}
+
+	return (prefilteredColor / totalWeight);
+}
+
+out vec4 OUT_col;
+
+void main()
+{
+   
+	vec3 N = getCubeDir(face, uv0);
+	OUT_col = prefilterEnvMap(N);
+}

+ 68 - 0
Templates/BaseGame/game/core/rendering/shaders/lighting/advanced/gl/probeShadingP.glsl

@@ -0,0 +1,68 @@
+//-----------------------------------------------------------------------------
+// Copyright (c) 2012 GarageGames, LLC
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to
+// deal in the Software without restriction, including without limitation the
+// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+// sell copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+// IN THE SOFTWARE.
+//-----------------------------------------------------------------------------
+
+#include "../../../gl/hlslCompat.glsl"
+#include "shadergen:/autogenConditioners.h"
+#include "../../../postFx/gl/postFX.glsl"
+#include "../../../gl/torque.glsl"
+
+uniform sampler2D colorBufferTex;
+uniform sampler2D diffuseLightingBuffer;
+uniform sampler2D matInfoTex;
+uniform sampler2D specularLightingBuffer;
+uniform sampler2D deferredTex;
+
+uniform float radius;
+uniform vec2 targetSize;
+uniform int captureRez;
+
+out vec4 OUT_col;
+
+void main()
+{
+   float depth = deferredUncondition( deferredTex, uv0 ).w;
+   if (depth>0.9999)
+   {
+      discard;
+      return;
+   }
+   vec3 colorBuffer = texture( colorBufferTex, uv0 ).rgb; //albedo
+   vec4 matInfo = texture(matInfoTex, uv0); //flags|smoothness|ao|metallic
+
+   bool emissive = getFlag(matInfo.r, 0);
+   if (emissive)
+   {
+     OUT_col = vec4(colorBuffer, 1.0);
+     return;
+   }
+	  
+   vec4 diffuseLighting = texture( diffuseLightingBuffer, uv0 ); //shadowmap*specular
+   colorBuffer *= diffuseLighting.rgb;
+   vec2 relUV = uv0*targetSize/captureRez;
+   
+   //we use a 1k depth range in the capture frustum. 
+   //reduce that a bit to get something resembling depth fidelity out of 8 bits
+   depth*=2000/radius;
+   
+   float rLen = length(vec3(relUV,depth)-vec3(0.5,0.5,0));
+   OUT_col = hdrEncode( vec4(colorBuffer,rLen));
+}

+ 209 - 0
Templates/BaseGame/game/core/rendering/shaders/lighting/advanced/gl/reflectionProbeArrayP.glsl

@@ -0,0 +1,209 @@
+#include "../../../gl/hlslCompat.glsl"
+#include "../../../postFx/gl/postFx.glsl"
+#include "../../../gl/torque.glsl"
+#include "shadergen:/autogenConditioners.h"
+#include "../../../gl/lighting.glsl"
+
+#line 7
+
+uniform sampler2D deferredBuffer;
+uniform sampler2D colorBuffer;
+uniform sampler2D matInfoBuffer;
+uniform sampler2D BRDFTexture;
+
+uniform vec4 rtParams0;
+uniform vec4 vsFarPlane;
+uniform mat4 cameraToWorld;
+uniform vec3 eyePosWorld;
+
+//cubemap arrays require all the same size. so shared mips# value
+uniform float cubeMips;
+
+uniform float numProbes;
+uniform samplerCubeArray specularCubemapAR;
+uniform samplerCubeArray irradianceCubemapAR;
+
+uniform vec4    inProbePosArray[MAX_PROBES];
+uniform vec4    inRefPosArray[MAX_PROBES];
+uniform mat4    worldToObjArray[MAX_PROBES];
+uniform vec4    bbMinArray[MAX_PROBES];
+uniform vec4    bbMaxArray[MAX_PROBES];
+uniform vec4    probeConfigData[MAX_PROBES];   //r,g,b/mode,radius,atten
+
+#if DEBUGVIZ_CONTRIB
+uniform vec4    probeContribColors[MAX_PROBES];
+#endif
+
+uniform samplerCube skylightSpecularMap;
+uniform samplerCube skylightIrradMap;
+uniform float hasSkylight;
+
+out vec4 OUT_col;
+
+void main()
+{
+   //unpack normal and linear depth 
+   vec4 normDepth = deferredUncondition(deferredBuffer, IN_uv0.xy);
+
+   //create surface
+   Surface surface = createSurface(normDepth, colorBuffer, matInfoBuffer, IN_uv0.xy, eyePosWorld, IN_wsEyeRay, cameraToWorld);
+
+   //early out if emissive
+   if (getFlag(surface.matFlag, 0))
+   {
+      discard;
+   }
+
+   float alpha = 1;
+
+   int i = 0;
+   float blendFactor[MAX_PROBES];
+   float blendSum = 0;
+   float blendFacSum = 0;
+   float invBlendSum = 0;
+   float probehits = 0;
+   //Set up our struct data
+   float contribution[MAX_PROBES];
+   if (alpha > 0)
+   {
+      //Process prooooobes
+      for (i = 0; i < numProbes; ++i)
+      {
+         contribution[i] = 0;
+
+         if (probeConfigData[i].r == 0) //box
+         {
+            contribution[i] = defineBoxSpaceInfluence(surface.P, worldToObjArray[i], probeConfigData[i].b);
+            if (contribution[i]>0.0)
+               probehits++;
+         }
+         else if (probeConfigData[i].r == 1) //sphere
+         {
+            contribution[i] = defineSphereSpaceInfluence(surface.P, inProbePosArray[i].xyz, probeConfigData[i].g);
+            if (contribution[i]>0.0)
+               probehits++;
+         }
+
+         contribution[i] = max(contribution[i],0);
+
+         blendSum += contribution[i];
+         invBlendSum += (1.0f - contribution[i]);
+      }
+      // Weight0 = normalized NDF, inverted to have 1 at center, 0 at boundary.
+	   // And as we invert, we need to divide by Num-1 to stay normalized (else sum is > 1). 
+	   // respect constraint B.
+	   // Weight1 = normalized inverted NDF, so we have 1 at center, 0 at boundary
+	   // and respect constraint A.
+      
+      if (probehits>1.0)
+	{
+            for (i = 0; i < numProbes; i++)
+            {
+                  blendFactor[i] = ((contribution[i] / blendSum)) / probehits;
+                  blendFactor[i] *= ((contribution[i]) / invBlendSum);
+                  blendFactor[i] = saturate(blendFactor[i]);
+                  blendFacSum += blendFactor[i];
+            }
+
+      // Normalize blendVal
+#if DEBUGVIZ_ATTENUATION == 0 //this can likely be removed when we fix the above normalization behavior
+            if (blendFacSum == 0.0f) // Possible with custom weight
+            {
+                  blendFacSum = 1.0f;
+            }
+#endif
+
+            float invBlendSumWeighted = 1.0f / blendFacSum;
+            for (i = 0; i < numProbes; ++i)
+            {
+                  blendFactor[i] *= invBlendSumWeighted;
+                  contribution[i] *= blendFactor[i];
+            }
+      }
+      
+#if DEBUGVIZ_ATTENUATION == 1
+      float contribAlpha = 1;
+      for (i = 0; i < numProbes; ++i)
+      {
+         contribAlpha -= contribution[i];
+      }
+
+      OUT_col = vec4(1 - contribAlpha, 1 - contribAlpha, 1 - contribAlpha, 1);
+      return;
+#endif
+
+#if DEBUGVIZ_CONTRIB == 1
+      vec3 finalContribColor = vec3(0, 0, 0);
+      float contribAlpha = 1;
+      for (i = 0; i < numProbes; ++i)
+      {
+         finalContribColor += contribution[i] *probeContribColors[i].rgb;
+         contribAlpha -= contribution[i];
+      }
+
+      //Skylight coloration for anything not covered by probes above
+      finalContribColor += vec3(0.3, 0.3, 0.3) * contribAlpha;
+
+      OUT_col = vec4(finalContribColor, 1);
+      return;
+#endif
+   }
+
+   vec3 irradiance = vec3(0, 0, 0);
+   vec3 specular = vec3(0, 0, 0);
+
+   // Radiance (Specular)
+#if DEBUGVIZ_SPECCUBEMAP == 0
+   float lod = surface.roughness*cubeMips;
+#elif DEBUGVIZ_SPECCUBEMAP == 1
+   float lod = 0;
+#endif
+
+   alpha = 1;
+   for (i = 0; i < numProbes; ++i)
+   {
+      float contrib = contribution[i];
+      if (contrib != 0)
+      {
+         float cubemapIdx = probeConfigData[i].a;
+         vec3 dir = boxProject(surface.P, surface.R, worldToObjArray[i], bbMinArray[i].xyz, bbMaxArray[i].xyz, inRefPosArray[i].xyz);
+
+         irradiance += textureLod(irradianceCubemapAR, vec4(dir, cubemapIdx), 0).xyz * contrib;
+         specular += textureLod(specularCubemapAR, vec4(dir, cubemapIdx), lod).xyz * contrib;
+         //irradiance += vec3(1,1,1) * contrib;
+         //specular += vec3(1,1,1) * contrib;
+         alpha -= contrib;
+      }
+   }
+
+   if (hasSkylight == 1 && alpha > 0.001)
+   {
+      irradiance += textureLod(skylightIrradMap, surface.R, 0).xyz * alpha;
+      specular += textureLod(skylightSpecularMap, surface.R, lod).xyz * alpha;
+   }
+
+#if DEBUGVIZ_SPECCUBEMAP == 1 && DEBUGVIZ_DIFFCUBEMAP == 0
+   OUT_col = vec4(specular, 1);
+   return;
+#elif DEBUGVIZ_DIFFCUBEMAP == 1
+   OUT_col = vec4(irradiance, 1);
+   return;
+#endif
+
+   vec3 F = FresnelSchlickRoughness(surface.NdotV, surface.f0, surface.roughness);
+
+   //energy conservation
+   vec3 kD = vec3(1,1,1) - F;
+   kD *= 1.0 - surface.metalness;
+
+   //apply brdf
+   //Do it once to save on texture samples
+   vec2 brdf = textureLod(BRDFTexture, vec2(surface.roughness, surface.NdotV),0).xy;
+   specular *= brdf.x * F + brdf.y;
+
+   //final diffuse color
+   vec3 diffuse = kD * irradiance * surface.baseColor.rgb;
+   vec4 finalColor = vec4(diffuse + specular * surface.ao, 1.0);
+
+   OUT_col = finalColor;
+}

+ 162 - 0
Templates/BaseGame/game/core/rendering/shaders/lighting/advanced/gl/reflectionProbeP.glsl

@@ -0,0 +1,162 @@
+//-----------------------------------------------------------------------------
+// Copyright (c) 2012 GarageGames, LLC
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to
+// deal in the Software without restriction, including without limitation the
+// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+// sell copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+// IN THE SOFTWARE.
+//-----------------------------------------------------------------------------
+#include "../../../gl/hlslCompat.glsl"
+#include "shadergen:/autogenConditioners.h"
+#include "farFrustumQuad.glsl"
+#include "../../../gl/torque.glsl"
+#include "../../../gl/lighting.glsl"
+#line 27
+
+in vec4 pos;
+in vec4 wsEyeDir;
+in vec4 ssPos;
+in vec4 vsEyeDir;
+
+uniform sampler2D deferredBuffer;
+uniform sampler2D colorBuffer;
+uniform sampler2D matInfoBuffer;
+uniform samplerCube cubeMap;
+uniform samplerCube irradianceCubemap;
+uniform sampler2D BRDFTexture;
+uniform float cubeMips;
+
+uniform vec4 rtParams0;
+
+uniform vec3 probeWSPos;
+uniform vec3 probeLSPos;
+uniform vec4 vsFarPlane;
+
+uniform float radius;
+uniform vec2 attenuation;
+
+uniform mat4 worldToObj;
+uniform mat4 cameraToWorld;
+
+uniform vec3 eyePosWorld;
+uniform vec3 bbMin;
+uniform vec3 bbMax;
+
+uniform float useSphereMode;
+
+// Box Projected IBL Lighting
+// Based on: http://www.gamedev.net/topic/568829-box-projected-cubemap-environment-mapping/
+// and https://seblagarde.wordpress.com/2012/09/29/image-based-lighting-approaches-and-parallax-corrected-cubemap/
+vec3 boxProject(vec3 wsPosition, vec3 reflectDir, vec3 boxWSPos, vec3 boxMin, vec3 boxMax)
+{ 
+    vec3 nrdir = reflectDir;
+	vec3 offset = wsPosition;
+    vec3 plane1vec = (boxMax - offset) / nrdir;
+    vec3 plane2vec = (boxMin - offset) / nrdir;
+	
+	vec3 furthestPlane = max(plane1vec, plane2vec);
+	float dist = min(min(furthestPlane.x, furthestPlane.y), furthestPlane.z);
+    vec3 posonbox = offset + nrdir * dist;
+
+    return posonbox - boxWSPos;
+}
+
+vec3 iblBoxSpecular(vec3 normal, vec3 wsPos, float roughness, vec3 surfToEye,
+                    sampler2D brdfTexture, 
+                    samplerCube radianceCube,
+                    vec3 boxPos,
+                    vec3 boxMin,
+                    vec3 boxMax)
+{
+    float ndotv = clamp(dot(normal, surfToEye), 0.0, 1.0);
+
+    // BRDF
+    vec2 brdf = textureLod(brdfTexture, vec2(roughness, ndotv),0).xy;
+
+    // Radiance (Specular)
+	float maxmip = pow(cubeMips+1,2);
+    float lod = roughness*maxmip;
+    vec3 r = reflect(surfToEye, normal);
+    vec3 cubeR = normalize(r);
+    cubeR = boxProject(wsPos, cubeR, boxPos, boxMin, boxMax);
+	
+    vec3 radiance = textureLod(radianceCube, cubeR, lod).xyz * (brdf.x + brdf.y);
+    
+    return radiance;
+}
+
+float defineBoxSpaceInfluence(vec3 surfPosWS, vec3 probePos, float radius, float atten)
+{
+    vec3 surfPosLS = tMul( worldToObj, vec4(surfPosWS,1.0)).xyz;
+
+    vec3 boxMinLS = probePos-(vec3(1,1,1)*radius);
+    vec3 boxMaxLS = probePos+(vec3(1,1,1)*radius);
+
+    float boxOuterRange = length(boxMaxLS - boxMinLS);
+    float boxInnerRange = boxOuterRange / atten;
+
+    vec3 localDir = vec3(abs(surfPosLS.x), abs(surfPosLS.y), abs(surfPosLS.z));
+    localDir = (localDir - boxInnerRange) / (boxOuterRange - boxInnerRange);
+
+    return max(localDir.x, max(localDir.y, localDir.z)) * -1;
+}
+out vec4 OUT_col;
+
+void main()
+{   
+
+    // Compute scene UV
+    vec2 uvScene = getUVFromSSPos( ssPos.xyz/ssPos.w, rtParams0 );
+
+   //eye ray WS/LS
+   vec3 vsEyeRay = getDistanceVectorToPlane( -vsFarPlane.w, vsEyeDir.xyz, vsFarPlane );
+   vec3 wsEyeRay = tMul(cameraToWorld, vec4(vsEyeRay, 0)).xyz;
+   
+   //unpack normal and linear depth 
+   vec4 normDepth = deferredUncondition(deferredBuffer, uvScene);
+   
+   //create surface
+   Surface surface = createSurface( normDepth, colorBuffer, matInfoBuffer,
+                                    uvScene, eyePosWorld, wsEyeRay, cameraToWorld);		  
+    float blendVal = 1.0;
+	if(useSphereMode>0)
+    {
+		vec3 L = probeWSPos - surface.P;
+		blendVal = 1.0-length(L)/radius;
+		clip(blendVal);		
+    }
+    else
+    {
+        float tempAttenVal = 3.5;
+		blendVal = defineBoxSpaceInfluence(surface.P, probeWSPos, radius, tempAttenVal);
+		clip(blendVal);
+		float compression = 0.05;
+		blendVal=(1.0-compression)+blendVal*compression;
+	}
+	//render into the bound space defined above
+	vec3 surfToEye = normalize(surface.P - eyePosWorld);
+	vec3 irradiance = textureLod(irradianceCubemap, surface.N,0).xyz;
+	vec3 specular = iblBoxSpecular(surface.N, surface.P, surface.roughness, surfToEye, BRDFTexture, cubeMap, probeWSPos, bbMin, bbMax);
+   vec3 F = FresnelSchlickRoughness(surface.NdotV, surface.f0, surface.roughness);
+   specular *= F;
+   //energy conservation
+	vec3 kD = vec3(1.0) - F;
+	kD *= 1.0 - surface.metalness;
+   //final diffuse color
+   vec3 diffuse = kD * irradiance * surface.baseColor.rgb;
+   
+   OUT_col = vec4(diffuse + specular * surface.ao, blendVal);
+}

+ 32 - 0
Templates/BaseGame/game/core/rendering/shaders/lighting/advanced/gl/reflectionProbeV.glsl

@@ -0,0 +1,32 @@
+#include "shadergen:/autogenConditioners.h"
+#include "../../torque.hlsl"
+
+// This is the shader input
+struct Vert
+{
+   float4 position : POSITION;
+   float2 uv0      : TEXCOORD0;
+   float3 wsEyeRay : TEXCOORD1;
+};
+
+// This is the shader output data.
+struct Conn
+{
+   float4 position : POSITION;
+   float2 uv0      : TEXCOORD0;
+   float3 wsEyeRay : TEXCOORD1;
+};
+
+// Render Target Paramaters
+float4 rtParams0;
+
+Conn main(Vert IN,
+          uniform float4x4 modelView : register(C0))	         
+{
+   Conn OUT;   
+   OUT.position = IN.position;
+   OUT.uv0 = viewportCoordToRenderTarget( IN.uv0, rtParams0 );
+   OUT.wsEyeRay = IN.wsEyeRay;
+   return OUT;
+}
+

+ 82 - 0
Templates/BaseGame/game/core/rendering/shaders/lighting/advanced/gl/skylightP.glsl

@@ -0,0 +1,82 @@
+//-----------------------------------------------------------------------------
+// Copyright (c) 2012 GarageGames, LLC
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to
+// deal in the Software without restriction, including without limitation the
+// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+// sell copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+// IN THE SOFTWARE.
+//-----------------------------------------------------------------------------
+#include "../../../gl/hlslCompat.glsl"
+#include "shadergen:/autogenConditioners.h"
+#include "farFrustumQuad.glsl"
+#include "../../../gl/lighting.glsl"
+#include "../../../gl/torque.glsl"
+#line 27
+
+in vec4 pos;
+in vec4 wsEyeDir;
+in vec4 ssPos;
+in vec4 vsEyeDir;
+
+uniform sampler2D deferredBuffer;
+uniform sampler2D colorBuffer;
+uniform sampler2D matInfoBuffer;
+uniform samplerCube cubeMap;
+uniform samplerCube irradianceCubemap;
+uniform sampler2D BRDFTexture;
+
+uniform vec4 rtParams0;
+
+uniform vec4 vsFarPlane;
+uniform mat4 cameraToWorld;
+uniform vec3 eyePosWorld;
+
+vec3 iblSpecular(in Surface surface, vec3 F)
+{
+	const float MAX_REFLECTION_LOD = 4.0;
+	vec3 prefilteredColor = textureLod(cubeMap, surface.R, surface.roughness * MAX_REFLECTION_LOD).rgb;
+	vec2 envBRDF  = texture(BRDFTexture, vec2(surface.NdotV, surface.roughness)).rg;
+	return prefilteredColor * (F * envBRDF.x + envBRDF.y);
+}
+
+out vec4 OUT_col;
+void main()
+{
+    // Compute scene UV
+    vec2 uvScene = getUVFromSSPos( ssPos.xyz/ssPos.w, rtParams0 );
+
+   //eye ray WS/LS
+   vec3 vsEyeRay = getDistanceVectorToPlane( -vsFarPlane.w, vsEyeDir.xyz, vsFarPlane );
+   vec3 wsEyeRay = tMul(cameraToWorld, vec4(vsEyeRay, 0)).xyz;
+   
+   //unpack normal and linear depth 
+   vec4 normDepth = deferredUncondition(deferredBuffer, uvScene);
+   
+   //create surface
+   Surface surface = createSurface( normDepth, colorBuffer, matInfoBuffer,
+                                    uvScene, eyePosWorld, wsEyeRay, cameraToWorld);
+
+   vec3 F = FresnelSchlickRoughness(surface.NdotV, surface.f0, surface.roughness);
+   vec3 irradiance = textureLod(irradianceCubemap, surface.N,0).rgb;
+   vec3 specular = iblSpecular(surface, F);
+   //energy conservation
+	vec3 kD = vec3(1.0) - F;
+	kD *= 1.0 - surface.metalness;
+   //final diffuse color
+   vec3 diffuse = kD * irradiance * surface.baseColor.rgb;
+
+   OUT_col = vec4(diffuse + specular * surface.ao, 0);
+}

+ 51 - 120
Templates/BaseGame/game/core/rendering/shaders/lighting/advanced/gl/spotLightP.glsl

@@ -22,7 +22,6 @@
 
 
 #include "../../../gl/hlslCompat.glsl"
 #include "../../../gl/hlslCompat.glsl"
 #include "farFrustumQuad.glsl"
 #include "farFrustumQuad.glsl"
-#include "lightingUtils.glsl"
 #include "../../shadowMap/shadowMapIO_GLSL.h"
 #include "../../shadowMap/shadowMapIO_GLSL.h"
 #include "shadergen:/autogenConditioners.h"
 #include "shadergen:/autogenConditioners.h"
 #include "softShadow.glsl"
 #include "softShadow.glsl"
@@ -34,11 +33,6 @@ in vec4 ssPos;
 in vec4 vsEyeDir;
 in vec4 vsEyeDir;
 in vec4 color;
 in vec4 color;
 
 
-#define IN_wsEyeDir wsEyeDir
-#define IN_ssPos ssPos
-#define IN_vsEyeDir vsEyeDir
-#define IN_color color
-
 #ifdef USE_COOKIE_TEX
 #ifdef USE_COOKIE_TEX
 
 
 /// The texture for cookie rendering.
 /// The texture for cookie rendering.
@@ -49,162 +43,99 @@ uniform sampler2D cookieMap;
 uniform sampler2D deferredBuffer;
 uniform sampler2D deferredBuffer;
 uniform sampler2D shadowMap;
 uniform sampler2D shadowMap;
 uniform sampler2D dynamicShadowMap;
 uniform sampler2D dynamicShadowMap;
-
-uniform sampler2D lightBuffer;
 uniform sampler2D colorBuffer;
 uniform sampler2D colorBuffer;
 uniform sampler2D matInfoBuffer;
 uniform sampler2D matInfoBuffer;
 
 
 uniform vec4 rtParams0;
 uniform vec4 rtParams0;
 
 
+uniform float  lightBrightness;
 uniform vec3 lightPosition;
 uniform vec3 lightPosition;
 uniform vec4 lightColor;
 uniform vec4 lightColor;
-uniform float  lightBrightness;
+
 uniform float  lightRange;
 uniform float  lightRange;
-uniform vec2 lightAttenuation;
+uniform float lightInvSqrRange;
 uniform vec3 lightDirection;
 uniform vec3 lightDirection;
-uniform vec4 lightSpotParams;
+uniform vec2 lightSpotParams;
 uniform vec4 lightMapParams;
 uniform vec4 lightMapParams;
 
 
 uniform vec4 vsFarPlane;
 uniform vec4 vsFarPlane;
-uniform mat4 viewToLightProj;
-uniform mat4 dynamicViewToLightProj;
-
+uniform mat4 worldToLightProj;
+uniform mat4 dynamicWorldToLightProj;
 uniform vec4 lightParams;
 uniform vec4 lightParams;
 uniform float shadowSoftness;
 uniform float shadowSoftness;
+uniform vec3 eyePosWorld;
 
 
-out vec4 OUT_col;
+uniform mat4 cameraToWorld;
+uniform mat4 worldToCamera;
 
 
+out vec4 OUT_col;
 void main()
 void main()
 {   
 {   
    // Compute scene UV
    // Compute scene UV
-   vec3 ssPos = IN_ssPos.xyz / IN_ssPos.w;
-   vec2 uvScene = getUVFromSSPos( ssPos, rtParams0 );
+   vec2 uvScene = getUVFromSSPos(ssPos.xyz/ssPos.w, rtParams0);
+
+   //unpack normal and linear depth 
+   vec4 normDepth = deferredUncondition(deferredBuffer, uvScene);
+      
+   //eye ray WS/VS
+   vec3 vsEyeRay = getDistanceVectorToPlane( -vsFarPlane.w, vsEyeDir.xyz, vsFarPlane );
+   vec3 wsEyeRay = tMul(cameraToWorld, vec4(vsEyeRay, 0)).xyz;
+
+   //create surface
+   Surface surface = createSurface( normDepth, colorBuffer,matInfoBuffer,
+                                    uvScene, eyePosWorld, wsEyeRay, cameraToWorld);
 
 
-   // Emissive.
-   vec4 matInfo = texture( matInfoBuffer, uvScene );   
-   bool emissive = getFlag( matInfo.r, 0 );
-   if ( emissive )
+   //early out if emissive
+   if (getFlag(surface.matFlag, 0))
    {
    {
-       OUT_col = vec4(0.0, 0.0, 0.0, 0.0);
+      OUT_col = vec4(0.0);
 	   return;
 	   return;
    }
    }
    
    
-   vec4 colorSample = texture( colorBuffer, uvScene );
-   vec3 subsurface = vec3(0.0,0.0,0.0); 
-   if (getFlag( matInfo.r, 1 ))
+   vec3 L = lightPosition - surface.P;
+   float dist = length(L);
+   vec3 lighting = vec3(0.0);
+	if(dist < lightRange)
    {
    {
-      subsurface = colorSample.rgb;
-      if (colorSample.r>colorSample.g)
-         subsurface = vec3(0.772549, 0.337255, 0.262745);
-	  else
-         subsurface = vec3(0.337255, 0.772549, 0.262745);
-	}
-	
-   // Sample/unpack the normal/z data
-   vec4 deferredSample = deferredUncondition( deferredBuffer, uvScene );
-   vec3 normal = deferredSample.rgb;
-   float depth = deferredSample.a;
-   
-   // Eye ray - Eye -> Pixel
-   vec3 eyeRay = getDistanceVectorToPlane( -vsFarPlane.w, IN_vsEyeDir.xyz, vsFarPlane );
-   vec3 viewSpacePos = eyeRay * depth;
-      
-   // Build light vec, get length, clip pixel if needed
-   vec3 lightToPxlVec = viewSpacePos - lightPosition;
-   float lenLightV = length( lightToPxlVec );
-   lightToPxlVec /= lenLightV;
-
-   //lightDirection = vec3( -lightDirection.xy, lightDirection.z ); //vec3( 0, 0, -1 );
-   float cosAlpha = dot( lightDirection, lightToPxlVec );   
-   clip( cosAlpha - lightSpotParams.x );
-   clip( lightRange - lenLightV );
-
-   float atten = attenuate( lightColor, lightAttenuation, lenLightV );
-   atten *= ( cosAlpha - lightSpotParams.x ) / lightSpotParams.y;
-   clip( atten - 1e-6 );
-   atten = saturate( atten );
-   
-   float nDotL = dot( normal, -lightToPxlVec );
-
+      SurfaceToLight surfaceToLight = createSurfaceToLight(surface, L);
+      #ifdef NO_SHADOW   
+         float shadowed = 1.0;      	
+      #else
    // Get the shadow texture coordinate
    // Get the shadow texture coordinate
-   vec4 pxlPosLightProj = tMul( viewToLightProj, vec4( viewSpacePos, 1 ) );
+         vec4 pxlPosLightProj = tMul( worldToLightProj, vec4( surface.P, 1 ) );
    vec2 shadowCoord = ( ( pxlPosLightProj.xy / pxlPosLightProj.w ) * 0.5 ) + vec2( 0.5, 0.5 );
    vec2 shadowCoord = ( ( pxlPosLightProj.xy / pxlPosLightProj.w ) * 0.5 ) + vec2( 0.5, 0.5 );
    shadowCoord.y = 1.0f - shadowCoord.y;
    shadowCoord.y = 1.0f - shadowCoord.y;
 
 
-   // Get the dynamic shadow texture coordinate
-   vec4 dynpxlPosLightProj = tMul( dynamicViewToLightProj, vec4( viewSpacePos, 1 ) );
-   vec2 dynshadowCoord = ( ( dynpxlPosLightProj.xy / dynpxlPosLightProj.w ) * 0.5 ) + vec2( 0.5, 0.5 );
-   dynshadowCoord.y = 1.0f - dynshadowCoord.y;
-   #ifdef NO_SHADOW
-   
-      float shadowed = 1.0;
-      	
-   #else
+         vec4 dynPxlPosLightProj = tMul( dynamicWorldToLightProj, vec4( surface.P, 1 ) );
+         vec2 dynShadowCoord = ( ( dynPxlPosLightProj.xy / dynPxlPosLightProj.w ) * 0.5 ) + vec2( 0.5, 0.5 );
+         dynShadowCoord.y = 1.0f - dynShadowCoord.y;
 
 
-      // Get a linear depth from the light source.
+         //distance to light in shadow map space
       float distToLight = pxlPosLightProj.z / lightRange;
       float distToLight = pxlPosLightProj.z / lightRange;
-
-      float static_shadowed = softShadow_filter( shadowMap,
-                                          ssPos.xy,
-                                          shadowCoord,
-                                          shadowSoftness,
-                                          distToLight,
-                                          nDotL,
-                                          lightParams.y );
-
-      float dynamic_shadowed = softShadow_filter( dynamicShadowMap,
-                                          ssPos.xy,
-                                          dynshadowCoord,
-                                          shadowSoftness,
-                                          distToLight,
-                                          nDotL,
-                                          lightParams.y );
+         float dynDistToLight = dynPxlPosLightProj.z / lightRange;
+         float static_shadowed = softShadow_filter(shadowMap, ssPos.xy/ssPos.w, shadowCoord, shadowSoftness, distToLight, surfaceToLight.NdotL, lightParams.y);
+         float dynamic_shadowed = softShadow_filter(dynamicShadowMap, ssPos.xy/ssPos.w, dynShadowCoord, shadowSoftness, dynDistToLight, surfaceToLight.NdotL, lightParams.y);
       float shadowed = min(static_shadowed, dynamic_shadowed);
       float shadowed = min(static_shadowed, dynamic_shadowed);
-   #endif // !NO_SHADOW
+      #endif      
    
    
-   vec3 lightcol = lightColor.rgb;
+      vec3 lightCol = lightColor.rgb;
    #ifdef USE_COOKIE_TEX
    #ifdef USE_COOKIE_TEX
 
 
       // Lookup the cookie sample.
       // Lookup the cookie sample.
-      vec4 cookie = texture( cookieMap, shadowCoord );
-
+      vec4 cookie = texture(cookieMap, tMul(worldToLightProj, -surfaceToLight.L));
       // Multiply the light with the cookie tex.
       // Multiply the light with the cookie tex.
-      lightcol *= cookie.rgb;
-
+      lightCol *= cookie.rgb;
       // Use a maximum channel luminance to attenuate 
       // Use a maximum channel luminance to attenuate 
       // the lighting else we get specular in the dark
       // the lighting else we get specular in the dark
       // regions of the cookie texture.
       // regions of the cookie texture.
-      atten *= max( cookie.r, max( cookie.g, cookie.b ) );
-
+      lightCol *= max(cookie.r, max(cookie.g, cookie.b));
    #endif
    #endif
 
 
-   // NOTE: Do not clip on fully shadowed pixels as it would
-   // cause the hardware occlusion query to disable the shadow.
-
-   // Specular term
-   float specular = AL_CalcSpecular(   -lightToPxlVec, 
-                                       normal, 
-                                       normalize( -eyeRay ) ) * lightBrightness * atten * shadowed;
-
-   float Sat_NL_Att = saturate( nDotL * atten * shadowed ) * lightBrightness;
-   vec3 lightColorOut = lightMapParams.rgb * lightcol;
-   vec4 addToResult = vec4(0.0);
-
-   // TODO: This needs to be removed when lightmapping is disabled
-   // as its extra work per-pixel on dynamic lit scenes.
-   //
-   // Special lightmapping pass.
-   if ( lightMapParams.a < 0.0 )
-   {
-      // This disables shadows on the backsides of objects.
-      shadowed = nDotL < 0.0f ? 1.0f : shadowed;
-
-      Sat_NL_Att = 1.0f;
-      shadowed = mix( 1.0f, shadowed, atten );
-      lightColorOut = vec3(shadowed);
-      specular *= lightBrightness;
-      addToResult = ( 1.0 - shadowed ) * abs(lightMapParams);
+      //get Punctual light contribution   
+      lighting = getPunctualLight(surface, surfaceToLight, lightCol, lightBrightness, lightInvSqrRange, shadowed);
+      //get spot angle attenuation
+      lighting *= getSpotAngleAtt(-surfaceToLight.L, lightDirection, lightSpotParams );
    }
    }
 
 
-   OUT_col = AL_DeferredOutput(lightColorOut+subsurface*(1.0-Sat_NL_Att), colorSample.rgb, matInfo, addToResult, specular, Sat_NL_Att);
+   OUT_col = vec4(lighting, 0);
 }
 }

+ 74 - 144
Templates/BaseGame/game/core/rendering/shaders/lighting/advanced/gl/vectorLightP.glsl

@@ -25,15 +25,15 @@
 #include "farFrustumQuad.glsl"
 #include "farFrustumQuad.glsl"
 #include "../../../gl/torque.glsl"
 #include "../../../gl/torque.glsl"
 #include "../../../gl/lighting.glsl"
 #include "../../../gl/lighting.glsl"
-#include "lightingUtils.glsl"
 #include "../../shadowMap/shadowMapIO_GLSL.h"
 #include "../../shadowMap/shadowMapIO_GLSL.h"
 #include "softShadow.glsl"
 #include "softShadow.glsl"
-
+#line 30
 in vec4 hpos;
 in vec4 hpos;
 in vec2 uv0;
 in vec2 uv0;
 in vec3 wsEyeRay;
 in vec3 wsEyeRay;
 in vec3 vsEyeRay;
 in vec3 vsEyeRay;
 
 
+uniform sampler2D deferredBuffer;
 uniform sampler2D shadowMap;
 uniform sampler2D shadowMap;
 uniform sampler2D dynamicShadowMap;
 uniform sampler2D dynamicShadowMap;
 
 
@@ -42,68 +42,68 @@ uniform sampler2D ssaoMask ;
 uniform vec4 rtParams3;
 uniform vec4 rtParams3;
 #endif
 #endif
 
 
-uniform sampler2D deferredBuffer;
-uniform sampler2D lightBuffer;
 uniform sampler2D colorBuffer;
 uniform sampler2D colorBuffer;
 uniform sampler2D matInfoBuffer;             
 uniform sampler2D matInfoBuffer;             
+uniform float  lightBrightness;
 uniform vec3 lightDirection;
 uniform vec3 lightDirection;
 uniform vec4 lightColor;
 uniform vec4 lightColor;
-uniform float  lightBrightness;
 uniform vec4 lightAmbient; 
 uniform vec4 lightAmbient; 
+
+uniform float shadowSoftness;
 uniform vec3 eyePosWorld; 
 uniform vec3 eyePosWorld; 
-uniform mat4x4 eyeMat;
+
 uniform vec4 atlasXOffset;
 uniform vec4 atlasXOffset;
 uniform vec4 atlasYOffset;
 uniform vec4 atlasYOffset;
-uniform vec2 atlasScale;
 uniform vec4 zNearFarInvNearFar;
 uniform vec4 zNearFarInvNearFar;
 uniform vec4 lightMapParams;
 uniform vec4 lightMapParams;
-uniform vec2 fadeStartLength;
+uniform vec4 farPlaneScalePSSM;
 uniform vec4 overDarkPSSM;
 uniform vec4 overDarkPSSM;
-uniform float shadowSoftness;
-   
+
+uniform vec2 fadeStartLength;
+uniform vec2 atlasScale;
+
+uniform mat4 eyeMat;
+uniform mat4 cameraToWorld;
+
 //static shadowMap
 //static shadowMap
-uniform mat4x4 worldToLightProj;
+uniform mat4 worldToLightProj;
 uniform vec4 scaleX;
 uniform vec4 scaleX;
 uniform vec4 scaleY;
 uniform vec4 scaleY;
 uniform vec4 offsetX;
 uniform vec4 offsetX;
 uniform vec4 offsetY;
 uniform vec4 offsetY;
-uniform vec4 farPlaneScalePSSM;
 
 
 //dynamic shadowMap
 //dynamic shadowMap
-uniform mat4x4 dynamicWorldToLightProj;
+uniform mat4 dynamicWorldToLightProj;
 uniform vec4 dynamicScaleX;
 uniform vec4 dynamicScaleX;
 uniform vec4 dynamicScaleY;
 uniform vec4 dynamicScaleY;
 uniform vec4 dynamicOffsetX;
 uniform vec4 dynamicOffsetX;
 uniform vec4 dynamicOffsetY;
 uniform vec4 dynamicOffsetY;
 uniform vec4 dynamicFarPlaneScalePSSM;
 uniform vec4 dynamicFarPlaneScalePSSM;
 
 
-vec4 AL_VectorLightShadowCast( sampler2D _sourceshadowMap,
+vec4 AL_VectorLightShadowCast( sampler2D _sourceShadowMap,
                                 vec2 _texCoord,
                                 vec2 _texCoord,
                                 mat4 _worldToLightProj,
                                 mat4 _worldToLightProj,
-                                vec4 _worldPos,
-                                vec4 _scaleX, vec4 _scaleY,
-                                vec4 _offsetX, vec4 _offsetY,
+                                vec3 _worldPos,
+                                vec4 _scaleX,
+                                vec4 _scaleY,
+                                vec4 _offsetX,
+                                vec4 _offsetY,
                                 vec4 _farPlaneScalePSSM,
                                 vec4 _farPlaneScalePSSM,
-                                vec4 _atlasXOffset, vec4 _atlasYOffset,
-                                vec2 _atlasScale,
-                                float _shadowSoftness, 
-                                float _dotNL ,
-                                vec4 _overDarkPSSM
-)
+                                float _dotNL)
 {
 {
 
 
       // Compute shadow map coordinate
       // Compute shadow map coordinate
-      vec4 pxlPosLightProj = tMul(_worldToLightProj, _worldPos);
+      vec4 pxlPosLightProj = tMul(_worldToLightProj, vec4(_worldPos,1));
       vec2 baseShadowCoord = pxlPosLightProj.xy / pxlPosLightProj.w;   
       vec2 baseShadowCoord = pxlPosLightProj.xy / pxlPosLightProj.w;   
 
 
-      // Distance to light, in shadowMap space
+      // Distance to light, in shadowmap space
       float distToLight = pxlPosLightProj.z / pxlPosLightProj.w;
       float distToLight = pxlPosLightProj.z / pxlPosLightProj.w;
          
          
       // Figure out which split to sample from.  Basically, we compute the shadowMap sample coord
       // Figure out which split to sample from.  Basically, we compute the shadowMap sample coord
       // for all of the splits and then check if its valid.  
       // for all of the splits and then check if its valid.  
-      vec4 shadowCoordX = vec4( baseShadowCoord.x );
-      vec4 shadowCoordY = vec4( baseShadowCoord.y );
-      vec4 farPlaneDists = vec4( distToLight );      
+      vec4 shadowCoordX = baseShadowCoord.xxxx;
+      vec4 shadowCoordY = baseShadowCoord.yyyy;
+      vec4 farPlaneDists = vec4(distToLight);      
       shadowCoordX *= _scaleX;
       shadowCoordX *= _scaleX;
       shadowCoordY *= _scaleY;
       shadowCoordY *= _scaleY;
       shadowCoordX += _offsetX;
       shadowCoordX += _offsetX;
@@ -132,10 +132,10 @@ vec4 AL_VectorLightShadowCast( sampler2D _sourceshadowMap,
       else
       else
          finalMask = vec4(0, 0, 0, 1);
          finalMask = vec4(0, 0, 0, 1);
          
          
-      vec3 debugColor = vec3(0);
+      vec3 debugColor = vec3(0,0,0);
    
    
       #ifdef NO_SHADOW
       #ifdef NO_SHADOW
-         debugColor = vec3(1.0);
+         debugColor = vec3(1.0,1.0,1.0);
       #endif
       #endif
 
 
       #ifdef PSSM_DEBUG_RENDER
       #ifdef PSSM_DEBUG_RENDER
@@ -164,16 +164,16 @@ vec4 AL_VectorLightShadowCast( sampler2D _sourceshadowMap,
       shadowCoord = baseShadowCoord * finalScale;      
       shadowCoord = baseShadowCoord * finalScale;      
       shadowCoord += finalOffset;
       shadowCoord += finalOffset;
 
 
-      // Convert to _texCoord space
+      // Convert to texcoord space
       shadowCoord = 0.5 * shadowCoord + vec2(0.5, 0.5);
       shadowCoord = 0.5 * shadowCoord + vec2(0.5, 0.5);
       shadowCoord.y = 1.0f - shadowCoord.y;
       shadowCoord.y = 1.0f - shadowCoord.y;
 
 
       // Move around inside of atlas 
       // Move around inside of atlas 
       vec2 aOffset;
       vec2 aOffset;
-      aOffset.x = dot(finalMask, _atlasXOffset);
-      aOffset.y = dot(finalMask, _atlasYOffset);
+      aOffset.x = dot(finalMask, atlasXOffset);
+      aOffset.y = dot(finalMask, atlasYOffset);
 
 
-      shadowCoord *= _atlasScale;
+      shadowCoord *= atlasScale;
       shadowCoord += aOffset;
       shadowCoord += aOffset;
               
               
       // Each split has a different far plane, take this into account.
       // Each split has a different far plane, take this into account.
@@ -181,147 +181,77 @@ vec4 AL_VectorLightShadowCast( sampler2D _sourceshadowMap,
       distToLight *= farPlaneScale;
       distToLight *= farPlaneScale;
       
       
       return vec4(debugColor,
       return vec4(debugColor,
-	                             softShadow_filter(  _sourceshadowMap,
-                                 _texCoord,
-                                 shadowCoord,
-                                 farPlaneScale * _shadowSoftness,
-                                 distToLight,
-                                 _dotNL,
-                                 dot( finalMask, _overDarkPSSM ) ) );
+                  softShadow_filter(  _sourceShadowMap,
+                  _texCoord,
+                  shadowCoord,
+                  farPlaneScale * shadowSoftness,
+                  distToLight,
+                  _dotNL,
+                  dot( finalMask, overDarkPSSM ) ) );
 }
 }
 
 
 out vec4 OUT_col;
 out vec4 OUT_col;
 void main()             
 void main()             
 {
 {
-   // Emissive.
-   float4 matInfo = texture( matInfoBuffer, uv0 );   
-   bool emissive = getFlag( matInfo.r, 0 );
-   if ( emissive )
-   {
-       OUT_col = vec4(1.0, 1.0, 1.0, 0.0);
-       return;
-   }
+   //unpack normal and linear depth  
+   vec4 normDepth = deferredUncondition(deferredBuffer, uv0);
+  
+   //create surface
+   Surface surface = createSurface( normDepth, colorBuffer, matInfoBuffer,
+                                    uv0, eyePosWorld, wsEyeRay, cameraToWorld);
    
    
-   vec4 colorSample = texture( colorBuffer, uv0 );
-   vec3 subsurface = vec3(0.0,0.0,0.0); 
-   if (getFlag( matInfo.r, 1 ))
+   //early out if emissive
+   if (getFlag(surface.matFlag, 0))
    {
    {
-      subsurface = colorSample.rgb;
-      if (colorSample.r>colorSample.g)
-         subsurface = vec3(0.772549, 0.337255, 0.262745);
-	  else
-         subsurface = vec3(0.337255, 0.772549, 0.262745);
+      OUT_col = vec4(0);
+	  return;
 	}
 	}
 	
 	
-   // Sample/unpack the normal/z data
-   vec4 deferredSample = deferredUncondition( deferredBuffer, uv0 );
-   vec3 normal = deferredSample.rgb;
-   float depth = deferredSample.a;
+   //create surface to light                           
+   SurfaceToLight surfaceToLight = createSurfaceToLight(surface, -lightDirection);
 
 
-   // Use eye ray to get ws pos
-   vec4 worldPos = vec4(eyePosWorld + wsEyeRay * depth, 1.0f);
-   
-   // Get the light attenuation.
-   float dotNL = dot(-lightDirection, normal);
-
-   #ifdef PSSM_DEBUG_RENDER
-      vec3 debugColor = vec3(0);
-   #endif
+   //light color might be changed by PSSM_DEBUG_RENDER
+   vec3 lightingColor = lightColor.rgb;
    
    
    #ifdef NO_SHADOW
    #ifdef NO_SHADOW
+      float shadow = 1.0;
+   #else
 
 
-      // Fully unshadowed.
-      float shadowed = 1.0;
+      // Fade out the shadow at the end of the range.
+      vec4 zDist = vec4(zNearFarInvNearFar.x + zNearFarInvNearFar.y * surface.depth);
+      float fadeOutAmt = ( zDist.x - fadeStartLength.x ) * fadeStartLength.y;
 
 
-      #ifdef PSSM_DEBUG_RENDER
-         debugColor = vec3(1.0);
-      #endif
+      vec4 static_shadowed_colors = AL_VectorLightShadowCast( shadowMap, uv0.xy, worldToLightProj, surface.P, scaleX, scaleY, offsetX, offsetY,
+                                                             farPlaneScalePSSM, surfaceToLight.NdotL);
 
 
-   #else
+      vec4 dynamic_shadowed_colors = AL_VectorLightShadowCast( dynamicShadowMap, uv0.xy, dynamicWorldToLightProj, surface.P, dynamicScaleX,
+                                                              dynamicScaleY, dynamicOffsetX, dynamicOffsetY, dynamicFarPlaneScalePSSM, surfaceToLight.NdotL);
 
 
-      vec4 static_shadowed_colors = AL_VectorLightShadowCast( shadowMap,
-                                                        uv0.xy,
-                                                        worldToLightProj,
-                                                        worldPos,
-                                                        scaleX, scaleY,
-                                                        offsetX, offsetY,
-                                                        farPlaneScalePSSM,
-                                                        atlasXOffset, atlasYOffset,
-                                                        atlasScale,
-                                                        shadowSoftness, 
-                                                        dotNL,
-                                                        overDarkPSSM);
-      vec4 dynamic_shadowed_colors = AL_VectorLightShadowCast( dynamicShadowMap,
-                                                        uv0.xy,
-                                                        dynamicWorldToLightProj,
-                                                        worldPos,
-                                                        dynamicScaleX, dynamicScaleY,
-                                                        dynamicOffsetX, dynamicOffsetY,
-                                                        dynamicFarPlaneScalePSSM,
-                                                        atlasXOffset, atlasYOffset,
-                                                        atlasScale,
-                                                        shadowSoftness, 
-                                                        dotNL,
-                                                        overDarkPSSM);  
       float static_shadowed = static_shadowed_colors.a;
       float static_shadowed = static_shadowed_colors.a;
       float dynamic_shadowed = dynamic_shadowed_colors.a;
       float dynamic_shadowed = dynamic_shadowed_colors.a;
 	  
 	  
       #ifdef PSSM_DEBUG_RENDER
       #ifdef PSSM_DEBUG_RENDER
-	     debugColor = static_shadowed_colors.rgb*0.5+dynamic_shadowed_colors.rgb*0.5;
+	     lightingColor = static_shadowed_colors.rgb*0.5+dynamic_shadowed_colors.rgb*0.5;
       #endif
       #endif
       
       
-      // Fade out the shadow at the end of the range.
-      vec4 zDist = vec4(zNearFarInvNearFar.x + zNearFarInvNearFar.y * depth);
-      float fadeOutAmt = ( zDist.x - fadeStartLength.x ) * fadeStartLength.y;
-      
-      static_shadowed = mix( static_shadowed, 1.0, saturate( fadeOutAmt ) );
-      dynamic_shadowed = mix( dynamic_shadowed, 1.0, saturate( fadeOutAmt ) );
+      static_shadowed = lerp( static_shadowed, 1.0, saturate( fadeOutAmt ) );
+      dynamic_shadowed = lerp( dynamic_shadowed, 1.0, saturate( fadeOutAmt ) );
             
             
-      // temp for debugging. uncomment one or the other.
-      //float shadowed = static_shadowed;
-      //float shadowed = dynamic_shadowed;
-      float shadowed = min(static_shadowed, dynamic_shadowed);
+      float shadow = min(static_shadowed, dynamic_shadowed);
       
       
       #ifdef PSSM_DEBUG_RENDER
       #ifdef PSSM_DEBUG_RENDER
          if ( fadeOutAmt > 1.0 )
          if ( fadeOutAmt > 1.0 )
-            debugColor = vec3(1.0);
+            lightingColor = 1.0;
       #endif
       #endif
 
 
-   #endif // !NO_SHADOW
-
-   // Specular term
-   float specular = AL_CalcSpecular(   -lightDirection, 
-                                       normal, 
-                                       normalize(-vsEyeRay) ) * lightBrightness * shadowed;
-   
-   float Sat_NL_Att = saturate( dotNL * shadowed ) * lightBrightness;
-   vec3 lightColorOut = lightMapParams.rgb * lightColor.rgb;
-   vec4 addToResult = (lightAmbient * (1 - ambientCameraFactor)) + ( lightAmbient * ambientCameraFactor * saturate(dot(normalize(-vsEyeRay), normal)) );
-
-   // TODO: This needs to be removed when lightmapping is disabled
-   // as its extra work per-pixel on dynamic lit scenes.
-   //
-   // Special lightmapping pass.
-   if ( lightMapParams.a < 0.0 )
-   {
-      // This disables shadows on the backsides of objects.
-      shadowed = dotNL < 0.0f ? 1.0f : shadowed;
-
-      Sat_NL_Att = 1.0f;
-      lightColorOut = vec3(shadowed);
-      specular *= lightBrightness;
-      addToResult = ( 1.0 - shadowed ) * abs(lightMapParams);
-   }
-
+   #endif //NO_SHADOW
    // Sample the AO texture.      
    // Sample the AO texture.      
    #ifdef USE_SSAO_MASK
    #ifdef USE_SSAO_MASK
-      float ao = 1.0 - texture( ssaoMask, viewportCoordToRenderTarget( uv0.xy, rtParams3 ) ).r;
-      addToResult *= ao;
+      surface.ao *= 1.0 - texture( ssaoMask, viewportCoordToRenderTarget( uv0.xy, rtParams3 ) ).r;
    #endif
    #endif
 
 
-   #ifdef PSSM_DEBUG_RENDER
-      lightColorOut = debugColor;
-   #endif
+   //get directional light contribution   
+   vec3 lighting = getDirectionalLight(surface, surfaceToLight, lightingColor.rgb, lightBrightness, shadow);
 
 
-   OUT_col = AL_DeferredOutput(lightColorOut+subsurface*(1.0-Sat_NL_Att), colorSample.rgb, matInfo, addToResult, specular, Sat_NL_Att); 
+   OUT_col = vec4(lighting, 0);
 }
 }

+ 63 - 0
Templates/BaseGame/game/core/rendering/shaders/lighting/advanced/irradianceP.hlsl

@@ -0,0 +1,63 @@
+//-----------------------------------------------------------------------------
+// Copyright (c) 2012 GarageGames, LLC
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to
+// deal in the Software without restriction, including without limitation the
+// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+// sell copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+// IN THE SOFTWARE.
+//-----------------------------------------------------------------------------
+
+#include "../../torque.hlsl"
+
+struct ConnectData
+{
+    float4 hpos    : TORQUE_POSITION;
+    float2 uv      : TEXCOORD;
+};
+
+uniform int face;
+
+TORQUE_UNIFORM_SAMPLERCUBE(environmentMap, 0);
+
+float4 main(ConnectData IN) : TORQUE_TARGET0
+{
+    float3 N = getCubeDir(face,IN.uv);
+    float3 irradiance = 0;
+    
+    // tangent space calculation from origin point
+    float3 up    = float3(0.0, 0.0, 1.0);
+    float3 right = cross(up, N);
+    up           = cross(N, right);
+       
+    float sampleDelta = 0.025;
+    int nrSamples = 0;
+    for(float phi = 0.0; phi < M_2PI_F; phi += sampleDelta)
+    {
+        for(float theta = 0.0; theta < M_HALFPI_F; theta += sampleDelta)
+        {
+            // spherical to cartesian (in tangent space)
+            float3 tangentSample = float3(sin(theta) * cos(phi),  sin(theta) * sin(phi), cos(theta));
+            // tangent space to world
+            float3 sampleVec = tangentSample.x * right + tangentSample.y * up + tangentSample.z * N; 
+
+            irradiance += TORQUE_TEXCUBE(environmentMap, sampleVec).rgb * cos(theta) * sin(theta);
+            nrSamples++;
+        }
+    }
+    irradiance = M_PI_F * irradiance * (1.0 / float(nrSamples));
+    
+    return float4(irradiance, 1.0);
+}

+ 56 - 122
Templates/BaseGame/game/core/rendering/shaders/lighting/advanced/pointLightP.hlsl

@@ -23,7 +23,6 @@
 #include "../../shaderModelAutoGen.hlsl"
 #include "../../shaderModelAutoGen.hlsl"
 
 
 #include "farFrustumQuad.hlsl"
 #include "farFrustumQuad.hlsl"
-#include "lightingUtils.hlsl"
 #include "../../lighting.hlsl"
 #include "../../lighting.hlsl"
 #include "../shadowMap/shadowMapIO_HLSL.h"
 #include "../shadowMap/shadowMapIO_HLSL.h"
 #include "softShadow.hlsl"
 #include "softShadow.hlsl"
@@ -37,7 +36,6 @@ struct ConvexConnectP
    float4 vsEyeDir : TEXCOORD2;
    float4 vsEyeDir : TEXCOORD2;
 };
 };
 
 
-
 #ifdef USE_COOKIE_TEX
 #ifdef USE_COOKIE_TEX
 
 
 /// The texture for cookie rendering.
 /// The texture for cookie rendering.
@@ -88,7 +86,9 @@ TORQUE_UNIFORM_SAMPLERCUBE(cookieMap, 3);
       // this value was found via experementation
       // this value was found via experementation
       // NOTE: this is wrong, it only biases in one direction, not towards the uv 
       // NOTE: this is wrong, it only biases in one direction, not towards the uv 
       // center ( 0.5 0.5 ).
       // center ( 0.5 0.5 ).
-      //shadowCoord.xy *= 0.997;
+      float offsetVal = 0.95;
+      shadowCoord.xy *= offsetVal;
+      shadowCoord.xy += (1.0-offsetVal).xx / 2.0;
 
 
       #ifndef SHADOW_PARABOLOID
       #ifndef SHADOW_PARABOLOID
 
 
@@ -129,149 +129,83 @@ uniform float4 lightMapParams;
 uniform float4 vsFarPlane;
 uniform float4 vsFarPlane;
 uniform float4 lightParams;
 uniform float4 lightParams;
 
 
-uniform float  lightRange;
+uniform float lightRange;
+uniform float lightInvSqrRange;
 uniform float shadowSoftness;
 uniform float shadowSoftness;
-uniform float2 lightAttenuation;
+uniform float4x4 worldToCamera;
+uniform float3x3 worldToLightProj;
+uniform float3x3 dynamicWorldToLightProj;
 
 
-uniform float3x3 viewToLightProj;
-uniform float3x3 dynamicViewToLightProj;
+uniform float3 eyePosWorld;
+uniform float4x4 cameraToWorld;
 
 
-float4 main( ConvexConnectP IN ) : TORQUE_TARGET0
+float4 main(   ConvexConnectP IN ) : SV_TARGET
 {   
 {   
    // Compute scene UV
    // Compute scene UV
    float3 ssPos = IN.ssPos.xyz / IN.ssPos.w;
    float3 ssPos = IN.ssPos.xyz / IN.ssPos.w;
-   float2 uvScene = getUVFromSSPos( ssPos, rtParams0 );
-   
-   // Emissive.
-   float4 matInfo = TORQUE_TEX2D( matInfoBuffer, uvScene );   
-   bool emissive = getFlag( matInfo.r, 0 );
-   if ( emissive )
-   {
-       return float4(0.0, 0.0, 0.0, 0.0);
-   }
-   float4 colorSample = TORQUE_TEX2D( colorBuffer, uvScene );
-   float3 subsurface = float3(0.0,0.0,0.0); 
-   if (getFlag( matInfo.r, 1 ))
-   {
-      subsurface = colorSample.rgb;
-      if (colorSample.r>colorSample.g)
-         subsurface = float3(0.772549, 0.337255, 0.262745);
-	  else
-         subsurface = float3(0.337255, 0.772549, 0.262745);
-	}
-   
-   // Sample/unpack the normal/z data
-   float4 deferredSample = TORQUE_DEFERRED_UNCONDITION( deferredBuffer, uvScene );
-   float3 normal = deferredSample.rgb;
-   float depth = deferredSample.a;
-   
-   // Eye ray - Eye -> Pixel
-   float3 eyeRay = getDistanceVectorToPlane( -vsFarPlane.w, IN.vsEyeDir.xyz, vsFarPlane );
-   float3 viewSpacePos = eyeRay * depth;
-      
-   // Build light vec, get length, clip pixel if needed
-   float3 lightVec = lightPosition - viewSpacePos;
-   float lenLightV = length( lightVec );
-   clip( lightRange - lenLightV );
+   float2 uvScene = getUVFromSSPos(ssPos, rtParams0);
 
 
-   // Get the attenuated falloff.
-   float atten = attenuate( lightColor, lightAttenuation, lenLightV );
-   clip( atten - 1e-6 );
+   //unpack normal and linear depth 
+   float4 normDepth = TORQUE_DEFERRED_UNCONDITION(deferredBuffer, uvScene);
+      
+   //eye ray WS/VS
+   float3 vsEyeRay = getDistanceVectorToPlane( -vsFarPlane.w, IN.vsEyeDir.xyz, vsFarPlane );
+   float3 wsEyeRay = mul(cameraToWorld, float4(vsEyeRay, 0)).xyz;
+
+   //create surface
+   Surface surface = createSurface( normDepth, TORQUE_SAMPLER2D_MAKEARG(colorBuffer),TORQUE_SAMPLER2D_MAKEARG(matInfoBuffer),
+                                    uvScene, eyePosWorld, wsEyeRay, cameraToWorld);
+
+   //early out if emissive
+   if (getFlag(surface.matFlag, 0))
+   {   
+      return 0.0.xxxx;
+	}
 
 
-   // Normalize lightVec
-   lightVec /= lenLightV;
-   
-   // If we can do dynamic branching then avoid wasting
-   // fillrate on pixels that are backfacing to the light.
-   float nDotL = dot( lightVec, normal );
-   //DB_CLIP( nDotL < 0 );
+   float3 L = lightPosition - surface.P;
+   float dist = length(L);
+   float3 lighting = 0.0.xxx;
+   [branch]
+	if(dist < lightRange)
+	{     
+      float distToLight = dist / lightRange;
+      SurfaceToLight surfaceToLight = createSurfaceToLight(surface, L);
 
 
    #ifdef NO_SHADOW
    #ifdef NO_SHADOW
-   
       float shadowed = 1.0;
       float shadowed = 1.0;
-      	
    #else
    #else
 
 
-      // Get a linear depth from the light source.
-      float distToLight = lenLightV / lightRange;      
+   #ifdef SHADOW_CUBE
 
 
-      #ifdef SHADOW_CUBE
-              
-         // TODO: We need to fix shadow cube to handle soft shadows!
-         float occ = TORQUE_TEXCUBE( shadowMap, mul( viewToLightProj, -lightVec ) ).r;
-         float shadowed = saturate( exp( lightParams.y * ( occ - distToLight ) ) );
-         
-      #else
-
-         // Static
-         float2 shadowCoord = decodeShadowCoord( mul( viewToLightProj, -lightVec ) ).xy;
-         float static_shadowed = softShadow_filter( TORQUE_SAMPLER2D_MAKEARG(shadowMap),
-                                             ssPos.xy,
-                                             shadowCoord,
-                                             shadowSoftness,
-                                             distToLight,
-                                             nDotL,
-                                             lightParams.y );
-
-         // Dynamic
-         float2 dynamicShadowCoord = decodeShadowCoord( mul( dynamicViewToLightProj, -lightVec ) ).xy;
-         float dynamic_shadowed = softShadow_filter( TORQUE_SAMPLER2D_MAKEARG(dynamicShadowMap),
-                                             ssPos.xy,
-                                             dynamicShadowCoord,
-                                             shadowSoftness,
-                                             distToLight,
-                                             nDotL,
-                                             lightParams.y );
-
-         float shadowed = min(static_shadowed, dynamic_shadowed);
-
-      #endif
+      // TODO: We need to fix shadow cube to handle soft shadows!
+      float occ = TORQUE_TEXCUBE( shadowMap, mul( worldToLightProj, -surfaceToLight.L ) ).r;
+      float shadowed = saturate( exp( lightParams.y * ( occ - distToLight ) ) );
 
 
+   #else
+      float2 shadowCoord = decodeShadowCoord( mul( worldToLightProj, -surfaceToLight.L ) ).xy;
+      float2 dynShadowCoord = decodeShadowCoord( mul( dynamicWorldToLightProj, -surfaceToLight.L ) ).xy;
+      float static_shadowed = softShadow_filter(TORQUE_SAMPLER2D_MAKEARG(shadowMap), ssPos.xy, shadowCoord, shadowSoftness, distToLight, surfaceToLight.NdotL, lightParams.y);
+      float dynamic_shadowed = softShadow_filter(TORQUE_SAMPLER2D_MAKEARG(dynamicShadowMap), ssPos.xy, dynShadowCoord, shadowSoftness, distToLight, surfaceToLight.NdotL, lightParams.y);
+      float shadowed = min(static_shadowed, dynamic_shadowed);
+   #endif
+   
    #endif // !NO_SHADOW
    #endif // !NO_SHADOW
    
    
-   float3 lightcol = lightColor.rgb;
+      float3 lightCol = lightColor.rgb;
    #ifdef USE_COOKIE_TEX
    #ifdef USE_COOKIE_TEX
-
       // Lookup the cookie sample.
       // Lookup the cookie sample.
-      float4 cookie = TORQUE_TEXCUBE( cookieMap, mul( viewToLightProj, -lightVec ) );
-
+      float4 cookie = TORQUE_TEXCUBE(cookieMap, mul(worldToLightProj, -surfaceToLight.L));
       // Multiply the light with the cookie tex.
       // Multiply the light with the cookie tex.
-      lightcol *= cookie.rgb;
-
+      lightCol *= cookie.rgb;
       // Use a maximum channel luminance to attenuate 
       // Use a maximum channel luminance to attenuate 
       // the lighting else we get specular in the dark
       // the lighting else we get specular in the dark
       // regions of the cookie texture.
       // regions of the cookie texture.
-      atten *= max( cookie.r, max( cookie.g, cookie.b ) );
-
+      lightCol *= max(cookie.r, max(cookie.g, cookie.b));
    #endif
    #endif
 
 
-   // NOTE: Do not clip on fully shadowed pixels as it would
-   // cause the hardware occlusion query to disable the shadow.
-
-   // Specular term
-   float specular = AL_CalcSpecular(   lightVec, 
-                                       normal, 
-                                       normalize( -eyeRay ) ) * lightBrightness * atten * shadowed;
-
-   float Sat_NL_Att = saturate( nDotL * atten * shadowed ) * lightBrightness;
-   float3 lightColorOut = lightMapParams.rgb * lightcol;
-   float4 addToResult = 0.0;
-    
-   // TODO: This needs to be removed when lightmapping is disabled
-   // as its extra work per-pixel on dynamic lit scenes.
-   //
-   // Special lightmapping pass.
-   if ( lightMapParams.a < 0.0 )
-   {
-      // This disables shadows on the backsides of objects.
-      shadowed = nDotL < 0.0f ? 1.0f : shadowed;
-
-      Sat_NL_Att = 1.0f;
-      shadowed = lerp( 1.0f, shadowed, atten );
-      lightColorOut = shadowed;
-      specular *= lightBrightness;
-      addToResult = ( 1.0 - shadowed ) * abs(lightMapParams);
+      //get punctual light contribution   
+      lighting = getPunctualLight(surface, surfaceToLight, lightCol, lightBrightness, lightInvSqrRange, shadowed);
    }
    }
-
-   return AL_DeferredOutput(lightColorOut+subsurface*(1.0-Sat_NL_Att), colorSample.rgb, matInfo, addToResult, specular, Sat_NL_Att);
+      
+   return float4(lighting, 0);
 }
 }

+ 130 - 0
Templates/BaseGame/game/core/rendering/shaders/lighting/advanced/prefilterP.hlsl

@@ -0,0 +1,130 @@
+//-----------------------------------------------------------------------------
+// Copyright (c) 2012 GarageGames, LLC
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to
+// deal in the Software without restriction, including without limitation the
+// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+// sell copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+// IN THE SOFTWARE.
+//-----------------------------------------------------------------------------
+
+#include "../../torque.hlsl"
+
+struct ConnectData
+{
+    float4 hpos     : SV_Position;
+    float2 uv      : TEXCOORD;
+};
+
+TORQUE_UNIFORM_SAMPLERCUBE(environmentMap, 0);
+
+uniform float roughness;
+uniform int face;
+uniform int mipSize;
+uniform int resolution;
+float RadicalInverse_VdC(uint bits)
+{
+	bits = (bits << 16u) | (bits >> 16u);
+	bits = ((bits & 0x55555555u) << 1u) | ((bits & 0xAAAAAAAAu) >> 1u);
+	bits = ((bits & 0x33333333u) << 2u) | ((bits & 0xCCCCCCCCu) >> 2u);
+	bits = ((bits & 0x0F0F0F0Fu) << 4u) | ((bits & 0xF0F0F0F0u) >> 4u);
+	bits = ((bits & 0x00FF00FFu) << 8u) | ((bits & 0xFF00FF00u) >> 8u);
+	return float(bits) * 2.3283064365386963e-10; // / 0x100000000
+}
+
+float2 Hammersley(uint i, uint N)
+{
+	return float2(float(i) / float(N), RadicalInverse_VdC(i));
+}
+
+float DistributionGGX(float3 N, float3 H, float roughness)
+{
+	float a = roughness * roughness;
+	float a2 = a * a;
+	float NdotH = max(dot(N, H), 0.0);
+	float NdotH2 = NdotH * NdotH;
+
+	float nom = a2;
+	float denom = (NdotH2 * (a2 - 1.0) + 1.0);
+	denom = M_PI_F * denom * denom;
+
+	return nom / denom;
+}
+
+float3 ImportanceSampleGGX(float2 Xi, float3 N)
+{
+	float a = roughness * roughness;
+
+	float phi = 2.0 * M_PI_F * Xi.x;
+	float cosTheta = sqrt((1.0 - Xi.y) / (1.0 + (a*a - 1.0) * Xi.y));
+	float sinTheta = sqrt(1.0 - cosTheta * cosTheta);
+
+	// from spherical coordinates to cartesian coordinates
+	float3 H;
+	H.x = cos(phi) * sinTheta;
+	H.y = sin(phi) * sinTheta;
+	H.z = cosTheta;
+
+	// from tangent-space vector to world-space sample vector
+	float3 up = abs(N.z) < 0.999 ? float3(0.0, 0.0, 1.0) : float3(1.0, 0.0, 0.0);
+	float3 tangent = normalize(cross(up, N));
+	float3 bitangent = cross(N, tangent);
+
+	float3 sampleVec = tangent * H.x + bitangent * H.y + N * H.z;
+	return normalize(sampleVec);
+}
+
+float4 prefilterEnvMap(float3 R)
+{
+    int sampleCount = resolution*2;
+	float3 N = R;
+	float3 V = R;
+	float totalWeight = 0.0;
+	float4 prefilteredColor = float4(0.0, 0.0, 0.0, 0.0);
+
+	for (int i = 0; i < sampleCount; ++i)
+	{
+			float2 Xi = Hammersley(i, sampleCount);
+			float3 H = ImportanceSampleGGX(Xi, N);
+			float3 L = normalize(2.0 * dot(V, H) * H - V);
+
+			float NdotL = max(dot(N, L), 0.0);
+			if (NdotL > 0.0)
+			{
+				// sample from the environment's mip level based on roughness/pdf
+				float D = DistributionGGX(N, H, roughness);
+				float NdotH = max(dot(N, H), 0.0);
+				float HdotV = max(dot(H, V), 0.0);
+				float pdf = D * NdotH / (4.0 * HdotV) + 0.0001;
+
+				float saTexel = 4.0 * M_PI_F / (6.0 * sampleCount * sampleCount);
+				float saSample = 1.0 / (float(sampleCount) * pdf + 0.0001);
+
+				float mipLevel = roughness == 0.0 ? 0.0 : 0.5 * log2(saSample / saTexel);
+
+				prefilteredColor += TORQUE_TEXCUBELOD(environmentMap, float4(L, mipLevel)) * NdotL;				
+
+				totalWeight += NdotL;
+			}
+	}
+
+	return (prefilteredColor / totalWeight);
+}
+
+float4 main(ConnectData IN) : TORQUE_TARGET0
+{
+	float3 N = getCubeDir(face, IN.uv);
+	return prefilterEnvMap(N);
+}

+ 203 - 0
Templates/BaseGame/game/core/rendering/shaders/lighting/advanced/reflectionProbeArrayP.hlsl

@@ -0,0 +1,203 @@
+#include "../../postFx/postFx.hlsl"
+#include "../../shaderModel.hlsl"
+#include "../../shaderModelAutoGen.hlsl"
+#include "../../lighting.hlsl"
+
+TORQUE_UNIFORM_SAMPLER2D(deferredBuffer, 0);
+TORQUE_UNIFORM_SAMPLER2D(colorBuffer, 1);
+TORQUE_UNIFORM_SAMPLER2D(matInfoBuffer, 2);
+TORQUE_UNIFORM_SAMPLER2D(BRDFTexture, 3);
+
+uniform float4 rtParams0;
+uniform float4 vsFarPlane;
+uniform float4x4 cameraToWorld;
+uniform float3 eyePosWorld;
+
+//cubemap arrays require all the same size. so shared mips# value
+uniform float cubeMips;
+
+uniform float numProbes;
+TORQUE_UNIFORM_SAMPLERCUBEARRAY(specularCubemapAR, 4);
+TORQUE_UNIFORM_SAMPLERCUBEARRAY(irradianceCubemapAR, 5);
+
+uniform float4    inProbePosArray[MAX_PROBES];
+uniform float4    inRefPosArray[MAX_PROBES];
+uniform float4x4  worldToObjArray[MAX_PROBES];
+uniform float4    bbMinArray[MAX_PROBES];
+uniform float4    bbMaxArray[MAX_PROBES];
+uniform float4    probeConfigData[MAX_PROBES];   //r,g,b/mode,radius,atten
+
+#if DEBUGVIZ_CONTRIB
+uniform float4    probeContribColors[MAX_PROBES];
+#endif
+
+TORQUE_UNIFORM_SAMPLERCUBE(skylightSpecularMap, 6);
+TORQUE_UNIFORM_SAMPLERCUBE(skylightIrradMap, 7);
+uniform float hasSkylight;
+
+float4 main(PFXVertToPix IN) : SV_TARGET
+{
+   //unpack normal and linear depth 
+   float4 normDepth = TORQUE_DEFERRED_UNCONDITION(deferredBuffer, IN.uv0.xy);
+
+   //create surface
+   Surface surface = createSurface(normDepth, TORQUE_SAMPLER2D_MAKEARG(colorBuffer),TORQUE_SAMPLER2D_MAKEARG(matInfoBuffer),
+      IN.uv0.xy, eyePosWorld, IN.wsEyeRay, cameraToWorld);
+
+   //early out if emissive
+   if (getFlag(surface.matFlag, 0))
+   {
+      discard;
+   }
+
+   float alpha = 1;
+
+   int i = 0;
+   float blendFactor[MAX_PROBES];
+   float blendSum = 0;
+   float blendFacSum = 0;
+   float invBlendSum = 0;
+   float probehits = 0;
+   //Set up our struct data
+   float contribution[MAX_PROBES];
+   if (alpha > 0)
+   {
+      //Process prooooobes
+      for (i = 0; i < numProbes; ++i)
+      {
+         contribution[i] = 0;
+
+         if (probeConfigData[i].r == 0) //box
+         {
+            contribution[i] = defineBoxSpaceInfluence(surface.P, worldToObjArray[i], probeConfigData[i].b);
+            if (contribution[i]>0.0)
+               probehits++;
+         }
+         else if (probeConfigData[i].r == 1) //sphere
+         {
+            contribution[i] = defineSphereSpaceInfluence(surface.P, inProbePosArray[i].xyz, probeConfigData[i].g);
+            if (contribution[i]>0.0)
+               probehits++;
+         }
+
+         contribution[i] = max(contribution[i],0);
+
+         blendSum += contribution[i];
+         invBlendSum += (1.0f - contribution[i]);
+      }
+      // Weight0 = normalized NDF, inverted to have 1 at center, 0 at boundary.
+	   // And as we invert, we need to divide by Num-1 to stay normalized (else sum is > 1). 
+	   // respect constraint B.
+	   // Weight1 = normalized inverted NDF, so we have 1 at center, 0 at boundary
+	   // and respect constraint A.
+      
+      if (probehits>1.0)
+	{
+            for (i = 0; i < numProbes; i++)
+            {
+                  blendFactor[i] = ((contribution[i] / blendSum)) / probehits;
+                  blendFactor[i] *= ((contribution[i]) / invBlendSum);
+                  blendFactor[i] = saturate(blendFactor[i]);
+                  blendFacSum += blendFactor[i];
+            }
+
+      // Normalize blendVal
+#if DEBUGVIZ_ATTENUATION == 0 //this can likely be removed when we fix the above normalization behavior
+            if (blendFacSum == 0.0f) // Possible with custom weight
+            {
+                  blendFacSum = 1.0f;
+            }
+#endif
+
+            float invBlendSumWeighted = 1.0f / blendFacSum;
+            for (i = 0; i < numProbes; ++i)
+            {
+                  blendFactor[i] *= invBlendSumWeighted;
+                  contribution[i] *= blendFactor[i];
+                  alpha -= contribution[i];
+            }
+      }
+      else
+            alpha -= blendSum;
+      
+#if DEBUGVIZ_ATTENUATION == 1
+      float contribAlpha = 1;
+      for (i = 0; i < numProbes; ++i)
+      {
+         contribAlpha -= contribution[i];
+      }
+
+      return float4(1 - contribAlpha, 1 - contribAlpha, 1 - contribAlpha, 1);
+#endif
+
+#if DEBUGVIZ_CONTRIB == 1
+      float3 finalContribColor = float3(0, 0, 0);
+      float contribAlpha = 1;
+      for (i = 0; i < numProbes; ++i)
+      {
+         finalContribColor += contribution[i] *probeContribColors[i].rgb;
+         contribAlpha -= contribution[i];
+      }
+
+      //Skylight coloration for anything not covered by probes above
+      finalContribColor += float3(0.3, 0.3, 0.3) * contribAlpha;
+
+      return float4(finalContribColor, 1);
+#endif
+   }
+
+   float3 irradiance = float3(0, 0, 0);
+   float3 specular = float3(0, 0, 0);
+
+   // Radiance (Specular)
+#if DEBUGVIZ_SPECCUBEMAP == 0
+   float lod = surface.roughness*cubeMips;
+#elif DEBUGVIZ_SPECCUBEMAP == 1
+   float lod = 0;
+#endif
+
+   alpha = 1;
+   for (i = 0; i < numProbes; ++i)
+   {
+      float contrib = contribution[i];
+      if (contrib != 0)
+      {
+         int cubemapIdx = probeConfigData[i].a;
+         float3 dir = boxProject(surface.P, surface.R, worldToObjArray[i], bbMinArray[i].xyz, bbMaxArray[i].xyz, inRefPosArray[i].xyz);
+
+         irradiance += TORQUE_TEXCUBEARRAYLOD(irradianceCubemapAR, dir, cubemapIdx, 0).xyz * contrib;
+         specular += TORQUE_TEXCUBEARRAYLOD(specularCubemapAR, dir, cubemapIdx, lod).xyz * contrib;
+         alpha -= contrib;
+      }
+   }
+
+   if (hasSkylight && alpha > 0.001)
+   {
+      irradiance += TORQUE_TEXCUBELOD(skylightIrradMap, float4(surface.R, 0)).xyz * alpha;
+      specular += TORQUE_TEXCUBELOD(skylightSpecularMap, float4(surface.R, lod)).xyz * alpha;
+   }
+
+#if DEBUGVIZ_SPECCUBEMAP == 1 && DEBUGVIZ_DIFFCUBEMAP == 0
+   return float4(specular, 1);
+#elif DEBUGVIZ_DIFFCUBEMAP == 1
+   return float4(irradiance, 1);
+#endif
+
+   float3 F = FresnelSchlickRoughness(surface.NdotV, surface.f0, surface.roughness);
+
+   //energy conservation
+   float3 kD = 1.0.xxx - F;
+   kD *= 1.0 - surface.metalness;
+
+   //apply brdf
+   //Do it once to save on texture samples
+   float2 brdf = TORQUE_TEX2DLOD(BRDFTexture, float4(surface.roughness, 1.0-surface.NdotV, 0.0, 0.0)).xy;
+   specular *= brdf.x * F + brdf.y;
+
+   //final diffuse color
+   float3 diffuse = kD * irradiance * surface.baseColor.rgb;
+   float4 finalColor = float4(diffuse + specular * surface.ao, 1.0);
+
+//finalColor.rgb += abs(surface.N);
+   return finalColor;
+}

+ 65 - 128
Templates/BaseGame/game/core/rendering/shaders/lighting/advanced/spotLightP.hlsl

@@ -24,7 +24,6 @@
 #include "../../shaderModelAutoGen.hlsl"
 #include "../../shaderModelAutoGen.hlsl"
 
 
 #include "farFrustumQuad.hlsl"
 #include "farFrustumQuad.hlsl"
-#include "lightingUtils.hlsl"
 #include "../../lighting.hlsl"
 #include "../../lighting.hlsl"
 #include "../shadowMap/shadowMapIO_HLSL.h"
 #include "../shadowMap/shadowMapIO_HLSL.h"
 #include "softShadow.hlsl"
 #include "softShadow.hlsl"
@@ -48,10 +47,8 @@ TORQUE_UNIFORM_SAMPLER2D(dynamicShadowMap,2);
 TORQUE_UNIFORM_SAMPLER2D(cookieMap, 3);
 TORQUE_UNIFORM_SAMPLER2D(cookieMap, 3);
 
 
 #endif
 #endif
-
-TORQUE_UNIFORM_SAMPLER2D(lightBuffer, 5);
-TORQUE_UNIFORM_SAMPLER2D(colorBuffer, 6);
-TORQUE_UNIFORM_SAMPLER2D(matInfoBuffer, 7);
+TORQUE_UNIFORM_SAMPLER2D(colorBuffer, 5);
+TORQUE_UNIFORM_SAMPLER2D(matInfoBuffer, 6);
 
 
 uniform float4 rtParams0;
 uniform float4 rtParams0;
 
 
@@ -60,150 +57,90 @@ uniform float3 lightPosition;
 
 
 uniform float4 lightColor;
 uniform float4 lightColor;
 
 
-uniform float  lightRange;
+uniform float lightRange;
+uniform float lightInvSqrRange;
 uniform float3 lightDirection;
 uniform float3 lightDirection;
 
 
-uniform float4 lightSpotParams;
+uniform float2 lightSpotParams;
 uniform float4 lightMapParams;
 uniform float4 lightMapParams;
 uniform float4 vsFarPlane;
 uniform float4 vsFarPlane;
-uniform float4x4 viewToLightProj;
+uniform float4x4 worldToLightProj;
+uniform float4x4 dynamicWorldToLightProj;
 uniform float4 lightParams;
 uniform float4 lightParams;
-uniform float4x4 dynamicViewToLightProj;
 
 
-uniform float2 lightAttenuation;
 uniform float shadowSoftness;
 uniform float shadowSoftness;
+uniform float3 eyePosWorld;
+
+uniform float4x4 cameraToWorld;
+uniform float4x4 worldToCamera;
 
 
-float4 main(   ConvexConnectP IN ) : TORQUE_TARGET0
+float4 main(   ConvexConnectP IN ) : SV_TARGET
 {   
 {   
    // Compute scene UV
    // Compute scene UV
    float3 ssPos = IN.ssPos.xyz / IN.ssPos.w;
    float3 ssPos = IN.ssPos.xyz / IN.ssPos.w;
-   float2 uvScene = getUVFromSSPos( ssPos, rtParams0 );
-   
-   // Emissive.
-   float4 matInfo = TORQUE_TEX2D( matInfoBuffer, uvScene );   
-   bool emissive = getFlag( matInfo.r, 0 );
-   if ( emissive )
-   {
-       return float4(0.0, 0.0, 0.0, 0.0);
-   }
+   float2 uvScene = getUVFromSSPos(ssPos, rtParams0);
 
 
-   float4 colorSample = TORQUE_TEX2D( colorBuffer, uvScene );
-   float3 subsurface = float3(0.0,0.0,0.0); 
-   if (getFlag( matInfo.r, 1 ))
-   {
-      subsurface = colorSample.rgb;
-      if (colorSample.r>colorSample.g)
-         subsurface = float3(0.772549, 0.337255, 0.262745);
-	  else
-         subsurface = float3(0.337255, 0.772549, 0.262745);
-	}
-	
-   // Sample/unpack the normal/z data
-   float4 deferredSample = TORQUE_DEFERRED_UNCONDITION( deferredBuffer, uvScene );
-   float3 normal = deferredSample.rgb;
-   float depth = deferredSample.a;
-   
-   // Eye ray - Eye -> Pixel
-   float3 eyeRay = getDistanceVectorToPlane( -vsFarPlane.w, IN.vsEyeDir.xyz, vsFarPlane );
-   float3 viewSpacePos = eyeRay * depth;
+   //unpack normal and linear depth 
+   float4 normDepth = TORQUE_DEFERRED_UNCONDITION(deferredBuffer, uvScene);
       
       
-   // Build light vec, get length, clip pixel if needed
-   float3 lightToPxlVec = viewSpacePos - lightPosition;
-   float lenLightV = length( lightToPxlVec );
-   lightToPxlVec /= lenLightV;
-
-   //lightDirection = float3( -lightDirection.xy, lightDirection.z ); //float3( 0, 0, -1 );
-   float cosAlpha = dot( lightDirection, lightToPxlVec );   
-   clip( cosAlpha - lightSpotParams.x );
-   clip( lightRange - lenLightV );
-
-   float atten = attenuate( lightColor, lightAttenuation, lenLightV );
-   atten *= ( cosAlpha - lightSpotParams.x ) / lightSpotParams.y;
-   clip( atten - 1e-6 );
-   atten = saturate( atten );
-   
-   float nDotL = dot( normal, -lightToPxlVec );
-
-   // Get the shadow texture coordinate
-   float4 pxlPosLightProj = mul( viewToLightProj, float4( viewSpacePos, 1 ) );
-   float2 shadowCoord = ( ( pxlPosLightProj.xy / pxlPosLightProj.w ) * 0.5 ) + float2( 0.5, 0.5 );
-   shadowCoord.y = 1.0f - shadowCoord.y;
+   //eye ray WS/VS
+   float3 vsEyeRay = getDistanceVectorToPlane( -vsFarPlane.w, IN.vsEyeDir.xyz, vsFarPlane );
+   float3 wsEyeRay = mul(cameraToWorld, float4(vsEyeRay, 0)).xyz;
+
+   //create surface
+   Surface surface = createSurface( normDepth, TORQUE_SAMPLER2D_MAKEARG(colorBuffer),TORQUE_SAMPLER2D_MAKEARG(matInfoBuffer),
+                                    uvScene, eyePosWorld, wsEyeRay, cameraToWorld);
+
+   //early out if emissive
+   if (getFlag(surface.matFlag, 0))
+   {   
+      return 0.0.xxxx;
+	}
 
 
-   // Get the dynamic shadow texture coordinate
-   float4 dynpxlPosLightProj = mul( dynamicViewToLightProj, float4( viewSpacePos, 1 ) );
-   float2 dynshadowCoord = ( ( dynpxlPosLightProj.xy / dynpxlPosLightProj.w ) * 0.5 ) + float2( 0.5, 0.5 );
-   dynshadowCoord.y = 1.0f - dynshadowCoord.y;
-   
-   #ifdef NO_SHADOW
-   
-      float shadowed = 1.0;
-      	
-   #else
-
-      // Get a linear depth from the light source.
-      float distToLight = pxlPosLightProj.z / lightRange;
-
-      float static_shadowed = softShadow_filter( TORQUE_SAMPLER2D_MAKEARG(shadowMap),
-                                          ssPos.xy,
-                                          shadowCoord,
-                                          shadowSoftness,
-                                          distToLight,
-                                          nDotL,
-                                          lightParams.y );
-                                          
-      float dynamic_shadowed = softShadow_filter( TORQUE_SAMPLER2D_MAKEARG(dynamicShadowMap),
-                                          ssPos.xy,
-                                          dynshadowCoord,
-                                          shadowSoftness,
-                                          distToLight,
-                                          nDotL,
-                                          lightParams.y );
-      float shadowed = min(static_shadowed, dynamic_shadowed);
-   #endif // !NO_SHADOW
-   
-   float3 lightcol = lightColor.rgb;
+   float3 L = lightPosition - surface.P;
+   float dist = length(L);
+   float3 lighting = 0.0.xxx;
+   [branch]
+	if(dist < lightRange)
+	{     
+      SurfaceToLight surfaceToLight = createSurfaceToLight(surface, L);
+      #ifdef NO_SHADOW   
+         float shadowed = 1.0;      	
+      #else
+         // Get the shadow texture coordinate
+         float4 pxlPosLightProj = mul( worldToLightProj, float4( surface.P, 1 ) );
+         float2 shadowCoord = ( ( pxlPosLightProj.xy / pxlPosLightProj.w ) * 0.5 ) + float2( 0.5, 0.5 );
+         shadowCoord.y = 1.0f - shadowCoord.y;
+
+         float4 dynPxlPosLightProj = mul( dynamicWorldToLightProj, float4( surface.P, 1 ) );
+         float2 dynShadowCoord = ( ( dynPxlPosLightProj.xy / dynPxlPosLightProj.w ) * 0.5 ) + float2( 0.5, 0.5 );
+         dynShadowCoord.y = 1.0f - dynShadowCoord.y;
+
+         //distance to light in shadow map space
+         float distToLight = pxlPosLightProj.z / lightRange;
+         float dynDistToLight = dynPxlPosLightProj.z / lightRange;
+         float static_shadowed = softShadow_filter(TORQUE_SAMPLER2D_MAKEARG(shadowMap), ssPos.xy, shadowCoord, shadowSoftness, distToLight, surfaceToLight.NdotL, lightParams.y);
+         float dynamic_shadowed = softShadow_filter(TORQUE_SAMPLER2D_MAKEARG(dynamicShadowMap), ssPos.xy, dynShadowCoord, shadowSoftness, dynDistToLight, surfaceToLight.NdotL, lightParams.y);
+         float shadowed = min(static_shadowed, dynamic_shadowed);
+      #endif      
+
+      float3 lightCol = lightColor.rgb;
    #ifdef USE_COOKIE_TEX
    #ifdef USE_COOKIE_TEX
-
       // Lookup the cookie sample.
       // Lookup the cookie sample.
-      float4 cookie = TORQUE_TEX2D( cookieMap, shadowCoord );
-
+      float4 cookie = TORQUE_TEXCUBE(cookieMap, mul(worldToLightProj, -surfaceToLight.L));
       // Multiply the light with the cookie tex.
       // Multiply the light with the cookie tex.
-      lightcol *= cookie.rgb;
-
+      lightCol *= cookie.rgb;
       // Use a maximum channel luminance to attenuate 
       // Use a maximum channel luminance to attenuate 
       // the lighting else we get specular in the dark
       // the lighting else we get specular in the dark
       // regions of the cookie texture.
       // regions of the cookie texture.
-      atten *= max( cookie.r, max( cookie.g, cookie.b ) );
-
+      lightCol *= max(cookie.r, max(cookie.g, cookie.b));
    #endif
    #endif
 
 
-   // NOTE: Do not clip on fully shadowed pixels as it would
-   // cause the hardware occlusion query to disable the shadow.
-
-   // Specular term
-   float specular = AL_CalcSpecular(   -lightToPxlVec, 
-                                       normal, 
-                                       normalize( -eyeRay ) ) * lightBrightness * atten * shadowed;
-
-   float Sat_NL_Att = saturate( nDotL * atten * shadowed ) * lightBrightness;
-   float3 lightColorOut = lightMapParams.rgb * lightcol;
-   float4 addToResult = 0.0;
-
-   // TODO: This needs to be removed when lightmapping is disabled
-   // as its extra work per-pixel on dynamic lit scenes.
-   //
-   // Special lightmapping pass.
-   if ( lightMapParams.a < 0.0 )
-   {
-      // This disables shadows on the backsides of objects.
-      shadowed = nDotL < 0.0f ? 1.0f : shadowed;
-
-      Sat_NL_Att = 1.0f;
-      shadowed = lerp( 1.0f, shadowed, atten );
-      lightColorOut = shadowed;
-      specular *= lightBrightness;
-      addToResult = ( 1.0 - shadowed ) * abs(lightMapParams);
+      //get Punctual light contribution   
+      lighting = getPunctualLight(surface, surfaceToLight, lightCol, lightBrightness, lightInvSqrRange, shadowed);
+      //get spot angle attenuation
+      lighting *= getSpotAngleAtt(-surfaceToLight.L, lightDirection, lightSpotParams );
    }
    }
-
-   return AL_DeferredOutput(lightColorOut+subsurface*(1.0-Sat_NL_Att), colorSample.rgb, matInfo, addToResult, specular, Sat_NL_Att);
+   
+   return float4(lighting, 0);
 }
 }

+ 45 - 127
Templates/BaseGame/game/core/rendering/shaders/lighting/advanced/vectorLightP.hlsl

@@ -26,7 +26,6 @@
 #include "farFrustumQuad.hlsl"
 #include "farFrustumQuad.hlsl"
 #include "../../torque.hlsl"
 #include "../../torque.hlsl"
 #include "../../lighting.hlsl"
 #include "../../lighting.hlsl"
-#include "lightingUtils.hlsl"
 #include "../shadowMap/shadowMapIO_HLSL.h"
 #include "../shadowMap/shadowMapIO_HLSL.h"
 #include "softShadow.hlsl"
 #include "softShadow.hlsl"
 
 
@@ -38,8 +37,7 @@ TORQUE_UNIFORM_SAMPLER2D(dynamicShadowMap, 2);
 TORQUE_UNIFORM_SAMPLER2D(ssaoMask, 3);
 TORQUE_UNIFORM_SAMPLER2D(ssaoMask, 3);
 uniform float4 rtParams3;
 uniform float4 rtParams3;
 #endif
 #endif
-//register 4?
-TORQUE_UNIFORM_SAMPLER2D(lightBuffer, 5);
+
 TORQUE_UNIFORM_SAMPLER2D(colorBuffer, 6);
 TORQUE_UNIFORM_SAMPLER2D(colorBuffer, 6);
 TORQUE_UNIFORM_SAMPLER2D(matInfoBuffer, 7);
 TORQUE_UNIFORM_SAMPLER2D(matInfoBuffer, 7);
 
 
@@ -63,6 +61,7 @@ uniform float2 fadeStartLength;
 uniform float2 atlasScale;
 uniform float2 atlasScale;
 
 
 uniform float4x4 eyeMat;
 uniform float4x4 eyeMat;
+uniform float4x4 cameraToWorld;
 
 
 // Static Shadows
 // Static Shadows
 uniform float4x4 worldToLightProj;
 uniform float4x4 worldToLightProj;
@@ -81,21 +80,16 @@ uniform float4 dynamicFarPlaneScalePSSM;
 float4 AL_VectorLightShadowCast( TORQUE_SAMPLER2D(sourceShadowMap),
 float4 AL_VectorLightShadowCast( TORQUE_SAMPLER2D(sourceShadowMap),
                                 float2 texCoord,
                                 float2 texCoord,
                                 float4x4 worldToLightProj,
                                 float4x4 worldToLightProj,
-                                float4 worldPos,
+                                float3 worldPos,
                                 float4 scaleX,
                                 float4 scaleX,
                                 float4 scaleY,
                                 float4 scaleY,
                                 float4 offsetX,
                                 float4 offsetX,
                                 float4 offsetY,
                                 float4 offsetY,
                                 float4 farPlaneScalePSSM,
                                 float4 farPlaneScalePSSM,
-                                float4 atlasXOffset,
-                                float4 atlasYOffset,
-                                float2 atlasScale,
-                                float shadowSoftness, 
-                                float dotNL ,
-                                float4 overDarkPSSM)
+                                float dotNL)
 {
 {
       // Compute shadow map coordinate
       // Compute shadow map coordinate
-      float4 pxlPosLightProj = mul(worldToLightProj, worldPos);
+      float4 pxlPosLightProj = mul(worldToLightProj, float4(worldPos,1));
       float2 baseShadowCoord = pxlPosLightProj.xy / pxlPosLightProj.w;   
       float2 baseShadowCoord = pxlPosLightProj.xy / pxlPosLightProj.w;   
 
 
       // Distance to light, in shadowmap space
       // Distance to light, in shadowmap space
@@ -139,7 +133,7 @@ float4 AL_VectorLightShadowCast( TORQUE_SAMPLER2D(sourceShadowMap),
       #ifdef NO_SHADOW
       #ifdef NO_SHADOW
          debugColor = float3(1.0,1.0,1.0);
          debugColor = float3(1.0,1.0,1.0);
       #endif
       #endif
-
+	  
       #ifdef PSSM_DEBUG_RENDER
       #ifdef PSSM_DEBUG_RENDER
          if ( finalMask.x > 0 )
          if ( finalMask.x > 0 )
             debugColor += float3( 1, 0, 0 );
             debugColor += float3( 1, 0, 0 );
@@ -182,147 +176,71 @@ float4 AL_VectorLightShadowCast( TORQUE_SAMPLER2D(sourceShadowMap),
       float farPlaneScale = dot( farPlaneScalePSSM, finalMask );
       float farPlaneScale = dot( farPlaneScalePSSM, finalMask );
       distToLight *= farPlaneScale;
       distToLight *= farPlaneScale;
 
 
-      return float4(debugColor,
-                    softShadow_filter(  TORQUE_SAMPLER2D_MAKEARG(sourceShadowMap),
-                                 texCoord,
-                                 shadowCoord,
-                                 farPlaneScale * shadowSoftness,
-                                 distToLight,
-                                 dotNL,
-                                 dot( finalMask, overDarkPSSM ) ) );
+      return float4(debugColor, softShadow_filter(  TORQUE_SAMPLER2D_MAKEARG(sourceShadowMap), texCoord, shadowCoord, farPlaneScale * shadowSoftness,
+                                distToLight, dotNL, dot( finalMask, overDarkPSSM ) ) );
 };
 };
 
 
-float4 main( FarFrustumQuadConnectP IN ) : TORQUE_TARGET0
+
+float4 main(FarFrustumQuadConnectP IN) : SV_TARGET
 {
 {
-   // Emissive.
-   float4 matInfo = TORQUE_TEX2D( matInfoBuffer, IN.uv0 );   
-   bool emissive = getFlag( matInfo.r, 0 );
-   if ( emissive )
-   {
-       return float4(1.0, 1.0, 1.0, 0.0);
-   }
-   
-   float4 colorSample = TORQUE_TEX2D( colorBuffer, IN.uv0 );
-   float3 subsurface = float3(0.0,0.0,0.0); 
-   if (getFlag( matInfo.r, 1 ))
-   {
-      subsurface = colorSample.rgb;
-      if (colorSample.r>colorSample.g)
-         subsurface = float3(0.772549, 0.337255, 0.262745);
-	  else
-         subsurface = float3(0.337255, 0.772549, 0.262745);
+   //unpack normal and linear depth  
+   float4 normDepth = TORQUE_DEFERRED_UNCONDITION(deferredBuffer, IN.uv0);
+  
+   //create surface
+   Surface surface = createSurface( normDepth, TORQUE_SAMPLER2D_MAKEARG(colorBuffer),TORQUE_SAMPLER2D_MAKEARG(matInfoBuffer),
+                                    IN.uv0, eyePosWorld, IN.wsEyeRay, cameraToWorld);
+                                    
+   //early out if emissive
+   if (getFlag(surface.matFlag, 0))
+   {   
+      return 0.0.xxxx;
 	}
 	}
-   // Sample/unpack the normal/z data
-   float4 deferredSample = TORQUE_DEFERRED_UNCONDITION( deferredBuffer, IN.uv0 );
-   float3 normal = deferredSample.rgb;
-   float depth = deferredSample.a;
-
-   // Use eye ray to get ws pos
-   float4 worldPos = float4(eyePosWorld + IN.wsEyeRay * depth, 1.0f);
    
    
-   // Get the light attenuation.
-   float dotNL = dot(-lightDirection, normal);
+   //create surface to light                           
+   SurfaceToLight surfaceToLight = createSurfaceToLight(surface, -lightDirection);
 
 
-   #ifdef PSSM_DEBUG_RENDER
-      float3 debugColor = float3(0,0,0);
-   #endif
+   //light color might be changed by PSSM_DEBUG_RENDER
+   float3 lightingColor = lightColor.rgb;
    
    
    #ifdef NO_SHADOW
    #ifdef NO_SHADOW
+      float shadow = 1.0;
+   #else
 
 
-      // Fully unshadowed.
-      float shadowed = 1.0;
+      // Fade out the shadow at the end of the range.
+      float4 zDist = (zNearFarInvNearFar.x + zNearFarInvNearFar.y * surface.depth);
+      float fadeOutAmt = ( zDist.x - fadeStartLength.x ) * fadeStartLength.y;
 
 
-      #ifdef PSSM_DEBUG_RENDER
-         debugColor = float3(1.0,1.0,1.0);
-      #endif
+      float4 static_shadowed_colors = AL_VectorLightShadowCast( TORQUE_SAMPLER2D_MAKEARG(shadowMap), IN.uv0.xy, worldToLightProj, surface.P, scaleX, scaleY, offsetX, offsetY,
+                                                             farPlaneScalePSSM, surfaceToLight.NdotL);
+
+      float4 dynamic_shadowed_colors = AL_VectorLightShadowCast( TORQUE_SAMPLER2D_MAKEARG(dynamicShadowMap), IN.uv0.xy, dynamicWorldToLightProj, surface.P, dynamicScaleX,
+                                                              dynamicScaleY, dynamicOffsetX, dynamicOffsetY, dynamicFarPlaneScalePSSM, surfaceToLight.NdotL);
 
 
-   #else
-      
-      float4 static_shadowed_colors = AL_VectorLightShadowCast( TORQUE_SAMPLER2D_MAKEARG(shadowMap),
-                                                        IN.uv0.xy,
-                                                        worldToLightProj,
-                                                        worldPos,
-                                                        scaleX, scaleY,
-                                                        offsetX, offsetY,
-                                                        farPlaneScalePSSM,
-                                                        atlasXOffset, atlasYOffset,
-                                                        atlasScale,
-                                                        shadowSoftness, 
-                                                        dotNL,
-                                                        overDarkPSSM);
-      float4 dynamic_shadowed_colors = AL_VectorLightShadowCast( TORQUE_SAMPLER2D_MAKEARG(dynamicShadowMap),
-                                                        IN.uv0.xy,
-                                                        dynamicWorldToLightProj,
-                                                        worldPos,
-                                                        dynamicScaleX, dynamicScaleY,
-                                                        dynamicOffsetX, dynamicOffsetY,
-                                                        dynamicFarPlaneScalePSSM,
-                                                        atlasXOffset, atlasYOffset,
-                                                        atlasScale,
-                                                        shadowSoftness, 
-                                                        dotNL,
-                                                        overDarkPSSM);
-      
       float static_shadowed = static_shadowed_colors.a;
       float static_shadowed = static_shadowed_colors.a;
       float dynamic_shadowed = dynamic_shadowed_colors.a;
       float dynamic_shadowed = dynamic_shadowed_colors.a;
 	  
 	  
       #ifdef PSSM_DEBUG_RENDER
       #ifdef PSSM_DEBUG_RENDER
-	     debugColor = static_shadowed_colors.rgb*0.5+dynamic_shadowed_colors.rgb*0.5;
+	     lightingColor = static_shadowed_colors.rgb*0.5+dynamic_shadowed_colors.rgb*0.5;
       #endif
       #endif
-  
-      // Fade out the shadow at the end of the range.
-      float4 zDist = (zNearFarInvNearFar.x + zNearFarInvNearFar.y * depth);
-      float fadeOutAmt = ( zDist.x - fadeStartLength.x ) * fadeStartLength.y;
 
 
       static_shadowed = lerp( static_shadowed, 1.0, saturate( fadeOutAmt ) );
       static_shadowed = lerp( static_shadowed, 1.0, saturate( fadeOutAmt ) );
       dynamic_shadowed = lerp( dynamic_shadowed, 1.0, saturate( fadeOutAmt ) );
       dynamic_shadowed = lerp( dynamic_shadowed, 1.0, saturate( fadeOutAmt ) );
 
 
-      // temp for debugging. uncomment one or the other.
-      //float shadowed = static_shadowed;
-      //float shadowed = dynamic_shadowed;
-      float shadowed = min(static_shadowed, dynamic_shadowed);
+      float shadow = min(static_shadowed, dynamic_shadowed);
 
 
       #ifdef PSSM_DEBUG_RENDER
       #ifdef PSSM_DEBUG_RENDER
          if ( fadeOutAmt > 1.0 )
          if ( fadeOutAmt > 1.0 )
-            debugColor = 1.0;
+            lightingColor = 1.0;
       #endif
       #endif
 
 
-   #endif // !NO_SHADOW
-
-   // Specular term
-   float specular = AL_CalcSpecular(   -lightDirection, 
-                                       normal, 
-                                       normalize(-IN.vsEyeRay) ) * lightBrightness * shadowed;
-                                    
-   float Sat_NL_Att = saturate( dotNL * shadowed ) * lightBrightness;
-   float3 lightColorOut = lightMapParams.rgb * lightColor.rgb;
-   
-   float4 addToResult = (lightAmbient * (1 - ambientCameraFactor)) + ( lightAmbient * ambientCameraFactor * saturate(dot(normalize(-IN.vsEyeRay), normal)) );
-
-   // TODO: This needs to be removed when lightmapping is disabled
-   // as its extra work per-pixel on dynamic lit scenes.
-   //
-   // Special lightmapping pass.
-   if ( lightMapParams.a < 0.0 )
-   {
-      // This disables shadows on the backsides of objects.
-      shadowed = dotNL < 0.0f ? 1.0f : shadowed;
-
-      Sat_NL_Att = 1.0f;
-      lightColorOut = shadowed;
-      specular *= lightBrightness;
-      addToResult = ( 1.0 - shadowed ) * abs(lightMapParams);
-   }
-
-   // Sample the AO texture.      
+   #endif //NO_SHADOW
+   // Sample the AO texture.
    #ifdef USE_SSAO_MASK
    #ifdef USE_SSAO_MASK
-      float ao = 1.0 - TORQUE_TEX2D( ssaoMask, viewportCoordToRenderTarget( IN.uv0.xy, rtParams3 ) ).r;
-      addToResult *= ao;
-   #endif
-
-   #ifdef PSSM_DEBUG_RENDER
-      lightColorOut = debugColor;
+      surface.ao *= 1.0 - TORQUE_TEX2D( ssaoMask, viewportCoordToRenderTarget( IN.uv0.xy, rtParams3 ) ).r;
    #endif
    #endif
+   
+   //get directional light contribution   
+   float3 lighting = getDirectionalLight(surface, surfaceToLight, lightingColor.rgb, lightBrightness, shadow);
 
 
-   return AL_DeferredOutput(lightColorOut+subsurface*(1.0-Sat_NL_Att), colorSample.rgb, matInfo, addToResult, specular, Sat_NL_Att);
+   return float4(lighting, 0);
 }
 }

+ 5 - 5
Templates/BaseGame/game/core/rendering/shaders/lighting/shadowMap/shadowMapIO_GLSL.h

@@ -24,16 +24,16 @@
 
 
 #define pkDepthBitShft 65536.0
 #define pkDepthBitShft 65536.0
 #define pkDepthChanMax 256.0
 #define pkDepthChanMax 256.0
-#define bias -0.5/255.0
-#define coeff 0.9999991
-//#define coeff 1.0
+#define gbias -0.5/255.0
+#define gcoeff 0.9999991
+//#define gcoeff 1.0
 
 
 vec4 encodeShadowMap( float depth )
 vec4 encodeShadowMap( float depth )
 {
 {
 #if defined(SM_Fmt_R8G8B8A8)   
 #if defined(SM_Fmt_R8G8B8A8)   
-   return frac( vec4(1.0, 255.0, 65025.0, 160581375.0) * depth ) + vec4(bias);
+   return frac( vec4(1.0, 255.0, 65025.0, 160581375.0) * depth ) + vec4(gbias);
 
 
-   //float4 packedValue = frac((depth / coeff) * float4(16777216.0, 65536.0, 256.0, 1.0));
+   //float4 packedValue = frac((depth / gcoeff) * float4(16777216.0, 65536.0, 256.0, 1.0));
    //return (packedValue - packedValue.xxyz * float4(0, 1.0 / 256, 1.0 / 256, 1.0 / 256));
    //return (packedValue - packedValue.xxyz * float4(0, 1.0 / 256, 1.0 / 256, 1.0 / 256));
 #else
 #else
    return vec4(depth);
    return vec4(depth);

+ 1 - 2
Templates/BaseGame/game/core/rendering/shaders/postFX/fogP.hlsl

@@ -32,8 +32,7 @@ uniform float3    fogData;
 uniform float4    rtParams0;
 uniform float4    rtParams0;
 
 
 float4 main( PFXVertToPix IN ) : TORQUE_TARGET0
 float4 main( PFXVertToPix IN ) : TORQUE_TARGET0
-{   
-   //float2 deferredCoord = ( IN.uv0.xy * rtParams0.zw ) + rtParams0.xy;   
+{
    float depth = TORQUE_DEFERRED_UNCONDITION( deferredTex, IN.uv0 ).w;
    float depth = TORQUE_DEFERRED_UNCONDITION( deferredTex, IN.uv0 ).w;
    //return float4( depth, 0, 0, 0.7 );
    //return float4( depth, 0, 0, 0.7 );
    
    

+ 3 - 7
Templates/BaseGame/game/core/rendering/shaders/postFX/fxaa/fxaaP.hlsl

@@ -23,11 +23,9 @@
 #include "../../shaderModel.hlsl"
 #include "../../shaderModel.hlsl"
 
 
 #define FXAA_PC 1
 #define FXAA_PC 1
-#if (TORQUE_SM <= 30)
-#define FXAA_HLSL_3 1
-#elif TORQUE_SM < 49
+#if TORQUE_SM == 40
 #define FXAA_HLSL_4 1
 #define FXAA_HLSL_4 1
-#elif TORQUE_SM >=50
+#elif TORQUE_SM > 40
 #define FXAA_HLSL_5 1
 #define FXAA_HLSL_5 1
 #endif
 #endif
 #define FXAA_QUALITY__PRESET 12
 #define FXAA_QUALITY__PRESET 12
@@ -48,9 +46,7 @@ uniform float2 oneOverTargetSize;
 
 
 float4 main( VertToPix IN ) : TORQUE_TARGET0
 float4 main( VertToPix IN ) : TORQUE_TARGET0
 {
 {
-#if (TORQUE_SM >= 10 && TORQUE_SM <=30)
-   FxaaTex tex = colorTex;
-#elif TORQUE_SM >=40
+#if TORQUE_SM >=40
    FxaaTex tex;
    FxaaTex tex;
    tex.smpl = colorTex;
    tex.smpl = colorTex;
    tex.tex = texture_colorTex;
    tex.tex = texture_colorTex;

+ 3 - 3
Templates/BaseGame/game/core/rendering/shaders/postFX/gammaP.hlsl

@@ -44,7 +44,7 @@ float4 main( PFXVertToPix IN ) : TORQUE_TARGET0
    color.rgb = ((color.rgb - 0.5f) * Contrast) + 0.5f;
    color.rgb = ((color.rgb - 0.5f) * Contrast) + 0.5f;
  
  
    // Apply brightness
    // Apply brightness
-   color.rgb += Brightness;
-
-    return color;    
+   //color.rgb += Brightness;
+   
+   return color;    
 }
 }

+ 36 - 11
Templates/BaseGame/game/core/rendering/shaders/postFX/hdr/finalPassCombineP.hlsl

@@ -43,6 +43,30 @@ uniform float g_fOneOverGamma;
 uniform float Brightness;
 uniform float Brightness;
 uniform float Contrast;
 uniform float Contrast;
 
 
+// uncharted 2 tonemapper see: http://filmicgames.com/archives/75
+float3 Uncharted2Tonemap(const float3 x)
+{
+   const float A = 0.15;
+   const float B = 0.50;
+   const float C = 0.10;
+   const float D = 0.20;
+   const float E = 0.02;
+   const float F = 0.30;
+   return ((x*(A*x + C*B) + D*E) / (x*(A*x + B) + D*F)) - E / F;
+}
+
+float3 tonemap(float3 color)
+{
+   const float W = 11.2;
+   float ExposureBias = 2.0f;
+   //float ExposureAdjust = 1.5f;
+   //c *= ExposureAdjust;
+   color = Uncharted2Tonemap(ExposureBias*color);
+   color = color * (1.0f / Uncharted2Tonemap(W));
+
+   return color;
+}
+
 float4 main( PFXVertToPix IN ) : TORQUE_TARGET0
 float4 main( PFXVertToPix IN ) : TORQUE_TARGET0
 {
 {
    float4 sample = hdrDecode( TORQUE_TEX2D( sceneTex, IN.uv0 ) );
    float4 sample = hdrDecode( TORQUE_TEX2D( sceneTex, IN.uv0 ) );
@@ -71,22 +95,23 @@ float4 main( PFXVertToPix IN ) : TORQUE_TARGET0
 
 
    // Add the bloom effect.
    // Add the bloom effect.
    sample += g_fBloomScale * bloom;
    sample += g_fBloomScale * bloom;
-   
-   // Map the high range of color values into a range appropriate for
-   // display, taking into account the user's adaptation level, 
-   // white point, and selected value for for middle gray.
-   if ( g_fEnableToneMapping > 0.0f )
-   {
-      float Lp = (g_fMiddleGray / (adaptedLum + 0.0001)) * hdrLuminance( sample.rgb );
-      //float toneScalar = ( Lp * ( 1.0 + ( Lp / ( g_fWhiteCutoff ) ) ) ) / ( 1.0 + Lp );
-	  float toneScalar = Lp;
-      sample.rgb = lerp( sample.rgb, sample.rgb * toneScalar, g_fEnableToneMapping );
-   }
 
 
    // Apply the color correction.
    // Apply the color correction.
    sample.r = TORQUE_TEX1D( colorCorrectionTex, sample.r ).r;
    sample.r = TORQUE_TEX1D( colorCorrectionTex, sample.r ).r;
    sample.g = TORQUE_TEX1D( colorCorrectionTex, sample.g ).g;
    sample.g = TORQUE_TEX1D( colorCorrectionTex, sample.g ).g;
    sample.b = TORQUE_TEX1D( colorCorrectionTex, sample.b ).b;
    sample.b = TORQUE_TEX1D( colorCorrectionTex, sample.b ).b;
 
 
+   // Apply contrast
+   sample.rgb = ((sample.rgb - 0.5f) * Contrast) + 0.5f;
+
+   // Apply brightness
+   //sample.rgb += Brightness;
+
+   //tonemapping - TODO fix up eye adaptation
+   if ( g_fEnableToneMapping > 0.0f )
+   {
+      sample.rgb = tonemap(sample.rgb);
+   }
+
    return sample;
    return sample;
 }
 }

+ 35 - 11
Templates/BaseGame/game/core/rendering/shaders/postFX/hdr/gl/finalPassCombineP.glsl

@@ -48,6 +48,29 @@ uniform float Contrast;
 
 
 out vec4 OUT_col;
 out vec4 OUT_col;
 
 
+// uncharted 2 tonemapper see: http://filmicgames.com/archives/75
+vec3 Uncharted2Tonemap(vec3 x)
+{
+   const float A = 0.15;
+   const float B = 0.50;
+   const float C = 0.10;
+   const float D = 0.20;
+   const float E = 0.02;
+   const float F = 0.30;
+   return ((x*(A*x + C*B) + D*E) / (x*(A*x + B) + D*F)) - E / F;
+}
+
+vec3 tonemap(vec3 c)
+{
+   const float W = 11.2;
+   float ExposureBias = 2.0f;
+   float ExposureAdjust = 1.5f;
+   c *= ExposureAdjust;
+   vec3 curr = Uncharted2Tonemap(ExposureBias*c);
+   vec3 whiteScale = 1.0f / Uncharted2Tonemap(vec3(W,W,W));
+   return curr*whiteScale;
+}
+
 void main()
 void main()
 {
 {
    vec4 _sample = hdrDecode( texture( sceneTex, IN_uv0 ) );
    vec4 _sample = hdrDecode( texture( sceneTex, IN_uv0 ) );
@@ -76,22 +99,23 @@ void main()
 
 
    // Add the bloom effect.
    // Add the bloom effect.
    _sample += g_fBloomScale * bloom;
    _sample += g_fBloomScale * bloom;
-   
-   // Map the high range of color values into a range appropriate for
-   // display, taking into account the user's adaptation level, 
-   // white point, and selected value for for middle gray.
-   if ( g_fEnableToneMapping > 0.0f )
-   {
-      float Lp = (g_fMiddleGray / (adaptedLum + 0.0001)) * hdrLuminance( _sample.rgb );
-      //float toneScalar = ( Lp * ( 1.0 + ( Lp / ( g_fWhiteCutoff ) ) ) ) / ( 1.0 + Lp );
-	  float toneScalar = Lp;
-      _sample.rgb = mix( _sample.rgb, _sample.rgb * toneScalar, g_fEnableToneMapping );
-   }
 
 
    // Apply the color correction.
    // Apply the color correction.
    _sample.r = texture( colorCorrectionTex, _sample.r ).r;
    _sample.r = texture( colorCorrectionTex, _sample.r ).r;
    _sample.g = texture( colorCorrectionTex, _sample.g ).g;
    _sample.g = texture( colorCorrectionTex, _sample.g ).g;
    _sample.b = texture( colorCorrectionTex, _sample.b ).b;
    _sample.b = texture( colorCorrectionTex, _sample.b ).b;
 
 
+   // Apply contrast
+   _sample.rgb = ((_sample.rgb - 0.5f) * Contrast) + 0.5f;
+
+   // Apply brightness
+   //_sample.rgb += Brightness;
+
+   //tonemapping - TODO fix up eye adaptation
+   if ( g_fEnableToneMapping > 0.0f )
+   {
+      _sample.rgb = tonemap(_sample.rgb);
+   }
+
    OUT_col = _sample;
    OUT_col = _sample;
 }
 }

+ 42 - 66
Templates/BaseGame/game/core/rendering/shaders/shaderModel.hlsl

@@ -24,74 +24,50 @@
 #define _TORQUE_SHADERMODEL_
 #define _TORQUE_SHADERMODEL_
 
 
 // Portability helpers for different shader models
 // Portability helpers for different shader models
-//Shader model 1.0 - 3.0
-#if (TORQUE_SM >= 10 && TORQUE_SM <=30)
-   // Semantics
-   #define TORQUE_POSITION POSITION
-   #define TORQUE_DEPTH DEPTH
-   #define TORQUE_TARGET0 COLOR0
-   #define TORQUE_TARGET1 COLOR1
-   #define TORQUE_TARGET2 COLOR2
-   #define TORQUE_TARGET3 COLOR3
-   
-   // Sampler uniforms
-   #define TORQUE_UNIFORM_SAMPLER1D(tex,regist) uniform sampler1D tex : register(S##regist)
-   #define TORQUE_UNIFORM_SAMPLER2D(tex,regist) uniform sampler2D tex : register(S##regist)
-   #define TORQUE_UNIFORM_SAMPLER3D(tex,regist) uniform sampler3D tex : register(S##regist)
-   #define TORQUE_UNIFORM_SAMPLERCUBE(tex,regist) uniform samplerCUBE tex : register(S##regist)
-   // Sampling functions
-   #define TORQUE_TEX1D(tex,coords) tex1D(tex,coords)
-   #define TORQUE_TEX2D(tex,coords) tex2D(tex,coords)
-   #define TORQUE_TEX2DPROJ(tex,coords) tex2Dproj(tex,coords) //this really is sm 2 or later
-   #define TORQUE_TEX3D(tex,coords) tex3D(tex,coords)
-   #define TORQUE_TEXCUBE(tex,coords) texCUBE(tex,coords)
-   
-   //Shader model 3.0 only
-   #if TORQUE_SM == 30
-      #define TORQUE_VPOS VPOS // This is a float2
-      // The mipmap LOD is specified in coord.w
-      #define TORQUE_TEX2DLOD(tex,coords) tex2Dlod(tex,coords)
-   #endif
+#define TORQUE_POSITION SV_Position
+#define TORQUE_DEPTH SV_Depth
+#define TORQUE_VPOS SV_Position //note float4 compared to SM 3 where it is a float2
+#define TORQUE_TARGET0 SV_Target0
+#define TORQUE_TARGET1 SV_Target1
+#define TORQUE_TARGET2 SV_Target2
+#define TORQUE_TARGET3 SV_Target3
+#define TORQUE_TARGET4 SV_Target4
+#define TORQUE_TARGET5 SV_Target5
+// Sampler uniforms
+//1D is emulated to a 2D for now
+#define TORQUE_UNIFORM_SAMPLER1D(tex,regist) uniform Texture2D texture_##tex : register(T##regist); uniform SamplerState tex : register(S##regist)
+#define TORQUE_UNIFORM_SAMPLER2D(tex,regist) uniform Texture2D texture_##tex : register(T##regist); uniform SamplerState tex : register(S##regist)
+#define TORQUE_UNIFORM_SAMPLER2DCMP(tex,regist) uniform Texture2D texture_##tex : register(T##regist); uniform SamplerComparisonState tex : register(S##regist)
+#define TORQUE_UNIFORM_SAMPLER3D(tex,regist) uniform Texture3D texture_##tex : register(T##regist); uniform SamplerState tex : register(S##regist)
+#define TORQUE_UNIFORM_SAMPLERCUBE(tex,regist) uniform TextureCube texture_##tex : register(T##regist); uniform SamplerState tex : register(S##regist)
+#define TORQUE_UNIFORM_SAMPLERCUBEARRAY(tex,regist) uniform TextureCubeArray texture_##tex : register(T##regist); uniform SamplerState tex : register(S##regist)
+// Sampling functions
+#define TORQUE_TEX1D(tex,coords) texture_##tex.Sample(tex,coords)
+#define TORQUE_TEX2D(tex,coords) texture_##tex.Sample(tex,coords)
+#define TORQUE_TEX2DPROJ(tex,coords) texture_##tex.Sample(tex,coords.xy / coords.w)
+#define TORQUE_TEX3D(tex,coords) texture_##tex.Sample(tex,coords)
+#define TORQUE_TEXCUBE(tex,coords) texture_##tex.Sample(tex,coords)
+#define TORQUE_TEXCUBEARRAY(tex,coords) texture_##tex.Sample(tex,coords)
+// The mipmap LOD is specified in coord.w
+#define TORQUE_TEX2DLOD(tex,coords) texture_##tex.SampleLevel(tex,coords.xy,coords.w)
+#define TORQUE_TEXCUBELOD(tex,coords) texture_##tex.SampleLevel(tex,coords.xyz,coords.w)
+#define TORQUE_TEXCUBEARRAYLOD(tex,coords,id,lod) texture_##tex.SampleLevel(tex,float4(coords.xyz,id),lod)
+// Tex2d comparison
+#define TORQUE_TEX2DCMP(tex,coords,compare) texture_##tex.SampleCmpLevelZero(tex,coords,compare)
 
 
-   //helper if you want to pass sampler/texture in a function
-   //2D
-   #define TORQUE_SAMPLER2D(tex) sampler2D tex
-   #define TORQUE_SAMPLER2D_MAKEARG(tex) tex
-   //Cube
-   #define TORQUE_SAMPLERCUBE(tex) samplerCUBE tex
-   #define TORQUE_SAMPLERCUBE_MAKEARG(tex) tex
-// Shader model 4.0+
-#elif TORQUE_SM >= 40
-   #define TORQUE_POSITION SV_Position
-   #define TORQUE_DEPTH SV_Depth
-   #define TORQUE_VPOS SV_Position //note float4 compared to SM 3 where it is a float2
-   #define TORQUE_TARGET0 SV_Target0
-   #define TORQUE_TARGET1 SV_Target1
-   #define TORQUE_TARGET2 SV_Target2
-   #define TORQUE_TARGET3 SV_Target3
-   // Sampler uniforms
-   //1D is emulated to a 2D for now
-   #define TORQUE_UNIFORM_SAMPLER1D(tex,regist) uniform Texture2D texture_##tex : register(T##regist); uniform SamplerState tex : register(S##regist)
-   #define TORQUE_UNIFORM_SAMPLER2D(tex,regist) uniform Texture2D texture_##tex : register(T##regist); uniform SamplerState tex : register(S##regist)
-   #define TORQUE_UNIFORM_SAMPLER3D(tex,regist) uniform Texture3D texture_##tex : register(T##regist); uniform SamplerState tex : register(S##regist)
-   #define TORQUE_UNIFORM_SAMPLERCUBE(tex,regist) uniform TextureCube texture_##tex : register(T##regist); uniform SamplerState tex : register(S##regist)
-   // Sampling functions
-   #define TORQUE_TEX1D(tex,coords) texture_##tex.Sample(tex,coords)
-   #define TORQUE_TEX2D(tex,coords) texture_##tex.Sample(tex,coords)
-   #define TORQUE_TEX2DPROJ(tex,coords) texture_##tex.Sample(tex,coords.xy / coords.w)
-   #define TORQUE_TEX3D(tex,coords) texture_##tex.Sample(tex,coords)
-   #define TORQUE_TEXCUBE(tex,coords) texture_##tex.Sample(tex,coords)
-   // The mipmap LOD is specified in coord.w
-   #define TORQUE_TEX2DLOD(tex,coords) texture_##tex.SampleLevel(tex,coords.xy,coords.w)
+#define TORQUE_TEX2DGATHER(tex,coords,compare,offset) texture_##tex.GatherCmp(tex,coords,compare,offset)
 
 
-   //helper if you want to pass sampler/texture in a function
-   //2D
-   #define TORQUE_SAMPLER2D(tex) Texture2D texture_##tex, SamplerState tex
-   #define TORQUE_SAMPLER2D_MAKEARG(tex) texture_##tex, tex
-   //Cube
-   #define TORQUE_SAMPLERCUBE(tex) TextureCube texture_##tex, SamplerState tex
-   #define TORQUE_SAMPLERCUBE_MAKEARG(tex) texture_##tex, tex
-#endif
+//helper if you want to pass sampler/texture in a function
+//2D
+#define TORQUE_SAMPLER2D(tex) Texture2D texture_##tex, SamplerState tex
+#define TORQUE_SAMPLER2D_MAKEARG(tex) texture_##tex, tex
+// Sampler comparison state - use above MAKEARG with this
+#define TORQUE_SAMPLER2DCMP(tex) Texture2D texture_##tex, SamplerComparisonState tex
+//Cube
+#define TORQUE_SAMPLERCUBE(tex) TextureCube texture_##tex, SamplerState tex
+#define TORQUE_SAMPLERCUBE_MAKEARG(tex) texture_##tex, tex
+#define TORQUE_SAMPLERCUBEARRAY(tex) TextureCubeArray texture_##tex, SamplerState tex
+#define TORQUE_SAMPLERCUBEARRAY_MAKEARG(tex) texture_##tex, tex
 
 
 #endif // _TORQUE_SHADERMODEL_
 #endif // _TORQUE_SHADERMODEL_
 
 

+ 3 - 5
Templates/BaseGame/game/core/rendering/shaders/shaderModelAutoGen.hlsl

@@ -24,12 +24,10 @@
 #define _TORQUE_SHADERMODEL_AUTOGEN_
 #define _TORQUE_SHADERMODEL_AUTOGEN_
 
 
 #include "shadergen:/autogenConditioners.h"
 #include "shadergen:/autogenConditioners.h"
+#include "./shaderModel.hlsl"
 
 
 // Portability helpers for autogenConditioners
 // Portability helpers for autogenConditioners
-#if (TORQUE_SM >= 10 && TORQUE_SM <=30)
-   #define TORQUE_DEFERRED_UNCONDITION(tex, coords) deferredUncondition(tex, coords)
-#elif TORQUE_SM >= 40
-   #define TORQUE_DEFERRED_UNCONDITION(tex, coords) deferredUncondition(tex, texture_##tex, coords)
-#endif
+
+#define TORQUE_DEFERRED_UNCONDITION(tex, coords) deferredUncondition(tex, texture_##tex, coords)
 
 
 #endif //_TORQUE_SHADERMODEL_AUTOGEN_
 #endif //_TORQUE_SHADERMODEL_AUTOGEN_

+ 54 - 47
Templates/BaseGame/game/core/rendering/shaders/torque.hlsl

@@ -167,22 +167,13 @@ float2 parallaxOffsetDxtnm(TORQUE_SAMPLER2D(texMap), float2 texCoord, float3 neg
    return offset;
    return offset;
 }
 }
 
 
-
-/// The maximum value for 16bit per component integer HDR encoding.
-static const float HDR_RGB16_MAX = 100.0;
-
 /// The maximum value for 10bit per component integer HDR encoding.
 /// The maximum value for 10bit per component integer HDR encoding.
 static const float HDR_RGB10_MAX = 4.0;
 static const float HDR_RGB10_MAX = 4.0;
 
 
 /// Encodes an HDR color for storage into a target.
 /// Encodes an HDR color for storage into a target.
 float3 hdrEncode( float3 sample )
 float3 hdrEncode( float3 sample )
 {
 {
-   #if defined( TORQUE_HDR_RGB16 )
-
-      return sample / HDR_RGB16_MAX;
-
-   #elif defined( TORQUE_HDR_RGB10 ) 
-
+   #if defined( TORQUE_HDR_RGB10 )
       return sample / HDR_RGB10_MAX;
       return sample / HDR_RGB10_MAX;
 
 
    #else
    #else
@@ -202,12 +193,7 @@ float4 hdrEncode( float4 sample )
 /// Decodes an HDR color from a target.
 /// Decodes an HDR color from a target.
 float3 hdrDecode( float3 sample )
 float3 hdrDecode( float3 sample )
 {
 {
-   #if defined( TORQUE_HDR_RGB16 )
-
-      return sample * HDR_RGB16_MAX;
-
-   #elif defined( TORQUE_HDR_RGB10 )
-
+   #if defined( TORQUE_HDR_RGB10 )
       return sample * HDR_RGB10_MAX;
       return sample * HDR_RGB10_MAX;
 
 
    #else
    #else
@@ -286,57 +272,78 @@ bool getFlag(float flags, int num)
    return (fmod(process, pow(2, squareNum)) >= squareNum); 
    return (fmod(process, pow(2, squareNum)) >= squareNum); 
 }
 }
 
 
-// #define TORQUE_STOCK_GAMMA
-#ifdef TORQUE_STOCK_GAMMA
 // Sample in linear space. Decodes gamma.
 // Sample in linear space. Decodes gamma.
 float4 toLinear(float4 tex)
 float4 toLinear(float4 tex)
 {
 {
-   return tex;
+   return float4(pow(abs(tex.rgb), 2.2), tex.a);
 }
 }
 // Encodes gamma.
 // Encodes gamma.
 float4 toGamma(float4 tex)
 float4 toGamma(float4 tex)
 {
 {
-   return tex;
+   return float4(pow(abs(tex.rgb), 1.0/2.2), tex.a);
 }
 }
+// Sample in linear space. Decodes gamma.
 float3 toLinear(float3 tex)
 float3 toLinear(float3 tex)
 {
 {
-   return tex;
+   return pow(abs(tex.rgb), 2.2);
 }
 }
 // Encodes gamma.
 // Encodes gamma.
 float3 toGamma(float3 tex)
 float3 toGamma(float3 tex)
 {
 {
-   return tex;
-}
-float3 toLinear(float3 tex)
-{
-   return tex;
-}
-// Encodes gamma.
-float3 toLinear(float3 tex)
-{
-   return tex;
-}
-#else
-// Sample in linear space. Decodes gamma.
-float4 toLinear(float4 tex)
-{
-   return float4(pow(abs(tex.rgb), 2.2), tex.a);
+   return pow(abs(tex.rgb), 1.0/2.2);
 }
 }
-// Encodes gamma.
-float4 toGamma(float4 tex)
+
+//
+float3 PBRFresnel(float3 albedo, float3 indirect, float metalness, float fresnel)
 {
 {
-   return float4(pow(abs(tex.rgb), 1.0/2.2), tex.a);
+   float3 diffuseColor = albedo - (albedo * metalness);
+   float3 reflectColor = lerp(indirect*albedo, indirect, fresnel);
+
+   return diffuseColor + reflectColor;
 }
 }
-// Sample in linear space. Decodes gamma.
-float3 toLinear(float3 tex)
+
+float3 simpleFresnel(float3 diffuseColor, float3 reflectColor, float metalness, float angle, float bias, float power)
 {
 {
-   return pow(abs(tex.rgb), 2.2);
+   float fresnelTerm = bias + (1.0 - bias) * pow(abs(1.0 - max(angle, 0)), power);
+
+   fresnelTerm *= metalness;
+
+   return lerp(diffuseColor, reflectColor, fresnelTerm);
 }
 }
-// Encodes gamma.
-float3 toGamma(float3 tex)
+
+//hlsl version of the glsl funcion mod - note hlsl fmod is different
+#define mod(x,y) (x-y*floor(x/y))
+
+//get direction for a cube face
+float3 getCubeDir(int face, float2 uv)
 {
 {
-   return pow(abs(tex.rgb), 1.0/2.2);
+	float2 debiased = uv * 2.0f - 1.0f;
+
+	float3 dir = 0;
+
+	switch (face)
+	{
+		case 0: dir = float3(1, -debiased.y, -debiased.x); 
+			break;
+
+		case 1: dir = float3(-1, -debiased.y, debiased.x); 
+			break;
+
+		case 2: dir = float3(debiased.x, 1, debiased.y); 
+			break;
+
+		case 3: dir = float3(debiased.x, -1, -debiased.y); 
+			break;
+
+		case 4: dir = float3(debiased.x, -debiased.y, 1); 
+			break;
+
+		case 5: dir = float3(-debiased.x, -debiased.y, -1); 
+			break;
+	};
+
+	return normalize(dir);
 }
 }
-#endif //
 
 
+#define sqr(a)		((a)*(a))
 #endif // _TORQUE_HLSL_
 #endif // _TORQUE_HLSL_

BIN
Templates/BaseGame/game/data/StaticShapeTest/Images/Grid_512_orange.png


+ 9 - 0
Templates/BaseGame/game/data/StaticShapeTest/Images/Grid_512_orange_ALBEDO.asset.taml

@@ -0,0 +1,9 @@
+<ImageAsset
+    canSave="true"
+    canSaveDynamicFields="true"
+    AssetName="Grid_512_orange_ALBEDO"
+    imageFile="@assetFile=Grid_512_orange.png"
+    useMips="true"
+    isHDRImage="false"
+    originalFilePath="E:/Gamedev/T3DMIT/clangtest/Templates/Full/game/core/art/grids/Grid_512_orange.png"
+    VersionId="1" />

+ 9 - 0
Templates/BaseGame/game/data/StaticShapeTest/Shapes/Cube.asset.taml

@@ -0,0 +1,9 @@
+<ShapeAsset
+    canSave="true"
+    canSaveDynamicFields="true"
+    AssetName="Cube"
+    fileName="@assetFile=Cube.fbx"
+    isNewShape="1"
+    materialSlot0="@Asset=StaticShapeTest:Grid_512_orange"
+    originalFilePath="E:/Gamedev/T3DMIT/clangtest/My Projects/T3DPreview4_0/art/StarterContent/Cube.fbx"
+    VersionId="1" />

+ 5 - 0
Templates/BaseGame/game/data/StaticShapeTest/Shapes/Cube.cs

@@ -0,0 +1,5 @@
+
+singleton TSShapeConstructor(CubeFbx)
+{
+   baseShape = "./Cube.fbx";
+};

BIN
Templates/BaseGame/game/data/StaticShapeTest/Shapes/Cube.fbx


+ 8 - 0
Templates/BaseGame/game/data/StaticShapeTest/Shapes/Cylinder.asset.taml

@@ -0,0 +1,8 @@
+<ShapeAsset
+    canSave="true"
+    canSaveDynamicFields="true"
+    AssetName="Cylinder"
+    fileName="@assetFile=Cylinder.fbx"
+    isNewShape="1"
+    originalFilePath="E:/Gamedev/T3DMIT/clangtest/My Projects/T3DPreview4_0/art/StarterContent/Cylinder.fbx"
+    VersionId="1" />

+ 5 - 0
Templates/BaseGame/game/data/StaticShapeTest/Shapes/Cylinder.cs

@@ -0,0 +1,5 @@
+
+singleton TSShapeConstructor(CylinderFbx)
+{
+   baseShape = "./Cylinder.fbx";
+};

BIN
Templates/BaseGame/game/data/StaticShapeTest/Shapes/Cylinder.fbx


+ 11 - 0
Templates/BaseGame/game/data/StaticShapeTest/Shapes/materials.cs

@@ -0,0 +1,11 @@
+
+singleton Material(Grid_512_Orange)
+{
+   mapTo = "Grid_512_orange";
+   diffuseColor[0] = "0.8 0.8 0.8 1";
+   diffuseMap[0] = "E:/Gamedev/T3DMIT/clangtest/Templates/Full/game/core/art/grids/Grid_512_orange.png";
+   specular[0] = "0.8 0.8 0.8 1";
+   specularPower[0] = "0.25";
+   specularStrength[0] = "25";
+   translucentBlendOp = "None";
+};

+ 10 - 0
Templates/BaseGame/game/data/StaticShapeTest/StaticShapeTest.cs

@@ -0,0 +1,10 @@
+function StaticShapeTest::onCreate(%this)
+{
+
+}
+
+function StaticShapeTest::onDestroy(%this)
+{
+
+}
+

+ 25 - 0
Templates/BaseGame/game/data/StaticShapeTest/StaticShapeTest.module

@@ -0,0 +1,25 @@
+<ModuleDefinition
+    canSave="true"
+    canSaveDynamicFields="true"
+    ModuleId="StaticShapeTest"
+    VersionId="1"
+    Group="Game"
+    scriptFile="StaticShapeTest.cs"
+    CreateFunction="onCreate"
+    DestroyFunction="onDestroy">
+    <DeclaredAssets
+        canSave="true"
+        canSaveDynamicFields="true"
+        Extension="asset.taml"
+        Recurse="true" />
+    <AutoloadAssets
+        canSave="true"
+        canSaveDynamicFields="true"
+        AssetType="ComponentAsset"
+        Recurse="true" />
+    <AutoloadAssets
+        canSave="true"
+        canSaveDynamicFields="true"
+        AssetType="GUIAsset"
+        Recurse="true" />
+</ModuleDefinition>

+ 9 - 0
Templates/BaseGame/game/data/StaticShapeTest/materials/Grid_512_orange.asset.taml

@@ -0,0 +1,9 @@
+<MaterialAsset
+    canSave="true"
+    canSaveDynamicFields="true"
+    AssetName="Grid_512_Orange"
+    scriptFile="@assetFile=data/StaticShapeTest/materials/Grid_512_orange.cs"
+    materialDefinitionName="Grid_512_Orange"
+    originalFilePath="E:/Gamedev/T3DMIT/clangtest/Templates/Full/game/core/art/grids/Grid_512_orange.png"
+    shaderGraph="data/StaticShapeTest/materials/Grid_512_orange.sgf"
+    VersionId="1" />

+ 7 - 0
Templates/BaseGame/game/data/StaticShapeTest/materials/Grid_512_orange.cs

@@ -0,0 +1,7 @@
+//--- OBJECT WRITE BEGIN ---
+singleton Material(Grid_512_orange) {
+   mapTo = "Grid_512_orange";
+   DiffuseMap[0] = "data/StaticShapeTest/Images/Grid_512_orange.png";
+   DiffuseMapAsset[0] = "StaticShapeTest:Grid_512_orange_ALBEDO";
+};
+//--- OBJECT WRITE END ---

+ 20 - 25
Templates/BaseGame/game/data/shaderCache/8625023c97ea6cf9_P.hlsl

@@ -4,17 +4,6 @@
 
 
 // Dependencies:
 // Dependencies:
 #include "core/rendering/shaders/lighting.hlsl"
 #include "core/rendering/shaders/lighting.hlsl"
-//------------------------------------------------------------------------------
-// Autogenerated 'Light Buffer Conditioner [RGB]' Uncondition Method
-//------------------------------------------------------------------------------
-inline void autogenUncondition_bde4cbab(in float4 bufferSample, out float3 lightColor, out float NL_att, out float specular)
-{
-   lightColor = bufferSample.rgb;
-   NL_att = dot(bufferSample.rgb, float3(0.3576, 0.7152, 0.1192));
-   specular = bufferSample.a;
-}
-
-
 #include "core/rendering/shaders/torque.hlsl"
 #include "core/rendering/shaders/torque.hlsl"
 
 
 // Features:
 // Features:
@@ -27,7 +16,8 @@ inline void autogenUncondition_bde4cbab(in float4 bufferSample, out float3 light
 struct ConnectData
 struct ConnectData
 {
 {
    float4 vpos            : SV_Position;
    float4 vpos            : SV_Position;
-   float4 screenspacePos  : TEXCOORD0;
+   float3 wsNormal        : TEXCOORD0;
+   float3 wsPosition      : TEXCOORD1;
 };
 };
 
 
 
 
@@ -42,10 +32,17 @@ struct Fragout
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 Fragout main( ConnectData IN,
 Fragout main( ConnectData IN,
               uniform float4    diffuseMaterialColor : register(C0),
               uniform float4    diffuseMaterialColor : register(C0),
-              uniform float4    rtParamslightInfoBuffer : register(C2),
-              uniform SamplerState lightInfoBuffer : register(S0),
-              uniform Texture2D lightInfoBufferTex : register(T0),
-              uniform float     visibility      : register(C1)
+              uniform float3    eyePosWorld     : register(C17),
+              uniform float4    inLightPos[3] : register(C1),
+              uniform float4    inLightInvRadiusSq : register(C4),
+              uniform float4    inLightColor[4] : register(C5),
+              uniform float4    inLightSpotDir[3] : register(C9),
+              uniform float4    inLightSpotAngle : register(C12),
+              uniform float4    inLightSpotFalloff : register(C13),
+              uniform float     smoothness      : register(C14),
+              uniform float     metalness       : register(C15),
+              uniform float4    ambient         : register(C18),
+              uniform float     visibility      : register(C16)
 )
 )
 {
 {
    Fragout OUT;
    Fragout OUT;
@@ -56,15 +53,13 @@ Fragout main( ConnectData IN,
    OUT.col = diffuseMaterialColor;
    OUT.col = diffuseMaterialColor;
    
    
    // Deferred RT Lighting
    // Deferred RT Lighting
-   float2 uvScene = IN.screenspacePos.xy / IN.screenspacePos.w;
-   uvScene = ( uvScene + 1.0 ) / 2.0;
-   uvScene.y = 1.0 - uvScene.y;
-   uvScene = ( uvScene * rtParamslightInfoBuffer.zw ) + rtParamslightInfoBuffer.xy;
-   float3 d_lightcolor;
-   float d_NL_Att;
-   float d_specular;
-   lightinfoUncondition(lightInfoBufferTex.Sample(lightInfoBuffer, uvScene), d_lightcolor, d_NL_Att, d_specular);
-   OUT.col *= float4(d_lightcolor, 1.0);
+   IN.wsNormal = normalize( half3( IN.wsNormal ) );
+   float3 wsView = normalize( eyePosWorld - IN.wsPosition );
+   float4 rtShading; float4 specular;
+   compute4Lights( wsView, IN.wsPosition, IN.wsNormal, float4( 1, 1, 1, 1 ),
+      inLightPos, inLightInvRadiusSq, inLightColor, inLightSpotDir, inLightSpotAngle, inLightSpotFalloff, smoothness, metalness, OUT.col,
+      rtShading, specular );
+   OUT.col *= float4( rtShading.rgb + ambient.rgb, 1 );
    
    
    // Visibility
    // Visibility
    fizzle( IN.vpos.xy, visibility );
    fizzle( IN.vpos.xy, visibility );

+ 6 - 14
Templates/BaseGame/game/data/shaderCache/8625023c97ea6cf9_V.hlsl

@@ -4,17 +4,6 @@
 
 
 // Dependencies:
 // Dependencies:
 #include "core/rendering/shaders/lighting.hlsl"
 #include "core/rendering/shaders/lighting.hlsl"
-//------------------------------------------------------------------------------
-// Autogenerated 'Light Buffer Conditioner [RGB]' Uncondition Method
-//------------------------------------------------------------------------------
-inline void autogenUncondition_bde4cbab(in float4 bufferSample, out float3 lightColor, out float NL_att, out float specular)
-{
-   lightColor = bufferSample.rgb;
-   NL_att = dot(bufferSample.rgb, float3(0.3576, 0.7152, 0.1192));
-   specular = bufferSample.a;
-}
-
-
 #include "core/rendering/shaders/torque.hlsl"
 #include "core/rendering/shaders/torque.hlsl"
 
 
 // Features:
 // Features:
@@ -38,7 +27,8 @@ struct VertData
 struct ConnectData
 struct ConnectData
 {
 {
    float4 hpos            : SV_Position;
    float4 hpos            : SV_Position;
-   float4 screenspacePos  : TEXCOORD0;
+   float3 wsNormal        : TEXCOORD0;
+   float3 outWsPosition   : TEXCOORD1;
 };
 };
 
 
 
 
@@ -46,7 +36,8 @@ struct ConnectData
 // Main
 // Main
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 ConnectData main( VertData IN,
 ConnectData main( VertData IN,
-                  uniform float4x4 modelview       : register(C0)
+                  uniform float4x4 modelview       : register(C0),
+                  uniform float4x4 objTrans        : register(C4)
 )
 )
 {
 {
    ConnectData OUT;
    ConnectData OUT;
@@ -57,7 +48,8 @@ ConnectData main( VertData IN,
    // Diffuse Color
    // Diffuse Color
    
    
    // Deferred RT Lighting
    // Deferred RT Lighting
-   OUT.screenspacePos = OUT.hpos;
+   OUT.wsNormal = mul( objTrans, float4( normalize( IN.normal ), 0.0 ) ).xyz;
+   OUT.outWsPosition = mul( objTrans, float4( IN.position.xyz, 1 ) ).xyz;
    
    
    // Visibility
    // Visibility
    
    

+ 0 - 22
Templates/BaseGame/game/data/shaderCache/autogenConditioners.h

@@ -1,25 +1,3 @@
-//------------------------------------------------------------------------------
-// Autogenerated 'Light Buffer Conditioner [RGB]' Condition Method
-//------------------------------------------------------------------------------
-inline float4 autogenCondition_bde4cbab(in float3 lightColor, in float NL_att, in float specular, in float4 bufferSample)
-{
-   float4 rgbLightInfoOut = float4(lightColor, 0) * NL_att + float4(bufferSample.rgb, specular);
-
-   return rgbLightInfoOut;
-}
-
-
-//------------------------------------------------------------------------------
-// Autogenerated 'Light Buffer Conditioner [RGB]' Uncondition Method
-//------------------------------------------------------------------------------
-inline void autogenUncondition_bde4cbab(in float4 bufferSample, out float3 lightColor, out float NL_att, out float specular)
-{
-   lightColor = bufferSample.rgb;
-   NL_att = dot(bufferSample.rgb, float3(0.3576, 0.7152, 0.1192));
-   specular = bufferSample.a;
-}
-
-
 //------------------------------------------------------------------------------
 //------------------------------------------------------------------------------
 // Autogenerated 'GBuffer Conditioner' Condition Method
 // Autogenerated 'GBuffer Conditioner' Condition Method
 //------------------------------------------------------------------------------
 //------------------------------------------------------------------------------

BIN
Templates/BaseGame/game/data/ui/art/BackgroundImage.png


File diff suppressed because it is too large
+ 915 - 52
Templates/BaseGame/game/tools/materialEditor/gui/guiMaterialPropertiesWindow.ed.gui


+ 2 - 0
Templates/BaseGame/game/tools/materialEditor/main.cs

@@ -121,6 +121,8 @@ function MaterialEditorPlugin::onActivated( %this )
       $wasInWireFrameMode = false;  
       $wasInWireFrameMode = false;  
    }
    }
    advancedTextureMapsRollout.Expanded = false;
    advancedTextureMapsRollout.Expanded = false;
+   accumulationPropertiesRollout.Expanded = false;
+   lightingPropertiesRollout.Expanded = false;
    materialAnimationPropertiesRollout.Expanded = false;
    materialAnimationPropertiesRollout.Expanded = false;
    materialAdvancedPropertiesRollout.Expanded = false;
    materialAdvancedPropertiesRollout.Expanded = false;
    WorldEditorPlugin.onActivated();
    WorldEditorPlugin.onActivated();

+ 230 - 17
Templates/BaseGame/game/tools/materialEditor/scripts/materialEditor.ed.cs

@@ -137,8 +137,6 @@ function MaterialEditorGui::open(%this)
    
    
    if( MaterialEditorGui.currentMode $= "Mesh" )
    if( MaterialEditorGui.currentMode $= "Mesh" )
       MaterialEditorGui.prepareActiveObject( true );
       MaterialEditorGui.prepareActiveObject( true );
-   else if( MaterialEditorGui.currentMode $= "asset" )
-      MaterialEditorGui.prepareActiveMaterial( MaterialEditorGui.currentMaterial, true );
    else
    else
       MaterialEditorGui.prepareActiveMaterial( "", true );
       MaterialEditorGui.prepareActiveMaterial( "", true );
       
       
@@ -290,9 +288,7 @@ function MaterialEditorGui::setMode( %this )
    }
    }
    else
    else
    {
    {
-      if(MaterialEditorGui.currentMode !$= "asset")
-         MaterialEditorGui.currentMode = "Material";
-         
+      MaterialEditorGui.currentMode = "Material";
       MatEdMaterialMode.setVisible(1);
       MatEdMaterialMode.setVisible(1);
       EWorldEditor.clearSelection();
       EWorldEditor.clearSelection();
    }
    }
@@ -597,6 +593,27 @@ function MaterialEditorGui::convertTextureFields(%this)
       %specMap = MaterialEditorGui.searchForTexture(MaterialEditorGui.currentMaterial, %specMap);
       %specMap = MaterialEditorGui.searchForTexture(MaterialEditorGui.currentMaterial, %specMap);
       MaterialEditorGui.currentMaterial.specularMap[%specI] = %specMap;
       MaterialEditorGui.currentMaterial.specularMap[%specI] = %specMap;
    }
    }
+   
+   for(%roughI = 0; %roughI < 4; %roughI++)
+   {
+      %roughMap = MaterialEditorGui.currentMaterial.roughMap[%roughI];      
+      %roughMap = MaterialEditorGui.searchForTexture(MaterialEditorGui.currentMaterial, %roughMap);
+      MaterialEditorGui.currentMaterial.roughMap[%specI] = %roughMap;
+   }
+   
+   for(%aoI = 0; %aoI < 4; %aoI++)
+   {
+      %aoMap = MaterialEditorGui.currentMaterial.aoMap[%aoI];      
+      %aoMap = MaterialEditorGui.searchForTexture(MaterialEditorGui.currentMaterial, %aoMap);
+      MaterialEditorGui.currentMaterial.aoMap[%specI] = %aoMap;
+   }
+   
+   for(%metalI = 0; %metalI < 4; %metalI++)
+   {
+      %metalMap = MaterialEditorGui.currentMaterial.metalMap[%metalI];      
+      %metalMap = MaterialEditorGui.searchForTexture(MaterialEditorGui.currentMaterial, %metalMap);
+      MaterialEditorGui.currentMaterial.metalMap[%metalI] = %metalMap;
+   }
 }
 }
 
 
 // still needs to be optimized further
 // still needs to be optimized further
@@ -879,7 +896,9 @@ function MaterialEditorGui::guiSync( %this, %material )
       MaterialEditorPropertiesWindow-->toneMapNameText.setText( (%material).toneMap[%layer] );
       MaterialEditorPropertiesWindow-->toneMapNameText.setText( (%material).toneMap[%layer] );
       MaterialEditorPropertiesWindow-->toneMapDisplayBitmap.setBitmap( (%material).toneMap[%layer] );
       MaterialEditorPropertiesWindow-->toneMapDisplayBitmap.setBitmap( (%material).toneMap[%layer] );
    }
    }
-   
+   MaterialEditorPropertiesWindow-->isSRGBCheckbox.setValue((%material).isSRGB[%layer]);
+   MaterialEditorPropertiesWindow-->invertSmoothnessCheckbox.setValue((%material).invertSmoothness[%layer]);
+      
    if((%material).specularMap[%layer] $= "") 
    if((%material).specularMap[%layer] $= "") 
    {
    {
       MaterialEditorPropertiesWindow-->specMapNameText.setText( "None" );
       MaterialEditorPropertiesWindow-->specMapNameText.setText( "None" );
@@ -891,6 +910,39 @@ function MaterialEditorGui::guiSync( %this, %material )
       MaterialEditorPropertiesWindow-->specMapDisplayBitmap.setBitmap( (%material).specularMap[%layer] );
       MaterialEditorPropertiesWindow-->specMapDisplayBitmap.setBitmap( (%material).specularMap[%layer] );
    }
    }
    
    
+   if((%material).roughMap[%layer] $= "") 
+   {
+      MaterialEditorPropertiesWindow-->roughMapNameText.setText( "None" );
+      MaterialEditorPropertiesWindow-->roughMapDisplayBitmap.setBitmap( "tools/materialeditor/gui/unknownImage" );
+   }
+   else
+   {
+      MaterialEditorPropertiesWindow-->roughMapNameText.setText( (%material).roughMap[%layer] );
+      MaterialEditorPropertiesWindow-->roughMapDisplayBitmap.setBitmap( (%material).roughMap[%layer] );
+   }
+   
+   if((%material).aoMap[%layer] $= "") 
+   {
+      MaterialEditorPropertiesWindow-->aoMapNameText.setText( "None" );
+      MaterialEditorPropertiesWindow-->aoMapDisplayBitmap.setBitmap( "tools/materialeditor/gui/unknownImage" );
+   }
+   else
+   {
+      MaterialEditorPropertiesWindow-->aoMapNameText.setText( (%material).aoMap[%layer] );
+      MaterialEditorPropertiesWindow-->aoMapDisplayBitmap.setBitmap( (%material).aoMap[%layer] );
+   }
+   
+   if((%material).metalMap[%layer] $= "") 
+   {
+      MaterialEditorPropertiesWindow-->metalMapNameText.setText( "None" );
+      MaterialEditorPropertiesWindow-->metalMapDisplayBitmap.setBitmap( "tools/materialeditor/gui/unknownImage" );
+   }
+   else
+   {
+      MaterialEditorPropertiesWindow-->metalMapNameText.setText( (%material).metalMap[%layer] );
+      MaterialEditorPropertiesWindow-->metalMapDisplayBitmap.setBitmap( (%material).metalMap[%layer] );
+   }
+   
    MaterialEditorPropertiesWindow-->accuScaleTextEdit.setText((%material).accuScale[%layer]);
    MaterialEditorPropertiesWindow-->accuScaleTextEdit.setText((%material).accuScale[%layer]);
    MaterialEditorPropertiesWindow-->accuScaleTextEdit.setText((%material).accuScale[%layer]);
    MaterialEditorPropertiesWindow-->accuScaleTextEdit.setText((%material).accuScale[%layer]);
    MaterialEditorPropertiesWindow-->accuDirectionTextEdit.setText((%material).accuDirection[%layer]);
    MaterialEditorPropertiesWindow-->accuDirectionTextEdit.setText((%material).accuDirection[%layer]);
@@ -908,11 +960,10 @@ function MaterialEditorGui::guiSync( %this, %material )
    MaterialEditorPropertiesWindow-->colorTintSwatch.color = (%material).diffuseColor[%layer];
    MaterialEditorPropertiesWindow-->colorTintSwatch.color = (%material).diffuseColor[%layer];
    MaterialEditorPropertiesWindow-->specularColorSwatch.color = (%material).specular[%layer];     
    MaterialEditorPropertiesWindow-->specularColorSwatch.color = (%material).specular[%layer];     
    
    
-   MaterialEditorPropertiesWindow-->specularPowerTextEdit.setText((%material).specularPower[%layer]);
-   MaterialEditorPropertiesWindow-->specularPowerSlider.setValue((%material).specularPower[%layer]);
-   MaterialEditorPropertiesWindow-->specularStrengthTextEdit.setText((%material).specularStrength[%layer]);
-   MaterialEditorPropertiesWindow-->specularStrengthSlider.setValue((%material).specularStrength[%layer]);
-   MaterialEditorPropertiesWindow-->pixelSpecularCheckbox.setValue((%material).pixelSpecular[%layer]);
+   MaterialEditorPropertiesWindow-->SmoothnessTextEdit.setText((%material).Smoothness[%layer]);
+   MaterialEditorPropertiesWindow-->SmoothnessSlider.setValue((%material).Smoothness[%layer]);
+   MaterialEditorPropertiesWindow-->MetalnessTextEdit.setText((%material).Metalness[%layer]);
+   MaterialEditorPropertiesWindow-->MetalnessSlider.setValue((%material).Metalness[%layer]);
    MaterialEditorPropertiesWindow-->glowCheckbox.setValue((%material).glow[%layer]);
    MaterialEditorPropertiesWindow-->glowCheckbox.setValue((%material).glow[%layer]);
    MaterialEditorPropertiesWindow-->emissiveCheckbox.setValue((%material).emissive[%layer]);
    MaterialEditorPropertiesWindow-->emissiveCheckbox.setValue((%material).emissive[%layer]);
    MaterialEditorPropertiesWindow-->parallaxTextEdit.setText((%material).parallaxScale[%layer]);
    MaterialEditorPropertiesWindow-->parallaxTextEdit.setText((%material).parallaxScale[%layer]);
@@ -980,11 +1031,34 @@ function MaterialEditorGui::guiSync( %this, %material )
    MaterialEditorPropertiesWindow-->SequenceSliderSSS.setValue( %numFrames );
    MaterialEditorPropertiesWindow-->SequenceSliderSSS.setValue( %numFrames );
    
    
    // Accumulation
    // Accumulation
-   MaterialEditorPropertiesWindow-->accuCheckbox.setValue((%material).accuEnabled[%layer]);   
+   MaterialEditorPropertiesWindow-->accuCheckbox.setValue((%material).accuEnabled[%layer]);
+   
+   MaterialEditorPropertiesWindow-->accuCheckbox.setValue((%material).accuEnabled[%layer]);
    
    
+   %this.getRoughChan((%material).SmoothnessChan[%layer]);
+   %this.getAOChan((%material).AOChan[%layer]);
+   %this.getMetalChan((%material).metalChan[%layer]);
    %this.preventUndo = false;
    %this.preventUndo = false;
 }
 }
 
 
+//=======================================
+function MaterialEditorGui::getRoughChan(%this, %channel)
+{
+	%guiElement = roughChanBtn @ %channel;
+	%guiElement.setStateOn(true);
+}
+
+function MaterialEditorGui::getAOChan(%this, %channel)
+{
+	%guiElement = AOChanBtn @ %channel;
+	%guiElement.setStateOn(true);
+}
+
+function MaterialEditorGui::getMetalChan(%this, %channel)
+{
+	%guiElement = metalChanBtn @ %channel;
+	%guiElement.setStateOn(true);
+}
 //=======================================
 //=======================================
 // Material Update Functionality
 // Material Update Functionality
 
 
@@ -1055,7 +1129,7 @@ function MaterialEditorGui::updateActiveMaterialName(%this, %name)
    // Some objects (ConvexShape, DecalRoad etc) reference Materials by name => need
    // Some objects (ConvexShape, DecalRoad etc) reference Materials by name => need
    // to find and update all these references so they don't break when we rename the
    // to find and update all these references so they don't break when we rename the
    // Material.
    // Material.
-   MaterialEditorGui.updateMaterialReferences( getScene(0), %action.oldName, %action.newName );
+   MaterialEditorGui.updateMaterialReferences( getRootScene(), %action.oldName, %action.newName );
 }
 }
 
 
 function MaterialEditorGui::updateMaterialReferences( %this, %obj, %oldName, %newName )
 function MaterialEditorGui::updateMaterialReferences( %this, %obj, %oldName, %newName )
@@ -1196,6 +1270,90 @@ function MaterialEditorGui::updateSpecMap(%this,%action)
    MaterialEditorGui.guiSync( materialEd_previewMaterial );
    MaterialEditorGui.guiSync( materialEd_previewMaterial );
 }
 }
 
 
+function MaterialEditorGui::updateRoughMap(%this,%action)
+{
+   %layer = MaterialEditorGui.currentLayer;
+   
+   if( %action )
+   {
+      %texture = MaterialEditorGui.openFile("texture");
+      if( %texture !$= "" )
+      {         
+         MaterialEditorPropertiesWindow-->roughMapDisplayBitmap.setBitmap(%texture);
+      
+         %bitmap = MaterialEditorPropertiesWindow-->roughMapDisplayBitmap.bitmap;
+         %bitmap = strreplace(%bitmap,"tools/materialEditor/scripts/","");
+         MaterialEditorPropertiesWindow-->roughMapDisplayBitmap.setBitmap(%bitmap);
+         MaterialEditorPropertiesWindow-->roughMapNameText.setText(%bitmap);
+         MaterialEditorGui.updateActiveMaterial("roughMap[" @ %layer @ "]","\"" @ %bitmap @ "\"");
+      }
+   }
+   else
+   {
+      MaterialEditorPropertiesWindow-->roughMapNameText.setText("None");
+      MaterialEditorPropertiesWindow-->roughMapDisplayBitmap.setBitmap("tools/materialeditor/gui/unknownImage");
+      MaterialEditorGui.updateActiveMaterial("roughMap[" @ %layer @ "]","");
+   }
+   
+   MaterialEditorGui.guiSync( materialEd_previewMaterial );
+}
+
+function MaterialEditorGui::updateaoMap(%this,%action)
+{
+   %layer = MaterialEditorGui.currentLayer;
+   
+   if( %action )
+   {
+      %texture = MaterialEditorGui.openFile("texture");
+      if( %texture !$= "" )
+      {         
+         MaterialEditorPropertiesWindow-->aoMapDisplayBitmap.setBitmap(%texture);
+      
+         %bitmap = MaterialEditorPropertiesWindow-->aoMapDisplayBitmap.bitmap;
+         %bitmap = strreplace(%bitmap,"tools/materialEditor/scripts/","");
+         MaterialEditorPropertiesWindow-->aoMapDisplayBitmap.setBitmap(%bitmap);
+         MaterialEditorPropertiesWindow-->aoMapNameText.setText(%bitmap);
+         MaterialEditorGui.updateActiveMaterial("aoMap[" @ %layer @ "]","\"" @ %bitmap @ "\"");
+      }
+   }
+   else
+   {
+      MaterialEditorPropertiesWindow-->aoMapNameText.setText("None");
+      MaterialEditorPropertiesWindow-->aoMapDisplayBitmap.setBitmap("tools/materialeditor/gui/unknownImage");
+      MaterialEditorGui.updateActiveMaterial("aoMap[" @ %layer @ "]","");
+   }
+   
+   MaterialEditorGui.guiSync( materialEd_previewMaterial );
+}
+
+function MaterialEditorGui::updatemetalMap(%this,%action)
+{
+   %layer = MaterialEditorGui.currentLayer;
+   
+   if( %action )
+   {
+      %texture = MaterialEditorGui.openFile("texture");
+      if( %texture !$= "" )
+      {         
+         MaterialEditorPropertiesWindow-->metalMapDisplayBitmap.setBitmap(%texture);
+      
+         %bitmap = MaterialEditorPropertiesWindow-->metalMapDisplayBitmap.bitmap;
+         %bitmap = strreplace(%bitmap,"tools/materialEditor/scripts/","");
+         MaterialEditorPropertiesWindow-->metalMapDisplayBitmap.setBitmap(%bitmap);
+         MaterialEditorPropertiesWindow-->metalMapNameText.setText(%bitmap);
+         MaterialEditorGui.updateActiveMaterial("metalMap[" @ %layer @ "]","\"" @ %bitmap @ "\"");
+      }
+   }
+   else
+   {
+      MaterialEditorPropertiesWindow-->metalMapNameText.setText("None");
+      MaterialEditorPropertiesWindow-->metalMapDisplayBitmap.setBitmap("tools/materialeditor/gui/unknownImage");
+      MaterialEditorGui.updateActiveMaterial("metalMap[" @ %layer @ "]","");
+   }
+   
+   MaterialEditorGui.guiSync( materialEd_previewMaterial );
+}
+
 function MaterialEditorGui::updateRotationOffset(%this, %isSlider, %onMouseUp)
 function MaterialEditorGui::updateRotationOffset(%this, %isSlider, %onMouseUp)
 {
 {
    %layer = MaterialEditorGui.currentLayer;
    %layer = MaterialEditorGui.currentLayer;
@@ -1948,7 +2106,7 @@ function MaterialEditorGui::createNewMaterial( %this )
    %material = getUniqueName( "newMaterial" );
    %material = getUniqueName( "newMaterial" );
    new Material(%material) 
    new Material(%material) 
    {
    {
-      diffuseMap[0] = "core/images/warnmat";
+      diffuseMap[0] = "core/art/warnmat";
       mapTo = "unmapped_mat";
       mapTo = "unmapped_mat";
       parentGroup = RootGroup;
       parentGroup = RootGroup;
    };
    };
@@ -1979,7 +2137,7 @@ function MaterialEditorGui::deleteMaterial( %this )
       %toMaterial = getUniqueName( "newMaterial" );
       %toMaterial = getUniqueName( "newMaterial" );
       new Material(%toMaterial) 
       new Material(%toMaterial) 
       {
       {
-         diffuseMap[0] = "core/images/warnmat";
+         diffuseMap[0] = "core/art/warnmat";
          mapTo = "unmapped_mat";
          mapTo = "unmapped_mat";
          parentGroup = RootGroup;
          parentGroup = RootGroup;
       };
       };
@@ -1997,7 +2155,7 @@ function MaterialEditorGui::deleteMaterial( %this )
          %toMaterial = getUniqueName( "newMaterial" );
          %toMaterial = getUniqueName( "newMaterial" );
          new Material(%toMaterial) 
          new Material(%toMaterial) 
          {
          {
-            diffuseMap[0] = "core/images/warnmat";
+            diffuseMap[0] = "core/art/warnmat";
             mapTo = "unmapped_mat";
             mapTo = "unmapped_mat";
             parentGroup = RootGroup;
             parentGroup = RootGroup;
          };    
          };    
@@ -2012,7 +2170,7 @@ function MaterialEditorGui::deleteMaterial( %this )
    %newMaterial = getUniqueName( "newMaterial" );
    %newMaterial = getUniqueName( "newMaterial" );
    new Material(%newMaterial) 
    new Material(%newMaterial) 
    {
    {
-      diffuseMap[0] = "core/images/warnmat";
+      diffuseMap[0] = "core/art/warnmat";
       mapTo = "unmapped_mat";
       mapTo = "unmapped_mat";
       parentGroup = RootGroup;
       parentGroup = RootGroup;
    };
    };
@@ -2272,3 +2430,58 @@ function MaterialEditorGui::updateAccuCheckbox(%this, %value)
    MaterialEditorGui.updateActiveMaterial("accuEnabled[" @ MaterialEditorGui.currentLayer @ "]", %value);   
    MaterialEditorGui.updateActiveMaterial("accuEnabled[" @ MaterialEditorGui.currentLayer @ "]", %value);   
    MaterialEditorGui.guiSync( materialEd_previewMaterial );
    MaterialEditorGui.guiSync( materialEd_previewMaterial );
 }
 }
+
+// channel in selectors
+function MaterialEditorGui::setRoughChan(%this, %value)
+{
+   MaterialEditorGui.updateActiveMaterial("SmoothnessChan[" @ MaterialEditorGui.currentLayer @ "]", %value);   
+   MaterialEditorGui.guiSync( materialEd_previewMaterial );
+}
+
+function MaterialEditorGui::setAOChan(%this, %value)
+{
+   MaterialEditorGui.updateActiveMaterial("aoChan[" @ MaterialEditorGui.currentLayer @ "]", %value);   
+   MaterialEditorGui.guiSync( materialEd_previewMaterial );
+}
+
+function MaterialEditorGui::setMetalChan(%this, %value)
+{
+   MaterialEditorGui.updateActiveMaterial("metalChan[" @ MaterialEditorGui.currentLayer @ "]", %value);   
+   MaterialEditorGui.guiSync( materialEd_previewMaterial );
+}
+
+function MaterialEditorGui::saveCompositeMap(%this)
+{
+    %saveAs = "";
+    %dlg = new SaveFileDialog()
+    {
+        Filters        = "png";
+        DefaultPath    = EditorSettings.value("art/shapes/textures");
+        ChangePath     = false;
+        OverwritePrompt   = true;
+    };
+
+    %ret = %dlg.Execute();
+    if(%ret)
+    {
+        // Immediately override/set the levelsDirectory
+        EditorSettings.setValue( "art/shapes/textures", collapseFilename(filePath( %dlg.FileName )) );
+        %saveAs = %dlg.FileName;
+    }
+    
+    %material = %this.currentMaterial;
+    %layer = %this.currentLayer;
+   
+    %roughMap = %material.roughMap[%layer];
+    %aoMap = %material.aoMap[%layer];
+    %metalMap = %material.metalMap[%layer];
+    
+    %smooth = %material.SmoothnessChan[%layer];
+    %ao = %material.AOChan[%layer];
+    %metal = %material.metalChan[%layer];
+    
+    %channelKey = %smooth SPC %ao SPC %metal SPC 3;
+    error("Storing: \"" @ %roughMap @"\" \""@  %aoMap @"\" \""@ %metalMap @"\" \""@ %channelKey @"\" \""@ %saveAs @"\"");
+    saveCompositeTexture(%roughMap,%aoMap,%metalMap,"",%channelKey, %saveAs);
+    %dlg.delete();
+}

File diff suppressed because it is too large
+ 61 - 0
Templates/BaseGame/game/tools/resources/ReflectProbeSphere.dae


+ 8 - 0
Templates/BaseGame/game/tools/resources/materials.cs

@@ -0,0 +1,8 @@
+singleton Material(ReflectProbePreviewMat)
+{
+   mapTo = "ReflectProbePreviewMat";
+   diffuseColor[0] = "1 1 1 1";
+   smoothness[0] = "1";
+   metalness[0] = "1";
+   translucentBlendOp = "None";
+};

+ 49 - 0
Templates/BaseGame/game/tools/resources/reflectionProbePreviewP.hlsl

@@ -0,0 +1,49 @@
+#include "shaders/common/shaderModelAutoGen.hlsl"
+
+#include "shaders/common/lighting/advanced/farFrustumQuad.hlsl"
+#include "shaders/common/lighting/advanced/lightingUtils.hlsl"
+#include "shaders/common/lighting.hlsl"
+#include "shaders/common/torque.hlsl"
+
+struct ConvexConnectP
+{
+   float4 pos : TORQUE_POSITION;
+   float4 wsEyeDir : TEXCOORD0;
+   float4 ssPos : TEXCOORD1;
+   float4 vsEyeDir : TEXCOORD2;
+};
+
+TORQUE_UNIFORM_SAMPLER2D(deferredBuffer, 0);
+TORQUE_UNIFORM_SAMPLERCUBE(cubeMap, 1);
+
+uniform float4 rtParams0;
+
+uniform float4x4 invViewMat;
+
+float4 main( ConvexConnectP IN ) : TORQUE_TARGET0
+{ 
+    // Compute scene UV
+    float3 ssPos = IN.ssPos.xyz / IN.ssPos.w;
+    float2 uvScene = getUVFromSSPos( ssPos, rtParams0 );
+
+    //float3 eyeRay = IN.vsEyeDir.xyz;
+
+    // Sample/unpack the normal/z data
+    float4 deferredSample = TORQUE_DEFERRED_UNCONDITION( deferredBuffer, uvScene );
+    float3 normal = deferredSample.rgb;
+    float depth = deferredSample.a;
+    if (depth>0.9999)
+        return float4(0,0,0,0);
+
+    // Need world-space normal.
+    float3 wsNormal = mul(float4(normal, 1), invViewMat).rgb;
+
+    float3 reflectionVec = reflect(IN.wsEyeDir, float4(normalize(wsNormal),1)).rgb;
+
+    float4 color = TORQUE_TEXCUBE(cubeMap, reflectionVec);
+
+    //simple visibility testing
+    //float4 color = float4(1,0,0,1);
+
+    return float4(color.rgb, 1);
+}

+ 58 - 0
Templates/BaseGame/game/tools/resources/reflectionProbePreviewV.hlsl

@@ -0,0 +1,58 @@
+//-----------------------------------------------------------------------------
+// Copyright (c) 2012 GarageGames, LLC
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to
+// deal in the Software without restriction, including without limitation the
+// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+// sell copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+// IN THE SOFTWARE.
+//-----------------------------------------------------------------------------
+
+#include "shaders/common/hlslStructs.hlsl"
+#include "shaders/common/shaderModel.hlsl"
+
+struct VertData
+{
+   float3 pos        : POSITION;
+   float tangentW        : TEXCOORD3;
+   float3 normal          : NORMAL;
+   float3 T               : TANGENT;
+   float2 texCoord        : TEXCOORD0;
+};
+
+struct ConvexConnectV
+{
+   float4 hpos : TORQUE_POSITION;
+   float4 wsEyeDir : TEXCOORD0;
+   float4 ssPos : TEXCOORD1;
+   float4 vsEyeDir : TEXCOORD2;
+};
+
+uniform float4x4 modelview;
+uniform float4x4 objTrans;
+uniform float4x4 worldViewOnly;
+uniform float3 eyePosWorld;
+
+ConvexConnectV main( VertData IN )
+{
+   ConvexConnectV OUT;
+
+   OUT.hpos = mul( modelview, float4(IN.pos,1.0) );
+   OUT.wsEyeDir = mul(objTrans, float4(IN.pos, 1.0)) - float4(eyePosWorld, 0.0);
+   OUT.vsEyeDir = mul(worldViewOnly, float4(IN.pos, 1.0));
+   OUT.ssPos = OUT.hpos;
+
+   return OUT;
+}

+ 47 - 47
Templates/BaseGame/game/tools/settings.xml

@@ -1,84 +1,84 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes" ?>
 <?xml version="1.0" encoding="utf-8" standalone="yes" ?>
 <EditorSettings>
 <EditorSettings>
+    <Group name="NavEditor">
+        <Setting name="SpawnClass">AIPlayer</Setting>
+    </Group>
     <Group name="WorldEditor">
     <Group name="WorldEditor">
-        <Setting name="orthoShowGrid">1</Setting>
-        <Setting name="forceLoadDAE">0</Setting>
         <Setting name="currentEditor">WorldEditorInspectorPlugin</Setting>
         <Setting name="currentEditor">WorldEditorInspectorPlugin</Setting>
-        <Setting name="displayType">6</Setting>
         <Setting name="dropType">screenCenter</Setting>
         <Setting name="dropType">screenCenter</Setting>
-        <Setting name="orthoFOV">50</Setting>
         <Setting name="undoLimit">40</Setting>
         <Setting name="undoLimit">40</Setting>
+        <Setting name="forceLoadDAE">0</Setting>
+        <Setting name="displayType">6</Setting>
+        <Setting name="orthoFOV">50</Setting>
+        <Setting name="orthoShowGrid">1</Setting>
+        <Group name="Render">
+            <Setting name="renderPopupBackground">1</Setting>
+            <Setting name="renderSelectionBox">1</Setting>
+            <Setting name="renderObjHandle">1</Setting>
+            <Setting name="renderObjText">1</Setting>
+            <Setting name="showMousePopupInfo">1</Setting>
+        </Group>
+        <Group name="Images">
+            <Setting name="lockedHandle">tools/worldEditor/images/LockedHandle</Setting>
+            <Setting name="selectHandle">tools/worldEditor/images/SelectHandle</Setting>
+            <Setting name="defaultHandle">tools/worldEditor/images/DefaultHandle</Setting>
+        </Group>
         <Group name="Color">
         <Group name="Color">
-            <Setting name="selectionBoxColor">255 255 0 255</Setting>
-            <Setting name="objMouseOverColor">0 255 0 255</Setting>
-            <Setting name="objSelectColor">255 0 0 255</Setting>
             <Setting name="dragRectColor">255 255 0 255</Setting>
             <Setting name="dragRectColor">255 255 0 255</Setting>
             <Setting name="objectTextColor">255 255 255 255</Setting>
             <Setting name="objectTextColor">255 255 255 255</Setting>
+            <Setting name="objMouseOverColor">0 255 0 255</Setting>
+            <Setting name="selectionBoxColor">255 255 0 255</Setting>
             <Setting name="objMouseOverSelectColor">0 0 255 255</Setting>
             <Setting name="objMouseOverSelectColor">0 0 255 255</Setting>
+            <Setting name="objSelectColor">255 0 0 255</Setting>
             <Setting name="popupBackgroundColor">100 100 100 255</Setting>
             <Setting name="popupBackgroundColor">100 100 100 255</Setting>
         </Group>
         </Group>
-        <Group name="ObjectIcons">
-            <Setting name="fadeIconsStartDist">8</Setting>
-            <Setting name="fadeIconsEndDist">20</Setting>
-            <Setting name="fadeIconsStartAlpha">255</Setting>
-            <Setting name="fadeIconsEndAlpha">0</Setting>
-            <Setting name="fadeIcons">1</Setting>
-        </Group>
-        <Group name="Render">
-            <Setting name="showMousePopupInfo">1</Setting>
-            <Setting name="renderObjText">1</Setting>
-            <Setting name="renderSelectionBox">1</Setting>
-            <Setting name="renderPopupBackground">1</Setting>
-            <Setting name="renderObjHandle">1</Setting>
-        </Group>
         <Group name="Grid">
         <Group name="Grid">
-            <Setting name="gridOriginColor">255 255 255 100</Setting>
             <Setting name="gridColor">102 102 102 100</Setting>
             <Setting name="gridColor">102 102 102 100</Setting>
             <Setting name="gridSnap">0</Setting>
             <Setting name="gridSnap">0</Setting>
             <Setting name="gridSize">1</Setting>
             <Setting name="gridSize">1</Setting>
             <Setting name="gridMinorColor">51 51 51 100</Setting>
             <Setting name="gridMinorColor">51 51 51 100</Setting>
-        </Group>
-        <Group name="Docs">
-            <Setting name="documentationLocal">../../../Documentation/Official Documentation.html</Setting>
-            <Setting name="documentationReference">../../../Documentation/Torque 3D - Script Manual.chm</Setting>
-            <Setting name="documentationURL">http://www.garagegames.com/products/torque-3d/documentation/user</Setting>
-            <Setting name="forumURL">http://www.garagegames.com/products/torque-3d/forums</Setting>
-        </Group>
-        <Group name="Images">
-            <Setting name="lockedHandle">tools/worldEditor/images/LockedHandle</Setting>
-            <Setting name="selectHandle">tools/worldEditor/images/SelectHandle</Setting>
-            <Setting name="defaultHandle">tools/worldEditor/images/DefaultHandle</Setting>
+            <Setting name="gridOriginColor">255 255 255 100</Setting>
         </Group>
         </Group>
         <Group name="Tools">
         <Group name="Tools">
-            <Setting name="boundingBoxCollision">0</Setting>
-            <Setting name="snapSoftSize">2</Setting>
-            <Setting name="dropAtScreenCenterMax">100</Setting>
-            <Setting name="snapSoft">0</Setting>
             <Setting name="objectsUseBoxCenter">1</Setting>
             <Setting name="objectsUseBoxCenter">1</Setting>
+            <Setting name="snapSoftSize">2</Setting>
             <Setting name="dropAtScreenCenterScalar">1</Setting>
             <Setting name="dropAtScreenCenterScalar">1</Setting>
             <Setting name="snapGround">0</Setting>
             <Setting name="snapGround">0</Setting>
+            <Setting name="dropAtScreenCenterMax">100</Setting>
+            <Setting name="boundingBoxCollision">0</Setting>
+            <Setting name="snapSoft">0</Setting>
+        </Group>
+        <Group name="ObjectIcons">
+            <Setting name="fadeIconsEndDist">20</Setting>
+            <Setting name="fadeIconsStartAlpha">255</Setting>
+            <Setting name="fadeIconsEndAlpha">0</Setting>
+            <Setting name="fadeIcons">1</Setting>
+            <Setting name="fadeIconsStartDist">8</Setting>
+        </Group>
+        <Group name="Docs">
+            <Setting name="documentationReference">../../../Documentation/Torque 3D - Script Manual.chm</Setting>
+            <Setting name="documentationLocal">../../../Documentation/Official Documentation.html</Setting>
+            <Setting name="documentationURL">http://www.garagegames.com/products/torque-3d/documentation/user</Setting>
+            <Setting name="forumURL">http://www.garagegames.com/products/torque-3d/forums</Setting>
         </Group>
         </Group>
     </Group>
     </Group>
     <Group name="AxisGizmo">
     <Group name="AxisGizmo">
-        <Setting name="renderInfoText">1</Setting>
-        <Setting name="mouseRotateScalar">0.8</Setting>
         <Setting name="axisGizmoMaxScreenLen">100</Setting>
         <Setting name="axisGizmoMaxScreenLen">100</Setting>
-        <Setting name="mouseScaleScalar">0.8</Setting>
         <Setting name="rotationSnap">15</Setting>
         <Setting name="rotationSnap">15</Setting>
-        <Setting name="renderWhenUsed">0</Setting>
         <Setting name="snapRotations">0</Setting>
         <Setting name="snapRotations">0</Setting>
+        <Setting name="mouseRotateScalar">0.8</Setting>
+        <Setting name="mouseScaleScalar">0.8</Setting>
+        <Setting name="renderWhenUsed">0</Setting>
+        <Setting name="renderInfoText">1</Setting>
         <Group name="Grid">
         <Group name="Grid">
-            <Setting name="renderPlane">0</Setting>
+            <Setting name="gridColor">255 255 255 20</Setting>
+            <Setting name="renderPlaneHashes">0</Setting>
             <Setting name="planeDim">500</Setting>
             <Setting name="planeDim">500</Setting>
+            <Setting name="renderPlane">0</Setting>
             <Setting name="snapToGrid">0</Setting>
             <Setting name="snapToGrid">0</Setting>
             <Setting name="gridSize">10 10 10</Setting>
             <Setting name="gridSize">10 10 10</Setting>
-            <Setting name="gridColor">255 255 255 20</Setting>
-            <Setting name="renderPlaneHashes">0</Setting>
         </Group>
         </Group>
     </Group>
     </Group>
-    <Group name="NavEditor">
-        <Setting name="SpawnClass">AIPlayer</Setting>
-    </Group>
     <Group name="LevelInformation">
     <Group name="LevelInformation">
         <Setting name="levelsDirectory">data/FPSGameplay/levels</Setting>
         <Setting name="levelsDirectory">data/FPSGameplay/levels</Setting>
         <Group name="levels">
         <Group name="levels">

+ 1559 - 1206
Templates/BaseGame/game/tools/worldEditor/gui/guiTerrainMaterialDlg.ed.gui

@@ -1,637 +1,239 @@
 //--- OBJECT WRITE BEGIN ---
 //--- OBJECT WRITE BEGIN ---
-%guiContent = new GuiControl(TerrainMaterialDlg, EditorGuiGroup) {
-   canSaveDynamicFields = "0";
-   isContainer = "1";
-   Profile = "ToolsGuiDefaultProfile";
-   HorizSizing = "right";
-   VertSizing = "bottom";
+%guiContent = new GuiControl(TerrainMaterialDlg,EditorGuiGroup) {
    position = "0 0";
    position = "0 0";
-   Extent = "800 768";
-   MinExtent = "8 2";
-   canSave = "1";
-   Visible = "1";
-   tooltipprofile = "ToolsGuiToolTipProfile";
+   extent = "1024 768";
+   minExtent = "8 2";
+   horizSizing = "right";
+   vertSizing = "bottom";
+   profile = "ToolsGuiDefaultProfile";
+   visible = "1";
+   active = "1";
+   tooltipProfile = "ToolsGuiToolTipProfile";
    hovertime = "1000";
    hovertime = "1000";
+   isContainer = "1";
+   canSave = "1";
+   canSaveDynamicFields = "1";
+      activeMat = "17411";
+      matIndex = "0";
+      onApplyCallback = "EPainter_TerrainMaterialUpdateCallback";
 
 
    new GuiWindowCtrl() {
    new GuiWindowCtrl() {
-      canSaveDynamicFields = "0";
-      isContainer = "1";
-      Profile = "ToolsGuiWindowProfile";
-      HorizSizing = "center";
-      VertSizing = "center";
-      position = "221 151";
-      Extent = "394 432";
-      MinExtent = "358 432";
-      canSave = "1";
-      Visible = "1";
-      tooltipprofile = "ToolsGuiToolTipProfile";
-      hovertime = "1000";
-      Docking = "None";
-      Margin = "4 4 4 4";
-      Padding = "0 0 0 0";
-      AnchorTop = "0";
-      AnchorBottom = "0";
-      AnchorLeft = "0";
-      AnchorRight = "0";
+      text = "Terrain Materials Editor";
       resizeWidth = "1";
       resizeWidth = "1";
       resizeHeight = "1";
       resizeHeight = "1";
       canMove = "1";
       canMove = "1";
       canClose = "1";
       canClose = "1";
       canMinimize = "0";
       canMinimize = "0";
       canMaximize = "0";
       canMaximize = "0";
-      minSize = "50 50";
+      canCollapse = "0";
       closeCommand = "TerrainMaterialDlg.dialogCancel();";
       closeCommand = "TerrainMaterialDlg.dialogCancel();";
-      EdgeSnap = "0";
-      text = "Terrain Materials Editor";
-      new GuiContainer(){ //Node Properties
+      edgeSnap = "0";
+      docking = "None";
+      margin = "4 4 4 4";
+      padding = "0 0 0 0";
+      anchorTop = "0";
+      anchorBottom = "0";
+      anchorLeft = "0";
+      anchorRight = "0";
+      position = "315 168";
+      extent = "394 432";
+      minExtent = "358 432";
+      horizSizing = "center";
+      vertSizing = "center";
+      profile = "ToolsGuiWindowProfile";
+      visible = "1";
+      active = "1";
+      tooltipProfile = "ToolsGuiToolTipProfile";
+      hovertime = "1000";
+      isContainer = "1";
+      canSave = "1";
+      canSaveDynamicFields = "0";
+
+      new GuiContainer() {
+         margin = "0 0 0 0";
+         padding = "0 0 0 0";
+         anchorTop = "1";
+         anchorBottom = "0";
+         anchorLeft = "1";
+         anchorRight = "0";
+         position = "6 25";
+         extent = "189 64";
+         minExtent = "8 2";
+         horizSizing = "width";
+         vertSizing = "bottom";
+         profile = "inspectorStyleRolloutDarkProfile";
+         visible = "1";
+         active = "1";
+         tooltipProfile = "GuiToolTipProfile";
+         hovertime = "1000";
          isContainer = "1";
          isContainer = "1";
-         Profile = "inspectorStyleRolloutDarkProfile";
-         HorizSizing = "width";
-         VertSizing = "bottom";
-         Position = "6 25";
-         Extent = "189 64";
-         
-         new GuiTextCtrl(){
-            Profile = "ToolsGuiDefaultProfile";
-            HorizSizing = "right";
-            VertSizing = "bottom";
-            Position = "5 0";
-            Extent = "91 18";
+         canSave = "1";
+         canSaveDynamicFields = "0";
+
+         new GuiTextCtrl() {
             text = "Terrain Materials";
             text = "Terrain Materials";
+            maxLength = "1024";
+            margin = "0 0 0 0";
+            padding = "0 0 0 0";
+            anchorTop = "1";
+            anchorBottom = "0";
+            anchorLeft = "1";
+            anchorRight = "0";
+            position = "5 0";
+            extent = "91 18";
+            minExtent = "8 2";
+            horizSizing = "right";
+            vertSizing = "bottom";
+            profile = "ToolsGuiDefaultProfile";
+            visible = "1";
+            active = "1";
+            tooltipProfile = "GuiToolTipProfile";
+            hovertime = "1000";
+            isContainer = "1";
+            canSave = "1";
+            canSaveDynamicFields = "0";
          };
          };
          new GuiBitmapButtonCtrl() {
          new GuiBitmapButtonCtrl() {
-            canSaveDynamicFields = "0";
-            isContainer = "0";
-            Profile = "ToolsGuiButtonProfile";
-            HorizSizing = "left";
-            VertSizing = "top";
-            position = "160 2";
-            Extent = "15 15";
-            MinExtent = "8 2";
-            canSave = "1";
-            Visible = "1";
-            Command = "TerrainMaterialDlg.newMat();";
-            tooltipprofile = "ToolsGuiToolTipProfile";
-            hovertime = "1000";
+            bitmap = "tools/gui/images/new";
+            bitmapMode = "Stretched";
+            autoFitExtents = "0";
+            useModifiers = "0";
+            useStates = "1";
+            masked = "0";
             groupNum = "-1";
             groupNum = "-1";
             buttonType = "PushButton";
             buttonType = "PushButton";
             useMouseEvents = "0";
             useMouseEvents = "0";
-            bitmap = "tools/gui/images/new";
-         };
-         new GuiBitmapButtonCtrl() {
-            canSaveDynamicFields = "0";
+            position = "160 2";
+            extent = "15 15";
+            minExtent = "8 2";
+            horizSizing = "left";
+            vertSizing = "top";
+            profile = "ToolsGuiButtonProfile";
+            visible = "1";
+            active = "1";
+            command = "TerrainMaterialDlg.newMat();";
+            tooltipProfile = "ToolsGuiToolTipProfile";
+            hovertime = "1000";
             isContainer = "0";
             isContainer = "0";
-            Profile = "ToolsGuiButtonProfile";
-            HorizSizing = "left";
-            VertSizing = "top";
-            position = "173 2";
-            Extent = "15 15";
-            MinExtent = "8 2";
             canSave = "1";
             canSave = "1";
-            Visible = "1";
-            Command = "TerrainMaterialDlg.deleteMat();";
-            tooltipprofile = "ToolsGuiToolTipProfile";
-            hovertime = "1000";
+            canSaveDynamicFields = "0";
+         };
+         new GuiBitmapButtonCtrl() {
+            bitmap = "tools/gui/images/delete";
+            bitmapMode = "Stretched";
+            autoFitExtents = "0";
+            useModifiers = "0";
+            useStates = "1";
+            masked = "0";
             groupNum = "-1";
             groupNum = "-1";
             buttonType = "PushButton";
             buttonType = "PushButton";
             useMouseEvents = "0";
             useMouseEvents = "0";
-            bitmap = "tools/gui/images/delete";
+            position = "173 2";
+            extent = "15 15";
+            minExtent = "8 2";
+            horizSizing = "left";
+            vertSizing = "top";
+            profile = "ToolsGuiButtonProfile";
+            visible = "1";
+            active = "1";
+            command = "TerrainMaterialDlg.deleteMat();";
+            tooltipProfile = "ToolsGuiToolTipProfile";
+            hovertime = "1000";
+            isContainer = "0";
+            canSave = "1";
+            canSaveDynamicFields = "0";
          };
          };
       };
       };
       new GuiContainer() {
       new GuiContainer() {
-         canSaveDynamicFields = "0";
-         internalName = "matSettingsParent";
-         isContainer = "1";
-         Profile = "inspectorStyleRolloutProfile";
-         HorizSizing = "left";
-         VertSizing = "height";
+         margin = "0 0 0 0";
+         padding = "0 0 0 0";
+         anchorTop = "1";
+         anchorBottom = "0";
+         anchorLeft = "1";
+         anchorRight = "0";
          position = "202 26";
          position = "202 26";
-         Extent = "185 363";
-         MinExtent = "8 2";
-         canSave = "1";
-         Visible = "1";
-         tooltipprofile = "ToolsGuiToolTipProfile";
+         extent = "185 363";
+         minExtent = "8 2";
+         horizSizing = "left";
+         vertSizing = "height";
+         profile = "inspectorStyleRolloutProfile";
+         visible = "1";
+         active = "1";
+         tooltipProfile = "ToolsGuiToolTipProfile";
          hovertime = "1000";
          hovertime = "1000";
-         Margin = "0 0 0 0";
-         Padding = "0 0 0 0";
-         AnchorTop = "1";
-         AnchorBottom = "0";
-         AnchorLeft = "1";
-         AnchorRight = "0";
+         isContainer = "1";
+         internalName = "matSettingsParent";
+         canSave = "1";
+         canSaveDynamicFields = "0";
 
 
-         new GuiBitmapCtrl() {
-            canSaveDynamicFields = "0";
-            isContainer = "0";
-            Profile = "ToolsGuiDefaultProfile";
-            HorizSizing = "width";
-            VertSizing = "bottom";
-            position = "1 0";
-            Extent = "183 2";
-            MinExtent = "8 2";
-            canSave = "1";
-            Visible = "1";
-            tooltipprofile = "ToolsGuiToolTipProfile";
-            hovertime = "1000";
-            bitmap = "core/art/gui/images/separator-v";
-            wrap = "0";
-         };
          new GuiTextCtrl() {
          new GuiTextCtrl() {
-            canSaveDynamicFields = "0";
-            isContainer = "0";
-            Profile = "ToolsGuiTextProfile";
-            HorizSizing = "right";
-            VertSizing = "bottom";
-            position = "8 22";
-            Extent = "44 17";
-            MinExtent = "8 2";
-            canSave = "1";
-            Visible = "1";
-            tooltipprofile = "ToolsGuiDefaultProfile";
-            hovertime = "1000";
-            Margin = "0 0 0 0";
-            Padding = "0 0 0 0";
-            AnchorTop = "1";
-            AnchorBottom = "0";
-            AnchorLeft = "1";
-            AnchorRight = "0";
             text = "Name";
             text = "Name";
             maxLength = "1024";
             maxLength = "1024";
-         };
-         new GuiTextEditCtrl() {
-            internalName = "matNameCtrl";
-            canSaveDynamicFields = "0";
+            margin = "0 0 0 0";
+            padding = "0 0 0 0";
+            anchorTop = "1";
+            anchorBottom = "0";
+            anchorLeft = "1";
+            anchorRight = "0";
+            position = "8 22";
+            extent = "44 17";
+            minExtent = "8 2";
+            horizSizing = "right";
+            vertSizing = "bottom";
+            profile = "ToolsGuiTextProfile";
+            visible = "1";
+            active = "1";
+            tooltipProfile = "ToolsGuiDefaultProfile";
+            hovertime = "1000";
             isContainer = "0";
             isContainer = "0";
-            Profile = "ToolsGuiTextEditProfile";
-            HorizSizing = "right";
-            VertSizing = "bottom";
-            position = "39 21";
-            Extent = "143 18";
-            MinExtent = "8 2";
             canSave = "1";
             canSave = "1";
-            Visible = "1";
-            tooltipprofile = "ToolsGuiToolTipProfile";
-            hovertime = "1000";
-            Margin = "0 0 0 0";
-            Padding = "0 0 0 0";
-            AnchorTop = "1";
-            AnchorBottom = "0";
-            AnchorLeft = "1";
-            AnchorRight = "0";
-            maxLength = "1024";
+            canSaveDynamicFields = "0";
+         };
+         new GuiTextEditCtrl() {
             historySize = "0";
             historySize = "0";
-            password = "0";
             tabComplete = "0";
             tabComplete = "0";
             sinkAllKeyEvents = "0";
             sinkAllKeyEvents = "0";
+            password = "0";
             passwordMask = "*";
             passwordMask = "*";
-            altCommand = "TerrainMaterialDlg.setMaterialName( $ThisControl.getText() );";
-         };
-         new GuiTextCtrl() {
-            canSaveDynamicFields = "0";
-            isContainer = "0";
-            Profile = "ToolsGuiInspectorTitleTextProfile";
-            HorizSizing = "right";
-            VertSizing = "bottom";
-            position = "8 0";
-            Extent = "117 16";
-            MinExtent = "8 2";
-            canSave = "1";
-            Visible = "1";
-            tooltipprofile = "ToolsGuiToolTipProfile";
-            hovertime = "1000";
-            Margin = "0 0 0 0";
-            Padding = "0 0 0 0";
-            AnchorTop = "1";
-            AnchorBottom = "0";
-            AnchorLeft = "1";
-            AnchorRight = "0";
-            text = "Material Properties";
+            text = "sand";
             maxLength = "1024";
             maxLength = "1024";
-         };
-         new GuiContainer() {
-            canSaveDynamicFields = "0";
-            isContainer = "1";
-            Profile = "ToolsGuiDefaultProfile";
-            HorizSizing = "width";
-            VertSizing = "bottom";
-            position = "6 43";
-            Extent = "185 75";
-            MinExtent = "8 2";
-            canSave = "1";
-            Visible = "1";
-            tooltipprofile = "ToolsGuiToolTipProfile";
+            margin = "0 0 0 0";
+            padding = "0 0 0 0";
+            anchorTop = "1";
+            anchorBottom = "0";
+            anchorLeft = "1";
+            anchorRight = "0";
+            position = "39 21";
+            extent = "143 18";
+            minExtent = "8 2";
+            horizSizing = "right";
+            vertSizing = "bottom";
+            profile = "ToolsGuiTextEditProfile";
+            visible = "1";
+            active = "1";
+            altCommand = "TerrainMaterialDlg.setMaterialName( $ThisControl.getText() );";
+            tooltipProfile = "ToolsGuiToolTipProfile";
             hovertime = "1000";
             hovertime = "1000";
-            Margin = "0 0 0 0";
-            Padding = "0 0 0 0";
-            AnchorTop = "1";
-            AnchorBottom = "0";
-            AnchorLeft = "1";
-            AnchorRight = "0";
-
-            new GuiCheckBoxCtrl() {
-               internalName = "sideProjectionCtrl";
-               canSaveDynamicFields = "0";
-               isContainer = "0";
-               Profile = "ToolsGuiCheckBoxProfile";
-               HorizSizing = "right";
-               VertSizing = "bottom";
-               position = "55 54";
-               Extent = "119 16";
-               MinExtent = "8 2";
-               canSave = "1";
-               Visible = "1";
-               tooltipprofile = "ToolsGuiToolTipProfile";
-               hovertime = "1000";
-               text = " Use Side Projection";
-               groupNum = "-1";
-               buttonType = "ToggleButton";
-               useMouseEvents = "0";
-               useInactiveState = "0";
-            };
-            new GuiBitmapCtrl() {
-               internalName = "baseTexCtrl";
-               canSaveDynamicFields = "0";
-               isContainer = "0";
-               Profile = "ToolsGuiDefaultProfile";
-               HorizSizing = "right";
-               VertSizing = "bottom";
-               position = "1 1";
-               Extent = "47 47";
-               MinExtent = "8 2";
-               canSave = "1";
-               Visible = "1";
-               tooltipprofile = "ToolsGuiToolTipProfile";
-               hovertime = "1000";
-               bitmap = "tools/materialEditor/gui/unknownImage";
-               wrap = "0";
-            };
-            new GuiBitmapButtonCtrl() {
-               canSaveDynamicFields = "0";
-               isContainer = "0";
-               Profile = "ToolsGuiDefaultProfile";
-               HorizSizing = "right";
-               VertSizing = "bottom";
-               position = "1 1";
-               Extent = "48 48";
-               MinExtent = "8 2";
-               canSave = "1";
-               Visible = "1";
-               Command = "TerrainMaterialDlg.changeBase();";
-               tooltipprofile = "ToolsGuiDefaultProfile";
-               ToolTip = "Change the Active Diffuse Map for this layer";
-               hovertime = "1000";
-               groupNum = "-1";
-               buttonType = "PushButton";
-               useMouseEvents = "0";
-               bitmap = "tools/materialEditor/gui/cubemapBtnBorder";
-            };
-            new GuiTextCtrl() {
-               canSaveDynamicFields = "0";
-               isContainer = "0";
-               Profile = "EditorTextProfile";
-               HorizSizing = "right";
-               VertSizing = "bottom";
-               position = "56 -3";
-               Extent = "39 18";
-               MinExtent = "8 2";
-               canSave = "1";
-               Visible = "1";
-               tooltipprofile = "ToolsGuiToolTipProfile";
-               hovertime = "1000";
-               Margin = "0 0 0 0";
-               Padding = "0 0 0 0";
-               AnchorTop = "1";
-               AnchorBottom = "0";
-               AnchorLeft = "1";
-               AnchorRight = "0";
-               text = "Diffuse";
-               maxLength = "1024";
-            };
-            new GuiTextCtrl() {
-               canSaveDynamicFields = "0";
-               isContainer = "0";
-               Profile = "ToolsGuiTextProfile";
-               HorizSizing = "width";
-               VertSizing = "bottom";
-               position = "56 16";
-               Extent = "116 17";
-               MinExtent = "8 2";
-               canSave = "1";
-               Visible = "1";
-               tooltipprofile = "ToolsGuiToolTipProfile";
-               hovertime = "1000";
-               Margin = "0 0 0 0";
-               Padding = "0 0 0 0";
-               AnchorTop = "1";
-               AnchorBottom = "0";
-               AnchorLeft = "1";
-               AnchorRight = "0";
-               text = "None";
-               maxLength = "1024";
-            };
-            new GuiButtonCtrl() {
-               canSaveDynamicFields = "0";
-               isContainer = "0";
-               Profile = "ToolsGuiButtonProfile";
-               HorizSizing = "left";
-               VertSizing = "bottom";
-               position = "116 0";
-               Extent = "40 16";
-               MinExtent = "8 2";
-               canSave = "1";
-               Visible = "1";
-               Command = "TerrainMaterialDlg.changeBase();";
-               tooltipprofile = "ToolsGuiToolTipProfile";
-               hovertime = "1000";
-               text = "Edit";
-               groupNum = "-1";
-               buttonType = "PushButton";
-               useMouseEvents = "0";
-            };
-            new GuiBitmapButtonCtrl() {
-               canSaveDynamicFields = "0";
-               isContainer = "0";
-               Profile = "ToolsGuiDefaultProfile";
-               HorizSizing = "left";
-               VertSizing = "bottom";
-               position = "159 0";
-               Extent = "16 16";
-               MinExtent = "8 2";
-               canSave = "1";
-               Visible = "1";
-               Command = "TerrainMaterialDlg-->baseTexCtrl.setBitmap(\"tools/materialEditor/gui/unknownImage\");";
-               tooltipprofile = "ToolsGuiToolTipProfile";
-               hovertime = "1000";
-               groupNum = "-1";
-               buttonType = "PushButton";
-               useMouseEvents = "0";
-               bitmap = "tools/gui/images/delete";
-            };
-            new GuiTextCtrl() {
-               canSaveDynamicFields = "0";
-               isContainer = "0";
-               Profile = "ToolsGuiTextProfile";
-               HorizSizing = "right";
-               VertSizing = "bottom";
-               position = "132 35";
-               Extent = "39 16";
-               MinExtent = "8 2";
-               canSave = "1";
-               Visible = "1";
-               tooltipprofile = "ToolsGuiToolTipProfile";
-               hovertime = "1000";
-               Margin = "0 0 0 0";
-               Padding = "0 0 0 0";
-               AnchorTop = "0";
-               AnchorBottom = "0";
-               AnchorLeft = "0";
-               AnchorRight = "0";
-               text = "Size";
-               maxLength = "1024";
-            };
-            new GuiTextEditCtrl() {
-               internalName = "baseSizeCtrl";
-               canSaveDynamicFields = "0";
-               isContainer = "0";
-               Profile = "ToolsGuiTextEditProfile";
-               HorizSizing = "right";
-               VertSizing = "bottom";
-               position = "94 34";
-               Extent = "34 18";
-               MinExtent = "8 2";
-               canSave = "1";
-               Visible = "1";
-               tooltipprofile = "ToolsGuiToolTipProfile";
-               hovertime = "1000";
-               Margin = "0 0 0 0";
-               Padding = "0 0 0 0";
-               AnchorTop = "0";
-               AnchorBottom = "0";
-               AnchorLeft = "0";
-               AnchorRight = "0";
-               maxLength = "1024";
-               historySize = "0";
-               password = "0";
-               tabComplete = "0";
-               sinkAllKeyEvents = "0";
-               passwordMask = "*";
-            };
-         };
-         new GuiBitmapCtrl() {
-            canSaveDynamicFields = "0";
             isContainer = "0";
             isContainer = "0";
-            Profile = "ToolsGuiDefaultProfile";
-            HorizSizing = "width";
-            VertSizing = "bottom";
-            position = "6 116";
-            Extent = "175 2";
-            MinExtent = "8 2";
+            internalName = "matNameCtrl";
             canSave = "1";
             canSave = "1";
-            Visible = "1";
-            tooltipprofile = "ToolsGuiToolTipProfile";
-            hovertime = "1000";
-            bitmap = "tools/gui/images/separator-v";
-            wrap = "0";
-         };
-         new GuiContainer() {
             canSaveDynamicFields = "0";
             canSaveDynamicFields = "0";
-            isContainer = "1";
-            Profile = "ToolsGuiDefaultProfile";
-            HorizSizing = "width";
-            VertSizing = "bottom";
-            position = "6 295";
-            Extent = "185 50";
-            MinExtent = "8 2";
-            canSave = "1";
-            Visible = "1";
-            tooltipprofile = "ToolsGuiToolTipProfile";
-            hovertime = "1000";
-            Margin = "0 0 0 0";
-            Padding = "0 0 0 0";
-            AnchorTop = "1";
-            AnchorBottom = "0";
-            AnchorLeft = "1";
-            AnchorRight = "0";
-
-            new GuiBitmapCtrl() {
-               internalName = "normTexCtrl";
-               canSaveDynamicFields = "0";
-               isContainer = "0";
-               Profile = "ToolsGuiDefaultProfile";
-               HorizSizing = "right";
-               VertSizing = "bottom";
-               position = "1 1";
-               Extent = "47 47";
-               MinExtent = "8 2";
-               canSave = "1";
-               Visible = "1";
-               tooltipprofile = "ToolsGuiToolTipProfile";
-               hovertime = "1000";
-               bitmap = "tools/materialEditor/gui/unknownImage";
-               wrap = "0";
-            };
-            new GuiTextCtrl() {
-               canSaveDynamicFields = "0";
-               isContainer = "0";
-               Profile = "EditorTextProfile";
-               HorizSizing = "right";
-               VertSizing = "bottom";
-               position = "56 -3";
-               Extent = "39 18";
-               MinExtent = "8 2";
-               canSave = "1";
-               Visible = "1";
-               tooltipprofile = "ToolsGuiToolTipProfile";
-               hovertime = "1000";
-               Margin = "0 0 0 0";
-               Padding = "0 0 0 0";
-               AnchorTop = "1";
-               AnchorBottom = "0";
-               AnchorLeft = "1";
-               AnchorRight = "0";
-               text = "Normal";
-               maxLength = "1024";
-            };
-            new GuiBitmapButtonCtrl() {
-               canSaveDynamicFields = "0";
-               isContainer = "0";
-               Profile = "ToolsGuiDefaultProfile";
-               HorizSizing = "right";
-               VertSizing = "bottom";
-               position = "1 1";
-               Extent = "48 48";
-               MinExtent = "8 2";
-               canSave = "1";
-               Visible = "1";
-               Command = "TerrainMaterialDlg.changeNormal();";
-               tooltipprofile = "ToolsGuiDefaultProfile";
-               ToolTip = "Change the active Normal Map for this layer.";
-               hovertime = "1000";
-               groupNum = "-1";
-               buttonType = "PushButton";
-               useMouseEvents = "0";
-               bitmap = "tools/materialEditor/gui/cubemapBtnBorder";
-            };
-            new GuiTextCtrl() {
-               canSaveDynamicFields = "0";
-               isContainer = "0";
-               Profile = "ToolsGuiTextProfile";
-               HorizSizing = "width";
-               VertSizing = "bottom";
-               position = "56 15";
-               Extent = "116 17";
-               MinExtent = "8 2";
-               canSave = "1";
-               Visible = "1";
-               tooltipprofile = "ToolsGuiToolTipProfile";
-               hovertime = "1000";
-               Margin = "0 0 0 0";
-               Padding = "0 0 0 0";
-               AnchorTop = "1";
-               AnchorBottom = "0";
-               AnchorLeft = "1";
-               AnchorRight = "0";
-               text = "None";
-               maxLength = "1024";
-            };
-            new GuiButtonCtrl() {
-               canSaveDynamicFields = "0";
-               isContainer = "0";
-               Profile = "ToolsGuiButtonProfile";
-               HorizSizing = "left";
-               VertSizing = "bottom";
-               position = "116 0";
-               Extent = "40 16";
-               MinExtent = "8 2";
-               canSave = "1";
-               Visible = "1";
-               Command = "TerrainMaterialDlg.changeNormal();";
-               tooltipprofile = "ToolsGuiToolTipProfile";
-               hovertime = "1000";
-               text = "Edit";
-               groupNum = "-1";
-               buttonType = "PushButton";
-               useMouseEvents = "0";
-            };
-            new GuiBitmapButtonCtrl() {
-               canSaveDynamicFields = "0";
-               isContainer = "0";
-               Profile = "ToolsGuiDefaultProfile";
-               HorizSizing = "left";
-               VertSizing = "bottom";
-               position = "159 0";
-               Extent = "16 16";
-               MinExtent = "8 2";
-               canSave = "1";
-               Visible = "1";
-               Command = "TerrainMaterialDlg-->normTexCtrl.setBitmap(\"tools/materialEditor/gui/unknownImage\");";
-               tooltipprofile = "ToolsGuiToolTipProfile";
-               hovertime = "1000";
-               groupNum = "-1";
-               buttonType = "PushButton";
-               useMouseEvents = "0";
-               bitmap = "tools/gui/images/delete";
-            };
-            new GuiTextCtrl() {
-               canSaveDynamicFields = "0";
-               isContainer = "0";
-               Profile = "ToolsGuiTextProfile";
-               HorizSizing = "right";
-               VertSizing = "bottom";
-               position = "92 34";
-               Extent = "77 16";
-               MinExtent = "8 2";
-               canSave = "1";
-               Visible = "1";
-               tooltipprofile = "ToolsGuiToolTipProfile";
-               hovertime = "1000";
-               Margin = "0 0 0 0";
-               Padding = "0 0 0 0";
-               AnchorTop = "1";
-               AnchorBottom = "0";
-               AnchorLeft = "1";
-               AnchorRight = "0";
-               text = "Parallax Scale";
-               maxLength = "1024";
-            };
-            new GuiTextEditCtrl() {
-               internalName = "parallaxScaleCtrl";
-               canSaveDynamicFields = "0";
-               isContainer = "0";
-               Profile = "ToolsGuiTextEditProfile";
-               HorizSizing = "right";
-               VertSizing = "bottom";
-               position = "55 33";
-               Extent = "34 18";
-               MinExtent = "8 2";
-               canSave = "1";
-               Visible = "1";
-               tooltipprofile = "ToolsGuiToolTipProfile";
-               hovertime = "1000";
-               Margin = "0 0 0 0";
-               Padding = "0 0 0 0";
-               AnchorTop = "0";
-               AnchorBottom = "0";
-               AnchorLeft = "0";
-               AnchorRight = "0";
-               text = "0.00";
-               maxLength = "1024";
-               historySize = "0";
-               password = "0";
-               tabComplete = "0";
-               sinkAllKeyEvents = "0";
-               passwordMask = "*";
-            };
          };
          };
-
-         new GuiBitmapCtrl() {
-            bitmap = "tools/gui/images/separator-v";
-            wrap = "0";
-            position = "6 288";
-            extent = "175 2";
+         new GuiTextCtrl() {
+            text = "Material Properties";
+            maxLength = "1024";
+            margin = "0 0 0 0";
+            padding = "0 0 0 0";
+            anchorTop = "1";
+            anchorBottom = "0";
+            anchorLeft = "1";
+            anchorRight = "0";
+            position = "8 0";
+            extent = "117 16";
             minExtent = "8 2";
             minExtent = "8 2";
-            horizSizing = "width";
+            horizSizing = "right";
             vertSizing = "bottom";
             vertSizing = "bottom";
-            profile = "ToolsGuiDefaultProfile";
+            profile = "ToolsGuiInspectorTitleTextProfile";
             visible = "1";
             visible = "1";
             active = "1";
             active = "1";
             tooltipProfile = "ToolsGuiToolTipProfile";
             tooltipProfile = "ToolsGuiToolTipProfile";
@@ -640,19 +242,27 @@
             canSave = "1";
             canSave = "1";
             canSaveDynamicFields = "0";
             canSaveDynamicFields = "0";
          };
          };
-         new GuiContainer() {
+         new GuiScrollCtrl() {
+            willFirstRespond = "1";
+            hScrollBar = "dynamic";
+            vScrollBar = "dynamic";
+            lockHorizScroll = "1";
+            lockVertScroll = "0";
+            constantThumbHeight = "0";
+            childMargin = "0 0";
+            mouseWheelScrollSpeed = "-1";
             margin = "0 0 0 0";
             margin = "0 0 0 0";
             padding = "0 0 0 0";
             padding = "0 0 0 0";
             anchorTop = "1";
             anchorTop = "1";
             anchorBottom = "0";
             anchorBottom = "0";
             anchorLeft = "1";
             anchorLeft = "1";
             anchorRight = "0";
             anchorRight = "0";
-            position = "6 122";
-            extent = "185 72";
+            position = "0 45";
+            extent = "189 329";
             minExtent = "8 2";
             minExtent = "8 2";
             horizSizing = "width";
             horizSizing = "width";
-            vertSizing = "bottom";
-            profile = "ToolsGuiDefaultProfile";
+            vertSizing = "height";
+            profile = "ToolsGuiScrollProfile";
             visible = "1";
             visible = "1";
             active = "1";
             active = "1";
             tooltipProfile = "ToolsGuiToolTipProfile";
             tooltipProfile = "ToolsGuiToolTipProfile";
@@ -661,730 +271,1473 @@
             canSave = "1";
             canSave = "1";
             canSaveDynamicFields = "0";
             canSaveDynamicFields = "0";
 
 
-            new GuiBitmapCtrl() {
-               bitmap = "tools/materialEditor/gui/unknownImage";
-               wrap = "0";
-               position = "1 1";
-               extent = "47 47";
-               minExtent = "8 2";
-               horizSizing = "right";
-               vertSizing = "bottom";
-               profile = "ToolsGuiDefaultProfile";
-               visible = "1";
-               active = "1";
-               tooltipProfile = "ToolsGuiToolTipProfile";
-               hovertime = "1000";
-               isContainer = "0";
-               internalName = "macroTexCtrl";
-               canSave = "1";
-               canSaveDynamicFields = "0";
-            };
-            new GuiBitmapButtonCtrl() {
-               bitmap = "tools/materialEditor/gui/cubemapBtnBorder";
-               bitmapMode = "Stretched";
-               autoFitExtents = "0";
-               useModifiers = "0";
-               useStates = "1";
-               groupNum = "-1";
-               buttonType = "PushButton";
-               useMouseEvents = "0";
-               position = "1 1";
-               extent = "48 48";
-               minExtent = "8 2";
-               horizSizing = "right";
-               vertSizing = "bottom";
-               profile = "ToolsGuiDefaultProfile";
-               visible = "1";
-               active = "1";
-               command = "TerrainMaterialDlg.changeMacro();";
-               tooltipProfile = "ToolsGuiDefaultProfile";
-               tooltip = "Change the active Macro Map for this layer.";
-               hovertime = "1000";
-               isContainer = "0";
-               canSave = "1";
-               canSaveDynamicFields = "0";
-            };
-            new GuiTextCtrl() {
-               text = "Macro";
-               maxLength = "1024";
+            new GuiContainer() {
                margin = "0 0 0 0";
                margin = "0 0 0 0";
                padding = "0 0 0 0";
                padding = "0 0 0 0";
                anchorTop = "1";
                anchorTop = "1";
                anchorBottom = "0";
                anchorBottom = "0";
                anchorLeft = "1";
                anchorLeft = "1";
                anchorRight = "0";
                anchorRight = "0";
-               position = "56 -3";
-               extent = "34 18";
+               position = "1 1";
+               extent = "174 73";
                minExtent = "8 2";
                minExtent = "8 2";
-               horizSizing = "right";
+               horizSizing = "width";
                vertSizing = "bottom";
                vertSizing = "bottom";
-               profile = "EditorTextProfile";
+               profile = "ToolsGuiDefaultProfile";
                visible = "1";
                visible = "1";
                active = "1";
                active = "1";
                tooltipProfile = "ToolsGuiToolTipProfile";
                tooltipProfile = "ToolsGuiToolTipProfile";
                hovertime = "1000";
                hovertime = "1000";
-               isContainer = "0";
+               isContainer = "1";
                canSave = "1";
                canSave = "1";
                canSaveDynamicFields = "0";
                canSaveDynamicFields = "0";
+
+               new GuiCheckBoxCtrl() {
+                  text = " Use Side Projection";
+                  groupNum = "-1";
+                  buttonType = "ToggleButton";
+                  useMouseEvents = "0";
+                  position = "55 54";
+                  extent = "119 16";
+                  minExtent = "8 2";
+                  horizSizing = "right";
+                  vertSizing = "bottom";
+                  profile = "ToolsGuiCheckBoxProfile";
+                  visible = "1";
+                  active = "1";
+                  tooltipProfile = "ToolsGuiToolTipProfile";
+                  hovertime = "1000";
+                  isContainer = "0";
+                  internalName = "sideProjectionCtrl";
+                  canSave = "1";
+                  canSaveDynamicFields = "0";
+               };
+               new GuiBitmapCtrl() {
+                  bitmap = "art/terrains/Example/sand";
+                  color = "255 255 255 255";
+                  wrap = "0";
+                  position = "1 1";
+                  extent = "47 47";
+                  minExtent = "8 2";
+                  horizSizing = "right";
+                  vertSizing = "bottom";
+                  profile = "ToolsGuiDefaultProfile";
+                  visible = "1";
+                  active = "1";
+                  tooltipProfile = "ToolsGuiToolTipProfile";
+                  hovertime = "1000";
+                  isContainer = "0";
+                  internalName = "baseTexCtrl";
+                  canSave = "1";
+                  canSaveDynamicFields = "0";
+               };
+               new GuiBitmapButtonCtrl() {
+                  bitmap = "tools/materialEditor/gui/cubemapBtnBorder";
+                  bitmapMode = "Stretched";
+                  autoFitExtents = "0";
+                  useModifiers = "0";
+                  useStates = "1";
+                  masked = "0";
+                  groupNum = "-1";
+                  buttonType = "PushButton";
+                  useMouseEvents = "0";
+                  position = "1 1";
+                  extent = "48 48";
+                  minExtent = "8 2";
+                  horizSizing = "right";
+                  vertSizing = "bottom";
+                  profile = "ToolsGuiDefaultProfile";
+                  visible = "1";
+                  active = "1";
+                  command = "TerrainMaterialDlg.changeBase();";
+                  tooltipProfile = "ToolsGuiDefaultProfile";
+                  tooltip = "Change the Active Diffuse Map for this layer";
+                  hovertime = "1000";
+                  isContainer = "0";
+                  canSave = "1";
+                  canSaveDynamicFields = "0";
+               };
+               new GuiTextCtrl() {
+                  text = "Diffuse";
+                  maxLength = "1024";
+                  margin = "0 0 0 0";
+                  padding = "0 0 0 0";
+                  anchorTop = "1";
+                  anchorBottom = "0";
+                  anchorLeft = "1";
+                  anchorRight = "0";
+                  position = "56 -3";
+                  extent = "39 18";
+                  minExtent = "8 2";
+                  horizSizing = "right";
+                  vertSizing = "bottom";
+                  profile = "EditorTextProfile";
+                  visible = "1";
+                  active = "1";
+                  tooltipProfile = "ToolsGuiToolTipProfile";
+                  hovertime = "1000";
+                  isContainer = "0";
+                  canSave = "1";
+                  canSaveDynamicFields = "0";
+               };
+               new GuiTextCtrl() {
+                  text = "None";
+                  maxLength = "1024";
+                  margin = "0 0 0 0";
+                  padding = "0 0 0 0";
+                  anchorTop = "1";
+                  anchorBottom = "0";
+                  anchorLeft = "1";
+                  anchorRight = "0";
+                  position = "56 16";
+                  extent = "79 17";
+                  minExtent = "8 2";
+                  horizSizing = "width";
+                  vertSizing = "bottom";
+                  profile = "ToolsGuiTextProfile";
+                  visible = "1";
+                  active = "1";
+                  tooltipProfile = "ToolsGuiToolTipProfile";
+                  hovertime = "1000";
+                  isContainer = "0";
+                  canSave = "1";
+                  canSaveDynamicFields = "0";
+               };
+               new GuiButtonCtrl() {
+                  text = "Edit";
+                  groupNum = "-1";
+                  buttonType = "PushButton";
+                  useMouseEvents = "0";
+                  position = "110 0";
+                  extent = "40 16";
+                  minExtent = "8 2";
+                  horizSizing = "left";
+                  vertSizing = "bottom";
+                  profile = "ToolsGuiButtonProfile";
+                  visible = "1";
+                  active = "1";
+                  command = "TerrainMaterialDlg.changeBase();";
+                  tooltipProfile = "ToolsGuiToolTipProfile";
+                  hovertime = "1000";
+                  isContainer = "0";
+                  canSave = "1";
+                  canSaveDynamicFields = "0";
+               };
+               new GuiBitmapButtonCtrl() {
+                  bitmap = "tools/gui/images/delete";
+                  bitmapMode = "Stretched";
+                  autoFitExtents = "0";
+                  useModifiers = "0";
+                  useStates = "1";
+                  masked = "0";
+                  groupNum = "-1";
+                  buttonType = "PushButton";
+                  useMouseEvents = "0";
+                  position = "153 0";
+                  extent = "16 16";
+                  minExtent = "8 2";
+                  horizSizing = "left";
+                  vertSizing = "bottom";
+                  profile = "ToolsGuiDefaultProfile";
+                  visible = "1";
+                  active = "1";
+                  command = "TerrainMaterialDlg-->baseTexCtrl.setBitmap(\"tools/materialEditor/gui/unknownImage\");";
+                  tooltipProfile = "ToolsGuiToolTipProfile";
+                  hovertime = "1000";
+                  isContainer = "0";
+                  canSave = "1";
+                  canSaveDynamicFields = "0";
+               };
+               new GuiTextCtrl() {
+                  text = "Size";
+                  maxLength = "1024";
+                  margin = "0 0 0 0";
+                  padding = "0 0 0 0";
+                  anchorTop = "0";
+                  anchorBottom = "0";
+                  anchorLeft = "0";
+                  anchorRight = "0";
+                  position = "132 35";
+                  extent = "39 16";
+                  minExtent = "8 2";
+                  horizSizing = "right";
+                  vertSizing = "bottom";
+                  profile = "ToolsGuiTextProfile";
+                  visible = "1";
+                  active = "1";
+                  tooltipProfile = "ToolsGuiToolTipProfile";
+                  hovertime = "1000";
+                  isContainer = "0";
+                  canSave = "1";
+                  canSaveDynamicFields = "0";
+               };
+               new GuiTextEditCtrl() {
+                  historySize = "0";
+                  tabComplete = "0";
+                  sinkAllKeyEvents = "0";
+                  password = "0";
+                  passwordMask = "*";
+                  text = "200";
+                  maxLength = "1024";
+                  margin = "0 0 0 0";
+                  padding = "0 0 0 0";
+                  anchorTop = "0";
+                  anchorBottom = "0";
+                  anchorLeft = "0";
+                  anchorRight = "0";
+                  position = "94 34";
+                  extent = "34 18";
+                  minExtent = "8 2";
+                  horizSizing = "right";
+                  vertSizing = "bottom";
+                  profile = "ToolsGuiTextEditProfile";
+                  visible = "1";
+                  active = "1";
+                  tooltipProfile = "ToolsGuiToolTipProfile";
+                  hovertime = "1000";
+                  isContainer = "0";
+                  internalName = "baseSizeCtrl";
+                  canSave = "1";
+                  canSaveDynamicFields = "0";
+               };
+               new GuiBitmapCtrl() {
+                  bitmap = "tools/gui/images/separator-v";
+                  color = "255 255 255 255";
+                  wrap = "0";
+                  position = "1 71";
+                  extent = "148 2";
+                  minExtent = "8 2";
+                  horizSizing = "width";
+                  vertSizing = "bottom";
+                  profile = "ToolsGuiDefaultProfile";
+                  visible = "1";
+                  active = "1";
+                  tooltipProfile = "ToolsGuiToolTipProfile";
+                  hovertime = "1000";
+                  isContainer = "0";
+                  canSave = "1";
+                  canSaveDynamicFields = "0";
+               };
             };
             };
-            new GuiTextCtrl() {
-               text = "None";
-               maxLength = "1024";
+            new GuiContainer() {
                margin = "0 0 0 0";
                margin = "0 0 0 0";
                padding = "0 0 0 0";
                padding = "0 0 0 0";
                anchorTop = "1";
                anchorTop = "1";
                anchorBottom = "0";
                anchorBottom = "0";
                anchorLeft = "1";
                anchorLeft = "1";
                anchorRight = "0";
                anchorRight = "0";
-               position = "56 17";
-               extent = "116 17";
+               position = "4 78";
+               extent = "174 76";
                minExtent = "8 2";
                minExtent = "8 2";
                horizSizing = "width";
                horizSizing = "width";
                vertSizing = "bottom";
                vertSizing = "bottom";
-               profile = "ToolsGuiTextProfile";
-               visible = "1";
-               active = "1";
-               tooltipProfile = "ToolsGuiToolTipProfile";
-               hovertime = "1000";
-               isContainer = "0";
-               canSave = "1";
-               canSaveDynamicFields = "0";
-            };
-            new GuiButtonCtrl() {
-               text = "Edit";
-               groupNum = "-1";
-               buttonType = "PushButton";
-               useMouseEvents = "0";
-               position = "116 0";
-               extent = "40 16";
-               minExtent = "8 2";
-               horizSizing = "left";
-               vertSizing = "bottom";
-               profile = "ToolsGuiButtonProfile";
-               visible = "1";
-               active = "1";
-               command = "TerrainMaterialDlg.changeMacro();";
-               tooltipProfile = "ToolsGuiToolTipProfile";
-               hovertime = "1000";
-               isContainer = "0";
-               canSave = "1";
-               canSaveDynamicFields = "0";
-            };
-            new GuiBitmapButtonCtrl() {
-               bitmap = "tools/gui/images/delete";
-               bitmapMode = "Stretched";
-               autoFitExtents = "0";
-               useModifiers = "0";
-               useStates = "1";
-               groupNum = "-1";
-               buttonType = "PushButton";
-               useMouseEvents = "0";
-               position = "159 0";
-               extent = "16 16";
-               minExtent = "8 2";
-               horizSizing = "left";
-               vertSizing = "bottom";
                profile = "ToolsGuiDefaultProfile";
                profile = "ToolsGuiDefaultProfile";
                visible = "1";
                visible = "1";
                active = "1";
                active = "1";
-               command = "TerrainMaterialDlg-->macroTexCtrl.setBitmap(\"tools/materialEditor/gui/unknownImage\");";
-               tooltipProfile = "ToolsGuiToolTipProfile";
-               hovertime = "1000";
-               isContainer = "0";
-               canSave = "1";
-               canSaveDynamicFields = "0";
-            };
-            new GuiTextCtrl() {
-               text = "Size";
-               maxLength = "1024";
-               margin = "0 0 0 0";
-               padding = "0 0 0 0";
-               anchorTop = "0";
-               anchorBottom = "0";
-               anchorLeft = "0";
-               anchorRight = "0";
-               position = "132 33";
-               extent = "39 16";
-               minExtent = "8 2";
-               horizSizing = "right";
-               vertSizing = "bottom";
-               profile = "ToolsGuiTextProfile";
-               visible = "1";
-               active = "1";
-               tooltipProfile = "ToolsGuiToolTipProfile";
-               hovertime = "1000";
-               isContainer = "0";
-               canSave = "1";
-               canSaveDynamicFields = "0";
-            };
-            new GuiTextEditCtrl() {
-               historySize = "0";
-               tabComplete = "0";
-               sinkAllKeyEvents = "0";
-               password = "0";
-               passwordMask = "*";
-               maxLength = "1024";
-               margin = "0 0 0 0";
-               padding = "0 0 0 0";
-               anchorTop = "0";
-               anchorBottom = "0";
-               anchorLeft = "0";
-               anchorRight = "0";
-               position = "94 32";
-               extent = "34 18";
-               minExtent = "8 2";
-               horizSizing = "right";
-               vertSizing = "bottom";
-               profile = "ToolsGuiTextEditProfile";
-               visible = "1";
-               active = "1";
                tooltipProfile = "ToolsGuiToolTipProfile";
                tooltipProfile = "ToolsGuiToolTipProfile";
                hovertime = "1000";
                hovertime = "1000";
-               isContainer = "0";
-               internalName = "macroSizeCtrl";
-               canSave = "1";
-               canSaveDynamicFields = "0";
-            };
-            new GuiTextCtrl() {
-               text = "Strength";
-               maxLength = "1024";
-               margin = "0 0 0 0";
-               padding = "0 0 0 0";
-               anchorTop = "0";
-               anchorBottom = "0";
-               anchorLeft = "0";
-               anchorRight = "0";
-               position = "39 54";
-               extent = "46 16";
-               minExtent = "8 2";
-               horizSizing = "right";
-               vertSizing = "bottom";
-               profile = "ToolsGuiTextProfile";
-               visible = "1";
-               active = "1";
-               tooltipProfile = "ToolsGuiToolTipProfile";
-               hovertime = "1000";
-               isContainer = "0";
+               isContainer = "1";
                canSave = "1";
                canSave = "1";
                canSaveDynamicFields = "0";
                canSaveDynamicFields = "0";
+
+               new GuiBitmapCtrl() {
+                  bitmap = "art/terrains/Example/sand_d";
+                  color = "255 255 255 255";
+                  wrap = "0";
+                  position = "1 1";
+                  extent = "47 47";
+                  minExtent = "8 2";
+                  horizSizing = "right";
+                  vertSizing = "bottom";
+                  profile = "ToolsGuiDefaultProfile";
+                  visible = "1";
+                  active = "1";
+                  tooltipProfile = "ToolsGuiToolTipProfile";
+                  hovertime = "1000";
+                  isContainer = "0";
+                  internalName = "detailTexCtrl";
+                  canSave = "1";
+                  canSaveDynamicFields = "0";
+               };
+               new GuiBitmapButtonCtrl() {
+                  bitmap = "tools/materialEditor/gui/cubemapBtnBorder";
+                  bitmapMode = "Stretched";
+                  autoFitExtents = "0";
+                  useModifiers = "0";
+                  useStates = "1";
+                  masked = "0";
+                  groupNum = "-1";
+                  buttonType = "PushButton";
+                  useMouseEvents = "0";
+                  position = "1 1";
+                  extent = "48 48";
+                  minExtent = "8 2";
+                  horizSizing = "right";
+                  vertSizing = "bottom";
+                  profile = "ToolsGuiDefaultProfile";
+                  visible = "1";
+                  active = "1";
+                  command = "TerrainMaterialDlg.changeDetail();";
+                  tooltipProfile = "ToolsGuiDefaultProfile";
+                  tooltip = "Change the active Detail Map for this layer.";
+                  hovertime = "1000";
+                  isContainer = "0";
+                  canSave = "1";
+                  canSaveDynamicFields = "0";
+               };
+               new GuiTextCtrl() {
+                  text = "Detail";
+                  maxLength = "1024";
+                  margin = "0 0 0 0";
+                  padding = "0 0 0 0";
+                  anchorTop = "1";
+                  anchorBottom = "0";
+                  anchorLeft = "1";
+                  anchorRight = "0";
+                  position = "56 -3";
+                  extent = "30 18";
+                  minExtent = "8 2";
+                  horizSizing = "right";
+                  vertSizing = "bottom";
+                  profile = "EditorTextProfile";
+                  visible = "1";
+                  active = "1";
+                  tooltipProfile = "ToolsGuiToolTipProfile";
+                  hovertime = "1000";
+                  isContainer = "0";
+                  canSave = "1";
+                  canSaveDynamicFields = "0";
+               };
+               new GuiTextCtrl() {
+                  text = "None";
+                  maxLength = "1024";
+                  margin = "0 0 0 0";
+                  padding = "0 0 0 0";
+                  anchorTop = "1";
+                  anchorBottom = "0";
+                  anchorLeft = "1";
+                  anchorRight = "0";
+                  position = "56 16";
+                  extent = "79 17";
+                  minExtent = "8 2";
+                  horizSizing = "width";
+                  vertSizing = "bottom";
+                  profile = "ToolsGuiTextProfile";
+                  visible = "1";
+                  active = "1";
+                  tooltipProfile = "ToolsGuiToolTipProfile";
+                  hovertime = "1000";
+                  isContainer = "0";
+                  canSave = "1";
+                  canSaveDynamicFields = "0";
+               };
+               new GuiButtonCtrl() {
+                  text = "Edit";
+                  groupNum = "-1";
+                  buttonType = "PushButton";
+                  useMouseEvents = "0";
+                  position = "111 0";
+                  extent = "40 16";
+                  minExtent = "8 2";
+                  horizSizing = "left";
+                  vertSizing = "bottom";
+                  profile = "ToolsGuiButtonProfile";
+                  visible = "1";
+                  active = "1";
+                  command = "TerrainMaterialDlg.changeDetail();";
+                  tooltipProfile = "ToolsGuiToolTipProfile";
+                  hovertime = "1000";
+                  isContainer = "0";
+                  canSave = "1";
+                  canSaveDynamicFields = "0";
+               };
+               new GuiBitmapButtonCtrl() {
+                  bitmap = "tools/gui/images/delete";
+                  bitmapMode = "Stretched";
+                  autoFitExtents = "0";
+                  useModifiers = "0";
+                  useStates = "1";
+                  masked = "0";
+                  groupNum = "-1";
+                  buttonType = "PushButton";
+                  useMouseEvents = "0";
+                  position = "154 0";
+                  extent = "16 16";
+                  minExtent = "8 2";
+                  horizSizing = "left";
+                  vertSizing = "bottom";
+                  profile = "ToolsGuiDefaultProfile";
+                  visible = "1";
+                  active = "1";
+                  command = "TerrainMaterialDlg-->detailTexCtrl.setBitmap(\"tools/materialEditor/gui/unknownImage\");";
+                  tooltipProfile = "ToolsGuiToolTipProfile";
+                  hovertime = "1000";
+                  isContainer = "0";
+                  canSave = "1";
+                  canSaveDynamicFields = "0";
+               };
+               new GuiTextCtrl() {
+                  text = "Size";
+                  maxLength = "1024";
+                  margin = "0 0 0 0";
+                  padding = "0 0 0 0";
+                  anchorTop = "0";
+                  anchorBottom = "0";
+                  anchorLeft = "0";
+                  anchorRight = "0";
+                  position = "132 33";
+                  extent = "39 16";
+                  minExtent = "8 2";
+                  horizSizing = "right";
+                  vertSizing = "bottom";
+                  profile = "ToolsGuiTextProfile";
+                  visible = "1";
+                  active = "1";
+                  tooltipProfile = "ToolsGuiToolTipProfile";
+                  hovertime = "1000";
+                  isContainer = "0";
+                  canSave = "1";
+                  canSaveDynamicFields = "0";
+               };
+               new GuiTextEditCtrl() {
+                  historySize = "0";
+                  tabComplete = "0";
+                  sinkAllKeyEvents = "0";
+                  password = "0";
+                  passwordMask = "*";
+                  text = "10";
+                  maxLength = "1024";
+                  margin = "0 0 0 0";
+                  padding = "0 0 0 0";
+                  anchorTop = "0";
+                  anchorBottom = "0";
+                  anchorLeft = "0";
+                  anchorRight = "0";
+                  position = "94 32";
+                  extent = "34 18";
+                  minExtent = "8 2";
+                  horizSizing = "right";
+                  vertSizing = "bottom";
+                  profile = "ToolsGuiTextEditProfile";
+                  visible = "1";
+                  active = "1";
+                  tooltipProfile = "ToolsGuiToolTipProfile";
+                  hovertime = "1000";
+                  isContainer = "0";
+                  internalName = "detSizeCtrl";
+                  canSave = "1";
+                  canSaveDynamicFields = "0";
+               };
+               new GuiTextCtrl() {
+                  text = "Strength";
+                  maxLength = "1024";
+                  margin = "0 0 0 0";
+                  padding = "0 0 0 0";
+                  anchorTop = "0";
+                  anchorBottom = "0";
+                  anchorLeft = "0";
+                  anchorRight = "0";
+                  position = "39 54";
+                  extent = "46 16";
+                  minExtent = "8 2";
+                  horizSizing = "right";
+                  vertSizing = "bottom";
+                  profile = "ToolsGuiTextProfile";
+                  visible = "1";
+                  active = "1";
+                  tooltipProfile = "ToolsGuiToolTipProfile";
+                  hovertime = "1000";
+                  isContainer = "0";
+                  canSave = "1";
+                  canSaveDynamicFields = "0";
+               };
+               new GuiTextEditCtrl() {
+                  historySize = "0";
+                  tabComplete = "0";
+                  sinkAllKeyEvents = "0";
+                  password = "0";
+                  passwordMask = "*";
+                  text = "1";
+                  maxLength = "1024";
+                  margin = "0 0 0 0";
+                  padding = "0 0 0 0";
+                  anchorTop = "0";
+                  anchorBottom = "0";
+                  anchorLeft = "0";
+                  anchorRight = "0";
+                  position = "1 53";
+                  extent = "34 18";
+                  minExtent = "8 2";
+                  horizSizing = "right";
+                  vertSizing = "bottom";
+                  profile = "ToolsGuiTextEditProfile";
+                  visible = "1";
+                  active = "1";
+                  tooltipProfile = "ToolsGuiToolTipProfile";
+                  hovertime = "1000";
+                  isContainer = "0";
+                  internalName = "detStrengthCtrl";
+                  canSave = "1";
+                  canSaveDynamicFields = "0";
+               };
+               new GuiTextCtrl() {
+                  text = "Distance";
+                  maxLength = "1024";
+                  margin = "0 0 0 0";
+                  padding = "0 0 0 0";
+                  anchorTop = "0";
+                  anchorBottom = "0";
+                  anchorLeft = "0";
+                  anchorRight = "0";
+                  position = "132 54";
+                  extent = "45 16";
+                  minExtent = "8 2";
+                  horizSizing = "right";
+                  vertSizing = "bottom";
+                  profile = "ToolsGuiTextProfile";
+                  visible = "1";
+                  active = "1";
+                  tooltipProfile = "ToolsGuiToolTipProfile";
+                  hovertime = "1000";
+                  isContainer = "0";
+                  canSave = "1";
+                  canSaveDynamicFields = "0";
+               };
+               new GuiTextEditCtrl() {
+                  historySize = "0";
+                  tabComplete = "0";
+                  sinkAllKeyEvents = "0";
+                  password = "0";
+                  passwordMask = "*";
+                  text = "100";
+                  maxLength = "1024";
+                  margin = "0 0 0 0";
+                  padding = "0 0 0 0";
+                  anchorTop = "0";
+                  anchorBottom = "0";
+                  anchorLeft = "0";
+                  anchorRight = "0";
+                  position = "94 53";
+                  extent = "34 18";
+                  minExtent = "8 2";
+                  horizSizing = "right";
+                  vertSizing = "bottom";
+                  profile = "ToolsGuiTextEditProfile";
+                  visible = "1";
+                  active = "1";
+                  tooltipProfile = "ToolsGuiToolTipProfile";
+                  hovertime = "1000";
+                  isContainer = "0";
+                  internalName = "detDistanceCtrl";
+                  canSave = "1";
+                  canSaveDynamicFields = "0";
+               };
+               new GuiBitmapCtrl() {
+                  bitmap = "core/art/gui/images/separator-v";
+                  color = "255 255 255 255";
+                  wrap = "0";
+                  position = "1 73";
+                  extent = "148 2";
+                  minExtent = "8 2";
+                  horizSizing = "width";
+                  vertSizing = "bottom";
+                  profile = "ToolsGuiDefaultProfile";
+                  visible = "1";
+                  active = "1";
+                  tooltipProfile = "ToolsGuiToolTipProfile";
+                  hovertime = "1000";
+                  isContainer = "0";
+                  canSave = "1";
+                  canSaveDynamicFields = "0";
+               };
             };
             };
-            new GuiTextEditCtrl() {
-               historySize = "0";
-               tabComplete = "0";
-               sinkAllKeyEvents = "0";
-               password = "0";
-               passwordMask = "*";
-               maxLength = "1024";
+            new GuiContainer() {
                margin = "0 0 0 0";
                margin = "0 0 0 0";
                padding = "0 0 0 0";
                padding = "0 0 0 0";
-               anchorTop = "0";
+               anchorTop = "1";
                anchorBottom = "0";
                anchorBottom = "0";
-               anchorLeft = "0";
+               anchorLeft = "1";
                anchorRight = "0";
                anchorRight = "0";
-               position = "1 53";
-               extent = "34 18";
+               position = "6 158";
+               extent = "174 54";
                minExtent = "8 2";
                minExtent = "8 2";
-               horizSizing = "right";
+               horizSizing = "width";
                vertSizing = "bottom";
                vertSizing = "bottom";
-               profile = "ToolsGuiTextEditProfile";
+               profile = "ToolsGuiDefaultProfile";
                visible = "1";
                visible = "1";
                active = "1";
                active = "1";
                tooltipProfile = "ToolsGuiToolTipProfile";
                tooltipProfile = "ToolsGuiToolTipProfile";
                hovertime = "1000";
                hovertime = "1000";
-               isContainer = "0";
-               internalName = "macroStrengthCtrl";
+               isContainer = "1";
                canSave = "1";
                canSave = "1";
                canSaveDynamicFields = "0";
                canSaveDynamicFields = "0";
+
+               new GuiBitmapCtrl() {
+                  bitmap = "tools/materialEditor/gui/unknownImage";
+                  color = "255 255 255 255";
+                  wrap = "0";
+                  position = "1 1";
+                  extent = "47 47";
+                  minExtent = "8 2";
+                  horizSizing = "right";
+                  vertSizing = "bottom";
+                  profile = "ToolsGuiDefaultProfile";
+                  visible = "1";
+                  active = "1";
+                  tooltipProfile = "ToolsGuiToolTipProfile";
+                  hovertime = "1000";
+                  isContainer = "0";
+                  internalName = "normTexCtrl";
+                  canSave = "1";
+                  canSaveDynamicFields = "0";
+               };
+               new GuiTextCtrl() {
+                  text = "Normal";
+                  maxLength = "1024";
+                  margin = "0 0 0 0";
+                  padding = "0 0 0 0";
+                  anchorTop = "1";
+                  anchorBottom = "0";
+                  anchorLeft = "1";
+                  anchorRight = "0";
+                  position = "56 -3";
+                  extent = "39 18";
+                  minExtent = "8 2";
+                  horizSizing = "right";
+                  vertSizing = "bottom";
+                  profile = "EditorTextProfile";
+                  visible = "1";
+                  active = "1";
+                  tooltipProfile = "ToolsGuiToolTipProfile";
+                  hovertime = "1000";
+                  isContainer = "0";
+                  canSave = "1";
+                  canSaveDynamicFields = "0";
+               };
+               new GuiBitmapButtonCtrl() {
+                  bitmap = "tools/materialEditor/gui/cubemapBtnBorder";
+                  bitmapMode = "Stretched";
+                  autoFitExtents = "0";
+                  useModifiers = "0";
+                  useStates = "1";
+                  masked = "0";
+                  groupNum = "-1";
+                  buttonType = "PushButton";
+                  useMouseEvents = "0";
+                  position = "1 1";
+                  extent = "48 48";
+                  minExtent = "8 2";
+                  horizSizing = "right";
+                  vertSizing = "bottom";
+                  profile = "ToolsGuiDefaultProfile";
+                  visible = "1";
+                  active = "1";
+                  command = "TerrainMaterialDlg.changeNormal();";
+                  tooltipProfile = "ToolsGuiDefaultProfile";
+                  tooltip = "Change the active Normal Map for this layer.";
+                  hovertime = "1000";
+                  isContainer = "0";
+                  canSave = "1";
+                  canSaveDynamicFields = "0";
+               };
+               new GuiTextCtrl() {
+                  text = "None";
+                  maxLength = "1024";
+                  margin = "0 0 0 0";
+                  padding = "0 0 0 0";
+                  anchorTop = "1";
+                  anchorBottom = "0";
+                  anchorLeft = "1";
+                  anchorRight = "0";
+                  position = "56 15";
+                  extent = "79 17";
+                  minExtent = "8 2";
+                  horizSizing = "width";
+                  vertSizing = "bottom";
+                  profile = "ToolsGuiTextProfile";
+                  visible = "1";
+                  active = "1";
+                  tooltipProfile = "ToolsGuiToolTipProfile";
+                  hovertime = "1000";
+                  isContainer = "0";
+                  canSave = "1";
+                  canSaveDynamicFields = "0";
+               };
+               new GuiButtonCtrl() {
+                  text = "Edit";
+                  groupNum = "-1";
+                  buttonType = "PushButton";
+                  useMouseEvents = "0";
+                  position = "111 0";
+                  extent = "40 16";
+                  minExtent = "8 2";
+                  horizSizing = "left";
+                  vertSizing = "bottom";
+                  profile = "ToolsGuiButtonProfile";
+                  visible = "1";
+                  active = "1";
+                  command = "TerrainMaterialDlg.changeNormal();";
+                  tooltipProfile = "ToolsGuiToolTipProfile";
+                  hovertime = "1000";
+                  isContainer = "0";
+                  canSave = "1";
+                  canSaveDynamicFields = "0";
+               };
+               new GuiBitmapButtonCtrl() {
+                  bitmap = "tools/gui/images/delete";
+                  bitmapMode = "Stretched";
+                  autoFitExtents = "0";
+                  useModifiers = "0";
+                  useStates = "1";
+                  masked = "0";
+                  groupNum = "-1";
+                  buttonType = "PushButton";
+                  useMouseEvents = "0";
+                  position = "154 0";
+                  extent = "16 16";
+                  minExtent = "8 2";
+                  horizSizing = "left";
+                  vertSizing = "bottom";
+                  profile = "ToolsGuiDefaultProfile";
+                  visible = "1";
+                  active = "1";
+                  command = "TerrainMaterialDlg-->normTexCtrl.setBitmap(\"tools/materialEditor/gui/unknownImage\");";
+                  tooltipProfile = "ToolsGuiToolTipProfile";
+                  hovertime = "1000";
+                  isContainer = "0";
+                  canSave = "1";
+                  canSaveDynamicFields = "0";
+               };
+               new GuiTextCtrl() {
+                  text = "Parallax Scale";
+                  maxLength = "1024";
+                  margin = "0 0 0 0";
+                  padding = "0 0 0 0";
+                  anchorTop = "1";
+                  anchorBottom = "0";
+                  anchorLeft = "1";
+                  anchorRight = "0";
+                  position = "92 34";
+                  extent = "77 16";
+                  minExtent = "8 2";
+                  horizSizing = "right";
+                  vertSizing = "bottom";
+                  profile = "ToolsGuiTextProfile";
+                  visible = "1";
+                  active = "1";
+                  tooltipProfile = "ToolsGuiToolTipProfile";
+                  hovertime = "1000";
+                  isContainer = "0";
+                  canSave = "1";
+                  canSaveDynamicFields = "0";
+               };
+               new GuiTextEditCtrl() {
+                  historySize = "0";
+                  tabComplete = "0";
+                  sinkAllKeyEvents = "0";
+                  password = "0";
+                  passwordMask = "*";
+                  text = "0";
+                  maxLength = "1024";
+                  margin = "0 0 0 0";
+                  padding = "0 0 0 0";
+                  anchorTop = "0";
+                  anchorBottom = "0";
+                  anchorLeft = "0";
+                  anchorRight = "0";
+                  position = "55 33";
+                  extent = "34 18";
+                  minExtent = "8 2";
+                  horizSizing = "right";
+                  vertSizing = "bottom";
+                  profile = "ToolsGuiTextEditProfile";
+                  visible = "1";
+                  active = "1";
+                  tooltipProfile = "ToolsGuiToolTipProfile";
+                  hovertime = "1000";
+                  isContainer = "0";
+                  internalName = "parallaxScaleCtrl";
+                  canSave = "1";
+                  canSaveDynamicFields = "0";
+               };
+               new GuiBitmapCtrl() {
+                  bitmap = "tools/gui/images/separator-v";
+                  color = "255 255 255 255";
+                  wrap = "0";
+                  position = "-10 53";
+                  extent = "148 2";
+                  minExtent = "8 2";
+                  horizSizing = "width";
+                  vertSizing = "bottom";
+                  profile = "ToolsGuiDefaultProfile";
+                  visible = "1";
+                  active = "1";
+                  tooltipProfile = "ToolsGuiToolTipProfile";
+                  hovertime = "1000";
+                  isContainer = "0";
+                  canSave = "1";
+                  canSaveDynamicFields = "0";
+               };
             };
             };
-            new GuiTextCtrl() {
-               text = "Distance";
-               maxLength = "1024";
+            new GuiContainer() {
                margin = "0 0 0 0";
                margin = "0 0 0 0";
                padding = "0 0 0 0";
                padding = "0 0 0 0";
-               anchorTop = "0";
+               anchorTop = "1";
                anchorBottom = "0";
                anchorBottom = "0";
-               anchorLeft = "0";
+               anchorLeft = "1";
                anchorRight = "0";
                anchorRight = "0";
-               position = "132 54";
-               extent = "45 16";
+               position = "6 216";
+               extent = "174 53";
                minExtent = "8 2";
                minExtent = "8 2";
-               horizSizing = "right";
+               horizSizing = "width";
                vertSizing = "bottom";
                vertSizing = "bottom";
-               profile = "ToolsGuiTextProfile";
+               profile = "ToolsGuiDefaultProfile";
                visible = "1";
                visible = "1";
                active = "1";
                active = "1";
                tooltipProfile = "ToolsGuiToolTipProfile";
                tooltipProfile = "ToolsGuiToolTipProfile";
                hovertime = "1000";
                hovertime = "1000";
-               isContainer = "0";
+               isContainer = "1";
                canSave = "1";
                canSave = "1";
                canSaveDynamicFields = "0";
                canSaveDynamicFields = "0";
+
+               new GuiBitmapCtrl() {
+                  bitmap = "tools/materialEditor/gui/unknownImage";
+                  color = "255 255 255 255";
+                  wrap = "0";
+                  position = "1 1";
+                  extent = "47 47";
+                  minExtent = "8 2";
+                  horizSizing = "right";
+                  vertSizing = "bottom";
+                  profile = "ToolsGuiDefaultProfile";
+                  visible = "1";
+                  active = "1";
+                  tooltipProfile = "ToolsGuiToolTipProfile";
+                  hovertime = "1000";
+                  isContainer = "0";
+                  internalName = "compositeTexCtrl";
+                  canSave = "1";
+                  canSaveDynamicFields = "0";
+               };
+               new GuiBitmapButtonCtrl() {
+                  bitmap = "tools/materialEditor/gui/cubemapBtnBorder";
+                  bitmapMode = "Stretched";
+                  autoFitExtents = "0";
+                  useModifiers = "0";
+                  useStates = "1";
+                  masked = "0";
+                  groupNum = "-1";
+                  buttonType = "PushButton";
+                  useMouseEvents = "0";
+                  position = "1 1";
+                  extent = "48 48";
+                  minExtent = "8 2";
+                  horizSizing = "right";
+                  vertSizing = "bottom";
+                  profile = "ToolsGuiDefaultProfile";
+                  visible = "1";
+                  active = "1";
+                  command = "TerrainMaterialDlg.changecomposite();";
+                  tooltipProfile = "ToolsGuiDefaultProfile";
+                  tooltip = "Change the active composite Map for this layer.";
+                  hovertime = "1000";
+                  isContainer = "0";
+                  canSave = "1";
+                  canSaveDynamicFields = "0";
+               };
+               new GuiTextCtrl() {
+                  text = "Composite";
+                  maxLength = "1024";
+                  margin = "0 0 0 0";
+                  padding = "0 0 0 0";
+                  anchorTop = "1";
+                  anchorBottom = "0";
+                  anchorLeft = "1";
+                  anchorRight = "0";
+                  position = "56 -3";
+                  extent = "61 18";
+                  minExtent = "8 2";
+                  horizSizing = "right";
+                  vertSizing = "bottom";
+                  profile = "EditorTextProfile";
+                  visible = "1";
+                  active = "1";
+                  tooltipProfile = "ToolsGuiToolTipProfile";
+                  hovertime = "1000";
+                  isContainer = "0";
+                  canSave = "1";
+                  canSaveDynamicFields = "0";
+               };
+               new GuiTextCtrl() {
+                  text = "None";
+                  maxLength = "1024";
+                  margin = "0 0 0 0";
+                  padding = "0 0 0 0";
+                  anchorTop = "1";
+                  anchorBottom = "0";
+                  anchorLeft = "1";
+                  anchorRight = "0";
+                  position = "56 17";
+                  extent = "79 17";
+                  minExtent = "8 2";
+                  horizSizing = "width";
+                  vertSizing = "bottom";
+                  profile = "ToolsGuiTextProfile";
+                  visible = "1";
+                  active = "1";
+                  tooltipProfile = "ToolsGuiToolTipProfile";
+                  hovertime = "1000";
+                  isContainer = "0";
+                  canSave = "1";
+                  canSaveDynamicFields = "0";
+               };
+               new GuiButtonCtrl() {
+                  text = "Edit";
+                  groupNum = "-1";
+                  buttonType = "PushButton";
+                  useMouseEvents = "0";
+                  position = "111 0";
+                  extent = "40 16";
+                  minExtent = "8 2";
+                  horizSizing = "left";
+                  vertSizing = "bottom";
+                  profile = "ToolsGuiButtonProfile";
+                  visible = "1";
+                  active = "1";
+                  command = "TerrainMaterialDlg.changecomposite();";
+                  tooltipProfile = "ToolsGuiToolTipProfile";
+                  hovertime = "1000";
+                  isContainer = "0";
+                  canSave = "1";
+                  canSaveDynamicFields = "0";
+               };
+               new GuiBitmapButtonCtrl() {
+                  bitmap = "tools/gui/images/delete";
+                  bitmapMode = "Stretched";
+                  autoFitExtents = "0";
+                  useModifiers = "0";
+                  useStates = "1";
+                  masked = "0";
+                  groupNum = "-1";
+                  buttonType = "PushButton";
+                  useMouseEvents = "0";
+                  position = "154 0";
+                  extent = "16 16";
+                  minExtent = "8 2";
+                  horizSizing = "left";
+                  vertSizing = "bottom";
+                  profile = "ToolsGuiDefaultProfile";
+                  visible = "1";
+                  active = "1";
+                  command = "TerrainMaterialDlg-->compositeTexCtrl.setBitmap(\"tools/materialEditor/gui/unknownImage\");";
+                  tooltipProfile = "ToolsGuiToolTipProfile";
+                  hovertime = "1000";
+                  isContainer = "0";
+                  canSave = "1";
+                  canSaveDynamicFields = "0";
+               };
+               new GuiBitmapCtrl() {
+                  bitmap = "tools/gui/images/separator-v";
+                  color = "255 255 255 255";
+                  wrap = "0";
+                  position = "4 51";
+                  extent = "148 2";
+                  minExtent = "8 2";
+                  horizSizing = "width";
+                  vertSizing = "bottom";
+                  profile = "ToolsGuiDefaultProfile";
+                  visible = "1";
+                  active = "1";
+                  tooltipProfile = "ToolsGuiToolTipProfile";
+                  hovertime = "1000";
+                  isContainer = "0";
+                  canSave = "1";
+                  canSaveDynamicFields = "0";
+               };
             };
             };
-            new GuiTextEditCtrl() {
-               historySize = "0";
-               tabComplete = "0";
-               sinkAllKeyEvents = "0";
-               password = "0";
-               passwordMask = "*";
-               maxLength = "1024";
+            new GuiContainer() {
                margin = "0 0 0 0";
                margin = "0 0 0 0";
                padding = "0 0 0 0";
                padding = "0 0 0 0";
-               anchorTop = "0";
+               anchorTop = "1";
                anchorBottom = "0";
                anchorBottom = "0";
-               anchorLeft = "0";
+               anchorLeft = "1";
                anchorRight = "0";
                anchorRight = "0";
-               position = "94 53";
-               extent = "34 18";
+               position = "6 272";
+               extent = "174 71";
                minExtent = "8 2";
                minExtent = "8 2";
-               horizSizing = "right";
+               horizSizing = "width";
                vertSizing = "bottom";
                vertSizing = "bottom";
-               profile = "ToolsGuiTextEditProfile";
+               profile = "ToolsGuiDefaultProfile";
                visible = "1";
                visible = "1";
                active = "1";
                active = "1";
                tooltipProfile = "ToolsGuiToolTipProfile";
                tooltipProfile = "ToolsGuiToolTipProfile";
                hovertime = "1000";
                hovertime = "1000";
-               isContainer = "0";
-               internalName = "macroDistanceCtrl";
+               isContainer = "1";
                canSave = "1";
                canSave = "1";
                canSaveDynamicFields = "0";
                canSaveDynamicFields = "0";
-            };
-         };
-         
-         new GuiBitmapCtrl() {
-            canSaveDynamicFields = "0";
-            isContainer = "0";
-            Profile = "ToolsGuiDefaultProfile";
-            HorizSizing = "width";
-            VertSizing = "bottom";
-            position = "6 200";
-            Extent = "175 2";
-            MinExtent = "8 2";
-            canSave = "1";
-            Visible = "1";
-            tooltipprofile = "ToolsGuiToolTipProfile";
-            hovertime = "1000";
-            bitmap = "tools/gui/images/separator-v";
-            wrap = "0";
-         };
-         new GuiContainer() {
-            canSaveDynamicFields = "0";
-            isContainer = "1";
-            Profile = "ToolsGuiDefaultProfile";
-            HorizSizing = "width";
-            VertSizing = "bottom";
-            position = "6 206";
-            Extent = "185 72";
-            MinExtent = "8 2";
-            canSave = "1";
-            Visible = "1";
-            tooltipprofile = "ToolsGuiToolTipProfile";
-            hovertime = "1000";
-            Margin = "0 0 0 0";
-            Padding = "0 0 0 0";
-            AnchorTop = "1";
-            AnchorBottom = "0";
-            AnchorLeft = "1";
-            AnchorRight = "0";
 
 
-            new GuiBitmapCtrl() {
-               internalName = "detailTexCtrl";
-               canSaveDynamicFields = "0";
-               isContainer = "0";
-               Profile = "ToolsGuiDefaultProfile";
-               HorizSizing = "right";
-               VertSizing = "bottom";
-               position = "1 1";
-               Extent = "47 47";
-               MinExtent = "8 2";
-               canSave = "1";
-               Visible = "1";
-               tooltipprofile = "ToolsGuiToolTipProfile";
-               hovertime = "1000";
-               bitmap = "tools/materialEditor/gui/unknownImage";
-               wrap = "0";
-            };
-            new GuiBitmapButtonCtrl() {
-               canSaveDynamicFields = "0";
-               isContainer = "0";
-               Profile = "ToolsGuiDefaultProfile";
-               HorizSizing = "right";
-               VertSizing = "bottom";
-               position = "1 1";
-               Extent = "48 48";
-               MinExtent = "8 2";
-               canSave = "1";
-               Visible = "1";
-               Command = "TerrainMaterialDlg.changeDetail();";
-               tooltipprofile = "ToolsGuiDefaultProfile";
-               ToolTip = "Change the active Detail Map for this layer.";
-               hovertime = "1000";
-               groupNum = "-1";
-               buttonType = "PushButton";
-               useMouseEvents = "0";
-               bitmap = "tools/materialEditor/gui/cubemapBtnBorder";
-            };
-            new GuiTextCtrl() {
-               canSaveDynamicFields = "0";
-               isContainer = "0";
-               Profile = "EditorTextProfile";
-               HorizSizing = "right";
-               VertSizing = "bottom";
-               position = "56 -3";
-               Extent = "30 18";
-               MinExtent = "8 2";
-               canSave = "1";
-               Visible = "1";
-               tooltipprofile = "ToolsGuiToolTipProfile";
-               hovertime = "1000";
-               Margin = "0 0 0 0";
-               Padding = "0 0 0 0";
-               AnchorTop = "1";
-               AnchorBottom = "0";
-               AnchorLeft = "1";
-               AnchorRight = "0";
-               text = "Detail";
-               maxLength = "1024";
-            };
-            new GuiTextCtrl() {
-               canSaveDynamicFields = "0";
-               isContainer = "0";
-               Profile = "ToolsGuiTextProfile";
-               HorizSizing = "width";
-               VertSizing = "bottom";
-               position = "56 16";
-               Extent = "116 17";
-               MinExtent = "8 2";
-               canSave = "1";
-               Visible = "1";
-               tooltipprofile = "ToolsGuiToolTipProfile";
-               hovertime = "1000";
-               Margin = "0 0 0 0";
-               Padding = "0 0 0 0";
-               AnchorTop = "1";
-               AnchorBottom = "0";
-               AnchorLeft = "1";
-               AnchorRight = "0";
-               text = "None";
-               maxLength = "1024";
-            };
-            new GuiButtonCtrl() {
-               canSaveDynamicFields = "0";
-               isContainer = "0";
-               Profile = "ToolsGuiButtonProfile";
-               HorizSizing = "left";
-               VertSizing = "bottom";
-               position = "116 0";
-               Extent = "40 16";
-               MinExtent = "8 2";
-               canSave = "1";
-               Visible = "1";
-               Command = "TerrainMaterialDlg.changeDetail();";
-               tooltipprofile = "ToolsGuiToolTipProfile";
-               hovertime = "1000";
-               text = "Edit";
-               groupNum = "-1";
-               buttonType = "PushButton";
-               useMouseEvents = "0";
-            };
-            new GuiBitmapButtonCtrl() {
-               canSaveDynamicFields = "0";
-               isContainer = "0";
-               Profile = "ToolsGuiDefaultProfile";
-               HorizSizing = "left";
-               VertSizing = "bottom";
-               position = "159 0";
-               Extent = "16 16";
-               MinExtent = "8 2";
-               canSave = "1";
-               Visible = "1";
-               Command = "TerrainMaterialDlg-->detailTexCtrl.setBitmap(\"tools/materialEditor/gui/unknownImage\");";
-               tooltipprofile = "ToolsGuiToolTipProfile";
-               hovertime = "1000";
-               groupNum = "-1";
-               buttonType = "PushButton";
-               useMouseEvents = "0";
-               bitmap = "tools/gui/images/delete";
-            };
-            new GuiTextCtrl() {
-               canSaveDynamicFields = "0";
-               isContainer = "0";
-               Profile = "ToolsGuiTextProfile";
-               HorizSizing = "right";
-               VertSizing = "bottom";
-               position = "132 33";
-               Extent = "39 16";
-               MinExtent = "8 2";
-               canSave = "1";
-               Visible = "1";
-               tooltipprofile = "ToolsGuiToolTipProfile";
-               hovertime = "1000";
-               Margin = "0 0 0 0";
-               Padding = "0 0 0 0";
-               AnchorTop = "0";
-               AnchorBottom = "0";
-               AnchorLeft = "0";
-               AnchorRight = "0";
-               text = "Size";
-               maxLength = "1024";
-            };
-            new GuiTextEditCtrl() {
-               internalName = "detSizeCtrl";
-               canSaveDynamicFields = "0";
-               isContainer = "0";
-               Profile = "ToolsGuiTextEditProfile";
-               HorizSizing = "right";
-               VertSizing = "bottom";
-               position = "94 32";
-               Extent = "34 18";
-               MinExtent = "8 2";
-               canSave = "1";
-               Visible = "1";
-               tooltipprofile = "ToolsGuiToolTipProfile";
-               hovertime = "1000";
-               Margin = "0 0 0 0";
-               Padding = "0 0 0 0";
-               AnchorTop = "0";
-               AnchorBottom = "0";
-               AnchorLeft = "0";
-               AnchorRight = "0";
-               maxLength = "1024";
-               historySize = "0";
-               password = "0";
-               tabComplete = "0";
-               sinkAllKeyEvents = "0";
-               passwordMask = "*";
-            };
-            new GuiTextCtrl() {
-               canSaveDynamicFields = "0";
-               isContainer = "0";
-               Profile = "ToolsGuiTextProfile";
-               HorizSizing = "right";
-               VertSizing = "bottom";
-               position = "39 54";
-               Extent = "46 16";
-               MinExtent = "8 2";
-               canSave = "1";
-               Visible = "1";
-               tooltipprofile = "ToolsGuiToolTipProfile";
-               hovertime = "1000";
-               Margin = "0 0 0 0";
-               Padding = "0 0 0 0";
-               AnchorTop = "0";
-               AnchorBottom = "0";
-               AnchorLeft = "0";
-               AnchorRight = "0";
-               text = "Strength";
-               maxLength = "1024";
-            };
-            new GuiTextEditCtrl() {
-               internalName = "detStrengthCtrl";
-               canSaveDynamicFields = "0";
-               isContainer = "0";
-               Profile = "ToolsGuiTextEditProfile";
-               HorizSizing = "right";
-               VertSizing = "bottom";
-               position = "1 53";
-               Extent = "34 18";
-               MinExtent = "8 2";
-               canSave = "1";
-               Visible = "1";
-               tooltipprofile = "ToolsGuiToolTipProfile";
-               hovertime = "1000";
-               Margin = "0 0 0 0";
-               Padding = "0 0 0 0";
-               AnchorTop = "0";
-               AnchorBottom = "0";
-               AnchorLeft = "0";
-               AnchorRight = "0";
-               maxLength = "1024";
-               historySize = "0";
-               password = "0";
-               tabComplete = "0";
-               sinkAllKeyEvents = "0";
-               passwordMask = "*";
-            };
-            new GuiTextCtrl() {
-               canSaveDynamicFields = "0";
-               isContainer = "0";
-               Profile = "ToolsGuiTextProfile";
-               HorizSizing = "right";
-               VertSizing = "bottom";
-               position = "132 54";
-               Extent = "45 16";
-               MinExtent = "8 2";
-               canSave = "1";
-               Visible = "1";
-               tooltipprofile = "ToolsGuiToolTipProfile";
-               hovertime = "1000";
-               Margin = "0 0 0 0";
-               Padding = "0 0 0 0";
-               AnchorTop = "0";
-               AnchorBottom = "0";
-               AnchorLeft = "0";
-               AnchorRight = "0";
-               text = "Distance";
-               maxLength = "1024";
-            };
-            new GuiTextEditCtrl() {
-               internalName = "detDistanceCtrl";
-               canSaveDynamicFields = "0";
-               isContainer = "0";
-               Profile = "ToolsGuiTextEditProfile";
-               HorizSizing = "right";
-               VertSizing = "bottom";
-               position = "94 53";
-               Extent = "34 18";
-               MinExtent = "8 2";
-               canSave = "1";
-               Visible = "1";
-               tooltipprofile = "ToolsGuiToolTipProfile";
-               hovertime = "1000";
-               Margin = "0 0 0 0";
-               Padding = "0 0 0 0";
-               AnchorTop = "0";
-               AnchorBottom = "0";
-               AnchorLeft = "0";
-               AnchorRight = "0";
-               maxLength = "1024";
-               historySize = "0";
-               password = "0";
-               tabComplete = "0";
-               sinkAllKeyEvents = "0";
-               passwordMask = "*";
+               new GuiBitmapCtrl() {
+                  bitmap = "tools/materialEditor/gui/unknownImage";
+                  color = "255 255 255 255";
+                  wrap = "0";
+                  position = "1 1";
+                  extent = "47 47";
+                  minExtent = "8 2";
+                  horizSizing = "right";
+                  vertSizing = "bottom";
+                  profile = "ToolsGuiDefaultProfile";
+                  visible = "1";
+                  active = "1";
+                  tooltipProfile = "ToolsGuiToolTipProfile";
+                  hovertime = "1000";
+                  isContainer = "0";
+                  internalName = "macroTexCtrl";
+                  canSave = "1";
+                  canSaveDynamicFields = "0";
+               };
+               new GuiBitmapButtonCtrl() {
+                  bitmap = "tools/materialEditor/gui/cubemapBtnBorder";
+                  bitmapMode = "Stretched";
+                  autoFitExtents = "0";
+                  useModifiers = "0";
+                  useStates = "1";
+                  masked = "0";
+                  groupNum = "-1";
+                  buttonType = "PushButton";
+                  useMouseEvents = "0";
+                  position = "1 1";
+                  extent = "48 48";
+                  minExtent = "8 2";
+                  horizSizing = "right";
+                  vertSizing = "bottom";
+                  profile = "ToolsGuiDefaultProfile";
+                  visible = "1";
+                  active = "1";
+                  command = "TerrainMaterialDlg.changeMacro();";
+                  tooltipProfile = "ToolsGuiDefaultProfile";
+                  tooltip = "Change the active Macro Map for this layer.";
+                  hovertime = "1000";
+                  isContainer = "0";
+                  canSave = "1";
+                  canSaveDynamicFields = "0";
+               };
+               new GuiTextCtrl() {
+                  text = "Macro";
+                  maxLength = "1024";
+                  margin = "0 0 0 0";
+                  padding = "0 0 0 0";
+                  anchorTop = "1";
+                  anchorBottom = "0";
+                  anchorLeft = "1";
+                  anchorRight = "0";
+                  position = "56 -3";
+                  extent = "34 18";
+                  minExtent = "8 2";
+                  horizSizing = "right";
+                  vertSizing = "bottom";
+                  profile = "EditorTextProfile";
+                  visible = "1";
+                  active = "1";
+                  tooltipProfile = "ToolsGuiToolTipProfile";
+                  hovertime = "1000";
+                  isContainer = "0";
+                  canSave = "1";
+                  canSaveDynamicFields = "0";
+               };
+               new GuiTextCtrl() {
+                  text = "None";
+                  maxLength = "1024";
+                  margin = "0 0 0 0";
+                  padding = "0 0 0 0";
+                  anchorTop = "1";
+                  anchorBottom = "0";
+                  anchorLeft = "1";
+                  anchorRight = "0";
+                  position = "56 17";
+                  extent = "111 17";
+                  minExtent = "8 2";
+                  horizSizing = "width";
+                  vertSizing = "bottom";
+                  profile = "ToolsGuiTextProfile";
+                  visible = "1";
+                  active = "1";
+                  tooltipProfile = "ToolsGuiToolTipProfile";
+                  hovertime = "1000";
+                  isContainer = "0";
+                  canSave = "1";
+                  canSaveDynamicFields = "0";
+               };
+               new GuiButtonCtrl() {
+                  text = "Edit";
+                  groupNum = "-1";
+                  buttonType = "PushButton";
+                  useMouseEvents = "0";
+                  position = "111 0";
+                  extent = "40 16";
+                  minExtent = "8 2";
+                  horizSizing = "left";
+                  vertSizing = "bottom";
+                  profile = "ToolsGuiButtonProfile";
+                  visible = "1";
+                  active = "1";
+                  command = "TerrainMaterialDlg.changeMacro();";
+                  tooltipProfile = "ToolsGuiToolTipProfile";
+                  hovertime = "1000";
+                  isContainer = "0";
+                  canSave = "1";
+                  canSaveDynamicFields = "0";
+               };
+               new GuiBitmapButtonCtrl() {
+                  bitmap = "tools/gui/images/delete";
+                  bitmapMode = "Stretched";
+                  autoFitExtents = "0";
+                  useModifiers = "0";
+                  useStates = "1";
+                  masked = "0";
+                  groupNum = "-1";
+                  buttonType = "PushButton";
+                  useMouseEvents = "0";
+                  position = "154 0";
+                  extent = "16 16";
+                  minExtent = "8 2";
+                  horizSizing = "left";
+                  vertSizing = "bottom";
+                  profile = "ToolsGuiDefaultProfile";
+                  visible = "1";
+                  active = "1";
+                  command = "TerrainMaterialDlg-->macroTexCtrl.setBitmap(\"tools/materialEditor/gui/unknownImage\");";
+                  tooltipProfile = "ToolsGuiToolTipProfile";
+                  hovertime = "1000";
+                  isContainer = "0";
+                  canSave = "1";
+                  canSaveDynamicFields = "0";
+               };
+               new GuiTextCtrl() {
+                  text = "Size";
+                  maxLength = "1024";
+                  margin = "0 0 0 0";
+                  padding = "0 0 0 0";
+                  anchorTop = "0";
+                  anchorBottom = "0";
+                  anchorLeft = "0";
+                  anchorRight = "0";
+                  position = "132 33";
+                  extent = "39 16";
+                  minExtent = "8 2";
+                  horizSizing = "right";
+                  vertSizing = "bottom";
+                  profile = "ToolsGuiTextProfile";
+                  visible = "1";
+                  active = "1";
+                  tooltipProfile = "ToolsGuiToolTipProfile";
+                  hovertime = "1000";
+                  isContainer = "0";
+                  canSave = "1";
+                  canSaveDynamicFields = "0";
+               };
+               new GuiTextEditCtrl() {
+                  historySize = "0";
+                  tabComplete = "0";
+                  sinkAllKeyEvents = "0";
+                  password = "0";
+                  passwordMask = "*";
+                  text = "200";
+                  maxLength = "1024";
+                  margin = "0 0 0 0";
+                  padding = "0 0 0 0";
+                  anchorTop = "0";
+                  anchorBottom = "0";
+                  anchorLeft = "0";
+                  anchorRight = "0";
+                  position = "94 32";
+                  extent = "34 18";
+                  minExtent = "8 2";
+                  horizSizing = "right";
+                  vertSizing = "bottom";
+                  profile = "ToolsGuiTextEditProfile";
+                  visible = "1";
+                  active = "1";
+                  tooltipProfile = "ToolsGuiToolTipProfile";
+                  hovertime = "1000";
+                  isContainer = "0";
+                  internalName = "macroSizeCtrl";
+                  canSave = "1";
+                  canSaveDynamicFields = "0";
+               };
+               new GuiTextCtrl() {
+                  text = "Strength";
+                  maxLength = "1024";
+                  margin = "0 0 0 0";
+                  padding = "0 0 0 0";
+                  anchorTop = "0";
+                  anchorBottom = "0";
+                  anchorLeft = "0";
+                  anchorRight = "0";
+                  position = "39 54";
+                  extent = "46 16";
+                  minExtent = "8 2";
+                  horizSizing = "right";
+                  vertSizing = "bottom";
+                  profile = "ToolsGuiTextProfile";
+                  visible = "1";
+                  active = "1";
+                  tooltipProfile = "ToolsGuiToolTipProfile";
+                  hovertime = "1000";
+                  isContainer = "0";
+                  canSave = "1";
+                  canSaveDynamicFields = "0";
+               };
+               new GuiTextEditCtrl() {
+                  historySize = "0";
+                  tabComplete = "0";
+                  sinkAllKeyEvents = "0";
+                  password = "0";
+                  passwordMask = "*";
+                  text = "0.7";
+                  maxLength = "1024";
+                  margin = "0 0 0 0";
+                  padding = "0 0 0 0";
+                  anchorTop = "0";
+                  anchorBottom = "0";
+                  anchorLeft = "0";
+                  anchorRight = "0";
+                  position = "1 53";
+                  extent = "34 18";
+                  minExtent = "8 2";
+                  horizSizing = "right";
+                  vertSizing = "bottom";
+                  profile = "ToolsGuiTextEditProfile";
+                  visible = "1";
+                  active = "1";
+                  tooltipProfile = "ToolsGuiToolTipProfile";
+                  hovertime = "1000";
+                  isContainer = "0";
+                  internalName = "macroStrengthCtrl";
+                  canSave = "1";
+                  canSaveDynamicFields = "0";
+               };
+               new GuiTextCtrl() {
+                  text = "Distance";
+                  maxLength = "1024";
+                  margin = "0 0 0 0";
+                  padding = "0 0 0 0";
+                  anchorTop = "0";
+                  anchorBottom = "0";
+                  anchorLeft = "0";
+                  anchorRight = "0";
+                  position = "132 54";
+                  extent = "45 16";
+                  minExtent = "8 2";
+                  horizSizing = "right";
+                  vertSizing = "bottom";
+                  profile = "ToolsGuiTextProfile";
+                  visible = "1";
+                  active = "1";
+                  tooltipProfile = "ToolsGuiToolTipProfile";
+                  hovertime = "1000";
+                  isContainer = "0";
+                  canSave = "1";
+                  canSaveDynamicFields = "0";
+               };
+               new GuiTextEditCtrl() {
+                  historySize = "0";
+                  tabComplete = "0";
+                  sinkAllKeyEvents = "0";
+                  password = "0";
+                  passwordMask = "*";
+                  text = "500";
+                  maxLength = "1024";
+                  margin = "0 0 0 0";
+                  padding = "0 0 0 0";
+                  anchorTop = "0";
+                  anchorBottom = "0";
+                  anchorLeft = "0";
+                  anchorRight = "0";
+                  position = "94 53";
+                  extent = "34 18";
+                  minExtent = "8 2";
+                  horizSizing = "right";
+                  vertSizing = "bottom";
+                  profile = "ToolsGuiTextEditProfile";
+                  visible = "1";
+                  active = "1";
+                  tooltipProfile = "ToolsGuiToolTipProfile";
+                  hovertime = "1000";
+                  isContainer = "0";
+                  internalName = "macroDistanceCtrl";
+                  canSave = "1";
+                  canSaveDynamicFields = "0";
+               };
             };
             };
          };
          };
       };
       };
       new GuiControl() {
       new GuiControl() {
-         canSaveDynamicFields = "0";
-         isContainer = "1";
-         Profile = "ToolsGuiDefaultProfile";
-         HorizSizing = "width";
-         VertSizing = "height";
          position = "6 42";
          position = "6 42";
-         Extent = "189 373";
-         MinExtent = "8 2";
-         canSave = "1";
-         Visible = "1";
-         tooltipprofile = "ToolsGuiToolTipProfile";
+         extent = "189 373";
+         minExtent = "8 2";
+         horizSizing = "width";
+         vertSizing = "height";
+         profile = "ToolsGuiDefaultProfile";
+         visible = "1";
+         active = "1";
+         tooltipProfile = "ToolsGuiToolTipProfile";
          hovertime = "1000";
          hovertime = "1000";
+         isContainer = "1";
+         canSave = "1";
+         canSaveDynamicFields = "0";
 
 
          new GuiScrollCtrl() {
          new GuiScrollCtrl() {
-            canSaveDynamicFields = "0";
-            isContainer = "1";
-            Profile = "ToolsGuiScrollProfile";
-            HorizSizing = "width";
-            VertSizing = "height";
-            position = "0 0";
-            Extent = "189 374";
-            MinExtent = "8 2";
-            canSave = "1";
-            Visible = "1";
-            tooltipprofile = "ToolsGuiToolTipProfile";
-            hovertime = "1000";
-            Margin = "0 0 0 0";
-            Padding = "0 0 0 0";
-            AnchorTop = "1";
-            AnchorBottom = "0";
-            AnchorLeft = "1";
-            AnchorRight = "0";
             willFirstRespond = "1";
             willFirstRespond = "1";
             hScrollBar = "dynamic";
             hScrollBar = "dynamic";
             vScrollBar = "dynamic";
             vScrollBar = "dynamic";
-            lockHorizScroll = "false";
-            lockVertScroll = "false";
+            lockHorizScroll = "0";
+            lockVertScroll = "0";
             constantThumbHeight = "0";
             constantThumbHeight = "0";
             childMargin = "0 0";
             childMargin = "0 0";
             mouseWheelScrollSpeed = "-1";
             mouseWheelScrollSpeed = "-1";
+            margin = "0 0 0 0";
+            padding = "0 0 0 0";
+            anchorTop = "1";
+            anchorBottom = "0";
+            anchorLeft = "1";
+            anchorRight = "0";
+            position = "0 -1";
+            extent = "189 374";
+            minExtent = "8 2";
+            horizSizing = "width";
+            vertSizing = "height";
+            profile = "ToolsGuiScrollProfile";
+            visible = "1";
+            active = "1";
+            tooltipProfile = "ToolsGuiToolTipProfile";
+            hovertime = "1000";
+            isContainer = "1";
+            canSave = "1";
+            canSaveDynamicFields = "0";
 
 
             new GuiTreeViewCtrl() {
             new GuiTreeViewCtrl() {
-               internalName = "matLibTree";
-               canSaveDynamicFields = "0";
-               class = "TerrainMaterialTreeCtrl";
-               className = "TerrainMaterialTreeCtrl";
-               isContainer = "1";
-               Profile = "ToolsGuiTreeViewProfile";
-               HorizSizing = "right";
-               VertSizing = "bottom";
-               position = "1 1";
-               Extent = "125 84";
-               MinExtent = "8 2";
-               canSave = "1";
-               Visible = "1";
-               tooltipprofile = "ToolsGuiToolTipProfile";
-               hovertime = "1000";
                tabSize = "16";
                tabSize = "16";
                textOffset = "2";
                textOffset = "2";
                fullRowSelect = "0";
                fullRowSelect = "0";
                itemHeight = "21";
                itemHeight = "21";
                destroyTreeOnSleep = "1";
                destroyTreeOnSleep = "1";
-               MouseDragging = "0";
-               MultipleSelections = "0";
-               DeleteObjectAllowed = "0";
-               DragToItemAllowed = "0";
-               ClearAllOnSingleSelection = "1";
+               mouseDragging = "0";
+               multipleSelections = "0";
+               deleteObjectAllowed = "0";
+               dragToItemAllowed = "0";
+               clearAllOnSingleSelection = "1";
                showRoot = "0";
                showRoot = "0";
-               internalNamesOnly = "1";
-               objectNamesOnly = "0";
+               useInspectorTooltips = "0";
+               tooltipOnWidthOnly = "0";
+               showObjectIds = "0";
+               showClassNames = "0";
+               showObjectNames = "0";
+               showInternalNames = "1";
+               showClassNameForUnnamedObjects = "0";
+               compareToObjectID = "1";
+               canRenameObjects = "1";
+               renameInternal = "0";
+               position = "1 1";
+               extent = "109 147";
+               minExtent = "8 2";
+               horizSizing = "right";
+               vertSizing = "bottom";
+               profile = "ToolsGuiTreeViewProfile";
+               visible = "1";
+               active = "1";
+               tooltipProfile = "ToolsGuiToolTipProfile";
+               hovertime = "1000";
+               isContainer = "1";
+               internalName = "matLibTree";
+               class = "TerrainMaterialTreeCtrl";
+               canSave = "1";
+               canSaveDynamicFields = "0";
             };
             };
          };
          };
       };
       };
       new GuiButtonCtrl() {
       new GuiButtonCtrl() {
-         canSaveDynamicFields = "0";
-         isContainer = "0";
-         Profile = "ToolsGuiButtonProfile";
-         HorizSizing = "left";
-         VertSizing = "top";
-         position = "202 394";
-         Extent = "98 22";
-         MinExtent = "8 2";
-         canSave = "1";
-         Visible = "1";
-         Command = "TerrainMaterialDlg.dialogApply();";
-         tooltipprofile = "ToolsGuiToolTipProfile";
-         hovertime = "1000";
          text = "Apply&Select";
          text = "Apply&Select";
          groupNum = "-1";
          groupNum = "-1";
          buttonType = "PushButton";
          buttonType = "PushButton";
          useMouseEvents = "0";
          useMouseEvents = "0";
-      };
-      new GuiButtonCtrl() {
-         canSaveDynamicFields = "0";
+         position = "202 394";
+         extent = "98 22";
+         minExtent = "8 2";
+         horizSizing = "left";
+         vertSizing = "top";
+         profile = "ToolsGuiButtonProfile";
+         visible = "1";
+         active = "1";
+         command = "TerrainMaterialDlg.dialogApply();";
+         tooltipProfile = "ToolsGuiToolTipProfile";
+         hovertime = "1000";
          isContainer = "0";
          isContainer = "0";
-         Profile = "ToolsGuiButtonProfile";
-         HorizSizing = "left";
-         VertSizing = "top";
-         position = "307 394";
-         Extent = "80 22";
-         MinExtent = "8 2";
          canSave = "1";
          canSave = "1";
-         Visible = "1";
-         Command = "TerrainMaterialDlg.dialogCancel();";
-         tooltipprofile = "ToolsGuiToolTipProfile";
-         hovertime = "1000";
+         canSaveDynamicFields = "0";
+      };
+      new GuiButtonCtrl() {
          text = "Cancel";
          text = "Cancel";
          groupNum = "-1";
          groupNum = "-1";
          buttonType = "PushButton";
          buttonType = "PushButton";
          useMouseEvents = "0";
          useMouseEvents = "0";
+         position = "307 394";
+         extent = "80 22";
+         minExtent = "8 2";
+         horizSizing = "left";
+         vertSizing = "top";
+         profile = "ToolsGuiButtonProfile";
+         visible = "1";
+         active = "1";
+         command = "TerrainMaterialDlg.dialogCancel();";
+         tooltipProfile = "ToolsGuiToolTipProfile";
+         hovertime = "1000";
+         isContainer = "0";
+         canSave = "1";
+         canSaveDynamicFields = "0";
       };
       };
-      
-      new GuiBitmapCtrl() { // inactive overlay
-         internalName = "inactiveOverlay";
-         Profile = "ToolsGuiDefaultProfile";
-         HorizSizing = "left";
-         VertSizing = "height";
-         position = "199 23";
-         Extent = "190 267";
-         isContainer = true;
-         Visible = false;
+      new GuiBitmapCtrl() {
          bitmap = "tools/gui/images/inactive-overlay";
          bitmap = "tools/gui/images/inactive-overlay";
-         
-         new GuiTextCtrl(){
-            internalName = "inactiveOverlayDlg";
-            Profile = "ToolsGuiTextCenterProfile";
-            HorizSizing = "width";
-            VertSizing = "center";
-            position = "0 104";
-            Extent = "190 64";
+         color = "255 255 255 255";
+         wrap = "0";
+         position = "199 23";
+         extent = "190 267";
+         minExtent = "8 2";
+         horizSizing = "left";
+         vertSizing = "height";
+         profile = "ToolsGuiDefaultProfile";
+         visible = "0";
+         active = "1";
+         tooltipProfile = "GuiToolTipProfile";
+         hovertime = "1000";
+         isContainer = "1";
+         internalName = "inactiveOverlay";
+         hidden = "1";
+         canSave = "1";
+         canSaveDynamicFields = "0";
+
+         new GuiTextCtrl() {
             text = "Inactive";
             text = "Inactive";
+            maxLength = "1024";
+            margin = "0 0 0 0";
+            padding = "0 0 0 0";
+            anchorTop = "1";
+            anchorBottom = "0";
+            anchorLeft = "1";
+            anchorRight = "0";
+            position = "0 104";
+            extent = "190 64";
+            minExtent = "8 2";
+            horizSizing = "width";
+            vertSizing = "center";
+            profile = "ToolsGuiTextCenterProfile";
+            visible = "1";
+            active = "1";
+            tooltipProfile = "GuiToolTipProfile";
+            hovertime = "1000";
+            isContainer = "1";
+            internalName = "inactiveOverlayDlg";
+            canSave = "1";
+            canSaveDynamicFields = "0";
          };
          };
       };
       };
    };
    };

+ 18 - 0
Templates/BaseGame/game/tools/worldEditor/gui/objectBuilderGui.ed.gui

@@ -877,6 +877,24 @@ function ObjectBuilderGui::buildParticleSimulation(%this)
 	%this.process();
 	%this.process();
 }
 }
 
 
+function ObjectBuilderGui::buildReflectionProbe(%this)
+{
+   %this.objectClassName = "ReflectionProbe";
+   %this.process();
+   
+   %defaultPath = filePath($Server::MissionFile) @ "/" @ fileBase($Server::MissionFile) @ "/probes/";   
+   %this.addField("reflectionPath", "TypeFilepath", "reflectionPath", %defaultPath);
+}
+
+function ObjectBuilderGui::buildSkylight(%this)
+{
+   %this.objectClassName = "Skylight";
+   %this.process();
+   
+   %defaultPath = filePath($Server::MissionFile) @ "/" @ fileBase($Server::MissionFile) @ "/probes/";   
+   %this.addField("reflectionPath", "TypeFilepath", "reflectionPath", %defaultPath);
+}
+
 //------------------------------------------------------------------------------
 //------------------------------------------------------------------------------
 // Mission
 // Mission
 //------------------------------------------------------------------------------
 //------------------------------------------------------------------------------

+ 192 - 0
Templates/BaseGame/game/tools/worldEditor/gui/probeBakeDlg.gui

@@ -0,0 +1,192 @@
+//--- OBJECT WRITE BEGIN ---
+%guiContent = new GuiControl(ProbeBakeDlg) {
+   position = "0 0";
+   extent = "1024 768";
+   minExtent = "8 2";
+   horizSizing = "right";
+   vertSizing = "bottom";
+   profile = "GuiDefaultProfile";
+   visible = "1";
+   active = "1";
+   tooltipProfile = "GuiToolTipProfile";
+   hovertime = "1000";
+   isContainer = "1";
+   canSave = "1";
+   canSaveDynamicFields = "1";
+
+   new GuiWindowCtrl() {
+      text = "Update Environment Probes";
+      resizeWidth = "0";
+      resizeHeight = "0";
+      canMove = "1";
+      canClose = "1";
+      canMinimize = "0";
+      canMaximize = "0";
+      canCollapse = "0";
+      closeCommand = "Canvas.popDialog(ProbeBakeDlg);";
+      edgeSnap = "0";
+      margin = "0 0 0 0";
+      padding = "0 0 0 0";
+      anchorTop = "1";
+      anchorBottom = "0";
+      anchorLeft = "1";
+      anchorRight = "0";
+      position = "392 314";
+      extent = "270 164";
+      minExtent = "8 2";
+      horizSizing = "right";
+      vertSizing = "bottom";
+      profile = "GuiWindowProfile";
+      visible = "1";
+      active = "1";
+      tooltipProfile = "GuiToolTipProfile";
+      hovertime = "1000";
+      isContainer = "1";
+      canSave = "1";
+      canSaveDynamicFields = "0";
+
+      new GuiTextCtrl() {
+         text = "Probe Resolution";
+         maxLength = "1024";
+         margin = "0 0 0 0";
+         padding = "0 0 0 0";
+         anchorTop = "1";
+         anchorBottom = "0";
+         anchorLeft = "1";
+         anchorRight = "0";
+         position = "11 32";
+         extent = "91 13";
+         minExtent = "8 2";
+         horizSizing = "right";
+         vertSizing = "bottom";
+         profile = "GuiTextProfile";
+         visible = "1";
+         active = "1";
+         tooltipProfile = "GuiToolTipProfile";
+         hovertime = "1000";
+         isContainer = "1";
+         canSave = "1";
+         canSaveDynamicFields = "0";
+      };
+      new GuiPopUpMenuCtrl(ProbeBakeDlg_ProbeResList) {
+         maxPopupHeight = "200";
+         sbUsesNAColor = "0";
+         reverseTextList = "0";
+         bitmapBounds = "16 16";
+         text = "64";
+         maxLength = "1024";
+         margin = "0 0 0 0";
+         padding = "0 0 0 0";
+         anchorTop = "1";
+         anchorBottom = "0";
+         anchorLeft = "1";
+         anchorRight = "0";
+         position = "103 29";
+         extent = "157 19";
+         minExtent = "8 2";
+         horizSizing = "right";
+         vertSizing = "bottom";
+         profile = "GuiPopUpMenuProfile";
+         visible = "1";
+         active = "1";
+         tooltipProfile = "GuiToolTipProfile";
+         hovertime = "1000";
+         isContainer = "1";
+         canSave = "1";
+         canSaveDynamicFields = "0";
+      };
+      new GuiTextCtrl() {
+         text = "Number of bake iterations";
+         maxLength = "1024";
+         margin = "0 0 0 0";
+         padding = "0 0 0 0";
+         anchorTop = "1";
+         anchorBottom = "0";
+         anchorLeft = "1";
+         anchorRight = "0";
+         position = "11 56";
+         extent = "129 13";
+         minExtent = "8 2";
+         horizSizing = "right";
+         vertSizing = "bottom";
+         profile = "GuiTextProfile";
+         visible = "1";
+         active = "1";
+         tooltipProfile = "GuiToolTipProfile";
+         hovertime = "1000";
+         isContainer = "1";
+         canSave = "1";
+         canSaveDynamicFields = "0";
+      };
+      new GuiTextEditCtrl(ProbeBakeDlg_NumIterTxt) {
+         historySize = "0";
+         tabComplete = "0";
+         sinkAllKeyEvents = "0";
+         password = "0";
+         passwordMask = "*";
+         text = "1";
+         maxLength = "1024";
+         margin = "0 0 0 0";
+         padding = "0 0 0 0";
+         anchorTop = "1";
+         anchorBottom = "0";
+         anchorLeft = "1";
+         anchorRight = "0";
+         position = "150 53";
+         extent = "108 18";
+         minExtent = "8 2";
+         horizSizing = "right";
+         vertSizing = "bottom";
+         profile = "GuiTextEditProfile";
+         visible = "1";
+         active = "1";
+         tooltipProfile = "GuiToolTipProfile";
+         hovertime = "1000";
+         isContainer = "1";
+         canSave = "1";
+         canSaveDynamicFields = "0";
+      };
+      new GuiButtonCtrl(ProbeBakeDlg_RunBake) {
+         text = "Update Probes";
+         groupNum = "-1";
+         buttonType = "PushButton";
+         useMouseEvents = "0";
+         position = "68 120";
+         extent = "140 30";
+         minExtent = "8 2";
+         horizSizing = "right";
+         vertSizing = "bottom";
+         profile = "GuiButtonProfile";
+         visible = "1";
+         active = "1";
+         tooltipProfile = "GuiToolTipProfile";
+         hovertime = "1000";
+         isContainer = "0";
+         canSave = "1";
+         canSaveDynamicFields = "0";
+      };
+      new GuiProgressCtrl(ProbeBakeDlg_Progress) {
+         maxLength = "1024";
+         margin = "0 0 0 0";
+         padding = "0 0 0 0";
+         anchorTop = "1";
+         anchorBottom = "0";
+         anchorLeft = "1";
+         anchorRight = "0";
+         position = "8 80";
+         extent = "251 25";
+         minExtent = "8 2";
+         horizSizing = "right";
+         vertSizing = "bottom";
+         profile = "GuiProgressProfile";
+         visible = "1";
+         active = "1";
+         tooltipProfile = "GuiToolTipProfile";
+         hovertime = "1000";
+         isContainer = "1";
+         canSave = "1";
+         canSaveDynamicFields = "0";
+      };
+   };
+};
+//--- OBJECT WRITE END ---

+ 13 - 3
Templates/BaseGame/game/tools/worldEditor/main.cs

@@ -44,6 +44,7 @@ function initializeWorldEditor()
    exec("./gui/SelectObjectsWindow.ed.gui");
    exec("./gui/SelectObjectsWindow.ed.gui");
    exec("./gui/ProceduralTerrainPainterGui.gui" );
    exec("./gui/ProceduralTerrainPainterGui.gui" );
    exec("./gui/shadowViz.gui" );
    exec("./gui/shadowViz.gui" );
+   exec("./gui/probeBakeDlg.gui" );
    
    
    // Load Scripts.
    // Load Scripts.
    exec("./scripts/menus.ed.cs");
    exec("./scripts/menus.ed.cs");
@@ -66,6 +67,7 @@ function initializeWorldEditor()
    exec("./scripts/cameraCommands.ed.cs");
    exec("./scripts/cameraCommands.ed.cs");
    exec("./scripts/lightViz.cs");
    exec("./scripts/lightViz.cs");
    exec("./scripts/shadowViz.cs");
    exec("./scripts/shadowViz.cs");
+   exec("./scripts/probeBake.ed.cs");
 
 
    // Load Custom Editors
    // Load Custom Editors
    loadDirectory(expandFilename("./scripts/editors"));
    loadDirectory(expandFilename("./scripts/editors"));
@@ -120,16 +122,24 @@ function initializeWorldEditor()
    EVisibility.addOption( "Debug Render: Light Frustums", "$Light::renderLightFrustums", "" );
    EVisibility.addOption( "Debug Render: Light Frustums", "$Light::renderLightFrustums", "" );
    EVisibility.addOption( "Debug Render: Bounding Boxes", "$Scene::renderBoundingBoxes", "" );
    EVisibility.addOption( "Debug Render: Bounding Boxes", "$Scene::renderBoundingBoxes", "" );
    EVisibility.addOption( "Debug Render: Physics World", "$PhysicsWorld::render", "togglePhysicsDebugViz" );
    EVisibility.addOption( "Debug Render: Physics World", "$PhysicsWorld::render", "togglePhysicsDebugViz" );
+   EVisibility.addOption( "Debug Render: Reflection Probes", "$Light::renderReflectionProbes", "" );
+   EVisibility.addOption( "Debug Render: Probe Previews", "$Light::renderPreviewProbes", "" );
    EVisibility.addOption( "AL: Disable Shadows", "$Shadows::disable", "" );   
    EVisibility.addOption( "AL: Disable Shadows", "$Shadows::disable", "" );   
-   EVisibility.addOption( "AL: Light Color Viz", "$AL_LightColorVisualizeVar", "toggleLightColorViz" );
-   EVisibility.addOption( "AL: Light Specular Viz", "$AL_LightSpecularVisualizeVar", "toggleLightSpecularViz" );
+   EVisibility.addOption( "AL: Diffuse Lighting Viz", "$AL_LightColorVisualizeVar", "toggleLightColorViz" );
+   EVisibility.addOption( "AL: Specular Lighting Viz", "$AL_LightSpecularVisualizeVar", "toggleLightSpecularViz" );
    EVisibility.addOption( "AL: Normals Viz", "$AL_NormalsVisualizeVar", "toggleNormalsViz" );
    EVisibility.addOption( "AL: Normals Viz", "$AL_NormalsVisualizeVar", "toggleNormalsViz" );
    EVisibility.addOption( "AL: Depth Viz", "$AL_DepthVisualizeVar", "toggleDepthViz" );
    EVisibility.addOption( "AL: Depth Viz", "$AL_DepthVisualizeVar", "toggleDepthViz" );
    EVisibility.addOption( "AL: Color Buffer", "$AL_ColorBufferShaderVar", "toggleColorBufferViz" );
    EVisibility.addOption( "AL: Color Buffer", "$AL_ColorBufferShaderVar", "toggleColorBufferViz" );
-   EVisibility.addOption( "AL: Spec Map", "$AL_SpecMapShaderVar", "toggleSpecMapViz");
+   EVisibility.addOption( "AL: Spec Map(Rough)", "$AL_RoughMapShaderVar", "toggleRoughMapViz");
+   EVisibility.addOption( "AL: Spec Map(Metal)", "$AL_MetalMapShaderVar", "toggleMetalMapViz");
    EVisibility.addOption( "AL: Backbuffer", "$AL_BackbufferVisualizeVar", "toggleBackbufferViz" );
    EVisibility.addOption( "AL: Backbuffer", "$AL_BackbufferVisualizeVar", "toggleBackbufferViz" );
    EVisibility.addOption( "AL: Glow Buffer", "$AL_GlowVisualizeVar", "toggleGlowViz" );
    EVisibility.addOption( "AL: Glow Buffer", "$AL_GlowVisualizeVar", "toggleGlowViz" );
    EVisibility.addOption( "AL: PSSM Cascade Viz", "$AL::PSSMDebugRender", "" );
    EVisibility.addOption( "AL: PSSM Cascade Viz", "$AL::PSSMDebugRender", "" );
+   EVisibility.addOption( "Probes: Attenuation", "$Probes::showAttenuation", "" );   
+   EVisibility.addOption( "Probes: Specular Cubemaps", "$Probes::showSpecularCubemaps", "" );   
+   EVisibility.addOption( "Probes: Diffuse Cubemaps", "$Probes::showDiffuseCubemaps", "" );   
+   EVisibility.addOption( "Probes: Contribution", "$Probes::showProbeContrib", "" );   
+
    EVisibility.addOption( "Frustum Lock", "$Scene::lockCull", "" );
    EVisibility.addOption( "Frustum Lock", "$Scene::lockCull", "" );
    EVisibility.addOption( "Disable Zone Culling", "$Scene::disableZoneCulling", "" );
    EVisibility.addOption( "Disable Zone Culling", "$Scene::disableZoneCulling", "" );
    EVisibility.addOption( "Disable Terrain Occlusion", "$Scene::disableTerrainOcclusion", "" );
    EVisibility.addOption( "Disable Terrain Occlusion", "$Scene::disableTerrainOcclusion", "" );

+ 5 - 0
Templates/BaseGame/game/tools/worldEditor/scripts/editors/creator.ed.cs

@@ -55,6 +55,11 @@ function EWCreatorWindow::init( %this )
       
       
       %this.registerMissionObject( "PointLight",          "Point Light" );
       %this.registerMissionObject( "PointLight",          "Point Light" );
       %this.registerMissionObject( "SpotLight",           "Spot Light" );
       %this.registerMissionObject( "SpotLight",           "Spot Light" );
+      
+      %this.registerMissionObject( "BoxEnvironmentProbe",       "Box Environment Probe" );
+      %this.registerMissionObject( "SphereEnvironmentProbe",    "Sphere Environment Probe" );
+      %this.registerMissionObject( "Skylight",       "Skylight" );
+      
       %this.registerMissionObject( "GroundCover",         "Ground Cover" );
       %this.registerMissionObject( "GroundCover",         "Ground Cover" );
       %this.registerMissionObject( "TerrainBlock",        "Terrain Block" );
       %this.registerMissionObject( "TerrainBlock",        "Terrain Block" );
       %this.registerMissionObject( "GroundPlane",         "Ground Plane" );
       %this.registerMissionObject( "GroundPlane",         "Ground Plane" );

+ 38 - 2
Templates/BaseGame/game/tools/worldEditor/scripts/interfaces/terrainMaterialDlg.ed.cs

@@ -294,6 +294,28 @@ function TerrainMaterialDlg::changeNormal( %this )
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 
 
+function TerrainMaterialDlg::changecomposite( %this )
+{
+   %ctrl = %this-->compositeTexCtrl;
+   %file = %ctrl.bitmap;
+   if( getSubStr( %file, 0 , 6 ) $= "tools/" )
+      %file = "";
+
+   %file = TerrainMaterialDlg._selectTextureFileDialog( %file );  
+   if( %file $= "" )
+   {
+      if( %ctrl.bitmap !$= "" )
+         %file = %ctrl.bitmap;
+      else
+         %file = "tools/materialEditor/gui/unknownImage";
+   }
+   
+   %file = makeRelativePath( %file, getMainDotCsDir() );
+   %ctrl.setBitmap( %file );  
+}
+
+//-----------------------------------------------------------------------------
+
 function TerrainMaterialDlg::newMat( %this )
 function TerrainMaterialDlg::newMat( %this )
 {
 {
    // Create a unique material name.
    // Create a unique material name.
@@ -394,7 +416,12 @@ function TerrainMaterialDlg::setActiveMaterial( %this, %mat )
          %this-->normTexCtrl.setBitmap( "tools/materialEditor/gui/unknownImage" );
          %this-->normTexCtrl.setBitmap( "tools/materialEditor/gui/unknownImage" );
       }else{
       }else{
          %this-->normTexCtrl.setBitmap( %mat.normalMap ); 
          %this-->normTexCtrl.setBitmap( %mat.normalMap ); 
-      }
+      }	  
+      if (%mat.compositeMap $= ""){
+         %this-->compositeTexCtrl.setBitmap( "tools/materialEditor/gui/unknownImage" );
+      }else{
+         %this-->compositeTexCtrl.setBitmap( %mat.compositeMap );
+      }	  
       %this-->detSizeCtrl.setText( %mat.detailSize );
       %this-->detSizeCtrl.setText( %mat.detailSize );
       %this-->baseSizeCtrl.setText( %mat.diffuseSize );
       %this-->baseSizeCtrl.setText( %mat.diffuseSize );
       %this-->detStrengthCtrl.setText( %mat.detailStrength );
       %this-->detStrengthCtrl.setText( %mat.detailStrength );
@@ -448,6 +475,11 @@ function TerrainMaterialDlg::saveDirtyMaterial( %this, %mat )
    }else{
    }else{
       %newMacro = %this-->macroTexCtrl.bitmap;  
       %newMacro = %this-->macroTexCtrl.bitmap;  
    }
    }
+   if (%this-->compositeTexCtrl.bitmap $= "tools/materialEditor/gui/unknownImage"){
+      %newComposite = "";
+   }else{
+      %newComposite = %this-->compositeTexCtrl.bitmap;  
+   }
    %detailSize = %this-->detSizeCtrl.getText();      
    %detailSize = %this-->detSizeCtrl.getText();      
    %diffuseSize = %this-->baseSizeCtrl.getText();     
    %diffuseSize = %this-->baseSizeCtrl.getText();     
    %detailStrength = %this-->detStrengthCtrl.getText();
    %detailStrength = %this-->detStrengthCtrl.getText();
@@ -466,6 +498,7 @@ function TerrainMaterialDlg::saveDirtyMaterial( %this, %mat )
          %mat.diffuseMap $= %newDiffuse &&
          %mat.diffuseMap $= %newDiffuse &&
          %mat.normalMap $= %newNormal &&
          %mat.normalMap $= %newNormal &&
          %mat.detailMap $= %newDetail &&
          %mat.detailMap $= %newDetail &&
+         %mat.compositeMap $= %newComposite &&
          %mat.macroMap $= %newMacro &&
          %mat.macroMap $= %newMacro &&
          %mat.detailSize == %detailSize &&
          %mat.detailSize == %detailSize &&
          %mat.diffuseSize == %diffuseSize &&
          %mat.diffuseSize == %diffuseSize &&
@@ -497,7 +530,8 @@ function TerrainMaterialDlg::saveDirtyMaterial( %this, %mat )
    }
    }
    
    
    %mat.diffuseMap = %newDiffuse;    
    %mat.diffuseMap = %newDiffuse;    
-   %mat.normalMap = %newNormal;    
+   %mat.normalMap = %newNormal;
+   %mat.compositeMap = %newComposite;
    %mat.detailMap = %newDetail;    
    %mat.detailMap = %newDetail;    
    %mat.macroMap = %newMacro;
    %mat.macroMap = %newMacro;
    %mat.detailSize = %detailSize;  
    %mat.detailSize = %detailSize;  
@@ -544,6 +578,7 @@ function TerrainMaterialDlg::snapshotMaterials( %this )
          diffuseMap = %mat.diffuseMap;
          diffuseMap = %mat.diffuseMap;
          normalMap = %mat.normalMap;
          normalMap = %mat.normalMap;
          detailMap = %mat.detailMap;
          detailMap = %mat.detailMap;
+         compositeMap = %mat.compositeMap;
          macroMap = %mat.macroMap;
          macroMap = %mat.macroMap;
          detailSize = %mat.detailSize;
          detailSize = %mat.detailSize;
          diffuseSize = %mat.diffuseSize;
          diffuseSize = %mat.diffuseSize;
@@ -578,6 +613,7 @@ function TerrainMaterialDlg::restoreMaterials( %this )
       %mat.diffuseMap = %obj.diffuseMap;
       %mat.diffuseMap = %obj.diffuseMap;
       %mat.normalMap = %obj.normalMap;
       %mat.normalMap = %obj.normalMap;
       %mat.detailMap = %obj.detailMap;
       %mat.detailMap = %obj.detailMap;
+      %mat.compositeMap = %obj.compositeMap;
       %mat.macroMap = %obj.macroMap;
       %mat.macroMap = %obj.macroMap;
       %mat.detailSize = %obj.detailSize;
       %mat.detailSize = %obj.detailSize;
       %mat.diffuseSize = %obj.diffuseSize;
       %mat.diffuseSize = %obj.diffuseSize;

+ 83 - 13
Templates/BaseGame/game/tools/worldEditor/scripts/lightViz.cs

@@ -61,39 +61,109 @@ function toggleColorBufferViz( %enable )
    }
    }
 }
 }
 
 
-new ShaderData( AL_SpecMapShader )
+//roughness map display (matinfo.b)
+new ShaderData( AL_RoughMapShader )
 {
 {
-   DXVertexShaderFile = $Core::CommonShaderPath @ "/postFX/postFxV.hlsl";
-   DXPixelShaderFile  = "./shaders/dbgSpecMapVisualizeP.hlsl";
+   DXVertexShaderFile = "shaders/common/postFx/postFxV.hlsl";
+   DXPixelShaderFile  = "shaders/common/lighting/advanced/dbgRoughMapVisualizeP.hlsl";
 
 
-   OGLVertexShaderFile = $Core::CommonShaderPath @ "/postFX/gl/postFxV.glsl";
-   OGLPixelShaderFile  = "./shaders/dbgSpecMapVisualizeP.glsl";
+   OGLVertexShaderFile = "shaders/common/postFx/gl/postFxV.glsl";
+   OGLPixelShaderFile  = "shaders/common/lighting/advanced/gl/dbgRoughMapVisualizeP.glsl";
 
 
    samplerNames[0] = "matinfoTex";
    samplerNames[0] = "matinfoTex";
    pixVersion = 2.0;
    pixVersion = 2.0;
 };
 };
 
 
-singleton PostEffect( AL_SpecMapVisualize )
+singleton PostEffect( AL_RoughMapVisualize )
 {   
 {   
-   shader = AL_SpecMapShader;
+   shader = AL_RoughMapShader;
    stateBlock = AL_DefaultVisualizeState;
    stateBlock = AL_DefaultVisualizeState;
    texture[0] = "#matinfo";
    texture[0] = "#matinfo";
    target = "$backBuffer";
    target = "$backBuffer";
    renderPriority = 9999;
    renderPriority = 9999;
 };
 };
 
 
-/// Toggles the visualization of the AL lighting specular power buffer.
-function toggleSpecMapViz( %enable )
+function toggleRoughMapViz( %enable )
+{   
+   if ( %enable $= "" )
+   {
+      $AL_RoughMapShaderVar = AL_RoughMapVisualize.isEnabled() ? false : true;
+      AL_RoughMapVisualize.toggle();
+   }
+   else if ( %enable )
+      AL_RoughMapVisualize.enable();
+   else if ( !%enable )
+      AL_RoughMapVisualize.disable();    
+}
+
+//metalness map display (matinfo.a)
+new ShaderData( AL_MetalMapShader )
+{
+   DXVertexShaderFile = "shaders/common/postFx/postFxV.hlsl";
+   DXPixelShaderFile  = "shaders/common/lighting/advanced/dbgMetalMapVisualizeP.hlsl";
+
+   OGLVertexShaderFile = "shaders/common/postFx/gl/postFxV.glsl";
+   OGLPixelShaderFile  = "shaders/common/lighting/advanced/gl/dbgMetalMapVisualizeP.glsl";
+
+   samplerNames[0] = "matinfoTex";
+   pixVersion = 2.0;
+};
+
+singleton PostEffect( AL_MetalMapVisualize )
+{   
+   shader = AL_MetalMapShader;
+   stateBlock = AL_DefaultVisualizeState;
+   texture[0] = "#matinfo";
+   target = "$backBuffer";
+   renderPriority = 9999;
+};
+
+function toggleMetalMapViz( %enable )
+{   
+   if ( %enable $= "" )
+   {
+      $AL_MetalMapShaderVar = AL_MetalMapVisualize.isEnabled() ? false : true;
+      AL_MetalMapVisualize.toggle();
+   }
+   else if ( %enable )
+      AL_MetalMapVisualize.enable();
+   else if ( !%enable )
+      AL_MetalMapVisualize.disable();    
+}
+
+//Light map display (indirectLighting)
+new ShaderData( AL_LightMapShader )
+{
+   DXVertexShaderFile = "shaders/common/postFx/postFxV.hlsl";
+   DXPixelShaderFile  = "shaders/common/lighting/advanced/dbgLightMapVisualizeP.hlsl";
+
+   OGLVertexShaderFile = "shaders/common/postFx/gl/postFxV.glsl";
+   OGLPixelShaderFile  = "shaders/common/lighting/advanced/gl/dbgLightMapVisualizeP.glsl";
+
+   samplerNames[0] = "specularLightingBuffer";
+   pixVersion = 2.0;
+};
+
+singleton PostEffect( AL_LightMapVisualize )
+{   
+   shader = AL_LightMapShader;
+   stateBlock = AL_DefaultVisualizeState;
+   texture[0] = "#specularLighting";
+   target = "$backBuffer";
+   renderPriority = 9999;
+};
+
+function toggleLightMapViz( %enable )
 {   
 {   
    if ( %enable $= "" )
    if ( %enable $= "" )
    {
    {
-      $AL_SpecMapShaderVar = AL_SpecMapVisualize.isEnabled() ? false : true;
-      AL_SpecMapVisualize.toggle();
+      $AL_LightMapShaderVar = AL_LightMapVisualize.isEnabled() ? false : true;
+      AL_LightMapVisualize.toggle();
    }
    }
    else if ( %enable )
    else if ( %enable )
-      AL_SpecMapVisualize.enable();
+      AL_LightMapVisualize.enable();
    else if ( !%enable )
    else if ( !%enable )
-      AL_SpecMapVisualize.disable();    
+      AL_LightMapVisualize.disable();    
 }
 }
 
 
 new GFXStateBlockData( AL_DepthVisualizeState )
 new GFXStateBlockData( AL_DepthVisualizeState )

+ 5 - 0
Templates/BaseGame/game/tools/worldEditor/scripts/lighting.ed.cs

@@ -61,3 +61,8 @@ function EditorLightingMenu::onMenuSelect( %this )
    //%selSize = EWorldEditor.getSelectionSize();
    //%selSize = EWorldEditor.getSelectionSize();
    %this.enableItem( 1, true /*%selSize == 1*/ );   
    %this.enableItem( 1, true /*%selSize == 1*/ );   
 }
 }
+
+function updateReflectionProbes()
+{
+  Canvas.pushDialog(ProbeBakeDlg);
+}

+ 2 - 0
Templates/BaseGame/game/tools/worldEditor/scripts/menus.ed.cs

@@ -322,6 +322,8 @@ function EditorGui::buildMenus(%this)
       item[0] = "Full Relight" TAB "Alt L" TAB "Editor.lightScene(\"\", forceAlways);";
       item[0] = "Full Relight" TAB "Alt L" TAB "Editor.lightScene(\"\", forceAlways);";
       item[1] = "Toggle ShadowViz" TAB "" TAB "toggleShadowViz();";
       item[1] = "Toggle ShadowViz" TAB "" TAB "toggleShadowViz();";
       item[2] = "-";
       item[2] = "-";
+      item[3] = "Update Reflection Probes" TAB "" TAB "updateReflectionProbes();";
+      item[4] = "-";
          
          
          // NOTE: The light managers will be inserted as the
          // NOTE: The light managers will be inserted as the
          // last menu items in EditorLightingMenu::onAdd().
          // last menu items in EditorLightingMenu::onAdd().

+ 56 - 0
Templates/BaseGame/game/tools/worldEditor/scripts/probeBake.ed.cs

@@ -0,0 +1,56 @@
+function ProbeBakeDlg::onWake(%this)
+{
+   //set up
+   ProbeBakeDlg_ProbeResList.add( "32" );  
+   ProbeBakeDlg_ProbeResList.add( "64" );
+   ProbeBakeDlg_ProbeResList.add( "128" );
+   ProbeBakeDlg_ProbeResList.add( "256" );
+   ProbeBakeDlg_ProbeResList.add( "512" );
+   ProbeBakeDlg_ProbeResList.add( "1024" );
+   ProbeBakeDlg_ProbeResList.add( "2048" );
+   
+   ProbeBakeDlg_ProbeResList.setSelected( 1, false );
+   
+   ProbeBakeDlg_NumIterTxt.setText("1");
+}
+
+function ProbeBakeDlg_RunBake::onClick(%this)
+{
+   %boxProbeIds = parseMissionGroupForIds("BoxEnvironmentProbe", "");
+   %sphereProbeIds = parseMissionGroupForIds("SphereEnvironmentProbe", "");
+   %skylightIds = parseMissionGroupForIds("Skylight", "");
+   
+   %probeIds = rtrim(ltrim(%boxProbeIds SPC %sphereProbeIds));
+   %probeIds = rtrim(ltrim(%probeIds SPC %skylightIds));
+   %probeCount = getWordCount(%probeIds);
+   
+   %numIter = ProbeBakeDlg_NumIterTxt.getText();
+   $pref::ReflectionProbes::BakeResolution = ProbeBakeDlg_ProbeResList.getText();
+   %progressStep = 100 / (%numIter * %probeCount);
+   %currentProgressValue = 0;
+   
+   ProbeBakeDlg_Progress.setValue(%currentProgressValue);
+   Canvas.repaint();
+   
+   for(%iter=0; %iter < %numIter; %iter++)
+   {
+      $pref::ReflectionProbes::RenderWithProbes = false;
+      
+      if(%iter != 0)
+         $pref::ReflectionProbes::RenderWithProbes = true;
+         
+      for(%i=0; %i < %probeCount; %i++)
+      {
+         %probe = getWord(%probeIds, %i);
+         
+         $pref::ReflectionProbes::CurrentLevelPath = filePath($Server::MissionFile) @ "/" @ fileBase($Server::MissionFile) @ "/probes/";
+         ProbeBin.bakeProbe(%probe);
+         
+         %currentProgressValue += %progressStep;
+         ProbeBakeDlg_Progress.setValue(%currentProgressValue);
+         Canvas.repaint();
+      }
+   }
+   
+   EWorldEditor.isDirty = true;
+}

Some files were not shown because too many files changed in this diff