Browse Source

Merge pull request #943 from AtomicGameEngine/JME-ATOMIC-UPDATE

Urho3D 1.6 Update
JoshEngebretson 9 years ago
parent
commit
5faa4c4e2f
100 changed files with 4267 additions and 793 deletions
  1. 33 2
      AUTHORS.md
  2. 11 5
      Build/CIScripts/BuildWeb.js
  3. 193 0
      Build/CMake/Modules/AtomicCommon.cmake
  4. 7 1
      Build/CMake/Modules/AtomicDesktop.cmake
  5. 11 12
      Build/CMake/Modules/AtomicIOS.cmake
  6. 1 1
      Build/CMake/Modules/AtomicMac.cmake
  7. 16 2
      Build/CMake/Modules/AtomicWeb.cmake
  8. 305 259
      Build/CMake/Toolchains/android.toolchain.cmake
  9. 66 40
      Build/CMake/Toolchains/emscripten.toolchain.cmake
  10. 3 3
      CMakeLists.txt
  11. 558 87
      Data/AtomicEditor/Deployment/Android/src/org/libsdl/app/SDLActivity.java
  12. 8 8
      Resources/CoreData/Materials/DefaultGrey.xml
  13. 1 1
      Resources/CoreData/PostProcess/BloomHDR.xml
  14. 30 0
      Resources/CoreData/RenderPaths/ForwardHWDepth.xml
  15. 29 0
      Resources/CoreData/RenderPaths/PBRDeferredHWDepth.xml
  16. 135 0
      Resources/CoreData/RenderPaths/Prepass.xml
  17. 13 13
      Resources/CoreData/Shaders/GLSL/Bloom.glsl
  18. 7 0
      Resources/CoreData/Shaders/GLSL/Constants.glsl
  19. 6 2
      Resources/CoreData/Shaders/GLSL/DeferredLight.glsl
  20. 300 0
      Resources/CoreData/Shaders/GLSL/IBL.glsl
  21. 161 62
      Resources/CoreData/Shaders/GLSL/Lighting.glsl
  22. 6 2
      Resources/CoreData/Shaders/GLSL/LitParticle.glsl
  23. 11 7
      Resources/CoreData/Shaders/GLSL/LitSolid.glsl
  24. 33 0
      Resources/CoreData/Shaders/GLSL/PBR.glsl
  25. 117 0
      Resources/CoreData/Shaders/GLSL/PBRDeferred.glsl
  26. 252 0
      Resources/CoreData/Shaders/GLSL/PBRLitSolid.glsl
  27. 0 6
      Resources/CoreData/Shaders/GLSL/PostProcess.glsl
  28. 6 2
      Resources/CoreData/Shaders/GLSL/PrepassLight.glsl
  29. 6 2
      Resources/CoreData/Shaders/GLSL/Samplers.glsl
  30. 10 3
      Resources/CoreData/Shaders/GLSL/ScreenPos.glsl
  31. 17 4
      Resources/CoreData/Shaders/GLSL/Shadow.glsl
  32. 34 0
      Resources/CoreData/Shaders/GLSL/ShadowBlur.glsl
  33. 5 7
      Resources/CoreData/Shaders/GLSL/Skybox.glsl
  34. 22 0
      Resources/CoreData/Shaders/GLSL/Skydome.glsl
  35. 8 4
      Resources/CoreData/Shaders/GLSL/TerrainBlend.glsl
  36. 79 9
      Resources/CoreData/Shaders/GLSL/Transform.glsl
  37. 29 10
      Resources/CoreData/Shaders/GLSL/Uniforms.glsl
  38. 4 0
      Resources/CoreData/Shaders/GLSL/Unlit.glsl
  39. 23 0
      Resources/CoreData/Shaders/GLSL/Urho2D.glsl
  40. 14 3
      Resources/CoreData/Shaders/GLSL/Vegetation.glsl
  41. 135 0
      Resources/CoreData/Shaders/HLSL/BRDF.hlsl
  42. 8 2
      Resources/CoreData/Shaders/HLSL/Basic.hlsl
  43. 9 9
      Resources/CoreData/Shaders/HLSL/Bloom.hlsl
  44. 22 26
      Resources/CoreData/Shaders/HLSL/Blur.hlsl
  45. 7 0
      Resources/CoreData/Shaders/HLSL/Constants.hlsl
  46. 7 3
      Resources/CoreData/Shaders/HLSL/DeferredLight.hlsl
  47. 9 2
      Resources/CoreData/Shaders/HLSL/Depth.hlsl
  48. 282 0
      Resources/CoreData/Shaders/HLSL/IBL.hlsl
  49. 148 47
      Resources/CoreData/Shaders/HLSL/Lighting.hlsl
  50. 8 5
      Resources/CoreData/Shaders/HLSL/LitParticle.hlsl
  51. 34 49
      Resources/CoreData/Shaders/HLSL/LitSolid.hlsl
  52. 34 0
      Resources/CoreData/Shaders/HLSL/PBR.hlsl
  53. 120 0
      Resources/CoreData/Shaders/HLSL/PBRDeferred.hlsl
  54. 337 0
      Resources/CoreData/Shaders/HLSL/PBRLitSolid.hlsl
  55. 6 2
      Resources/CoreData/Shaders/HLSL/PrepassLight.hlsl
  56. 10 1
      Resources/CoreData/Shaders/HLSL/Samplers.hlsl
  57. 9 2
      Resources/CoreData/Shaders/HLSL/ScreenPos.hlsl
  58. 31 7
      Resources/CoreData/Shaders/HLSL/Shadow.hlsl
  59. 48 0
      Resources/CoreData/Shaders/HLSL/ShadowBlur.hlsl
  60. 6 2
      Resources/CoreData/Shaders/HLSL/Skybox.hlsl
  61. 22 0
      Resources/CoreData/Shaders/HLSL/Skydome.hlsl
  62. 8 5
      Resources/CoreData/Shaders/HLSL/TerrainBlend.hlsl
  63. 71 2
      Resources/CoreData/Shaders/HLSL/Transform.hlsl
  64. 24 6
      Resources/CoreData/Shaders/HLSL/Uniforms.hlsl
  65. 9 3
      Resources/CoreData/Shaders/HLSL/Unlit.hlsl
  66. 27 0
      Resources/CoreData/Shaders/HLSL/Urho2D.hlsl
  67. 43 8
      Resources/CoreData/Shaders/HLSL/Vegetation.hlsl
  68. 18 2
      Resources/CoreData/Shaders/HLSL/VegetationDepth.hlsl
  69. 18 2
      Resources/CoreData/Shaders/HLSL/VegetationShadow.hlsl
  70. 3 0
      Resources/CoreData/Shaders/HLSL/Water.hlsl
  71. 10 0
      Resources/CoreData/Techniques/DiffAlphaMaskTranslucent.xml
  72. 5 0
      Resources/CoreData/Techniques/DiffAlphaTranslucent.xml
  73. 1 1
      Resources/CoreData/Techniques/DiffLightMap.xml
  74. 10 0
      Resources/CoreData/Techniques/DiffNormalAlphaMaskTranslucent.xml
  75. 5 0
      Resources/CoreData/Techniques/DiffNormalAlphaTranslucent.xml
  76. 10 0
      Resources/CoreData/Techniques/DiffNormalPackedAlphaMaskTranslucent.xml
  77. 5 0
      Resources/CoreData/Techniques/DiffNormalPackedAlphaTranslucent.xml
  78. 3 0
      Resources/CoreData/Techniques/DiffSkyboxHDRScale.xml
  79. 3 0
      Resources/CoreData/Techniques/DiffSkydome.xml
  80. 8 0
      Resources/CoreData/Techniques/PBR/DiffNormalSpecEmissive.xml
  81. 5 0
      Resources/CoreData/Techniques/PBR/DiffNormalSpecEmissiveAlpha.xml
  82. 8 0
      Resources/CoreData/Techniques/PBR/PBRDiff.xml
  83. 5 0
      Resources/CoreData/Techniques/PBR/PBRDiffAlpha.xml
  84. 8 0
      Resources/CoreData/Techniques/PBR/PBRDiffNormal.xml
  85. 5 0
      Resources/CoreData/Techniques/PBR/PBRDiffNormalAlpha.xml
  86. 7 0
      Resources/CoreData/Techniques/PBR/PBRDiffNormalEmissive.xml
  87. 5 0
      Resources/CoreData/Techniques/PBR/PBRDiffNormalEmissiveAlpha.xml
  88. 8 0
      Resources/CoreData/Techniques/PBR/PBRMetallicRoughDiffNormalSpec.xml
  89. 8 0
      Resources/CoreData/Techniques/PBR/PBRMetallicRoughDiffNormalSpecEmissive.xml
  90. 5 0
      Resources/CoreData/Techniques/PBR/PBRMetallicRoughDiffNormalSpecEmissiveAlpha.xml
  91. 8 0
      Resources/CoreData/Techniques/PBR/PBRMetallicRoughDiffSpec.xml
  92. 5 0
      Resources/CoreData/Techniques/PBR/PBRMetallicRoughDiffSpecAlpha.xml
  93. 9 0
      Resources/CoreData/Techniques/PBR/PBRNoTexture.xml
  94. 5 0
      Resources/CoreData/Techniques/PBR/PBRNoTextureAlpha.xml
  95. 0 1
      Resources/CoreData/Textures/LUTIdentity.png
  96. 0 2
      Script/AtomicNET/AtomicNET/Core/Constants.cs
  97. 2 1
      Script/Packages/Atomic/Atomic2D.json
  98. 0 43
      Script/Packages/Atomic/Atomic3D.json
  99. 30 2
      Script/Packages/Atomic/Graphics.json
  100. 1 1
      Script/Packages/Atomic/Package.json

+ 33 - 2
AUTHORS.md

@@ -57,9 +57,12 @@ Urho3D development, contributions and bugfixes by:
 - Lasse Öörni ([email protected], AgentC at GameDev.net)
 - Wei Tjong Yao
 - Aster Jian
+- Vivienne Anthony
 - Colin Barrett
 - Erik Beran
+- Loic Blot
 - Danny Boisvert
+- Sergey Bosko
 - Carlo Carollo
 - Pete Chown
 - Christian Clavet
@@ -68,34 +71,52 @@ Urho3D development, contributions and bugfixes by:
 - Chris Friesen
 - Alex Fuller
 - Mika Heinonen
+- Jukka Jylänki
 - Graham King
 - Jason Kinzer
+- Eugene Kozlov
 - Gunnar Kriik
+- Aliaksandr Kryvashein
+- Artem Kulyk
 - Ali Kämäräinen
 - Pete Leigh
+- Frode 'Modanung' Lindeijer
 - Thorbjørn Lindeijer
+- Nathanial Lydick
+- Xavier Maupeu
 - Jonne Nauha
 - Paul Noome
 - David Palacios
 - Alex Parlett
 - Jordan Patterson
+- Anton Petrov
 - Vladimir Pobedinsky
+- Franck Poulain
+- Pranjal Raihan
 - Nick Royer
-- Jonathan Sandusky
 - Miika Santala
+- Anatoly Sennov
+- Bengt Soderstrom
+- Hualin Song
 - James Thomas
 - Joshua Tippetts
+- Yusuf Umar
 - Daniel Wiberg
 - Steven Zhang
+- Rokas Kupstys
 - AGreatFish
+- BlueMagnificent
 - Enhex
 - Firegorilla
+- Lumak
 - Magic.Lixin
 - Mike3D
-- Modanung
 - MonkeyFirst
+- Newb I the Newbd
 - OvermindDL1
 - Skrylar
+- TheComet93
+- Y-way
 - 1vanK
 - andmar1x
 - amadeus_osa
@@ -103,19 +124,29 @@ Urho3D development, contributions and bugfixes by:
 - att
 - celeron55
 - cosmy1
+- damu
+- dragonCASTjosh
 - feltech
+- fredakilla
 - hdunderscore
+- lvshiling
 - marynate
 - mightyCelu
+- neat3d
 - nemerle
 - ninjastone
+- proller
 - raould
 - rasteron
 - reattiva
 - rifai
+- rikorin
 - skaiware
+- ssinai1
+- svifylabs
 - szamq
 - thebluefish
+- tommy3
 - yushli
 
 Urho3D is greatly inspired by OGRE (http://www.ogre3d.org) and Horde3D

+ 11 - 5
Build/CIScripts/BuildWeb.js

@@ -24,13 +24,19 @@ namespace('build', function() {
       atomicTool + " bind " + bcommon.atomicRoot + " Script/Packages/Atomic/ WEB",
       atomicTool + " bind " + bcommon.atomicRoot + " Script/Packages/AtomicPlayer/ WEB",
       "cmake -DEMSCRIPTEN=1 -DCMAKE_TOOLCHAIN_FILE=" + bcommon.atomicRoot + "Build/CMake/Toolchains/emscripten.toolchain.cmake -DCMAKE_BUILD_TYPE=Release ../../../../",
-      "make -j4",
-      "cd ./Source/AtomicPlayer/Application && mv ./AtomicPlayer ./AtomicPlayer.bc && " +
-      // -s ERROR_ON_UNDEFINED_SYMBOLS=1 (disabled for pthread errors currently on incoming)
-      "emcc -O3 -s USE_PTHREADS=0 -s ASM_JS=1 -s VERBOSE=0 -s USE_SDL=2 -s TOTAL_MEMORY=134217728 -s AGGRESSIVE_VARIABLE_ELIMINATION=1 -s NO_EXIT_RUNTIME=1 ./AtomicPlayer.bc -o  ./AtomicPlayer.html"
-
+      "make -j4"
     ]
 
+    // TODO: Verify the follow settings for CI Build
+
+    /*
+
+    "cd ./Source/AtomicPlayer/Application && mv ./AtomicPlayer ./AtomicPlayer.bc && " +
+    // -s ERROR_ON_UNDEFINED_SYMBOLS=1 (disabled for pthread errors currently on incoming)
+    "emcc -O3 -s USE_PTHREADS=0 -s ASM_JS=1 -s VERBOSE=0 -s USE_SDL=2 -s TOTAL_MEMORY=134217728 -s AGGRESSIVE_VARIABLE_ELIMINATION=1 -s NO_EXIT_RUNTIME=1 ./AtomicPlayer.bc -o  ./AtomicPlayer.html"
+
+    */
+
     jake.exec(cmds, function() {
 
       var webPlayerBinary = playerBuildDir + "Source/AtomicPlayer/Application/AtomicPlayer.js";

+ 193 - 0
Build/CMake/Modules/AtomicCommon.cmake

@@ -1,3 +1,29 @@
+#
+# Portions Copyright (c) 2008-2016 the Urho3D project.
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION 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 (CMakeParseArguments)
+
+# Urho compatibility
+add_definitions(-DATOMIC_CXX11=1)
 
 set (CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -DATOMIC_DEBUG")
 set (CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DATOMIC_DEBUG")
@@ -6,6 +32,173 @@ set (ATOMIC_LINK_LIBRARIES ${ATOMIC_LINK_LIBRARIES} AtomicBuildInfo)
 
 if(CMAKE_SIZEOF_VOID_P MATCHES 8)
   set(ATOMIC_PROJECT_ARCH "x86_64")
+  set(ATOMIC_64BIT 1)
+  add_definitions(-DATOMIC_64BIT=1)
 else()
   set(ATOMIC_PROJECT_ARCH "x86")
 endif()
+
+# THIS IS JUST TO KEEP COMPATIBILITY WITH URHO3D CMAKE
+macro (install_header_files)
+
+endmacro()
+
+# Macro for defining source files with optional arguments as follows:
+#  GLOB_CPP_PATTERNS <list> - Use the provided globbing patterns for CPP_FILES instead of the default *.cpp
+#  GLOB_H_PATTERNS <list> - Use the provided globbing patterns for H_FILES instead of the default *.h
+#  EXCLUDE_PATTERNS <list> - Use the provided patterns for excluding matched source files
+#  EXTRA_CPP_FILES <list> - Include the provided list of files into CPP_FILES result
+#  EXTRA_H_FILES <list> - Include the provided list of files into H_FILES result
+#  PCH <list> - Enable precompiled header support on the defined source files using the specified header file, the list is "<path/to/header> [C++|C]"
+#  PARENT_SCOPE - Glob source files in current directory but set the result in parent-scope's variable ${DIR}_CPP_FILES and ${DIR}_H_FILES instead
+#  RECURSE - Option to glob recursively
+#  GROUP - Option to group source files based on its relative path to the corresponding parent directory (only works when PARENT_SCOPE option is not in use)
+macro (define_source_files)
+    # Source files are defined by globbing source files in current source directory and also by including the extra source files if provided
+    cmake_parse_arguments (ARG "PARENT_SCOPE;RECURSE;GROUP" "" "PCH;EXTRA_CPP_FILES;EXTRA_H_FILES;GLOB_CPP_PATTERNS;GLOB_H_PATTERNS;EXCLUDE_PATTERNS" ${ARGN})
+    if (NOT ARG_GLOB_CPP_PATTERNS)
+        set (ARG_GLOB_CPP_PATTERNS *.cpp)    # Default glob pattern
+    endif ()
+    if (NOT ARG_GLOB_H_PATTERNS)
+        set (ARG_GLOB_H_PATTERNS *.h)
+    endif ()
+    if (ARG_RECURSE)
+        set (ARG_RECURSE _RECURSE)
+    else ()
+        unset (ARG_RECURSE)
+    endif ()
+    file (GLOB${ARG_RECURSE} CPP_FILES RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} ${ARG_GLOB_CPP_PATTERNS})
+    file (GLOB${ARG_RECURSE} H_FILES RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} ${ARG_GLOB_H_PATTERNS})
+    if (ARG_EXCLUDE_PATTERNS)
+        set (CPP_FILES_WITH_SENTINEL ";${CPP_FILES};")  # Stringify the lists
+        set (H_FILES_WITH_SENTINEL ";${H_FILES};")
+        foreach (PATTERN ${ARG_EXCLUDE_PATTERNS})
+            foreach (LOOP RANGE 1)
+                string (REGEX REPLACE ";${PATTERN};" ";;" CPP_FILES_WITH_SENTINEL "${CPP_FILES_WITH_SENTINEL}")
+                string (REGEX REPLACE ";${PATTERN};" ";;" H_FILES_WITH_SENTINEL "${H_FILES_WITH_SENTINEL}")
+            endforeach ()
+        endforeach ()
+        set (CPP_FILES ${CPP_FILES_WITH_SENTINEL})      # Convert strings back to lists, extra sentinels are harmless
+        set (H_FILES ${H_FILES_WITH_SENTINEL})
+    endif ()
+    list (APPEND CPP_FILES ${ARG_EXTRA_CPP_FILES})
+    list (APPEND H_FILES ${ARG_EXTRA_H_FILES})
+    set (SOURCE_FILES ${CPP_FILES} ${H_FILES})
+
+    # Optionally enable PCH
+    if (ARG_PCH)
+        enable_pch (${ARG_PCH})
+    endif ()
+
+    # Optionally accumulate source files at parent scope
+    if (ARG_PARENT_SCOPE)
+        get_filename_component (NAME ${CMAKE_CURRENT_SOURCE_DIR} NAME)
+        set (${NAME}_CPP_FILES ${CPP_FILES} PARENT_SCOPE)
+        set (${NAME}_H_FILES ${H_FILES} PARENT_SCOPE)
+    # Optionally put source files into further sub-group (only works when PARENT_SCOPE option is not in use)
+    elseif (ARG_GROUP)
+        foreach (CPP_FILE ${CPP_FILES})
+            get_filename_component (PATH ${CPP_FILE} PATH)
+            if (PATH)
+                string (REPLACE / \\ PATH ${PATH})
+                source_group ("Source Files\\${PATH}" FILES ${CPP_FILE})
+            endif ()
+        endforeach ()
+        foreach (H_FILE ${H_FILES})
+            get_filename_component (PATH ${H_FILE} PATH)
+            if (PATH)
+                string (REPLACE / \\ PATH ${PATH})
+                source_group ("Header Files\\${PATH}" FILES ${H_FILE})
+            endif ()
+        endforeach ()
+    endif ()
+endmacro ()
+
+
+# Macro for setting up dependency lib for compilation and linking of a target
+macro (setup_target)
+    # Include directories
+    include_directories (${INCLUDE_DIRS})
+    # Link libraries
+    target_link_libraries (${TARGET_NAME} ${ABSOLUTE_PATH_LIBS} ${LIBS})
+    # Enable PCH if requested
+    if (${TARGET_NAME}_HEADER_PATHNAME)
+        enable_pch (${${TARGET_NAME}_HEADER_PATHNAME})
+    endif ()
+    # Set additional linker dependencies (only work for Makefile-based generator according to CMake documentation)
+    if (LINK_DEPENDS)
+        string (REPLACE ";" "\;" LINK_DEPENDS "${LINK_DEPENDS}")        # Stringify for string replacement
+        list (APPEND TARGET_PROPERTIES LINK_DEPENDS "${LINK_DEPENDS}")  # Stringify with semicolons already escaped
+        unset (LINK_DEPENDS)
+    endif ()
+    if (TARGET_PROPERTIES)
+        set_target_properties (${TARGET_NAME} PROPERTIES ${TARGET_PROPERTIES})
+        unset (TARGET_PROPERTIES)
+    endif ()
+
+endmacro ()
+
+# Macro for checking the SOURCE_FILES variable is properly initialized
+macro (check_source_files)
+    if (NOT SOURCE_FILES)
+        message (FATAL_ERROR "Could not configure and generate the project file because no source files have been defined yet. "
+            "You can define the source files explicitly by setting the SOURCE_FILES variable in your CMakeLists.txt; or "
+            "by calling the define_source_files() macro which would by default glob all the C++ source files found in the same scope of "
+            "CMakeLists.txt where the macro is being called and the macro would set the SOURCE_FILES variable automatically. "
+            "If your source files are not located in the same directory as the CMakeLists.txt or your source files are "
+            "more than just C++ language then you probably have to pass in extra arguments when calling the macro in order to make it works. "
+            "See the define_source_files() macro definition in the CMake/Modules/Urho3D-CMake-common.cmake for more detail.")
+    endif ()
+endmacro ()
+
+# Macro for setting up a library target
+# Macro arguments:
+#  NODEPS - setup library target without defining Urho3D dependency libraries (applicable for downstream projects)
+#  STATIC/SHARED/MODULE/EXCLUDE_FROM_ALL - see CMake help on add_library() command
+# CMake variables:
+#  SOURCE_FILES - list of source files
+#  INCLUDE_DIRS - list of directories for include search path
+#  LIBS - list of dependent libraries that are built internally in the project
+#  ABSOLUTE_PATH_LIBS - list of dependent libraries that are external to the project
+#  LINK_DEPENDS - list of additional files on which a target binary depends for linking (Makefile-based generator only)
+#  TARGET_PROPERTIES - list of target properties
+macro (setup_library)
+
+    cmake_parse_arguments (ARG NODEPS "" "" ${ARGN})
+    check_source_files ()
+    add_library (${TARGET_NAME} ${ARG_UNPARSED_ARGUMENTS} ${SOURCE_FILES})
+    get_target_property (LIB_TYPE ${TARGET_NAME} TYPE)
+
+    setup_target ()
+
+    # Setup the compiler flags for building shared library
+    if (LIB_TYPE STREQUAL SHARED_LIBRARY)
+        # Hide the symbols that are not explicitly marked for export
+        add_compiler_export_flags ()
+    endif ()
+
+endmacro ()
+
+# Macro for setting up an executable target
+# Macro arguments:
+#  PRIVATE - setup executable target without installing it
+#  TOOL - setup a tool executable target
+#  NODEPS - setup executable target without defining Urho3D dependency libraries
+#  WIN32/MACOSX_BUNDLE/EXCLUDE_FROM_ALL - see CMake help on add_executable() command
+# CMake variables:
+#  SOURCE_FILES - list of source files
+#  INCLUDE_DIRS - list of directories for include search path
+#  LIBS - list of dependent libraries that are built internally in the project
+#  ABSOLUTE_PATH_LIBS - list of dependent libraries that are external to the project
+#  LINK_DEPENDS - list of additional files on which a target binary depends for linking (Makefile-based generator only)
+#  TARGET_PROPERTIES - list of target properties
+macro (setup_executable)
+
+    cmake_parse_arguments (ARG "PRIVATE;TOOL;NODEPS" "" "" ${ARGN})
+    check_source_files ()
+
+    add_executable (${TARGET_NAME} ${ARG_UNPARSED_ARGUMENTS} ${SOURCE_FILES})
+
+    setup_target ()
+
+endmacro ()

+ 7 - 1
Build/CMake/Modules/AtomicDesktop.cmake

@@ -5,7 +5,13 @@ include_directories(${CMAKE_SOURCE_DIR}/Source/ThirdParty/Poco/Foundation/includ
 
 add_definitions( -DATOMIC_PLATFORM_DESKTOP -DATOMIC_NAVIGATION -DATOMIC_TBUI -DATOMIC_FILEWATCHER -DPOCO_NO_AUTOMATIC_LIBS -DPOCO_STATIC )
 
-set (ATOMIC_LINK_LIBRARIES ${ATOMIC_LINK_LIBRARIES} LibCpuId SQLite libsquish)
+set (ATOMIC_LINK_LIBRARIES ${ATOMIC_LINK_LIBRARIES} libsquish)
+
+if (NOT LINUX)
+
+    set (ATOMIC_LINK_LIBRARIES ${ATOMIC_LINK_LIBRARIES} LibCpuId)
+
+endif()
 
 # Check whether the CEF submodule is available
 if (EXISTS ${CMAKE_SOURCE_DIR}/Submodules/CEF)

+ 11 - 12
Build/CMake/Modules/AtomicIOS.cmake

@@ -7,24 +7,23 @@ set (JAVASCRIPT_BINDINGS_PLATFORM "IOS")
 add_definitions (-DIOS -DATOMIC_PLATFORM_IOS -DATOMIC_OPENGL -DKNET_UNIX -DATOMIC_TBUI)
 set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-invalid-offsetof -std=gnu++0x")
 
-# set the architecture for iOS
-#if (${IOS_PLATFORM} STREQUAL "OS")
-#    set (IOS_ARCH armv7 armv7s arm64)
-#elseif (${IOS_PLATFORM} STREQUAL "SIMULATOR")
-#    set (IOS_ARCH i386)
-# elseif (${IOS_PLATFORM} STREQUAL "SIMULATOR64")
-#    set (IOS_ARCH x86_64)
-#endif (${IOS_PLATFORM} STREQUAL "OS")
+set (CMAKE_CROSSCOMPILING TRUE)
+set (CMAKE_XCODE_EFFECTIVE_PLATFORMS -iphoneos -iphonesimulator)
+set (CMAKE_OSX_SYSROOT iphoneos)    # Set Base SDK to "Latest iOS"
+set (CMAKE_XCODE_ATTRIBUTE_CLANG_ENABLE_OBJC_ARC YES)
 
 set (CMAKE_OSX_ARCHITECTURES $(ARCHS_STANDARD_INCLUDING_64_BIT))
-set (CMAKE_XCODE_EFFECTIVE_PLATFORMS -iphoneos -iphonesimulator)
 
-# Set Base SDK to "Latest iOS"
-set (CMAKE_OSX_SYSROOT iphoneos)
+# This is a CMake hack in order to make standard CMake check modules that use try_compile() internally work on iOS platform
+# The injected "flags" are not compiler flags, they are actually CMake variables meant for another CMake subprocess that builds the source file being passed in the try_compile() command
+# CAVEAT: these injected "flags" must always be kept at the end of the string variable, i.e. when adding more compiler flags later on then those new flags must be prepended in front of these flags instead
+set (CMAKE_REQUIRED_FLAGS ";-DSmileyHack=byYaoWT;-DCMAKE_MACOSX_BUNDLE=1;-DCMAKE_XCODE_ATTRIBUTE_CODE_SIGNING_REQUIRED=0")
 
 # Obtain iOS sysroot path
 execute_process (COMMAND xcodebuild -version -sdk ${CMAKE_OSX_SYSROOT} Path OUTPUT_VARIABLE IOS_SYSROOT OUTPUT_STRIP_TRAILING_WHITESPACE)
 
+message (${IOS_SYSROOT})
+
 set (CMAKE_FIND_ROOT_PATH ${IOS_SYSROOT})
 
-set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -framework AudioToolbox -framework CoreAudio -framework CoreGraphics -framework Foundation -framework OpenGLES -framework QuartzCore -framework UIKit")
+set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -framework AudioToolbox -framework CoreAudio -framework CoreGraphics -framework Foundation -framework OpenGLES -framework QuartzCore -framework UIKit -framework CoreMotion -framework GameController")

+ 1 - 1
Build/CMake/Modules/AtomicMac.cmake

@@ -24,4 +24,4 @@ list (APPEND ATOMIC_LINK_LIBRARIES GLEW)
 
 set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-invalid-offsetof -std=gnu++11 -stdlib=libc++")
 
-set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -stdlib=libc++ -framework AudioUnit -framework Carbon -framework Cocoa -framework CoreAudio -framework ForceFeedback -framework IOKit -framework OpenGL -framework CoreServices -framework Security")
+set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -stdlib=libc++ -framework AudioUnit -framework Carbon -framework Cocoa -framework CoreAudio -framework CoreVideo -framework ForceFeedback -framework IOKit -framework OpenGL -framework CoreServices -framework Security")

+ 16 - 2
Build/CMake/Modules/AtomicWeb.cmake

@@ -4,8 +4,22 @@ include(AtomicCommon)
 set (JAVASCRIPT_BINDINGS_PLATFORM "WEB")
 
 add_definitions(-DATOMIC_PLATFORM_WEB)
-add_definitions(-DATOMIC_OPENGL -Wno-warn-absolute-paths -DATOMIC_TBUI)
+add_definitions(-DATOMIC_OPENGL -Wno-warn-absolute-paths -DATOMIC_TBUI -DNO_POPEN)
+
+set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-warn-absolute-paths -Wno-unknown-warning-option")
+set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-invalid-offsetof -std=gnu++0x -Wno-warn-absolute-paths -Wno-unknown-warning-option")
+
+set (CMAKE_EXECUTABLE_SUFFIX_C .html)
+set (CMAKE_EXECUTABLE_SUFFIX_CXX .html)
+
+# Linker flags
+set (MEMORY_LINKER_FLAGS "-s ALLOW_MEMORY_GROWTH=1")
+#set (MEMORY_LINKER_FLAGS "-s TOTAL_MEMORY=${EMSCRIPTEN_TOTAL_MEMORY}")
+
+set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${MEMORY_LINKER_FLAGS} -s NO_EXIT_RUNTIME=1")
+set (CMAKE_EXE_LINKER_FLAGS_RELEASE "${CMAKE_EXE_LINKER_FLAGS_RELEASE} -O3 -s AGGRESSIVE_VARIABLE_ELIMINATION=1")     # Remove variables to make the -O3 regalloc easier
+set (CMAKE_EXE_LINKER_FLAGS_DEBUG "${CMAKE_EXE_LINKER_FLAGS_DEBUG} -g4")     # Preserve LLVM debug information, show line number debug comments, and generate source maps
+
 
-set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-invalid-offsetof -std=gnu++0x")
 
 set (ATOMIC_LINK_LIBRARIES ${ATOMIC_LINK_LIBRARIES})

+ 305 - 259
Build/CMake/Toolchains/android.toolchain.cmake

@@ -29,8 +29,8 @@
 # POSSIBILITY OF SUCH DAMAGE.
 
 # ------------------------------------------------------------------------------
-#  Android CMake toolchain file, for use with the Android NDK r5-r10d
-#  Requires cmake 2.6.3 or newer (2.8.5 or newer is recommended).
+#  Android CMake toolchain file, for use with the Android NDK r5-r12b
+#  Requires cmake 2.6.3 or newer (2.8.9 or newer is recommended).
 #  See home page: https://github.com/taka-no-me/android-cmake
 #
 #  Usage Linux:
@@ -39,12 +39,6 @@
 #   $ cmake -DCMAKE_TOOLCHAIN_FILE=path/to/the/android.toolchain.cmake ..
 #   $ make -j8
 #
-#  Usage Linux (using standalone toolchain):
-#   $ export ANDROID_STANDALONE_TOOLCHAIN=/absolute/path/to/android-toolchain
-#   $ mkdir build && cd build
-#   $ cmake -DCMAKE_TOOLCHAIN_FILE=path/to/the/android.toolchain.cmake ..
-#   $ make -j8
-#
 #  Usage Windows:
 #     You need native port of make to build your project.
 #     Android NDK r7 (and newer) already has make.exe on board.
@@ -63,11 +57,6 @@
 #    ANDROID_NDK=/opt/android-ndk - path to the NDK root.
 #      Can be set as environment variable. Can be set only at first cmake run.
 #
-#    ANDROID_STANDALONE_TOOLCHAIN=/opt/android-toolchain - path to the
-#      standalone toolchain. This option is not used if full NDK is found
-#      (ignored if ANDROID_NDK is set).
-#      Can be set as environment variable. Can be set only at first cmake run.
-#
 #    ANDROID_ABI=armeabi-v7a - specifies the target Application Binary
 #      Interface (ABI). This option nearly matches to the APP_ABI variable
 #      used by ndk-build tool from Android NDK.
@@ -95,36 +84,62 @@
 #
 #    ANDROID_TOOLCHAIN_NAME=arm-linux-androideabi-4.9 - the name of compiler
 #      toolchain to be used. The list of possible values depends on the NDK
-#      version. For NDK r10c the possible values are:
+#      version.
+#
+#      For NDK r12b the possible values are:
+#
+#        * aarch64-linux-android-4.9
+#        * aarch64-linux-android-clang
+#        * arm-linux-androideabi-4.9 (default)
+#        * arm-linux-androideabi-clang
+#        * mips64el-linux-android-4.9
+#        * mips64el-linux-android-clang
+#        * mipsel-linux-android-4.9
+#        * mipsel-linux-android-clang
+#        * x86-4.9
+#        * x86-clang
+#        * x86_64-4.9
+#        * x86_64-clang
+#
+#      For NDK r11c the possible values are:
+#
+#        * aarch64-linux-android-4.9
+#        * aarch64-linux-android-clang3.6 (it is actually Clang 3.8)
+#        * arm-linux-androideabi-4.9 (default)
+#        * arm-linux-androideabi-clang3.6 (it is actually Clang 3.8)
+#        * mips64el-linux-android-4.9
+#        * mips64el-linux-android-clang3.6 (it is actually Clang 3.8)
+#        * mipsel-linux-android-4.9
+#        * mipsel-linux-android-clang3.6 (it is actually Clang 3.8)
+#        * x86-4.9
+#        * x86-clang3.6 (it is actually Clang 3.8)
+#        * x86_64-4.9
+#        * x86_64-clang3.6 (it is actually Clang 3.8)
+#
+#      For NDK r10e the possible values are:
 #
 #        * aarch64-linux-android-4.9
-#        * aarch64-linux-android-clang3.4
 #        * aarch64-linux-android-clang3.5
-#        * arm-linux-androideabi-4.6
-#        * arm-linux-androideabi-4.8
+#        * aarch64-linux-android-clang3.6
 #        * arm-linux-androideabi-4.9 (default)
-#        * arm-linux-androideabi-clang3.4
 #        * arm-linux-androideabi-clang3.5
+#        * arm-linux-androideabi-clang3.6
 #        * mips64el-linux-android-4.9
-#        * mips64el-linux-android-clang3.4
 #        * mips64el-linux-android-clang3.5
-#        * mipsel-linux-android-4.6
-#        * mipsel-linux-android-4.8
+#        * mips64el-linux-android-clang3.6
 #        * mipsel-linux-android-4.9
-#        * mipsel-linux-android-clang3.4
 #        * mipsel-linux-android-clang3.5
-#        * x86-4.6
-#        * x86-4.8
+#        * mipsel-linux-android-clang3.6
 #        * x86-4.9
-#        * x86-clang3.4
 #        * x86-clang3.5
+#        * x86-clang3.6
 #        * x86_64-4.9
-#        * x86_64-clang3.4
 #        * x86_64-clang3.5
+#        * x86_64-clang3.6
 #
 #    ANDROID_FORCE_ARM_BUILD=OFF - set ON to generate 32-bit ARM instructions
-#      instead of Thumb. Is not available for "x86" (inapplicable) and
-#      "armeabi-v6 with VFP" (is forced to be ON) ABIs.
+#      instead of Thumb. Is not available for "armeabi-v6 with VFP"
+#      (is forced to be ON) ABI.
 #
 #    ANDROID_NO_UNDEFINED=ON - set ON to show all undefined symbols as linker
 #      errors even if they are not used.
@@ -133,13 +148,6 @@
 #      libraries. Automatically turned for NDK r5x and r6x due to GLESv2
 #      problems.
 #
-#    LIBRARY_OUTPUT_PATH_ROOT=${CMAKE_SOURCE_DIR} - where to output binary
-#      files. See additional details below.
-#
-#    ANDROID_SET_OBSOLETE_VARIABLES=ON - if set, then toolchain defines some
-#      obsolete variables which were used by previous versions of this file for
-#      backward compatibility.
-#
 #    ANDROID_STL=gnustl_static - specify the runtime to use.
 #
 #      Possible values are:
@@ -172,6 +180,10 @@
 #                          Implies -frtti -fno-exceptions.
 #                          Available for NDK r7b and newer.
 #                          Silently degrades to gnustl_static if not available.
+#        c++_static     -> Use the LLVM libc++ runtime as a static library.
+#                          Implies -frtti -fexceptions.
+#        c++_shared     -> Use the LLVM libc++ runtime as a shared library.
+#                          Implies -frtti -fexceptions.
 #
 #    ANDROID_STL_FORCE_FEATURES=ON - turn rtti and exceptions support based on
 #      chosen runtime. If disabled, then the user is responsible for settings
@@ -200,29 +212,22 @@
 #    will be set true, mutually exclusive. NEON option will be set true
 #    if VFP is set to NEON.
 #
-#    LIBRARY_OUTPUT_PATH_ROOT should be set in cache to determine where Android
-#    libraries will be installed.
-#    Default is ${CMAKE_SOURCE_DIR}, and the android libs will always be
-#    under the ${LIBRARY_OUTPUT_PATH_ROOT}/libs/${ANDROID_NDK_ABI_NAME}
-#    (depending on the target ABI). This is convenient for Android packaging.
-#
 # ------------------------------------------------------------------------------
 
 # Modified by Lasse Oorni and Yao Wei Tjong for Urho3D
 
 cmake_minimum_required( VERSION 2.6.3 )
 
+if( DEFINED CMAKE_CROSSCOMPILING )
+ return()
+endif()
+
 # Urho3D: on Windows Cygwin-based NDK tools may fail in the linking phase with too long command line. Turn on response files to avoid this
 if( CMAKE_HOST_WIN32 )
  set( CMAKE_C_USE_RESPONSE_FILE_FOR_OBJECTS 1 )
  set( CMAKE_CXX_USE_RESPONSE_FILE_FOR_OBJECTS 1 )
 endif()
 
-if( DEFINED CMAKE_CROSSCOMPILING )
- # subsequent toolchain loading is not really needed
- return()
-endif()
-
 if( CMAKE_TOOLCHAIN_FILE )
  # touch toolchain variable to suppress "unused variable" warning
 endif()
@@ -243,22 +248,22 @@ endif()
 # this one not so much
 set( CMAKE_SYSTEM_VERSION 1 )
 
-# rpath makes low sence for Android
+# rpath makes low sense for Android
 set( CMAKE_SHARED_LIBRARY_RUNTIME_C_FLAG "" )
 set( CMAKE_SKIP_RPATH TRUE CACHE BOOL "If set, runtime paths are not added when using shared libraries." )
 
 # NDK search paths
-set( ANDROID_SUPPORTED_NDK_VERSIONS ${ANDROID_EXTRA_NDK_VERSIONS} -r10d -r10c -r10b -r10 -r9d -r9c -r9b -r9 -r8e -r8d -r8c -r8b -r8 -r7c -r7b -r7 -r6b -r6 -r5c -r5b -r5 "" )
-if(NOT DEFINED ANDROID_NDK_SEARCH_PATHS)
+set( ANDROID_SUPPORTED_NDK_VERSIONS ${ANDROID_EXTRA_NDK_VERSIONS} -r12b -r11c -r11b -r11 -r10e -r10d -r10c -r10b -r10 -r9d -r9c -r9b -r9 -r8e -r8d -r8c -r8b -r8 -r7c -r7b -r7 -r6b -r6 -r5c -r5b -r5 "" )
+if( NOT DEFINED ANDROID_NDK_SEARCH_PATHS )
  if( CMAKE_HOST_WIN32 )
   file( TO_CMAKE_PATH "$ENV{PROGRAMFILES}" ANDROID_NDK_SEARCH_PATHS )
-  set( ANDROID_NDK_SEARCH_PATHS "${ANDROID_NDK_SEARCH_PATHS}/android-ndk" "$ENV{SystemDrive}/NVPACK/android-ndk" )
+  set( ANDROID_NDK_SEARCH_PATHS "${ANDROID_NDK_SEARCH_PATHS}" "$ENV{SystemDrive}/NVPACK" )
  else()
   file( TO_CMAKE_PATH "$ENV{HOME}" ANDROID_NDK_SEARCH_PATHS )
-  set( ANDROID_NDK_SEARCH_PATHS /opt/android-ndk "${ANDROID_NDK_SEARCH_PATHS}/NVPACK/android-ndk" )
+  set( ANDROID_NDK_SEARCH_PATHS /opt "${ANDROID_NDK_SEARCH_PATHS}/NVPACK" )
  endif()
 endif()
-if(NOT DEFINED ANDROID_STANDALONE_TOOLCHAIN_SEARCH_PATH)
+if( NOT DEFINED ANDROID_STANDALONE_TOOLCHAIN_SEARCH_PATH )
  set( ANDROID_STANDALONE_TOOLCHAIN_SEARCH_PATH /opt/android-toolchain )
 endif()
 
@@ -271,116 +276,100 @@ set( ANDROID_SUPPORTED_ABIS_mips "mips" )
 set( ANDROID_SUPPORTED_ABIS_mips64 "mips64" )
 
 # API level defaults
-# Urho3D: default to API 12
-set( ANDROID_DEFAULT_NDK_API_LEVEL 12 )
+# Urho3D: default to API 9
+set( ANDROID_DEFAULT_NDK_API_LEVEL 9 )
 set( ANDROID_DEFAULT_NDK_API_LEVEL_arm64 21 )
-set( ANDROID_DEFAULT_NDK_API_LEVEL_x86 12)
+set( ANDROID_DEFAULT_NDK_API_LEVEL_x86 9 )
 set( ANDROID_DEFAULT_NDK_API_LEVEL_x86_64 21 )
-set( ANDROID_DEFAULT_NDK_API_LEVEL_mips 12 )
+set( ANDROID_DEFAULT_NDK_API_LEVEL_mips 9 )
 set( ANDROID_DEFAULT_NDK_API_LEVEL_mips64 21 )
 
 
 macro( __LIST_FILTER listvar regex )
- if( ${listvar} )
-  foreach( __val ${${listvar}} )
-   if( __val MATCHES "${regex}" )
-    list( REMOVE_ITEM ${listvar} "${__val}" )
-   endif()
-  endforeach()
- endif()
+  if( ${listvar} )
+    foreach( __val ${${listvar}} )
+      if( __val MATCHES "${regex}" )
+        list( REMOVE_ITEM ${listvar} "${__val}" )
+      endif()
+    endforeach()
+  endif()
 endmacro()
 
 macro( __INIT_VARIABLE var_name )
- set( __test_path 0 )
- foreach( __var ${ARGN} )
-  if( __var STREQUAL "PATH" )
-   set( __test_path 1 )
-   break()
-  endif()
- endforeach()
- if( __test_path AND NOT EXISTS "${${var_name}}" )
-  unset( ${var_name} CACHE )
- endif()
- if( "${${var_name}}" STREQUAL "" )
-  set( __values 0 )
+  set( __test_path 0 )
   foreach( __var ${ARGN} )
-   if( __var STREQUAL "VALUES" )
-    set( __values 1 )
-   elseif( NOT __var STREQUAL "PATH" )
-    set( __obsolete 0 )
-    if( __var MATCHES "^OBSOLETE_.*$" )
-     string( REPLACE "OBSOLETE_" "" __var "${__var}" )
-     set( __obsolete 1 )
-    endif()
-    if( __var MATCHES "^ENV_.*$" )
-     string( REPLACE "ENV_" "" __var "${__var}" )
-     set( __value "$ENV{${__var}}" )
-    elseif( DEFINED ${__var} )
-     set( __value "${${__var}}" )
-    else()
-     if( __values )
-      set( __value "${__var}" )
-     else()
-      set( __value "" )
-     endif()
-    endif()
-    if( NOT "${__value}" STREQUAL "" )
-     if( __test_path )
-      if( EXISTS "${__value}" )
-       file( TO_CMAKE_PATH "${__value}" ${var_name} )
-       if( __obsolete AND NOT _CMAKE_IN_TRY_COMPILE )
-        message( WARNING "Using value of obsolete variable ${__var} as initial value for ${var_name}. Please note, that ${__var} can be completely removed in future versions of the toolchain." )
-       endif()
-       break()
-      endif()
-     else()
-      set( ${var_name} "${__value}" )
-       if( __obsolete AND NOT _CMAKE_IN_TRY_COMPILE )
-        message( WARNING "Using value of obsolete variable ${__var} as initial value for ${var_name}. Please note, that ${__var} can be completely removed in future versions of the toolchain." )
-       endif()
+    if( __var STREQUAL PATH )   # Urho3D: avoid CMP0054 warning
+      set( __test_path 1 )
       break()
-     endif()
     endif()
-   endif()
   endforeach()
-  unset( __value )
-  unset( __values )
-  unset( __obsolete )
- elseif( __test_path )
-  file( TO_CMAKE_PATH "${${var_name}}" ${var_name} )
- endif()
- unset( __test_path )
+
+  if( __test_path AND NOT EXISTS "${${var_name}}" )
+    unset( ${var_name} CACHE )
+  endif()
+
+  if( " ${${var_name}}" STREQUAL " " )
+    set( __values 0 )
+    foreach( __var ${ARGN} )
+      if( __var STREQUAL "VALUES" )
+        set( __values 1 )
+      elseif( NOT __var STREQUAL PATH )      # Urho3D: avoid CMP0054 warning
+        if( __var MATCHES "^ENV_.*$" )
+          string( REPLACE "ENV_" "" __var "${__var}" )
+          set( __value "$ENV{${__var}}" )
+        elseif( DEFINED ${__var} )
+          set( __value "${${__var}}" )
+        elseif( __values )
+          set( __value "${__var}" )
+        else()
+          set( __value "" )
+        endif()
+
+        if( NOT " ${__value}" STREQUAL " " AND (NOT __test_path OR EXISTS "${__value}") )
+          set( ${var_name} "${__value}" )
+          break()
+        endif()
+      endif()
+    endforeach()
+    unset( __value )
+    unset( __values )
+  endif()
+
+  if( __test_path )
+    file( TO_CMAKE_PATH "${${var_name}}" ${var_name} )
+  endif()
+  unset( __test_path )
 endmacro()
 
 macro( __DETECT_NATIVE_API_LEVEL _var _path )
- SET( __ndkApiLevelRegex "^[\t ]*#define[\t ]+__ANDROID_API__[\t ]+([0-9]+)[\t ]*.*$" )
- FILE( STRINGS ${_path} __apiFileContent REGEX "${__ndkApiLevelRegex}" )
- if( NOT __apiFileContent )
-  message( SEND_ERROR "Could not get Android native API level. Probably you have specified invalid level value, or your copy of NDK/toolchain is broken." )
- endif()
- string( REGEX REPLACE "${__ndkApiLevelRegex}" "\\1" ${_var} "${__apiFileContent}" )
- unset( __apiFileContent )
- unset( __ndkApiLevelRegex )
+  set( __ndkApiLevelRegex "^[\t ]*#define[\t ]+__ANDROID_API__[\t ]+([0-9]+)[\t ]*.*$" )
+  file( STRINGS ${_path} __apiFileContent REGEX "${__ndkApiLevelRegex}" )
+  if( NOT __apiFileContent )
+    message( SEND_ERROR "Could not get Android native API level. Probably you have specified invalid level value, or your copy of NDK/toolchain is broken." )
+  endif()
+  string( REGEX REPLACE "${__ndkApiLevelRegex}" "\\1" ${_var} "${__apiFileContent}" )
+  unset( __apiFileContent )
+  unset( __ndkApiLevelRegex )
 endmacro()
 
 macro( __DETECT_TOOLCHAIN_MACHINE_NAME _var _root )
  if( EXISTS "${_root}" )
-  file( GLOB __gccExePath RELATIVE "${_root}/bin/" "${_root}/bin/*-gcc${TOOL_OS_SUFFIX}" )
-  __LIST_FILTER( __gccExePath "^[.].*" )
-  list( LENGTH __gccExePath __gccExePathsCount )
-  if( NOT __gccExePathsCount EQUAL 1  AND NOT _CMAKE_IN_TRY_COMPILE )
-   message( WARNING "Could not determine machine name for compiler from ${_root}" )
-   set( ${_var} "" )
+    file( GLOB __gccExePath RELATIVE "${_root}/bin/" "${_root}/bin/*-gcc${TOOL_OS_SUFFIX}" )
+    __LIST_FILTER( __gccExePath "^[.].*" )
+    list( LENGTH __gccExePath __gccExePathsCount )
+    if( NOT __gccExePathsCount EQUAL 1  AND NOT _CMAKE_IN_TRY_COMPILE )
+      message( WARNING "Could not determine machine name for compiler from ${_root}" )
+      set( ${_var} "" )
+    else()
+      get_filename_component( __gccExeName "${__gccExePath}" NAME_WE )
+      string( REPLACE "-gcc" "" ${_var} "${__gccExeName}" )
+    endif()
+    unset( __gccExePath )
+    unset( __gccExePathsCount )
+    unset( __gccExeName )
   else()
-   get_filename_component( __gccExeName "${__gccExePath}" NAME_WE )
-   string( REPLACE "-gcc" "" ${_var} "${__gccExeName}" )
+    set( ${_var} "" )
   endif()
-  unset( __gccExePath )
-  unset( __gccExePathsCount )
-  unset( __gccExeName )
- else()
-  set( ${_var} "" )
- endif()
 endmacro()
 
 
@@ -428,17 +417,19 @@ if( NOT ANDROID_NDK_HOST_X64 )
 endif()
 
 # see if we have path to Android NDK
-__INIT_VARIABLE( ANDROID_NDK PATH ENV_ANDROID_NDK )
+if( NOT ANDROID_NDK AND NOT ANDROID_STANDALONE_TOOLCHAIN )
+  __INIT_VARIABLE( ANDROID_NDK PATH ENV_ANDROID_NDK )
+endif()
 if( NOT ANDROID_NDK )
  # see if we have path to Android standalone toolchain
- __INIT_VARIABLE( ANDROID_STANDALONE_TOOLCHAIN PATH ENV_ANDROID_STANDALONE_TOOLCHAIN OBSOLETE_ANDROID_NDK_TOOLCHAIN_ROOT OBSOLETE_ENV_ANDROID_NDK_TOOLCHAIN_ROOT )
+ __INIT_VARIABLE( ANDROID_STANDALONE_TOOLCHAIN PATH ENV_ANDROID_STANDALONE_TOOLCHAIN )
 
  if( NOT ANDROID_STANDALONE_TOOLCHAIN )
   #try to find Android NDK in one of the the default locations
   set( __ndkSearchPaths )
   foreach( __ndkSearchPath ${ANDROID_NDK_SEARCH_PATHS} )
    foreach( suffix ${ANDROID_SUPPORTED_NDK_VERSIONS} )
-    list( APPEND __ndkSearchPaths "${__ndkSearchPath}${suffix}" )
+    list( APPEND __ndkSearchPaths "${__ndkSearchPath}/android-ndk${suffix}" )
    endforeach()
   endforeach()
   __INIT_VARIABLE( ANDROID_NDK PATH VALUES ${__ndkSearchPaths} )
@@ -464,16 +455,19 @@ if( ANDROID_NDK )
  get_filename_component( ANDROID_NDK "${ANDROID_NDK}" ABSOLUTE )
  set( ANDROID_NDK "${ANDROID_NDK}" CACHE INTERNAL "Path of the Android NDK" FORCE )
  set( BUILD_WITH_ANDROID_NDK True )
- if( EXISTS "${ANDROID_NDK}/RELEASE.TXT" )
-  file( STRINGS "${ANDROID_NDK}/RELEASE.TXT" ANDROID_NDK_RELEASE_FULL LIMIT_COUNT 1 REGEX "r[0-9]+[a-z]?" )
-  string( REGEX MATCH "r([0-9]+)([a-z]?)" ANDROID_NDK_RELEASE "${ANDROID_NDK_RELEASE_FULL}" )
+ # Urho3D - major refactoring on how the NDK release and version are being captured
+ if( EXISTS "${ANDROID_NDK}/RELEASE.TXT" )  # Prior to r11
+  file( STRINGS "${ANDROID_NDK}/RELEASE.TXT" __line LIMIT_COUNT 1 REGEX "r[0-9]+[a-z]?" )
+  string( REGEX MATCH "r([0-9]+)([a-z]?)" ANDROID_NDK_RELEASE "${__line}" )
+  string( FIND " abcdefghijklmnopqastuvwxyz" ${CMAKE_MATCH_2} __index )
+  set( ANDROID_NDK_VERSION ${CMAKE_MATCH_1}.${__index}.0 )
+ elseif( EXISTS "${ANDROID_NDK}/source.properties" )    # r11 onward
+  file( STRINGS "${ANDROID_NDK}/source.properties" __line LIMIT_COUNT 1 REGEX "[0-9]+\\.[0-9]+\\.[0-9]+" )
+  string( REGEX MATCH "[0-9]+\\.[0-9]+\\.[0-9]+" ANDROID_NDK_VERSION "${__line}" )
+  set( ANDROID_NDK_RELEASE r${ANDROID_NDK_VERSION} )
  else()
-  set( ANDROID_NDK_RELEASE "r1x" )
-  set( ANDROID_NDK_RELEASE_FULL "unreleased" )
+  message( FATAL_ERROR "Unrecognized Android NDK release" )
  endif()
- string( REGEX REPLACE "r([0-9]+)([a-z]?)" "\\1*1000" ANDROID_NDK_RELEASE_NUM "${ANDROID_NDK_RELEASE}" )
- string( FIND " abcdefghijklmnopqastuvwxyz" "${CMAKE_MATCH_2}" __ndkReleaseLetterNum )
- math( EXPR ANDROID_NDK_RELEASE_NUM "${ANDROID_NDK_RELEASE_NUM}+${__ndkReleaseLetterNum}" )
 elseif( ANDROID_STANDALONE_TOOLCHAIN )
  get_filename_component( ANDROID_STANDALONE_TOOLCHAIN "${ANDROID_STANDALONE_TOOLCHAIN}" ABSOLUTE )
  # try to detect change
@@ -496,7 +490,7 @@ else()
     or
       export ANDROID_STANDALONE_TOOLCHAIN=~/my-android-toolchain
     or put the toolchain or NDK in the default path:
-      sudo ln -s ~/my-android-ndk ${ANDROID_NDK_SEARCH_PATH}
+      sudo ln -s ~/my-android-ndk ${ANDROID_NDK_SEARCH_PATH}/android-ndk
       sudo ln -s ~/my-android-toolchain ${ANDROID_STANDALONE_TOOLCHAIN_SEARCH_PATH}" )
 endif()
 
@@ -504,22 +498,25 @@ endif()
 if( BUILD_WITH_ANDROID_NDK )
  if( NOT DEFINED ANDROID_NDK_LAYOUT )
   # try to automatically detect the layout
-  if( EXISTS "${ANDROID_NDK}/RELEASE.TXT")
-   set( ANDROID_NDK_LAYOUT "RELEASE" )
+  if( EXISTS "${ANDROID_NDK}/RELEASE.TXT" )
+   set( ANDROID_NDK_LAYOUT RELEASE )
+  # Urho3D - new NDK layout after r11
+  elseif( EXISTS "${ANDROID_NDK}/source.properties" )
+   set( ANDROID_NDK_LAYOUT RELEASE2 )
   elseif( EXISTS "${ANDROID_NDK}/../../linux-x86/toolchain/" )
-   set( ANDROID_NDK_LAYOUT "LINARO" )
+   set( ANDROID_NDK_LAYOUT LINARO )
   elseif( EXISTS "${ANDROID_NDK}/../../gcc/" )
-   set( ANDROID_NDK_LAYOUT "ANDROID" )
+   set( ANDROID_NDK_LAYOUT ANDROID )
   endif()
  endif()
  set( ANDROID_NDK_LAYOUT "${ANDROID_NDK_LAYOUT}" CACHE STRING "The inner layout of NDK" )
  mark_as_advanced( ANDROID_NDK_LAYOUT )
- if( ANDROID_NDK_LAYOUT STREQUAL "LINARO" )
+ if( ANDROID_NDK_LAYOUT STREQUAL LINARO )
   set( ANDROID_NDK_HOST_SYSTEM_NAME ${ANDROID_NDK_HOST_SYSTEM_NAME2} ) # only 32-bit at the moment
   set( ANDROID_NDK_TOOLCHAINS_PATH "${ANDROID_NDK}/../../${ANDROID_NDK_HOST_SYSTEM_NAME}/toolchain" )
   set( ANDROID_NDK_TOOLCHAINS_SUBPATH  "" )
   set( ANDROID_NDK_TOOLCHAINS_SUBPATH2 "" )
- elseif( ANDROID_NDK_LAYOUT STREQUAL "ANDROID" )
+ elseif( ANDROID_NDK_LAYOUT STREQUAL ANDROID )      # Urho3D: avoid CMP0054 warning
   set( ANDROID_NDK_HOST_SYSTEM_NAME ${ANDROID_NDK_HOST_SYSTEM_NAME2} ) # only 32-bit at the moment
   set( ANDROID_NDK_TOOLCHAINS_PATH "${ANDROID_NDK}/../../gcc/${ANDROID_NDK_HOST_SYSTEM_NAME}/arm" )
   set( ANDROID_NDK_TOOLCHAINS_SUBPATH  "" )
@@ -529,6 +526,11 @@ if( BUILD_WITH_ANDROID_NDK )
   set( ANDROID_NDK_TOOLCHAINS_SUBPATH  "/prebuilt/${ANDROID_NDK_HOST_SYSTEM_NAME}" )
   set( ANDROID_NDK_TOOLCHAINS_SUBPATH2 "/prebuilt/${ANDROID_NDK_HOST_SYSTEM_NAME2}" )
  endif()
+ if( ANDROID_NDK_LAYOUT STREQUAL RELEASE2 )
+  set( ANDROID_NDK_TOOLCHAINS_CONFIG_PATH ${ANDROID_NDK}/build/core/toolchains )
+ else()
+  set( ANDROID_NDK_TOOLCHAINS_CONFIG_PATH ${ANDROID_NDK_TOOLCHAINS_PATH} )
+ endif()
  get_filename_component( ANDROID_NDK_TOOLCHAINS_PATH "${ANDROID_NDK_TOOLCHAINS_PATH}" ABSOLUTE )
 
  # try to detect change of NDK
@@ -580,14 +582,21 @@ endif()
 
 macro( __GLOB_NDK_TOOLCHAINS __availableToolchainsVar __availableToolchainsLst __toolchain_subpath )
  foreach( __toolchain ${${__availableToolchainsLst}} )
-  if( "${__toolchain}" MATCHES "-clang3[.][0-9]$" AND NOT EXISTS "${ANDROID_NDK_TOOLCHAINS_PATH}/${__toolchain}${__toolchain_subpath}" )
+  # Urho3D - add support for r12b which drops the Clang version number from the toolchain name
+  if( "${__toolchain}" MATCHES "-clang.*$" AND NOT EXISTS "${ANDROID_NDK_TOOLCHAINS_PATH}/${__toolchain}${__toolchain_subpath}" )
    SET( __toolchainVersionRegex "^TOOLCHAIN_VERSION[\t ]+:=[\t ]+(.*)$" )
-   FILE( STRINGS "${ANDROID_NDK_TOOLCHAINS_PATH}/${__toolchain}/setup.mk" __toolchainVersionStr REGEX "${__toolchainVersionRegex}" )
+   FILE( STRINGS "${ANDROID_NDK_TOOLCHAINS_CONFIG_PATH}/${__toolchain}/setup.mk" __toolchainVersionStr REGEX "${__toolchainVersionRegex}" )
    if( __toolchainVersionStr )
     string( REGEX REPLACE "${__toolchainVersionRegex}" "\\1" __toolchainVersionStr "${__toolchainVersionStr}" )
-    string( REGEX REPLACE "-clang3[.][0-9]$" "-${__toolchainVersionStr}" __gcc_toolchain "${__toolchain}" )
+    string( REGEX REPLACE "-clang.*$" "-${__toolchainVersionStr}" __gcc_toolchain "${__toolchain}" )
    else()
-    string( REGEX REPLACE "-clang3[.][0-9]$" "-4.6" __gcc_toolchain "${__toolchain}" )
+    # Urho3D - fallback to use the latest GCC toolchain available
+    foreach( __gcc_ver 4.9 4.8 4.6 )
+     string( REGEX REPLACE -clang.*$ -${__gcc_ver} __gcc_toolchain "${__toolchain}" )
+     if( EXISTS "${ANDROID_NDK_TOOLCHAINS_PATH}/${__gcc_toolchain}" )
+      break()
+     endif()
+    endforeach()
    endif()
    unset( __toolchainVersionStr )
    unset( __toolchainVersionRegex )
@@ -632,7 +641,7 @@ if( BUILD_WITH_ANDROID_NDK )
  set( __availableToolchainMachines "" )
  set( __availableToolchainArchs "" )
  set( __availableToolchainCompilerVersions "" )
- if( ANDROID_TOOLCHAIN_NAME AND EXISTS "${ANDROID_NDK_TOOLCHAINS_PATH}/${ANDROID_TOOLCHAIN_NAME}/" )
+ if( ANDROID_TOOLCHAIN_NAME AND EXISTS "${ANDROID_NDK_TOOLCHAINS_CONFIG_PATH}/${ANDROID_TOOLCHAIN_NAME}/" )
   # do not go through all toolchains if we know the name
   set( __availableToolchainsLst "${ANDROID_TOOLCHAIN_NAME}" )
   __GLOB_NDK_TOOLCHAINS( __availableToolchains __availableToolchainsLst "${ANDROID_NDK_TOOLCHAINS_SUBPATH}" )
@@ -644,7 +653,7 @@ if( BUILD_WITH_ANDROID_NDK )
   endif()
  endif()
  if( NOT __availableToolchains )
-  file( GLOB __availableToolchainsLst RELATIVE "${ANDROID_NDK_TOOLCHAINS_PATH}" "${ANDROID_NDK_TOOLCHAINS_PATH}/*" )
+  file( GLOB __availableToolchainsLst RELATIVE "${ANDROID_NDK_TOOLCHAINS_CONFIG_PATH}" "${ANDROID_NDK_TOOLCHAINS_CONFIG_PATH}/*" )
   # Urho3D: bug fix - remove redundant if check which prevented the sort to take place
   list(SORT __availableToolchainsLst) # we need clang to go after gcc
   __LIST_FILTER( __availableToolchainsLst "^[.]" )
@@ -677,7 +686,7 @@ if( NOT ANDROID_SUPPORTED_ABIS )
 endif()
 
 # choose target ABI
-__INIT_VARIABLE( ANDROID_ABI OBSOLETE_ARM_TARGET OBSOLETE_ARM_TARGETS VALUES ${ANDROID_SUPPORTED_ABIS} )
+__INIT_VARIABLE( ANDROID_ABI VALUES ${ANDROID_SUPPORTED_ABIS} )
 # verify that target ABI is supported
 list( FIND ANDROID_SUPPORTED_ABIS "${ANDROID_ABI}" __androidAbiIdx )
 if( __androidAbiIdx EQUAL -1 )
@@ -768,7 +777,7 @@ if( CMAKE_BINARY_DIR AND EXISTS "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMa
 endif()
 
 if( ANDROID_ARCH_NAME STREQUAL "arm" AND NOT ARMEABI_V6 )
- __INIT_VARIABLE( ANDROID_FORCE_ARM_BUILD OBSOLETE_FORCE_ARM VALUES OFF )
+ __INIT_VARIABLE( ANDROID_FORCE_ARM_BUILD VALUES OFF )
  set( ANDROID_FORCE_ARM_BUILD ${ANDROID_FORCE_ARM_BUILD} CACHE BOOL "Use 32-bit ARM instructions instead of Thumb-1" FORCE )
  mark_as_advanced( ANDROID_FORCE_ARM_BUILD )
 else()
@@ -877,23 +886,14 @@ endif()
 
 # runtime choice (STL, rtti, exceptions)
 if( NOT ANDROID_STL )
- # honor legacy ANDROID_USE_STLPORT
- if( DEFINED ANDROID_USE_STLPORT )
-  if( ANDROID_USE_STLPORT )
-   set( ANDROID_STL stlport_static )
-  endif()
-  message( WARNING "You are using an obsolete variable ANDROID_USE_STLPORT to select the STL variant. Use -DANDROID_STL=stlport_static instead." )
- endif()
- if( NOT ANDROID_STL )
   set( ANDROID_STL gnustl_static )
- endif()
 endif()
 set( ANDROID_STL "${ANDROID_STL}" CACHE STRING "C++ runtime" )
 set( ANDROID_STL_FORCE_FEATURES ON CACHE BOOL "automatically configure rtti and exceptions support based on C++ runtime" )
 mark_as_advanced( ANDROID_STL ANDROID_STL_FORCE_FEATURES )
 
 if( BUILD_WITH_ANDROID_NDK )
- if( NOT "${ANDROID_STL}" MATCHES "^(none|system|system_re|gabi\\+\\+_static|gabi\\+\\+_shared|stlport_static|stlport_shared|gnustl_static|gnustl_shared)$")
+ if( NOT "${ANDROID_STL}" MATCHES "^(none|system|system_re|gabi\\+\\+_static|gabi\\+\\+_shared|stlport_static|stlport_shared|gnustl_static|gnustl_shared|c\\+\\+_static|c\\+\\+_shared)$")
   message( FATAL_ERROR "ANDROID_STL is set to invalid value \"${ANDROID_STL}\".
 The possible values are:
   none           -> Do not configure the runtime.
@@ -905,15 +905,19 @@ The possible values are:
   stlport_shared -> Use the STLport runtime as a shared library.
   gnustl_static  -> (default) Use the GNU STL as a static library.
   gnustl_shared  -> Use the GNU STL as a shared library.
+  c++_static     -> Use LLVM libc++ runtime as static library.
+  c++_shared     -> Use LLVM libc++ runtime as shared library.
 " )
  endif()
 elseif( BUILD_WITH_STANDALONE_TOOLCHAIN )
- if( NOT "${ANDROID_STL}" MATCHES "^(none|gnustl_static|gnustl_shared)$")
+ if( NOT "${ANDROID_STL}" MATCHES "^(none|gnustl_static|gnustl_shared|c\\+\\+_static|c\\+\\+_shared)$")
   message( FATAL_ERROR "ANDROID_STL is set to invalid value \"${ANDROID_STL}\".
 The possible values are:
   none           -> Do not configure the runtime.
   gnustl_static  -> (default) Use the GNU STL as a static library.
   gnustl_shared  -> Use the GNU STL as a shared library.
+  c++_static     -> Use LLVM libc++ runtime as static library.
+  c++_shared     -> Use LLVM libc++ runtime as shared library.
 " )
  endif()
 endif()
@@ -985,7 +989,7 @@ if( BUILD_WITH_STANDALONE_TOOLCHAIN )
    set( __libsupcxx "${__libstl}/libsupc++.a" )
    set( __libstl    "${__libstl}/libstdc++.a" )
   endif()
-  if( NOT EXISTS "${__libsupcxx}" )
+  if( NOT EXISTS "${__libsupcxx}" AND NOT ANDROID_STL MACHES "c\\+\\+_(static|shared)" )
    message( FATAL_ERROR "The required libstdsupc++.a is missing in your standalone toolchain.
  Usually it happens because of bug in make-standalone-toolchain.sh script from NDK r7, r7b and r7c.
  You need to either upgrade to newer NDK or manually copy
@@ -1011,14 +1015,20 @@ if( "${ANDROID_TOOLCHAIN_NAME}" STREQUAL "standalone-clang" )
  set( ANDROID_COMPILER_IS_CLANG 1 )
  execute_process( COMMAND "${ANDROID_CLANG_TOOLCHAIN_ROOT}/bin/clang${TOOL_OS_SUFFIX}" --version OUTPUT_VARIABLE ANDROID_CLANG_VERSION OUTPUT_STRIP_TRAILING_WHITESPACE )
  string( REGEX MATCH "[0-9]+[.][0-9]+" ANDROID_CLANG_VERSION "${ANDROID_CLANG_VERSION}")
-elseif( "${ANDROID_TOOLCHAIN_NAME}" MATCHES "-clang3[.][0-9]?$" )
- string( REGEX MATCH "3[.][0-9]$" ANDROID_CLANG_VERSION "${ANDROID_TOOLCHAIN_NAME}")
+elseif( "${ANDROID_TOOLCHAIN_NAME}" MATCHES "-clang(.*)$" )
+ set (ANDROID_CLANG_VERSION ${CMAKE_MATCH_1})
  string( REGEX REPLACE "-clang${ANDROID_CLANG_VERSION}$" "-${ANDROID_COMPILER_VERSION}" ANDROID_GCC_TOOLCHAIN_NAME "${ANDROID_TOOLCHAIN_NAME}" )
- if( NOT EXISTS "${ANDROID_NDK_TOOLCHAINS_PATH}/llvm-${ANDROID_CLANG_VERSION}${ANDROID_NDK_TOOLCHAINS_SUBPATH}/bin/clang${TOOL_OS_SUFFIX}" )
+ if( ANDROID_NDK_LAYOUT STREQUAL RELEASE2)
+  set( ANDROID_CLANG_TOOLCHAIN_ROOT "${ANDROID_NDK_TOOLCHAINS_PATH}/llvm${ANDROID_NDK_TOOLCHAINS_SUBPATH}" )
+ else()
+  set( ANDROID_CLANG_TOOLCHAIN_ROOT "${ANDROID_NDK_TOOLCHAINS_PATH}/llvm-${ANDROID_CLANG_VERSION}${ANDROID_NDK_TOOLCHAINS_SUBPATH}" )
+ endif()
+
+ if( NOT EXISTS "${ANDROID_CLANG_TOOLCHAIN_ROOT}/bin/clang${TOOL_OS_SUFFIX}" )
+  unset( ANDROID_CLANG_TOOLCHAIN_ROOT )
   message( FATAL_ERROR "Could not find the Clang compiler driver" )
  endif()
  set( ANDROID_COMPILER_IS_CLANG 1 )
- set( ANDROID_CLANG_TOOLCHAIN_ROOT "${ANDROID_NDK_TOOLCHAINS_PATH}/llvm-${ANDROID_CLANG_VERSION}${ANDROID_NDK_TOOLCHAINS_SUBPATH}" )
 else()
  set( ANDROID_GCC_TOOLCHAIN_NAME "${ANDROID_TOOLCHAIN_NAME}" )
  unset( ANDROID_COMPILER_IS_CLANG CACHE )
@@ -1046,20 +1056,20 @@ if( BUILD_WITH_ANDROID_NDK )
   set( ANDROID_EXCEPTIONS       ON )
   set( ANDROID_STL_INCLUDE_DIRS "${ANDROID_NDK}/sources/cxx-stl/system/include" )
  elseif( ANDROID_STL MATCHES "gabi" )
-  if( ANDROID_NDK_RELEASE_NUM LESS 7000 ) # before r7
-   message( FATAL_ERROR "gabi++ is not awailable in your NDK. You have to upgrade to NDK r7 or newer to use gabi++.")
+  if( ANDROID_NDK_VERSION VERSION_LESS 7 ) # before r7
+   message( FATAL_ERROR "gabi++ is not available in your NDK. You have to upgrade to NDK r7 or newer to use gabi++.")
   endif()
   set( ANDROID_RTTI             ON )
   set( ANDROID_EXCEPTIONS       OFF )
   set( ANDROID_STL_INCLUDE_DIRS "${ANDROID_NDK}/sources/cxx-stl/gabi++/include" )
   set( __libstl                 "${ANDROID_NDK}/sources/cxx-stl/gabi++/libs/${ANDROID_NDK_ABI_NAME}/libgabi++_static.a" )
  elseif( ANDROID_STL MATCHES "stlport" )
-  if( NOT ANDROID_NDK_RELEASE_NUM LESS 8004 ) # before r8d
+  if( NOT ANDROID_NDK_VERSION VERSION_LESS 8.4 ) # before r8d
    set( ANDROID_EXCEPTIONS       ON )
   else()
    set( ANDROID_EXCEPTIONS       OFF )
   endif()
-  if( ANDROID_NDK_RELEASE_NUM LESS 7000 ) # before r7
+  if( ANDROID_NDK_VERSION VERSION_LESS 7 ) # before r7
    set( ANDROID_RTTI            OFF )
   else()
    set( ANDROID_RTTI            ON )
@@ -1086,6 +1096,22 @@ if( BUILD_WITH_ANDROID_NDK )
   else()
    set( __libstl                "${__libstl}/libs/${ANDROID_NDK_ABI_NAME}/libstdc++.a" )
   endif()
+  # Urho3D - cherry pick from jroger's PR #54
+ elseif( ANDROID_STL MATCHES "c\\+\\+_(shared|static)" )
+  set( ANDROID_EXCEPTIONS       ON )
+  set( ANDROID_RTTI             ON )
+  set( ANDROID_CXX_ROOT         "${ANDROID_NDK}/sources/cxx-stl/" )
+  set( ANDROID_LLVM_ROOT        "${ANDROID_CXX_ROOT}/llvm-libc++" )
+  set( ANDROID_ABI_INCLUDE_DIRS "${ANDROID_CXX_ROOT}/llvm-libc++abi/libcxxabi/include" )
+  set( ANDROID_STL_INCLUDE_DIRS "${ANDROID_LLVM_ROOT}/libcxx/include"
+                                "${ANDROID_ABI_INCLUDE_DIRS}" )
+  # android support sfiles
+  include_directories ( SYSTEM ${ANDROID_NDK}/sources/android/support/include )
+  if( EXISTS "${ANDROID_LLVM_ROOT}/libs/${ANDROID_NDK_ABI_NAME}/libc++_shared.so" )
+   set( __libstl               "${ANDROID_LLVM_ROOT}/libs/${ANDROID_NDK_ABI_NAME}/libc++_static.a" )
+  else()
+   message( "c++ library doesn't exist" )
+  endif()
  else()
   message( FATAL_ERROR "Unknown runtime: ${ANDROID_STL}" )
  endif()
@@ -1109,7 +1135,7 @@ if( BUILD_WITH_ANDROID_NDK )
    endif()
   endif()
   if( NOT EXISTS "${__libsupcxx}")
-   message( ERROR "Could not find libsupc++.a for a chosen platform. Either your NDK is not supported or is broken.")
+   message( FATAL_ERROR "Could not find libsupc++.a for a chosen platform. Either your NDK is not supported or is broken.")
   endif()
  endif()
 endif()
@@ -1147,6 +1173,35 @@ if( NOT CMAKE_C_COMPILER )
    set( CMAKE_C_COMPILER_ARG1   "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-gcc${TOOL_OS_SUFFIX}" CACHE PATH "C compiler")
    set( CMAKE_CXX_COMPILER_ARG1 "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-g++${TOOL_OS_SUFFIX}" CACHE PATH "C++ compiler")
   endif()
+ # Urho3D - there are two ways to use ccache, by prefixing compiler toolchain with 'ccache' command (as done by NDK_CCACHE code branch above) or
+ #          let ccache masquerade as the compiler by creating a symbolic link named as the compiler pointing back to 'ccache' command
+ #          Urho3D has to use the second way because the first one does not handle our precompiled header build rules well
+ elseif ("$ENV{USE_CCACHE}" AND NOT CMAKE_HOST_WIN32)   # Need to stringify to guard against undefined environment variable
+    execute_process (COMMAND which ccache RESULT_VARIABLE EXIT_CODE OUTPUT_VARIABLE CCACHE ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE)
+    if (EXIT_CODE EQUAL 0)
+        if (ANDROID_COMPILER_IS_CLANG)
+            set (PATH ${ANDROID_CLANG_TOOLCHAIN_ROOT}/bin)
+            execute_process (COMMAND ${CMAKE_COMMAND} -E create_symlink ${CCACHE} ${CMAKE_BINARY_DIR}/${_clang_name})
+            set (CMAKE_C_COMPILER ${CMAKE_BINARY_DIR}/${_clang_name} CACHE PATH "C compiler")
+            execute_process (COMMAND ${CMAKE_COMMAND} -E create_symlink ${CCACHE} ${CMAKE_BINARY_DIR}/${_clang_name}++)
+            set (CMAKE_CXX_COMPILER ${CMAKE_BINARY_DIR}/${_clang_name}++ CACHE PATH "C++ compiler")
+        else ()
+            set (PATH ${ANDROID_TOOLCHAIN_ROOT}/bin)
+            execute_process (COMMAND ${CMAKE_COMMAND} -E create_symlink ${CCACHE} ${CMAKE_BINARY_DIR}/${ANDROID_TOOLCHAIN_MACHINE_NAME}-gcc)
+            set (CMAKE_C_COMPILER ${CMAKE_BINARY_DIR}/${ANDROID_TOOLCHAIN_MACHINE_NAME}-gcc CACHE PATH "C compiler")
+            execute_process (COMMAND ${CMAKE_COMMAND} -E create_symlink ${CCACHE} ${CMAKE_BINARY_DIR}/${ANDROID_TOOLCHAIN_MACHINE_NAME}-g++)
+            set (CMAKE_CXX_COMPILER ${CMAKE_BINARY_DIR}/${ANDROID_TOOLCHAIN_MACHINE_NAME}-g++ CACHE PATH "C++ compiler")
+        endif ()
+    else ()
+        # To avoid repeating the code to instruct CMake to fallback to use the actual Android compiler toolchain below, we raise this as an error instead of warning
+        message (FATAL_ERROR "ccache may not have been installed on this host system. "
+            "This is required to enable ccache support for Android compiler toolchain. "
+            "In order to rectify this, install ccache software package first or do not set the USE_CCACHE environment variable.")
+    endif ()
+    if (NOT $ENV{PATH} MATCHES ${PATH})
+        message (FATAL_ERROR "The bin directory containing the compiler toolchain (${PATH}) has not been added in the PATH environment variable. "
+            "This is required to enable ccache support for Android compiler toolchain.")
+    endif ()
  else()
   if( ANDROID_COMPILER_IS_CLANG )
    set( CMAKE_C_COMPILER   "${ANDROID_CLANG_TOOLCHAIN_ROOT}/bin/${_clang_name}${TOOL_OS_SUFFIX}"   CACHE PATH "C compiler")
@@ -1158,7 +1213,12 @@ if( NOT CMAKE_C_COMPILER )
  endif()
  set( CMAKE_ASM_COMPILER "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-gcc${TOOL_OS_SUFFIX}"     CACHE PATH "assembler" )
  set( CMAKE_STRIP        "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-strip${TOOL_OS_SUFFIX}"   CACHE PATH "strip" )
- set( CMAKE_AR           "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-ar${TOOL_OS_SUFFIX}"      CACHE PATH "archive" )
+ if( EXISTS "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-gcc-ar${TOOL_OS_SUFFIX}" )
+  # Use gcc-ar if we have it for better LTO support.
+  set( CMAKE_AR           "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-gcc-ar${TOOL_OS_SUFFIX}"      CACHE PATH "archive" )
+ else()
+  set( CMAKE_AR           "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-ar${TOOL_OS_SUFFIX}"      CACHE PATH "archive" )
+ endif()
  set( CMAKE_LINKER       "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-ld${TOOL_OS_SUFFIX}"      CACHE PATH "linker" )
  set( CMAKE_NM           "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-nm${TOOL_OS_SUFFIX}"      CACHE PATH "nm" )
  set( CMAKE_OBJCOPY      "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-objcopy${TOOL_OS_SUFFIX}" CACHE PATH "objcopy" )
@@ -1211,15 +1271,21 @@ set( CMAKE_ASM_SOURCE_FILE_EXTENSIONS s S asm )
 
 foreach( lang C CXX ASM )
  if( ANDROID_COMPILER_IS_CLANG )
-  set( CMAKE_${lang}_COMPILER_VERSION ${ANDROID_CLANG_VERSION} )
+  if (ANDROID_CLANG_VERSION)
+   set( CMAKE_${lang}_COMPILER_VERSION ${ANDROID_CLANG_VERSION} )
+  else ()
+   set (CMAKE_${lang}_COMPILER_VERSION 3.8)
+  endif ()
  else()
   set( CMAKE_${lang}_COMPILER_VERSION ${ANDROID_COMPILER_VERSION} )
  endif()
 endforeach()
 
 # flags and definitions
-remove_definitions( -DANDROID )
-add_definitions( -DANDROID )
+# Urho3D: comment out redundant command which actually may interfere with compile definition cache generation when enabling PCH
+#remove_definitions( -DANDROID )
+# Urho3D: comment out redundant compiler defines as we use __ANDROID__ in our code base consistently
+#add_definitions( -DANDROID )
 
 if( ANDROID_SYSROOT MATCHES "[ ;\"]" )
  if( CMAKE_HOST_WIN32 )
@@ -1247,7 +1313,7 @@ endif()
 
 # NDK flags
 if (ARM64_V8A )
- set( ANDROID_CXX_FLAGS         "${ANDROID_CXX_FLAGS} -ffunction-sections -funwind-tables" )
+ set( ANDROID_CXX_FLAGS         "${ANDROID_CXX_FLAGS} -funwind-tables" )
  set( ANDROID_CXX_FLAGS_RELEASE "-fomit-frame-pointer -fstrict-aliasing" )
  set( ANDROID_CXX_FLAGS_DEBUG   "-fno-omit-frame-pointer -fno-strict-aliasing" )
  if( NOT ANDROID_COMPILER_IS_CLANG )
@@ -1277,7 +1343,7 @@ elseif( X86 OR X86_64 )
  set( ANDROID_CXX_FLAGS_RELEASE "-fomit-frame-pointer -fstrict-aliasing" )
  set( ANDROID_CXX_FLAGS_DEBUG   "-fno-omit-frame-pointer -fno-strict-aliasing" )
 elseif( MIPS OR MIPS64 )
- set( ANDROID_CXX_FLAGS         "${ANDROID_CXX_FLAGS} -fno-strict-aliasing -finline-functions -ffunction-sections -funwind-tables -fmessage-length=0" )
+ set( ANDROID_CXX_FLAGS         "${ANDROID_CXX_FLAGS} -fno-strict-aliasing -finline-functions -funwind-tables -fmessage-length=0" )
  set( ANDROID_CXX_FLAGS_RELEASE "-fomit-frame-pointer" )
  set( ANDROID_CXX_FLAGS_DEBUG   "-fno-omit-frame-pointer" )
  if( NOT ANDROID_COMPILER_IS_CLANG )
@@ -1358,14 +1424,14 @@ if( EXISTS "${__libstl}" OR EXISTS "${__libsupcxx}" )
 endif()
 
 # variables controlling optional build flags
-if( ANDROID_NDK_RELEASE_NUM LESS 7000 ) # before r7
+if( ANDROID_NDK_VERSION VERSION_LESS 7 ) # before r7
  # libGLESv2.so in NDK's prior to r7 refers to missing external symbols.
  # So this flag option is required for all projects using OpenGL from native.
  __INIT_VARIABLE( ANDROID_SO_UNDEFINED                      VALUES ON )
 else()
  __INIT_VARIABLE( ANDROID_SO_UNDEFINED                      VALUES OFF )
 endif()
-__INIT_VARIABLE( ANDROID_NO_UNDEFINED OBSOLETE_NO_UNDEFINED VALUES ON )
+__INIT_VARIABLE( ANDROID_NO_UNDEFINED                       VALUES ON )
 __INIT_VARIABLE( ANDROID_FUNCTION_LEVEL_LINKING             VALUES ON )
 __INIT_VARIABLE( ANDROID_GOLD_LINKER                        VALUES ON )
 __INIT_VARIABLE( ANDROID_NOEXECSTACK                        VALUES ON )
@@ -1373,7 +1439,7 @@ __INIT_VARIABLE( ANDROID_RELRO                              VALUES ON )
 
 set( ANDROID_NO_UNDEFINED           ${ANDROID_NO_UNDEFINED}           CACHE BOOL "Show all undefined symbols as linker errors" )
 set( ANDROID_SO_UNDEFINED           ${ANDROID_SO_UNDEFINED}           CACHE BOOL "Allows or disallows undefined symbols in shared libraries" )
-set( ANDROID_FUNCTION_LEVEL_LINKING ${ANDROID_FUNCTION_LEVEL_LINKING} CACHE BOOL "Allows or disallows undefined symbols in shared libraries" )
+set( ANDROID_FUNCTION_LEVEL_LINKING ${ANDROID_FUNCTION_LEVEL_LINKING} CACHE BOOL "Put each function in separate section and enable garbage collection of unused input sections at link time" )
 set( ANDROID_GOLD_LINKER            ${ANDROID_GOLD_LINKER}            CACHE BOOL "Enables gold linker" )
 set( ANDROID_NOEXECSTACK            ${ANDROID_NOEXECSTACK}            CACHE BOOL "Allows or disallows undefined symbols in shared libraries" )
 set( ANDROID_RELRO                  ${ANDROID_RELRO}                  CACHE BOOL "Enables RELRO - a memory corruption mitigation technique" )
@@ -1409,9 +1475,9 @@ if( ANDROID_FUNCTION_LEVEL_LINKING )
 endif()
 
 if( ANDROID_COMPILER_VERSION VERSION_EQUAL "4.6" )
- if( ANDROID_GOLD_LINKER AND (CMAKE_HOST_UNIX OR ANDROID_NDK_RELEASE_NUM GREATER 8002) AND (ARMEABI OR ARMEABI_V7A OR X86) )
+ if( ANDROID_GOLD_LINKER AND (CMAKE_HOST_UNIX OR ANDROID_NDK_VERSION VERSION_GREATER 8.2) AND (ARMEABI OR ARMEABI_V7A OR X86) )
   set( ANDROID_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} -fuse-ld=gold" )
- elseif( ANDROID_NDK_RELEASE_NUM GREATER 8002 ) # after r8b
+ elseif( ANDROID_NDK_VERSION VERSION_GREATER 8.2 ) # after r8b
   set( ANDROID_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} -fuse-ld=bfd" )
  elseif( ANDROID_NDK_RELEASE STREQUAL "r8b" AND ARMEABI AND NOT _CMAKE_IN_TRY_COMPILE )
   message( WARNING "The default bfd linker from arm GCC 4.6 toolchain can fail with 'unresolvable R_ARM_THM_CALL relocation' error message. See https://code.google.com/p/android/issues/detail?id=35342
@@ -1444,9 +1510,8 @@ endif()
 # cache flags
 set( CMAKE_CXX_FLAGS           ""                        CACHE STRING "c++ flags" )
 set( CMAKE_C_FLAGS             ""                        CACHE STRING "c flags" )
-# Urho3D: optimise for size
-set( CMAKE_CXX_FLAGS_RELEASE   "-Os -DNDEBUG"            CACHE STRING "c++ Release flags" )
-set( CMAKE_C_FLAGS_RELEASE     "-Os -DNDEBUG"            CACHE STRING "c Release flags" )
+set( CMAKE_CXX_FLAGS_RELEASE   "-O3 -DNDEBUG"            CACHE STRING "c++ Release flags" )
+set( CMAKE_C_FLAGS_RELEASE     "-O3 -DNDEBUG"            CACHE STRING "c Release flags" )
 set( CMAKE_CXX_FLAGS_DEBUG     "-O0 -g -DDEBUG -D_DEBUG" CACHE STRING "c++ Debug flags" )
 set( CMAKE_C_FLAGS_DEBUG       "-O0 -g -DDEBUG -D_DEBUG" CACHE STRING "c Debug flags" )
 set( CMAKE_SHARED_LINKER_FLAGS ""                        CACHE STRING "shared linker flags" )
@@ -1476,14 +1541,9 @@ if( MIPS AND BUILD_WITH_ANDROID_NDK AND ANDROID_NDK_RELEASE STREQUAL "r8" )
  set( CMAKE_EXE_LINKER_FLAGS    "-Wl,-T,${ANDROID_NDK_TOOLCHAINS_PATH}/${ANDROID_GCC_TOOLCHAIN_NAME}/mipself.x ${CMAKE_EXE_LINKER_FLAGS}" )
 endif()
 
-# pie/pic
-if( NOT (ANDROID_NATIVE_API_LEVEL LESS 16) AND (NOT DEFINED ANDROID_APP_PIE OR ANDROID_APP_PIE) AND (CMAKE_VERSION VERSION_GREATER 2.8.8) )
- set( CMAKE_POSITION_INDEPENDENT_CODE TRUE )
+# Urho3D: CMake is able to take care of the PIC flag by itself, so we only need to worry about the PIE flag for executable target targeting API level 16+ (Android 4.1+)
+if( NOT ANDROID_NATIVE_API_LEVEL LESS 16 )
  set( CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fPIE -pie")
-else()
- set( CMAKE_POSITION_INDEPENDENT_CODE FALSE )
- set( CMAKE_CXX_FLAGS "-fpic ${CMAKE_CXX_FLAGS}" )
- set( CMAKE_C_FLAGS   "-fpic ${CMAKE_C_FLAGS}" )
 endif()
 
 # configure rtti
@@ -1556,31 +1616,39 @@ endif()
 
 # setup output directories
 # Urho3D: Prefer binary dir over source dir, which is anyway equal to source dir when not using out-of-source build tree
-set( LIBRARY_OUTPUT_PATH_ROOT ${CMAKE_BINARY_DIR} CACHE PATH "root for library output, set this to change where android libs are installed to" )
+if( NOT LIBRARY_OUTPUT_PATH_ROOT )
+ set( LIBRARY_OUTPUT_PATH_ROOT ${CMAKE_BINARY_DIR} CACHE PATH "root for library output, set this to change where android libs are installed to" )
+endif()
 # Urho3D: Do not prepend ${ANDROID_TOOLCHAIN_ROOT} to prefix dir on user behalf, let user specify that via DESTDIR; revert CMAKE_INSTALL_PREFIX to CMake's default
 #set( CMAKE_INSTALL_PREFIX "${ANDROID_TOOLCHAIN_ROOT}/user" CACHE STRING "path for installing" )
 
-if(NOT _CMAKE_IN_TRY_COMPILE)
- if( EXISTS "${CMAKE_SOURCE_DIR}/jni/CMakeLists.txt" )
-  set( EXECUTABLE_OUTPUT_PATH "${LIBRARY_OUTPUT_PATH_ROOT}/bin/${ANDROID_NDK_ABI_NAME}" CACHE PATH "Output directory for applications" )
- else()
-  set( EXECUTABLE_OUTPUT_PATH "${LIBRARY_OUTPUT_PATH_ROOT}/bin" CACHE PATH "Output directory for applications" )
- endif()
- # Urho3D: All libraries are first generated in CMake default binary directory and only the main target library is later copied to below output path by Urho3D own build script
- set( ANDROID_LIBRARY_OUTPUT_PATH "${LIBRARY_OUTPUT_PATH_ROOT}/libs/${ANDROID_NDK_ABI_NAME}" CACHE PATH "path for android libs" FORCE )
- mark_as_advanced (ANDROID_LIBRARY_OUTPUT_PATH)
-endif()
+# Urho3D: Bug fix - not sure what was the original intention as it always tries to overwrite when it is user defined?
+#if( DEFINED LIBRARY_OUTPUT_PATH_ROOT
+#      OR EXISTS "${CMAKE_SOURCE_DIR}/AndroidManifest.xml"
+#      OR (EXISTS "${CMAKE_SOURCE_DIR}/../AndroidManifest.xml" AND EXISTS "${CMAKE_SOURCE_DIR}/../jni/") )
+#  set( LIBRARY_OUTPUT_PATH_ROOT ${CMAKE_SOURCE_DIR} CACHE PATH "Root for binaries output, set this to change where Android libs are installed to" )
+  if( NOT _CMAKE_IN_TRY_COMPILE )
+    if( EXISTS "${CMAKE_SOURCE_DIR}/jni/CMakeLists.txt" )
+      set( EXECUTABLE_OUTPUT_PATH "${LIBRARY_OUTPUT_PATH_ROOT}/bin/${ANDROID_NDK_ABI_NAME}" CACHE PATH "Output directory for applications" )
+    else()
+      set( EXECUTABLE_OUTPUT_PATH "${LIBRARY_OUTPUT_PATH_ROOT}/bin" CACHE PATH "Output directory for applications" )
+    endif()
+    # Urho3D: All libraries are first generated in CMake default binary directory and only the main target library is later copied to below output path by Urho3D own build script
+    set( ANDROID_LIBRARY_OUTPUT_PATH "${LIBRARY_OUTPUT_PATH_ROOT}/libs/${ANDROID_NDK_ABI_NAME}" CACHE PATH "path for android libs" FORCE )
+    mark_as_advanced (ANDROID_LIBRARY_OUTPUT_PATH)
+  endif()
+#endif()
 
 # Urho3D: Copy shared STL library to final Android library output path pointed by ANDROID_LIBRARY_OUTPUT_PATH variable as CMake's LIBRARY_OUTPUT_PATH still points to its default
 # copy shared stl library to build directory
-if( NOT _CMAKE_IN_TRY_COMPILE AND __libstl MATCHES "[.]so$" )
- get_filename_component( __libstlname "${__libstl}" NAME )
- execute_process( COMMAND "${CMAKE_COMMAND}" -E copy_if_different "${__libstl}" "${ANDROID_LIBRARY_OUTPUT_PATH}/${__libstlname}" RESULT_VARIABLE __fileCopyProcess )
- if( NOT __fileCopyProcess EQUAL 0 OR NOT EXISTS "${ANDROID_LIBRARY_OUTPUT_PATH}/${__libstlname}")
-   message( SEND_ERROR "Failed copying of ${__libstl} to the ${ANDROID_LIBRARY_OUTPUT_PATH}/${__libstlname}" )
- endif()
- unset( __fileCopyProcess )
- unset( __libstlname )
+if( NOT _CMAKE_IN_TRY_COMPILE AND __libstl MATCHES "[.]so$" AND DEFINED ANDROID_LIBRARY_OUTPUT_PATH )
+  get_filename_component( __libstlname "${__libstl}" NAME )
+  execute_process( COMMAND "${CMAKE_COMMAND}" -E copy_if_different "${__libstl}" "${ANDROID_LIBRARY_OUTPUT_PATH}/${__libstlname}" RESULT_VARIABLE __fileCopyProcess )
+  if( NOT __fileCopyProcess EQUAL 0 OR NOT EXISTS "${ANDROID_LIBRARY_OUTPUT_PATH}/${__libstlname}")
+    message( SEND_ERROR "Failed copying of ${__libstl} to the ${ANDROID_LIBRARY_OUTPUT_PATH}/${__libstlname}" )
+  endif()
+  unset( __fileCopyProcess )
+  unset( __libstlname )
 endif()
 
 
@@ -1665,9 +1733,9 @@ endmacro()
 
 
 # export toolchain settings for the try_compile() command
-if( NOT PROJECT_NAME STREQUAL "CMAKE_TRY_COMPILE" )
+if( NOT _CMAKE_IN_TRY_COMPILE )
  set( __toolchain_config "")
- foreach( __var NDK_CCACHE  LIBRARY_OUTPUT_PATH_ROOT  ANDROID_FORBID_SYGWIN  ANDROID_SET_OBSOLETE_VARIABLES
+ foreach( __var NDK_CCACHE  LIBRARY_OUTPUT_PATH_ROOT  ANDROID_FORBID_SYGWIN
                 ANDROID_NDK_HOST_X64
                 ANDROID_NDK
                 ANDROID_NDK_LAYOUT
@@ -1689,7 +1757,7 @@ if( NOT PROJECT_NAME STREQUAL "CMAKE_TRY_COMPILE" )
                 ANDROID_APP_PIE
                 )
   if( DEFINED ${__var} )
-   if( "${__var}" MATCHES " ")
+   if( ${__var} MATCHES " ")
     set( __toolchain_config "${__toolchain_config}set( ${__var} \"${${__var}}\" CACHE INTERNAL \"\" )\n" )
    else()
     set( __toolchain_config "${__toolchain_config}set( ${__var} ${${__var}} CACHE INTERNAL \"\" )\n" )
@@ -1714,16 +1782,6 @@ if( CMAKE_GENERATOR MATCHES "Ninja" AND CMAKE_HOST_WIN32 )
 endif()
 
 
-# set some obsolete variables for backward compatibility
-set( ANDROID_SET_OBSOLETE_VARIABLES ON CACHE BOOL "Define obsolete Andrid-specific cmake variables" )
-mark_as_advanced( ANDROID_SET_OBSOLETE_VARIABLES )
-if( ANDROID_SET_OBSOLETE_VARIABLES )
- set( ANDROID_API_LEVEL ${ANDROID_NATIVE_API_LEVEL} )
- set( ARM_TARGET "${ANDROID_ABI}" )
- set( ARMEABI_NDK_NAME "${ANDROID_NDK_ABI_NAME}" )
-endif()
-
-
 # Variables controlling behavior or set by cmake toolchain:
 #   ANDROID_ABI : "armeabi-v7a" (default), "armeabi", "armeabi-v7a with NEON", "armeabi-v7a with VFPV3", "armeabi-v6 with VFP", "x86", "mips", "arm64-v8a", "x86_64", "mips64"
 #   ANDROID_NATIVE_API_LEVEL : 3,4,5,8,9,14,15,16,17,18,19,21 (depends on NDK version)
@@ -1737,22 +1795,15 @@ endif()
 #   ANDROID_RELRO : ON/OFF
 #   ANDROID_FORCE_ARM_BUILD : ON/OFF
 #   ANDROID_STL_FORCE_FEATURES : ON/OFF
-#   ANDROID_SET_OBSOLETE_VARIABLES : ON/OFF
+#   ANDROID_LIBM_PATH : path to libm.so (set to something like $(TOP)/out/target/product/<product_name>/obj/lib/libm.so) to workaround unresolved `sincos`
 # Can be set only at the first run:
-#   ANDROID_NDK
-#   ANDROID_STANDALONE_TOOLCHAIN
+#   ANDROID_NDK : path to your NDK install
+#   NDK_CCACHE : path to your ccache executable
 #   ANDROID_TOOLCHAIN_NAME : the NDK name of compiler toolchain
 #   ANDROID_NDK_HOST_X64 : try to use x86_64 toolchain (default for x64 host systems)
 #   ANDROID_NDK_LAYOUT : the inner NDK structure (RELEASE, LINARO, ANDROID)
 #   LIBRARY_OUTPUT_PATH_ROOT : <any valid path>
-#   NDK_CCACHE : <path to your ccache executable>
-# Obsolete:
-#   ANDROID_API_LEVEL : superseded by ANDROID_NATIVE_API_LEVEL
-#   ARM_TARGET : superseded by ANDROID_ABI
-#   ARM_TARGETS : superseded by ANDROID_ABI (can be set only)
-#   ANDROID_NDK_TOOLCHAIN_ROOT : superseded by ANDROID_STANDALONE_TOOLCHAIN (can be set only)
-#   ANDROID_USE_STLPORT : superseded by ANDROID_STL=stlport_static
-#   ANDROID_LEVEL : superseded by ANDROID_NATIVE_API_LEVEL (completely removed)
+#   ANDROID_STANDALONE_TOOLCHAIN
 #
 # Primary read-only variables:
 #   ANDROID : always TRUE
@@ -1766,19 +1817,16 @@ endif()
 #   X86_64 : TRUE if configured for x86_64
 #   MIPS : TRUE if configured for mips
 #   MIPS64 : TRUE if configured for mips64
-#   BUILD_ANDROID : always TRUE
 #   BUILD_WITH_ANDROID_NDK : TRUE if NDK is used
 #   BUILD_WITH_STANDALONE_TOOLCHAIN : TRUE if standalone toolchain is used
 #   ANDROID_NDK_HOST_SYSTEM_NAME : "windows", "linux-x86" or "darwin-x86" depending on host platform
 #   ANDROID_NDK_ABI_NAME : "armeabi", "armeabi-v7a", "x86", "mips", "arm64-v8a", "x86_64", "mips64" depending on ANDROID_ABI
-#   ANDROID_NDK_RELEASE : from r5 to r10d; set only for NDK
-#   ANDROID_NDK_RELEASE_NUM : numeric ANDROID_NDK_RELEASE version (1000*major+minor)
+#   ANDROID_NDK_RELEASE : from r5 to r12b; set only for NDK
+#   ANDROID_NDK_VERSION : major.minor.patch; set only for NDK; e.g. r10e = 10.5.0 but r11c = 11.2.2725575 (as defined in the source.properties)
 #   ANDROID_ARCH_NAME : "arm", "x86", "mips", "arm64", "x86_64", "mips64" depending on ANDROID_ABI
 #   ANDROID_SYSROOT : path to the compiler sysroot
 #   TOOL_OS_SUFFIX : "" or ".exe" depending on host platform
 #   ANDROID_COMPILER_IS_CLANG : TRUE if clang compiler is used
-# Obsolete:
-#   ARMEABI_NDK_NAME : superseded by ANDROID_NDK_ABI_NAME
 #
 # Secondary (less stable) read-only variables:
 #   ANDROID_COMPILER_VERSION : GCC version used (not Clang version)
@@ -1793,12 +1841,10 @@ endif()
 #   ANDROID_RTTI : if rtti is enabled by the runtime
 #   ANDROID_EXCEPTIONS : if exceptions are enabled by the runtime
 #   ANDROID_GCC_TOOLCHAIN_NAME : read-only, differs from ANDROID_TOOLCHAIN_NAME only if clang is used
-#   ANDROID_LIBM_PATH : path to libm.so (set to something like $(TOP)/out/target/product/<product_name>/obj/lib/libm.so) to workaround unresolved `sincos`
 #
 # Defaults:
 #   ANDROID_DEFAULT_NDK_API_LEVEL
 #   ANDROID_DEFAULT_NDK_API_LEVEL_${ARCH}
 #   ANDROID_NDK_SEARCH_PATHS
-#   ANDROID_STANDALONE_TOOLCHAIN_SEARCH_PATH
 #   ANDROID_SUPPORTED_ABIS_${ARCH}
-#   ANDROID_SUPPORTED_NDK_VERSIONS
+#   ANDROID_SUPPORTED_NDK_VERSIONS

+ 66 - 40
Build/CMake/Toolchains/emscripten.toolchain.cmake

@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2008-2015 the Urho3D project.
+# Copyright (c) 2008-2016 the Urho3D project.
 #
 # Permission is hereby granted, free of charge, to any person obtaining a copy
 # of this software and associated documentation files (the "Software"), to deal
@@ -20,9 +20,9 @@
 # THE SOFTWARE.
 #
 
-# Based on cmake/Modules/Platform/Emscripten.cmake from https://github.com/kripken/emscripten
-
-cmake_minimum_required (VERSION 2.6.3)
+if (DEFINED CMAKE_CROSSCOMPILING)
+    return ()
+endif ()
 
 if (CMAKE_TOOLCHAIN_FILE)
     # Reference toolchain variable to suppress "unused variable" warning
@@ -35,20 +35,59 @@ set (CMAKE_SYSTEM_NAME Linux)
 set (CMAKE_SYSTEM_VERSION 1)
 
 # specify the cross compiler
-if (NOT EMSCRIPTEN_ROOT_PATH AND DEFINED ENV{EMSCRIPTEN})
-    file (TO_CMAKE_PATH $ENV{EMSCRIPTEN} EMSCRIPTEN_ROOT_PATH)
+if (CMAKE_HOST_WIN32)
+    set (TOOL_EXT .bat)
 endif ()
-if (NOT EXISTS ${EMSCRIPTEN_ROOT_PATH}/emcc)
+if (NOT EMSCRIPTEN_ROOT_PATH)
+    if (DEFINED ENV{EMSCRIPTEN_ROOT_PATH})
+        file (TO_CMAKE_PATH $ENV{EMSCRIPTEN_ROOT_PATH} EMSCRIPTEN_ROOT_PATH)
+    elseif (DEFINED ENV{EMSCRIPTEN})
+        file (TO_CMAKE_PATH $ENV{EMSCRIPTEN} EMSCRIPTEN_ROOT_PATH)
+    endif ()
+endif ()
+if (NOT EXISTS ${EMSCRIPTEN_ROOT_PATH}/emcc${TOOL_EXT})
     message (FATAL_ERROR "Could not find Emscripten cross compilation tool. "
-        "Use EMSCRIPTEN_ROOT_PATH environment variable or build option to specify the location of the toolchain.")
+        "Use EMSCRIPTEN_ROOT_PATH environment variable or build option to specify the location of the toolchain. "
+        "Or use the canonical EMSCRIPTEN environment variable by calling emsdk_env script.")
 endif ()
-if (CMAKE_HOST_WIN32)
-    set (TOOL_EXT .bat)
+if (NOT EMCC_VERSION)
+    execute_process (COMMAND ${EMSCRIPTEN_ROOT_PATH}/emcc${TOOL_EXT} --version RESULT_VARIABLE EXIT_CODE OUTPUT_VARIABLE EMCC_VERSION ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE)
+    if (EXIT_CODE EQUAL 0)
+        string (REGEX MATCH "[^ .]+\\.[^.]+\\.[^ ]+" EMCC_VERSION "${EMCC_VERSION}")    # Stringify as it could be empty when an error has occured
+    else ()
+        message (FATAL_ERROR "Could not determine the emcc version. Make sure you have installed and activated the Emscripten SDK correctly.")
+    endif ()
+    set (EMCC_VERSION ${EMCC_VERSION} CACHE STRING "emcc version being used in this build tree")    # Cache the result even when there was error in determining the version
+endif ()
+set (COMPILER_PATH ${EMSCRIPTEN_ROOT_PATH})
+# ccache support could only be enabled for emcc prior to 1.31.3 when the CCACHE_CPP2 env var is also set to 1, newer emcc version could enable ccache support without this caveat (see https://github.com/kripken/emscripten/issues/3365 for more detail)
+# The CCACHE_CPP2 env var tells ccache to fallback to use original input source file instead of preprocessed one when passing on the compilation task to the compiler proper
+if (NOT CMAKE_C_COMPILER AND "$ENV{USE_CCACHE}" AND NOT CMAKE_HOST_WIN32 AND ("$ENV{CCACHE_CPP2}" OR NOT EMCC_VERSION VERSION_LESS 1.31.3))
+    if (NOT $ENV{PATH} MATCHES ${EMSCRIPTEN_ROOT_PATH})
+        message (FATAL_ERROR "The bin directory containing the compiler toolchain (${EMSCRIPTEN_ROOT_PATH}) has not been added in the PATH environment variable. "
+            "This is required to enable ccache support for Emscripten compiler toolchain.")
+    endif ()
+    execute_process (COMMAND which ccache RESULT_VARIABLE EXIT_CODE OUTPUT_VARIABLE CCACHE ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE)
+    if (EXIT_CODE EQUAL 0)
+        foreach (name emcc em++)
+            execute_process (COMMAND ${CMAKE_COMMAND} -E create_symlink ${CCACHE} ${CMAKE_BINARY_DIR}/${name})
+        endforeach ()
+        set (COMPILER_PATH ${CMAKE_BINARY_DIR})
+    else ()
+        message (WARNING "ccache may not have been installed on this host system. "
+            "This is required to enable ccache support for Emscripten compiler toolchain. CMake has been configured to use the actual compiler toolchain instead of ccache. "
+            "In order to rectify this, the build tree must be regenerated after installing ccache.")
+    endif ()
 endif ()
-set (CMAKE_C_COMPILER   ${EMSCRIPTEN_ROOT_PATH}/emcc${TOOL_EXT}     CACHE PATH "C compiler")
-set (CMAKE_CXX_COMPILER ${EMSCRIPTEN_ROOT_PATH}/em++${TOOL_EXT}     CACHE PATH "C++ compiler")
+set (CMAKE_C_COMPILER   ${COMPILER_PATH}/emcc${TOOL_EXT}            CACHE PATH "C compiler")
+set (CMAKE_CXX_COMPILER ${COMPILER_PATH}/em++${TOOL_EXT}            CACHE PATH "C++ compiler")
 set (CMAKE_AR           ${EMSCRIPTEN_ROOT_PATH}/emar${TOOL_EXT}     CACHE PATH "archive")
 set (CMAKE_RANLIB       ${EMSCRIPTEN_ROOT_PATH}/emranlib${TOOL_EXT} CACHE PATH "ranlib")
+set (CMAKE_LINKER       ${EMSCRIPTEN_ROOT_PATH}/emlink.py           CACHE PATH "linker")
+# Specific to Emscripten
+set (EMRUN              ${EMSCRIPTEN_ROOT_PATH}/emrun${TOOL_EXT}    CACHE PATH "emrun")
+set (EMPACKAGER         python ${EMSCRIPTEN_ROOT_PATH}/tools/file_packager.py CACHE PATH "file_packager.py")
+set (EMBUILDER          python ${EMSCRIPTEN_ROOT_PATH}/embuilder.py CACHE PATH "embuilder.py")
 
 # specify the system root
 if (NOT EMSCRIPTEN_SYSROOT)
@@ -71,35 +110,21 @@ set (CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
 set (CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
 set (CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
 
-# Don't do compiler autodetection, since we are cross-compiling.
-include (CMakeForceCompiler)
-CMAKE_FORCE_C_COMPILER ("${CMAKE_C_COMPILER}" Clang)
-CMAKE_FORCE_CXX_COMPILER ("${CMAKE_CXX_COMPILER}" Clang)
-
-# Hardwire support for cmake-2.8/Modules/CMakeBackwardsCompatibilityC.cmake without having CMake to try complex things
-# to autodetect these:
-set (CMAKE_SKIP_COMPATIBILITY_TESTS 1)
-set (CMAKE_SIZEOF_CHAR 1)
-set (CMAKE_SIZEOF_UNSIGNED_SHORT 2)
-set (CMAKE_SIZEOF_SHORT 2)
-set (CMAKE_SIZEOF_INT 4)
-set (CMAKE_SIZEOF_UNSIGNED_LONG 4)
-set (CMAKE_SIZEOF_UNSIGNED_INT 4)
-set (CMAKE_SIZEOF_LONG 4)
-set (CMAKE_SIZEOF_VOID_P 4)
-set (CMAKE_SIZEOF_FLOAT 4)
-set (CMAKE_SIZEOF_DOUBLE 8)
-set (CMAKE_C_SIZEOF_DATA_PTR 4)
-set (CMAKE_CXX_SIZEOF_DATA_PTR 4)
-set (CMAKE_HAVE_LIMITS_H 1)
-set (CMAKE_HAVE_UNISTD_H 1)
-set (CMAKE_HAVE_PTHREAD_H 1)
-set (CMAKE_HAVE_SYS_PRCTL_H 1)
-set (CMAKE_WORDS_BIGENDIAN 0)
-set (CMAKE_DL_LIBS)
+# Still perform the compiler checks except for those stated otherwise below
+foreach (LANG C CXX)
+    # Since currently CMake does not able to identify Emscripten compiler toolchain, set the compiler identification explicitly
+    set (CMAKE_${LANG}_COMPILER_ID_RUN TRUE)
+    set (CMAKE_${LANG}_COMPILER_ID Clang)
+    # The ABI info could not be checked as per normal as CMake does not understand the test build output from Emscripten, so bypass it also
+    set (CMAKE_${LANG}_ABI_COMPILED TRUE)
+    set (CMAKE_${LANG}_SIZEOF_DATA_PTR 4)   # Assume it is always 32-bit for now (we could have used our CheckCompilerToolChains.cmake module here)
+    # There could be a bug in CMake itself where setting CMAKE_EXECUTABLE_SUFFIX variable outside of the scope, where it processes the platform configuration files, does not being honored by try_compile() command and as a result all the check macros that depend on try_compile() do not work properly when the CMAKE_EXECUTABLE_SUFFIX variable is only being set later futher down the road; At least one of the CMake devs has the opinion that this is the intended behavior but it is an unconvincing explanation because setting CMAKE_EXECUTABLE_SUFFIX variable later does have the desired effect everywhere else EXCEPT the try_compile() command
+    # We are forced to set CMAKE_EXECUTABLE_SUFFIX_C and CMAKE_EXECUTABLE_SUFFIX_CXX here as a workaround; we could not just set CMAKE_EXECUTABLE_SUFFIX directly because CMake processes platform configuration files after the toolchain file and since we tell CMake that we are cross-compiling for 'Linux' platform via CMAKE_SYSTEM_NAME variable, CMake initializes the CMAKE_EXECUTABLE_SUFFIX to empty string (as expected for Linux platform); the workaround avoids our setting from being overwritten by platform configuration files by using the C and CXX language variants of the variable
+    # The executable suffix needs to be .js for the below Emscripten-specific compiler setting to be effective
+    set (CMAKE_EXECUTABLE_SUFFIX_${LANG} .js)
+endforeach ()
 
-# In order for check_function_exists() detection to work, we must signal it to pass an additional flag, which causes the compilation
-# to abort if linking results in any undefined symbols. The CMake detection mechanism depends on the undefined symbol error to be raised.
+# Set required compiler flags for internal CMake various check_xxx() macros which rely on the error to occur for the check to be performed correctly
 set (CMAKE_REQUIRED_FLAGS "-s ERROR_ON_UNDEFINED_SYMBOLS=1")
 
 # Use response files on Windows host
@@ -112,4 +137,5 @@ if (CMAKE_HOST_WIN32)
     endforeach ()
 endif ()
 
+set (WEB 1)
 set (EMSCRIPTEN 1)

+ 3 - 3
CMakeLists.txt

@@ -25,7 +25,7 @@ endif()
 # this is here as QtCreator is having trouble picking up #include <Atomic/*> without it
 include_directories(${CMAKE_SOURCE_DIR}/Source ${CMAKE_SOURCE_DIR}/Source/AtomicEditor/Source)
 
-set (ATOMIC_LINK_LIBRARIES Atomic Box2D Duktape TurboBadger FreeType JO LZ4 PugiXml STB)
+set (ATOMIC_LINK_LIBRARIES Atomic Box2D Duktape TurboBadger FreeType JO LZ4 PugiXml STB SDL)
 
 if (NOT ATOMIC_BUILD_2D)
     add_definitions( -DATOMIC_PHYSICS -DATOMIC_3D)
@@ -33,8 +33,8 @@ if (NOT ATOMIC_BUILD_2D)
 endif()
 
 if (NOT EMSCRIPTEN)
-    add_definitions( -DATOMIC_NETWORK)
-    set (ATOMIC_LINK_LIBRARIES ${ATOMIC_LINK_LIBRARIES} SDL Civetweb Recast Detour DetourCrowd DetourTileCache kNet libcurl )
+    add_definitions( -DATOMIC_THREADING -DATOMIC_NETWORK)
+    set (ATOMIC_LINK_LIBRARIES ${ATOMIC_LINK_LIBRARIES} Civetweb Recast Detour DetourCrowd DetourTileCache kNet libcurl )
 endif()
 
 add_definitions( -DATOMIC_WEB )

File diff suppressed because it is too large
+ 558 - 87
Data/AtomicEditor/Deployment/Android/src/org/libsdl/app/SDLActivity.java


+ 8 - 8
Resources/CoreData/Materials/DefaultGrey.xml

@@ -1,19 +1,19 @@
 <renderpath>
-    <rendertarget name="vblur" tag="Bloom" sizedivisor="4 4" format="rgb" filter="true" />
-    <rendertarget name="hblur" tag="Bloom" sizedivisor="4 4" format="rgb" filter="true" />
-    <command type="quad" tag="Bloom" vs="Bloom" ps="Bloom" psdefines="BRIGHT" output="vblur">
+    <rendertarget name="blurv" tag="Bloom" sizedivisor="4 4" format="rgb" filter="true" />
+    <rendertarget name="blurh" tag="Bloom" sizedivisor="4 4" format="rgb" filter="true" />
+    <command type="quad" tag="Bloom" vs="Bloom" ps="Bloom" psdefines="BRIGHT" output="blurv">
         <parameter name="BloomThreshold" value="0.3" />
         <texture unit="diffuse" name="viewport" />
     </command>
-    <command type="quad" tag="Bloom" vs="Bloom" ps="Bloom" psdefines="HBLUR" output="hblur">
-        <texture unit="diffuse" name="vblur" />
+    <command type="quad" tag="Bloom" vs="Bloom" ps="Bloom" psdefines="BLURH" output="blurh">
+        <texture unit="diffuse" name="blurv" />
     </command>
-    <command type="quad" tag="Bloom" vs="Bloom" ps="Bloom" psdefines="VBLUR" output="vblur">
-        <texture unit="diffuse" name="hblur" />
+    <command type="quad" tag="Bloom" vs="Bloom" ps="Bloom" psdefines="BLURV" output="blurv">
+        <texture unit="diffuse" name="blurh" />
     </command>
     <command type="quad" tag="Bloom" vs="Bloom" ps="Bloom" psdefines="COMBINE" output="viewport">
         <parameter name="BloomMix" value="0.9 0.4" />
         <texture unit="diffuse" name="viewport" />
-        <texture unit="normal" name="vblur" />
+        <texture unit="normal" name="blurv" />
     </command>
 </renderpath>

+ 1 - 1
Resources/CoreData/PostProcess/BloomHDR.xml

@@ -2,7 +2,7 @@
     <rendertarget name="depth" sizedivisor="1 1" format="lineardepth" />
     <command type="clear" color="1 1 1 1" depth="1.0" stencil="0" output="depth" />
     <command type="scenepass" pass="depth" output="depth" />
-    <command type="clear" color="fog" />
+    <command type="clear" color="fog" depth="1.0" stencil="0" />
     <command type="scenepass" pass="base" vertexlights="true" metadata="base" />
     <command type="forwardlights" pass="light" />
     <command type="scenepass" pass="postopaque" />

+ 30 - 0
Resources/CoreData/RenderPaths/ForwardHWDepth.xml

@@ -0,0 +1,30 @@
+<renderpath>
+    <rendertarget name="specular" sizedivisor="1 1" format="rgba16f" />
+    <rendertarget name="albedo" sizedivisor="1 1" format="rgba16f" />
+    <rendertarget name="normal" sizedivisor="1 1" format="rgba16f" />
+    <rendertarget name="depth" sizedivisor="1 1" format="lineardepth" />
+    <command type="clear" color="0 0 0 0" depth="1.0" stencil="0" />
+    <command type="clear" color="0 0 0 0" output="albedo" />
+    <command type="clear" color="0 0 0 0" output="specular" />
+    <command type="clear" color="0 0 0 0" output="normal" />
+    <command type="clear" color="0 0 0 0" depth="1.0" output="depth" />
+    <command type="scenepass" pass="base" vertexlights="true" metadata="base" />
+    <command type="scenepass" pass="deferred" marktostencil="true" vertexlights="true" metadata="gbuffer">
+        <output index="0" name="specular" />
+        <output index="1" name="albedo" />
+        <output index="2" name="normal" />
+        <output index="3" name="depth" />
+    </command>
+    <command type="lightvolumes" vs="PBRDeferred" ps="PBRDeferred" psdefines="PBRDEFERRED PBR" vsdefines="PBR" output="viewport">
+        <texture unit="specular" name="specular" />
+        <texture unit="albedo" name="albedo" />
+        <texture unit="normal" name="normal" />
+        <texture unit="depth" name="depth" />
+    </command>
+    <command type="scenepass" pass="postopaque" />
+    <command type="scenepass" pass="refract">
+        <texture unit="environment" name="viewport" />
+    </command>
+    <command type="scenepass" pass="alpha" vertexlights="true" sort="backtofront" metadata="alpha" />
+    <command type="scenepass" pass="postalpha" sort="backtofront" />
+</renderpath>

+ 29 - 0
Resources/CoreData/RenderPaths/PBRDeferredHWDepth.xml

@@ -0,0 +1,29 @@
+<renderpath>
+    <rendertarget name="specular" sizedivisor="1 1" format="rgba16f" />
+    <rendertarget name="albedo" sizedivisor="1 1" format="rgba16f" />
+    <rendertarget name="normal" sizedivisor="1 1" format="rgba16f" />
+    <rendertarget name="depth" sizedivisor="1 1" format="readabledepth" />
+    <command type="clear" color="0 0 0 0" depth="1.0" stencil="0" depthstencil="depth" />
+    <command type="clear" color="0 0 0 0" output="albedo" depthstencil="depth"/>
+    <command type="clear" color="0 0 0 0" output="specular" depthstencil="depth" />
+    <command type="clear" color="0 0 0 0" output="normal" depthstencil="depth" />
+    <command type="clear" color="0 0 0 0" depth="1.0" output="depth" depthstencil="depth" />
+    <command type="scenepass" pass="base" vertexlights="true" metadata="base" depthstencil="depth" />
+    <command type="scenepass" pass="deferred" marktostencil="true" vertexlights="true" metadata="gbuffer" depthstencil="depth">
+        <output index="0" name="specular" />
+        <output index="1" name="albedo" />
+        <output index="2" name="normal" />
+    </command>
+    <command type="lightvolumes" vs="PBRDeferred" ps="PBRDeferred" psdefines="PBRDEFERRED PBR HWDEPTH" vsdefines="PBR" output="viewport" depthstencil="depth">
+        <texture unit="specular" name="specular" />
+        <texture unit="albedo" name="albedo" />
+        <texture unit="normal" name="normal" />
+        <texture unit="depth" name="depth" />
+    </command>
+    <command type="scenepass" pass="postopaque" depthstencil="depth"/>
+    <command type="scenepass" pass="refract" depthstencil="depth">
+        <texture unit="environment" name="viewport" />
+    </command>
+    <command type="scenepass" pass="alpha" vertexlights="true" sort="backtofront" metadata="alpha" depthstencil="depth" />
+    <command type="scenepass" pass="postalpha" sort="backtofront" depthstencil="depth" />
+</renderpath>

+ 135 - 0
Resources/CoreData/RenderPaths/Prepass.xml

@@ -0,0 +1,135 @@
+#line 20001
+#ifdef COMPILEPS
+  #ifdef PBR
+    // Following BRDF methods are based upon research Frostbite EA
+    //[Lagrade et al. 2014, "Moving Frostbite to Physically Based Rendering"]
+    
+    //Schlick Fresnel
+    //specular  = the rgb specular color value of the pixel
+    //VdotH     = the dot product of the camera view direction and the half vector 
+    vec3 SchlickFresnel(vec3 specular, float VdotH)
+    {
+        return specular + (vec3(1.0, 1.0, 1.0) - specular) * pow(1.0 - VdotH, 5.0);
+    }
+
+    //Schlick Gaussian Fresnel
+    //specular  = the rgb specular color value of the pixel
+    //VdotH     = the dot product of the camera view direction and the half vector 
+    vec3 SchlickGaussianFresnel(in vec3 specular, in float VdotH)
+    {
+        float sphericalGaussian = pow(2.0, (-5.55473 * VdotH - 6.98316) * VdotH);
+        return specular + (vec3(1.0, 1.0, 1.0) - specular) * sphericalGaussian;
+    }
+
+    //Get Fresnel
+    //specular  = the rgb specular color value of the pixel
+    //VdotH     = the dot product of the camera view direction and the half vector 
+    vec3 Fresnel(vec3 specular, float VdotH)
+    {
+        return SchlickFresnel(specular, VdotH);
+    }
+
+    // Smith GGX corrected Visibility
+    // NdotL        = the dot product of the normal and direction to the light
+    // NdotV        = the dot product of the normal and the camera view direction
+    // roughness    = the roughness of the pixel
+    float SmithGGXSchlickVisibility(float NdotL, float NdotV, float roughness)
+    {
+        float rough2 = roughness * roughness;
+        float lambdaV = NdotL  * sqrt((-NdotV * rough2 + NdotV) * NdotV + rough2);   
+        float lambdaL = NdotV  * sqrt((-NdotL * rough2 + NdotL) * NdotL + rough2);
+    
+        return 0.5 / (lambdaV + lambdaL);
+    }
+
+    // Get Visibility
+    // NdotL        = the dot product of the normal and direction to the light
+    // NdotV        = the dot product of the normal and the camera view direction
+    // roughness    = the roughness of the pixel
+    float Visibility(float NdotL, float NdotV, float roughness)
+    {
+        return SmithGGXSchlickVisibility(NdotL, NdotV, roughness);
+    }
+
+    // Blinn Distribution
+    // NdotH        = the dot product of the normal and the half vector
+    // roughness    = the roughness of the pixel
+    float BlinnPhongDistribution(in float NdotH, in float roughness)
+    {
+        float specPower = max((2.0 / (roughness * roughness)) - 2.0, 1e-4); // Calculate specular power from roughness
+        return pow(clamp(NdotH, 0.0, 1.0), specPower);
+    }
+
+    // Beckmann Distribution
+    // NdotH        = the dot product of the normal and the half vector
+    // roughness    = the roughness of the pixel
+    float BeckmannDistribution(in float NdotH, in float roughness)
+    {
+        float rough2 = roughness * roughness;
+        float roughnessA = 1.0 / (4.0 * rough2 * pow(NdotH, 4.0));
+        float roughnessB = NdotH * NdotH - 1.0;
+        float roughnessC = rough2 * NdotH * NdotH;
+        return roughnessA * exp(roughnessB / roughnessC);
+    }
+
+    // GGX Distribution
+    // NdotH        = the dot product of the normal and the half vector
+    // roughness    = the roughness of the pixel
+    float GGXDistribution(float NdotH, float roughness)
+    {
+        float rough2 = roughness * roughness;
+        float tmp =  (NdotH * rough2 - NdotH) * NdotH + 1.0;
+        return rough2 / (tmp * tmp);
+    }
+
+    // Get Distribution
+    // NdotH        = the dot product of the normal and the half vector
+    // roughness    = the roughness of the pixel
+    float Distribution(float NdotH, float roughness)
+    {
+        return GGXDistribution(NdotH, roughness);
+    }
+
+    // Lambertian Diffuse
+    // diffuseColor = the rgb color value of the pixel
+    // roughness    = the roughness of the pixel
+    // NdotV        = the normal dot with the camera view direction
+    // NdotL        = the normal dot with the light direction
+    // VdotH        = the camera view direction dot with the half vector
+    vec3 LambertianDiffuse(vec3 diffuseColor, float NdotL)
+    {
+        return diffuseColor * NdotL;
+    }
+
+    // Burley Diffuse
+    // diffuseColor = the rgb color value of the pixel
+    // roughness    = the roughness of the pixel
+    // NdotV        = the normal dot with the camera view direction
+    // NdotL        = the normal dot with the light direction
+    // VdotH        = the camera view direction dot with the half vector
+    vec3 BurleyDiffuse(vec3 diffuseColor, float roughness, float NdotV, float NdotL, float VdotH)
+    {
+        float energyBias = mix(roughness, 0.0, 0.5);
+        float energyFactor = mix(roughness, 1.0, 1.0 / 1.51);
+        float fd90 = energyBias + 2.0 * VdotH * VdotH * roughness;
+        float f0 = 1.0;
+        float lightScatter = f0 + (fd90 - f0) * pow(1.0f - NdotL, 5.0f);
+        float viewScatter = f0 + (fd90 - f0) * pow(1.0f - NdotV, 5.0f);
+
+        return diffuseColor * lightScatter * viewScatter * energyFactor;
+    }
+
+    //Get Diffuse
+    // diffuseColor = the rgb color value of the pixel
+    // roughness    = the roughness of the pixel
+    // NdotV        = the normal dot with the camera view direction
+    // NdotL        = the normal dot with the light direction
+    // VdotH        = the camera view direction dot with the half vector
+    vec3 Diffuse(vec3 diffuseColor, float roughness, float NdotV, float NdotL, float VdotH)
+    {
+        //return LambertianDiffuse(diffuseColor, NdotL);
+        return BurleyDiffuse(diffuseColor, roughness, NdotV, NdotL, VdotH);
+    }
+
+  #endif
+#endif

+ 13 - 13
Resources/CoreData/Shaders/GLSL/Bloom.glsl

@@ -9,7 +9,7 @@ varying vec2 vScreenPos;
 #ifdef COMPILEPS
 uniform float cBloomThreshold;
 uniform vec2 cBloomMix;
-uniform vec2 cHBlurInvSize;
+uniform vec2 cBlurHInvSize;
 #endif
 
 void VS()
@@ -28,21 +28,21 @@ void PS()
     gl_FragColor = vec4((rgb - vec3(cBloomThreshold, cBloomThreshold, cBloomThreshold)) / (1.0 - cBloomThreshold), 1.0);
     #endif
 
-    #ifdef HBLUR
-    vec3 rgb = texture2D(sDiffMap, vTexCoord + vec2(-2.0, 0.0) * cHBlurInvSize).rgb * 0.1;
-    rgb += texture2D(sDiffMap, vTexCoord + vec2(-1.0, 0.0) * cHBlurInvSize).rgb * 0.25;
-    rgb += texture2D(sDiffMap, vTexCoord + vec2(0.0, 0.0) * cHBlurInvSize).rgb * 0.3;
-    rgb += texture2D(sDiffMap, vTexCoord + vec2(1.0, 0.0) * cHBlurInvSize).rgb * 0.25;
-    rgb += texture2D(sDiffMap, vTexCoord + vec2(2.0, 0.0) * cHBlurInvSize).rgb * 0.1;
+    #ifdef BLURH
+    vec3 rgb = texture2D(sDiffMap, vTexCoord + vec2(-2.0, 0.0) * cBlurHInvSize).rgb * 0.1;
+    rgb += texture2D(sDiffMap, vTexCoord + vec2(-1.0, 0.0) * cBlurHInvSize).rgb * 0.25;
+    rgb += texture2D(sDiffMap, vTexCoord + vec2(0.0, 0.0) * cBlurHInvSize).rgb * 0.3;
+    rgb += texture2D(sDiffMap, vTexCoord + vec2(1.0, 0.0) * cBlurHInvSize).rgb * 0.25;
+    rgb += texture2D(sDiffMap, vTexCoord + vec2(2.0, 0.0) * cBlurHInvSize).rgb * 0.1;
     gl_FragColor = vec4(rgb, 1.0);
     #endif
 
-    #ifdef VBLUR
-    vec3 rgb = texture2D(sDiffMap, vTexCoord + vec2(0.0, -2.0) * cHBlurInvSize).rgb * 0.1;
-    rgb += texture2D(sDiffMap, vTexCoord + vec2(0.0, -1.0) * cHBlurInvSize).rgb * 0.25;
-    rgb += texture2D(sDiffMap, vTexCoord + vec2(0.0, 0.0) * cHBlurInvSize).rgb * 0.3;
-    rgb += texture2D(sDiffMap, vTexCoord + vec2(0.0, 1.0) * cHBlurInvSize).rgb * 0.25;
-    rgb += texture2D(sDiffMap, vTexCoord + vec2(0.0, 2.0) * cHBlurInvSize).rgb * 0.1;
+    #ifdef BLURV
+    vec3 rgb = texture2D(sDiffMap, vTexCoord + vec2(0.0, -2.0) * cBlurHInvSize).rgb * 0.1;
+    rgb += texture2D(sDiffMap, vTexCoord + vec2(0.0, -1.0) * cBlurHInvSize).rgb * 0.25;
+    rgb += texture2D(sDiffMap, vTexCoord + vec2(0.0, 0.0) * cBlurHInvSize).rgb * 0.3;
+    rgb += texture2D(sDiffMap, vTexCoord + vec2(0.0, 1.0) * cBlurHInvSize).rgb * 0.25;
+    rgb += texture2D(sDiffMap, vTexCoord + vec2(0.0, 2.0) * cBlurHInvSize).rgb * 0.1;
     gl_FragColor = vec4(rgb, 1.0);
     #endif
 

+ 7 - 0
Resources/CoreData/Shaders/GLSL/Constants.glsl

@@ -0,0 +1,7 @@
+#define M_PI 3.14159265358979323846
+#define M_EPSILON 0.0001
+
+#ifdef PBR
+#define ROUGHNESS_FLOOR 0.003
+#define METALNESS_FLOOR 0.03
+#endif

+ 6 - 2
Resources/CoreData/Shaders/GLSL/DeferredLight.glsl

@@ -66,6 +66,10 @@ void PS()
         vec4 normalInput = texture2DProj(sNormalBuffer, vScreenPos);
     #endif
 
+    // Position acquired via near/far ray is relative to camera. Bring position to world space
+    vec3 eyeVec = -worldPos;
+    worldPos += cCameraPosPS;
+    
     vec3 normal = normalize(normalInput.rgb * 2.0 - 1.0);
     vec4 projWorldPos = vec4(worldPos, 1.0);
     vec3 lightColor;
@@ -74,7 +78,7 @@ void PS()
     float diff = GetDiffuse(normal, worldPos, lightDir);
 
     #ifdef SHADOW
-        diff *= GetShadowDeferred(projWorldPos, depth);
+        diff *= GetShadowDeferred(projWorldPos, normal, depth);
     #endif
 
     #if defined(SPOTLIGHT)
@@ -88,7 +92,7 @@ void PS()
     #endif
 
     #ifdef SPECULAR
-        float spec = GetSpecular(normal, -worldPos, lightDir, normalInput.a * 255.0);
+        float spec = GetSpecular(normal, eyeVec, lightDir, normalInput.a * 255.0);
         gl_FragColor = diff * vec4(lightColor * (albedoInput.rgb + spec * cLightColor.a * albedoInput.aaa), 0.0);
     #else
         gl_FragColor = diff * vec4(lightColor * albedoInput.rgb, 0.0);

+ 300 - 0
Resources/CoreData/Shaders/GLSL/IBL.glsl

@@ -0,0 +1,300 @@
+#line 10001
+#ifdef COMPILEPS
+
+    //
+    // Legacy Importance Sampled IBL
+    //
+
+    // vec3 ImportanceSampleSimple(in vec2 Xi, in float roughness, in vec3 T, in vec3 B, in vec3 N)
+    // {
+    //     float a = roughness * roughness;
+    //     mat3 tbn = mat3(T, B, N);
+    //     #ifdef IBLFAST
+    //         const float blurFactor = 0.0;
+    //     #else
+    //         const float blurFactor = 5.0;
+    //     #endif
+    //     vec2 xx = Xi.xy * blurFactor;
+    //     xx = xx - 1.0 * trunc(xx/1.0); // hlsl style modulo
+    //     vec3 Xi3 = mix(vec3(0,0,1), normalize(vec3(xx, 1.0)), a);
+    //     vec3 XiWS = tbn * Xi3;
+    //     return normalize(N + XiWS);
+    // }
+
+    // // Karis '13
+    // vec3 ImportanceSampleGGX(in vec2 Xi, in float roughness, in vec3 T, in vec3 B, in vec3 N)
+    // {
+    //     float a = roughness * roughness;
+    //     float Phi = 2.0 * M_PI * Xi.x;
+    //     float CosTheta = sqrt((1.0 - Xi.y) / (1.0 + (a*a - 1.0) * Xi.y));
+    //     float SinTheta = sqrt(1.0 - CosTheta * CosTheta);
+    //     vec3 H = vec3(0,0,0);
+    //     H.x = SinTheta * cos(Phi);
+    //     H.y = SinTheta * sin(Phi);
+    //     H.z = CosTheta;
+
+    //     vec3 UpVector = abs(N.z) < 0.999 ? vec3(0.0, 0.0, 1.0) : vec3(1.0, 0.0, 0.0);
+    //     vec3 TangentX = normalize(cross(UpVector, N));
+    //     vec3 TangentY = cross(N, TangentX);
+    //     // Tangent to world space
+    //     return TangentX * H.x + TangentY * H.y + N * H.z;
+    // }
+
+    // #ifdef IBLFAST
+    //     #define IMPORTANCE_SAMPLES 1
+    // #else
+    //     #define IMPORTANCE_SAMPLES 4
+    // #endif
+
+    // #define IMPORTANCE_KERNEL_SIZE 16
+    // vec2 IMPORTANCE_KERNEL[IMPORTANCE_KERNEL_SIZE] = vec2[] (
+    //     vec2(-0.0780436, 0.0558389),
+    //     vec2(0.034318, -0.0635879),
+    //     vec2(0.00230821, 0.0807279),
+    //     vec2(0.0124638, 0.117585),
+    //     vec2(0.093943, -0.0944602),
+    //     vec2(0.139348, -0.109816),
+    //     vec2(-0.181872, -0.129649),
+    //     vec2(0.240066, -0.0494057),
+    //     vec2(0.115965, -0.0374714),
+    //     vec2(-0.294819, -0.100726),
+    //     vec2(-0.149652, 0.37459),
+    //     vec2(0.261695, -0.292813),
+    //     vec2(-0.37944, -0.425145),
+    //     vec2(0.628994, -0.189387),
+    //     vec2(-0.331257, -0.646864),
+    //     vec2(-0.467004, 0.439687)
+    //   );
+
+    //   float GetMipFromRougness(float roughness)
+    //   {
+    //       float smoothness = 1.0 - roughness;
+    //       return (1.0 - smoothness * smoothness) * 10.0;
+    //   }
+
+    // /// Perform importance sampling
+    // ///     reflectVec: calculated vector of reflection
+    // ///     wsNormal: world-space normal of the surface
+    // ///     toCamera: direction from the pixel to the camera
+    // ///     specular: specular color
+    // ///     roughness: surface roughness
+    // ///     reflectionCubeColor: output color for diffuse
+    // // Implementation based on Epics 2013 course notes
+    // vec3 ImportanceSampling(in vec3 reflectVec, in vec3 tangent, in vec3 bitangent, in vec3 wsNormal, in vec3 toCamera,  in vec3 diffColor, in vec3 specColor, in float roughness, inout vec3 reflectionCubeColor)
+    // {
+    //     reflectionCubeColor = vec3(1,1,1);
+
+    //     vec3 reflectSpec = normalize(GetSpecularDominantDir(wsNormal, reflectVec, roughness));
+
+    //     vec3 V = normalize(-toCamera);
+    //     vec3 N = normalize(wsNormal);
+    //     float ndv = clamp(abs(dot(N, V)), 0.0, 1.0);
+
+    //     float specMipLevel = GetMipFromRougness(roughness);
+
+    //     vec3 accumulatedColor = vec3(0,0,0);
+    //     for (int i = 0; i < IMPORTANCE_SAMPLES; ++i)
+    //     {
+    //         vec3 kd = vec3(1,1,1);
+    //         vec3 diffuseFactor = vec3(0,0,0);
+    //         vec3 specularFactor = vec3(0,0,0);
+
+    //         {
+    //             // Diffuse IBL
+    //             const float rough = 1.0;
+    //             const float mipLevel = 9.0;
+
+    //             vec3 H = ImportanceSampleSimple(IMPORTANCE_KERNEL[i], rough, tangent, bitangent, N);
+    //             vec3 L = 2.0 * dot( V, H ) * H - V;
+
+    //             float vdh = clamp(abs(dot(V, H)), 0.0, 1.0);
+    //             float ndh = clamp(abs(dot(N, H)), 0.0, 1.0);
+    //             float ndl = clamp(abs(dot(N, L)), 0.0, 1.0);
+
+    //             vec3 sampledColor = textureLod(sZoneCubeMap, L, mipLevel).rgb;
+
+    //             vec3 diffuseTerm = Diffuse(diffColor, rough, ndv, ndl, vdh);
+    //             vec3 lightTerm = sampledColor;
+
+    //             diffuseFactor = lightTerm * diffuseTerm;
+    //         }
+
+    //         {
+    //             // Specular IBL
+    //             float rough = roughness;
+    //             float mipLevel = specMipLevel;
+
+    //             vec3 H = ImportanceSampleSimple(IMPORTANCE_KERNEL[i], rough, tangent, bitangent, N);
+    //             vec3 L = 2.0 * dot( V, H ) * H - V;
+    //             vec3 sampledColor = textureLod(sZoneCubeMap, L, mipLevel).rgb;
+
+    //             float vdh = clamp(abs(dot(V, H)), 0.0, 1.0);
+    //             float ndh = clamp(abs(dot(N, H)), 0.0, 1.0);
+    //             float ndl = clamp(abs(dot(N, L)), 0.0, 1.0);
+
+    //             vec3 fresnelTerm = Fresnel(specColor, vdh);
+    //             float distTerm = 1.0; // Optimization, this term is mathematically cancelled out  -- Distribution(ndh, roughness);
+    //             float visTerm = Visibility(ndl, ndv, rough);
+
+    //             vec3 lightTerm = sampledColor * ndl;
+
+    //             float pdf = ndl > 0.05 ? ImportanceSamplePDF(distTerm, ndh, vdh) : 4.0; // reduce artifacts at extreme grazing angles
+
+    //             vec3 specularTerm = SpecularBRDF(distTerm, fresnelTerm, visTerm, ndl, ndv);
+
+    //             // energy conservation:
+    //             // Specular conservation:
+    //             specularFactor = lightTerm * specularTerm / pdf;
+    //             specularFactor = max(
+    //               clamp(normalize(specularFactor) * (length(sampledColor * specColor)), 0.0, 1.0),
+    //               specularFactor
+    //             );
+
+    //             // Diffuse conservation:
+    //             //kd = (sampledColor * specColor)/specularFactor; //energy conservation
+    //             kd = 1.0 - specularFactor;
+    //         }
+
+    //         accumulatedColor += specularFactor + diffuseFactor * kd;
+    //     }
+
+    //     return (accumulatedColor / IMPORTANCE_SAMPLES);
+    // }
+
+    // vec3 ImportanceSamplingSimple(in vec3 reflectVec, in vec3 tangent, in vec3 bitangent, in vec3 wsNormal, in vec3 toCamera,  in vec3 diffColor, in vec3 specColor, in float roughness, inout vec3 reflectionCubeColor)
+    // {
+    //     reflectionCubeColor = vec3(1,1,1);
+
+    //     reflectVec = normalize(GetSpecularDominantDir(wsNormal, reflectVec, roughness));
+
+    //     vec3 Hn = normalize(-toCamera + wsNormal);
+    //     float ndv = clamp(dot(-toCamera, wsNormal), 0.0, 1.0);
+    //     float vdh = clamp(dot(-toCamera, Hn), 0.0, 1.0);
+    //     float ndh = clamp(dot(wsNormal, Hn), 0.0, 1.0);
+
+    //     vec3 accumulatedColor = vec3(0,0,0);
+    //     for (int i = 0; i < IMPORTANCE_SAMPLES; ++i)
+    //     {
+    //         vec3 kd = vec3(1,1,1);
+    //         vec3 diffuseFactor = vec3(0,0,0);
+    //         vec3 specularFactor = vec3(0,0,0);
+
+    //         {
+    //             // Diffuse IBL
+    //             const float rough = 1.0;
+    //             const float mipLevel = 9.0;
+
+    //             vec3 perturb = ImportanceSampleGGX(IMPORTANCE_KERNEL[i].xy, rough, tangent, bitangent, wsNormal);
+    //             vec3 sampleVec = wsNormal + perturb; //perturb by the sample vector
+
+    //             vec3 sampledColor = textureLod(sZoneCubeMap, sampleVec, mipLevel).rgb;
+    //             float ndl = clamp(dot(sampleVec, wsNormal), 0.0, 1.0);
+
+    //             vec3 diffuseTerm = Diffuse(diffColor, rough, ndv, ndl, vdh);
+    //             vec3 lightTerm = sampledColor;
+
+    //             diffuseFactor = lightTerm * diffuseTerm;
+    //         }
+
+    //         {
+    //             // Specular IBL
+    //             float rough = roughness;
+    //             float mipLevel =  GetMipFromRougness(rough);
+
+    //             vec3 perturb = ImportanceSampleGGX(IMPORTANCE_KERNEL[i].xy, rough, tangent, bitangent, reflectVec);
+    //             vec3 sampleVec = reflectVec + perturb; //perturb by the sample vector
+
+    //             vec3 sampledColor = textureCube(sZoneCubeMap, sampleVec, mipLevel).rgb;
+    //             float ndl = clamp(dot(sampleVec, wsNormal), 0.0, 1.0);
+
+    //             vec3 fresnelTerm = SchlickFresnel(specColor, ndh) ;
+    //             float distTerm = 1.0; //Optimization, this term is mathematically cancelled out  //Distribution(ndh, roughness);
+    //             float visTerm = SmithGGXVisibility(ndl, ndv, rough);
+    //             vec3 lightTerm = sampledColor * ndl;
+
+    //             float pdf = 1.0; //ImportanceSamplePDF(distTerm, ndh, vdh);
+
+    //             specularFactor = lightTerm * SpecularBRDF(distTerm, fresnelTerm, visTerm, ndl, ndv) / pdf;
+    //             specularFactor *= pdf * ndv * (4.0 * ndl * ndv); // hacks
+    //             kd = (1.0 - clamp(specularFactor, 0.0, 1.0)); //energy conservation
+    //         }
+
+    //         accumulatedColor += specularFactor + diffuseFactor * kd;
+    //     }
+
+    //     return accumulatedColor / IMPORTANCE_SAMPLES;
+    // }
+
+    /// Determine reflection vector based on surface roughness, rougher uses closer to the normal and smoother uses closer to the reflection vector
+    ///     normal: surface normal
+    ///     reflection: vector of reflection off of the surface
+    ///     roughness: surface roughness
+    vec3 GetSpecularDominantDir(vec3 normal, vec3 reflection, float roughness)
+    {
+        float smoothness = 1.0 - roughness;
+        float lerpFactor = smoothness * (sqrt(smoothness) + roughness);
+        return mix(normal, reflection, lerpFactor);
+    }
+
+    float GetMipFromRougness(float roughness)
+    {
+        float smoothness = 1.0 - roughness;
+        return (1.0 - smoothness * smoothness) * 10.0;
+    }
+
+
+    vec3 EnvBRDFApprox (vec3 SpecularColor, float Roughness, float NoV)
+    {
+        vec4 c0 = vec4(-1, -0.0275, -0.572, 0.022 );
+        vec4 c1 = vec4(1, 0.0425, 1.0, -0.04 );
+        vec4 r = Roughness * c0 + c1;
+        float a004 = min( r.x * r.x, exp2( -9.28 * NoV ) ) * r.x + r.y;
+        vec2 AB = vec2( -1.04, 1.04 ) * a004 + r.zw;
+        return SpecularColor * AB.x + AB.y;
+    }
+
+    /// Calculate IBL contributation
+    ///     reflectVec: reflection vector for cube sampling
+    ///     wsNormal: surface normal in word space
+    ///     toCamera: normalized direction from surface point to camera
+    ///     roughness: surface roughness
+    ///     ambientOcclusion: ambient occlusion
+    vec3 ImageBasedLighting(vec3 reflectVec, vec3 tangent, vec3 bitangent, vec3 wsNormal, vec3 toCamera, vec3 diffColor, vec3 specColor, float roughness, inout vec3 reflectionCubeColor)
+    {
+        reflectVec = GetSpecularDominantDir(wsNormal, reflectVec, roughness);
+        float ndv = clamp(dot(-toCamera, wsNormal), 0.0, 1.0);
+
+        // PMREM Mipmapmode https://seblagarde.wordpress.com/2012/06/10/amd-cubemapgen-for-physically-based-rendering/
+        //float GlossScale = 16.0;
+        //float GlossBias = 5.0;
+        float mipSelect = roughness * 9.0; //exp2(GlossScale * roughness * roughness + GlossBias) - exp2(GlossBias);
+
+        // OpenGL ES does not support textureLod without extensions and does not have the sZoneCubeMap sampler,
+        // so for now, sample without explicit LOD, and from the environment sampler, where the zone texture will be put
+        // on mobile hardware
+        #ifndef GL_ES
+            vec3 cube = textureLod(sZoneCubeMap, reflectVec, mipSelect).rgb;
+            vec3 cubeD = textureLod(sZoneCubeMap, wsNormal, 9.0).rgb;
+        #else
+            vec3 cube = textureCube(sEnvCubeMap, reflectVec).rgb;
+            vec3 cubeD = textureCube(sEnvCubeMap, wsNormal).rgb;
+        #endif
+
+        // Fake the HDR texture
+        float brightness = clamp(cAmbientColor.a, 0.0, 1.0);
+        float darknessCutoff = clamp((cAmbientColor.a - 1.0) * 0.1, 0.0, 0.25);
+
+        const float hdrMaxBrightness = 5.0;
+        vec3 hdrCube = pow(cube + darknessCutoff, vec3(max(1.0, cAmbientColor.a)));
+        hdrCube += max(vec3(0.0), hdrCube - vec3(1.0)) * hdrMaxBrightness;
+
+        vec3 hdrCubeD = pow(cubeD + darknessCutoff, vec3(max(1.0, cAmbientColor.a)));
+        hdrCubeD += max(vec3(0.0), hdrCubeD - vec3(1.0)) * hdrMaxBrightness;
+
+        vec3 environmentSpecular = EnvBRDFApprox(specColor, roughness, ndv);
+        vec3 environmentDiffuse = EnvBRDFApprox(diffColor, 1.0, ndv);
+
+        return (hdrCube * environmentSpecular + hdrCubeD * environmentDiffuse) * brightness;
+        //return ImportanceSampling(reflectVec, tangent, bitangent, wsNormal, toCamera, diffColor, specColor, roughness, reflectionCubeColor);
+    }
+#endif

+ 161 - 62
Resources/CoreData/Shaders/GLSL/Lighting.glsl

@@ -16,7 +16,11 @@ float GetVertexLight(int index, vec3 worldPos, vec3 normal)
     // Directional light
     if (invRange == 0.0)
     {
-        float NdotL = max(dot(normal, lightDir), 0.0);
+        #ifdef TRANSLUCENT
+            float NdotL = abs(dot(normal, lightDir));
+        #else
+            float NdotL = max(dot(normal, lightDir), 0.0);
+        #endif
         return NdotL;
     }
     // Point/spot light
@@ -25,7 +29,11 @@ float GetVertexLight(int index, vec3 worldPos, vec3 normal)
         vec3 lightVec = (lightPos - worldPos) * invRange;
         float lightDist = length(lightVec);
         vec3 localDir = lightVec / lightDist;
-        float NdotL = max(dot(normal, localDir), 0.0);
+        #ifdef TRANSLUCENT
+            float NdotL = abs(dot(normal, localDir));
+        #else
+            float NdotL = max(dot(normal, localDir), 0.0);
+        #endif
         float atten = clamp(1.0 - lightDist * lightDist, 0.0, 1.0);
         float spotEffect = dot(localDir, lightDir);
         float spotAtten = clamp((spotEffect - cutoff) * invCutoff, 0.0, 1.0);
@@ -66,8 +74,23 @@ float GetVertexLightVolumetric(int index, vec3 worldPos)
     #define NUMCASCADES 1
 #endif
 
-vec4 GetShadowPos(int index, vec4 projWorldPos)
+vec4 GetShadowPos(int index, vec3 normal, vec4 projWorldPos)
 {
+    #ifdef NORMALOFFSET
+        float normalOffsetScale[4];
+        normalOffsetScale[0] = cNormalOffsetScale.x;
+        normalOffsetScale[1] = cNormalOffsetScale.y;
+        normalOffsetScale[2] = cNormalOffsetScale.z;
+        normalOffsetScale[3] = cNormalOffsetScale.w;
+
+        #ifdef DIRLIGHT
+            float cosAngle = clamp(1.0 - dot(normal, cLightDir), 0.0, 1.0);
+        #else
+            float cosAngle = clamp(1.0 - dot(normal, normalize(cLightPos - projWorldPos.xyz)), 0.0, 1.0);
+        #endif
+        projWorldPos.xyz += cosAngle * normalOffsetScale[index] * normal;
+    #endif
+
     #if defined(DIRLIGHT)
         return projWorldPos * cLightMatrices[index];
     #elif defined(SPOTLIGHT)
@@ -85,12 +108,35 @@ float GetDiffuse(vec3 normal, vec3 worldPos, out vec3 lightDir)
 {
     #ifdef DIRLIGHT
         lightDir = cLightDirPS;
-        return max(dot(normal, lightDir), 0.0);
+        #ifdef TRANSLUCENT
+            return abs(dot(normal, lightDir));
+        #else
+            return max(dot(normal, lightDir), 0.0);
+        #endif
     #else
         vec3 lightVec = (cLightPosPS.xyz - worldPos) * cLightPosPS.w;
         float lightDist = length(lightVec);
         lightDir = lightVec / lightDist;
-        return max(dot(normal, lightDir), 0.0) * texture2D(sLightRampMap, vec2(lightDist, 0.0)).r;
+        #ifdef TRANSLUCENT
+            return abs(dot(normal, lightDir)) * texture2D(sLightRampMap, vec2(lightDist, 0.0)).r;
+        #else
+            return max(dot(normal, lightDir), 0.0) * texture2D(sLightRampMap, vec2(lightDist, 0.0)).r;
+        #endif
+    #endif
+}
+
+float GetAtten(vec3 normal, vec3 worldPos, out vec3 lightDir)
+{
+     #ifdef DIRLIGHT
+        lightDir = cLightDirPS;
+        return clamp(dot(normal, lightDir), 0.0, 1.0);
+    #else
+        vec3 lightVec = (cLightPosPS.xyz - worldPos) * cLightPosPS.w;
+        float lightDist = length(lightVec);
+        float falloff = pow(clamp(1.0 - pow(lightDist / 1.0, 4.0), 0.0, 1.0), 2.0) / (pow(lightDist, 2.0) + 1.0);
+
+        lightDir = lightVec / vec3(lightDist, lightDist, lightDist);
+        return clamp(dot(normal, lightDir), 0.0, 1.0) * falloff;
     #endif
 }
 
@@ -107,7 +153,7 @@ float GetDiffuseVolumetric(vec3 worldPos)
 
 float GetSpecular(vec3 normal, vec3 eyeVec, vec3 lightDir, float specularPower)
 {
-    vec3 halfVec = normalize(normalize(eyeVec) + lightDir);
+    vec3 halfVec = normalize(normalize(eyeVec) + lightDir);  
     return pow(max(dot(normal, halfVec), 0.0), specularPower);
 }
 
@@ -124,54 +170,88 @@ float GetIntensity(vec3 color)
     #define NUMCASCADES 1
 #endif
 
+#ifdef VSM_SHADOW
+float ReduceLightBleeding(float min, float p_max)  
+{  
+    return clamp((p_max - min) / (1.0 - min), 0.0, 1.0);  
+}
+
+float Chebyshev(vec2 Moments, float depth)  
+{  
+    //One-tailed inequality valid if depth > Moments.x  
+    float p = float(depth <= Moments.x);  
+    //Compute variance.  
+    float Variance = Moments.y - (Moments.x * Moments.x); 
+
+    float minVariance = cVSMShadowParams.x;
+    Variance = max(Variance, minVariance);
+    //Compute probabilistic upper bound.  
+    float d = depth - Moments.x;  
+    float p_max = Variance / (Variance + d*d); 
+    // Prevent light bleeding
+    p_max = ReduceLightBleeding(cVSMShadowParams.y, p_max);
+
+    return max(p, p_max);
+}
+#endif
+
+#ifndef GL_ES
 float GetShadow(vec4 shadowPos)
 {
-    #ifndef GL_ES
-        #ifndef LQSHADOW
-            // Take four samples and average them
-            // Note: in case of sampling a point light cube shadow, we optimize out the w divide as it has already been performed
-            #ifndef POINTLIGHT
-                vec2 offsets = cShadowMapInvSize * shadowPos.w;
-            #else
-                vec2 offsets = cShadowMapInvSize;
-            #endif
-            #ifndef GL3
-                return cShadowIntensity.y + cShadowIntensity.x * (shadow2DProj(sShadowMap, shadowPos).r +
-                    shadow2DProj(sShadowMap, vec4(shadowPos.x + offsets.x, shadowPos.yzw)).r +
-                    shadow2DProj(sShadowMap, vec4(shadowPos.x, shadowPos.y + offsets.y, shadowPos.zw)).r +
-                    shadow2DProj(sShadowMap, vec4(shadowPos.xy + offsets.xy, shadowPos.zw)).r);
-            #else
-                return cShadowIntensity.y + cShadowIntensity.x * (textureProj(sShadowMap, shadowPos) +
-                    textureProj(sShadowMap, vec4(shadowPos.x + offsets.x, shadowPos.yzw)) +
-                    textureProj(sShadowMap, vec4(shadowPos.x, shadowPos.y + offsets.y, shadowPos.zw)) +
-                    textureProj(sShadowMap, vec4(shadowPos.xy + offsets.xy, shadowPos.zw)));
-            #endif
+    #if defined(SIMPLE_SHADOW)
+        // Take one sample
+        #ifndef GL3
+            float inLight = shadow2DProj(sShadowMap, shadowPos).r;
         #else
-            // Take one sample
-            #ifndef GL3
-                float inLight = shadow2DProj(sShadowMap, shadowPos).r;
-            #else
-                float inLight = textureProj(sShadowMap, shadowPos);
-            #endif
-            return cShadowIntensity.y + cShadowIntensity.x * inLight;
+            float inLight = textureProj(sShadowMap, shadowPos);
         #endif
-    #else
-        #ifndef LQSHADOW
-            // Take four samples and average them
+        return cShadowIntensity.y + cShadowIntensity.x * inLight;
+    #elif defined(PCF_SHADOW)
+        // Take four samples and average them
+        // Note: in case of sampling a point light cube shadow, we optimize out the w divide as it has already been performed
+        #ifndef POINTLIGHT
             vec2 offsets = cShadowMapInvSize * shadowPos.w;
-            vec4 inLight = vec4(
-                texture2DProj(sShadowMap, shadowPos).r * shadowPos.w > shadowPos.z,
-                texture2DProj(sShadowMap, vec4(shadowPos.x + offsets.x, shadowPos.yzw)).r * shadowPos.w > shadowPos.z,
-                texture2DProj(sShadowMap, vec4(shadowPos.x, shadowPos.y + offsets.y, shadowPos.zw)).r * shadowPos.w > shadowPos.z,
-                texture2DProj(sShadowMap, vec4(shadowPos.xy + offsets.xy, shadowPos.zw)).r * shadowPos.w > shadowPos.z
-            );
-            return cShadowIntensity.y + dot(inLight, vec4(cShadowIntensity.x));
         #else
-            // Take one sample
-            return cShadowIntensity.y + (texture2DProj(sShadowMap, shadowPos).r * shadowPos.w > shadowPos.z ? cShadowIntensity.x : 0.0);
+            vec2 offsets = cShadowMapInvSize;
+        #endif
+        #ifndef GL3
+            return cShadowIntensity.y + cShadowIntensity.x * (shadow2DProj(sShadowMap, shadowPos).r +
+                shadow2DProj(sShadowMap, vec4(shadowPos.x + offsets.x, shadowPos.yzw)).r +
+                shadow2DProj(sShadowMap, vec4(shadowPos.x, shadowPos.y + offsets.y, shadowPos.zw)).r +
+                shadow2DProj(sShadowMap, vec4(shadowPos.xy + offsets.xy, shadowPos.zw)).r);
+        #else
+            return cShadowIntensity.y + cShadowIntensity.x * (textureProj(sShadowMap, shadowPos) +
+                textureProj(sShadowMap, vec4(shadowPos.x + offsets.x, shadowPos.yzw)) +
+                textureProj(sShadowMap, vec4(shadowPos.x, shadowPos.y + offsets.y, shadowPos.zw)) +
+                textureProj(sShadowMap, vec4(shadowPos.xy + offsets.xy, shadowPos.zw)));
         #endif
+    #elif defined(VSM_SHADOW)
+        vec2 samples = texture2D(sShadowMap, shadowPos.xy / shadowPos.w).rg; 
+        return cShadowIntensity.y + cShadowIntensity.x * Chebyshev(samples, shadowPos.z / shadowPos.w);
     #endif
 }
+#else
+float GetShadow(highp vec4 shadowPos)
+{
+    #if defined(SIMPLE_SHADOW)
+        // Take one sample
+        return cShadowIntensity.y + (texture2DProj(sShadowMap, shadowPos).r * shadowPos.w > shadowPos.z ? cShadowIntensity.x : 0.0);
+    #elif defined(PCF_SHADOW)
+        // Take four samples and average them
+        vec2 offsets = cShadowMapInvSize * shadowPos.w;
+        vec4 inLight = vec4(
+            texture2DProj(sShadowMap, shadowPos).r * shadowPos.w > shadowPos.z,
+            texture2DProj(sShadowMap, vec4(shadowPos.x + offsets.x, shadowPos.yzw)).r * shadowPos.w > shadowPos.z,
+            texture2DProj(sShadowMap, vec4(shadowPos.x, shadowPos.y + offsets.y, shadowPos.zw)).r * shadowPos.w > shadowPos.z,
+            texture2DProj(sShadowMap, vec4(shadowPos.xy + offsets.xy, shadowPos.zw)).r * shadowPos.w > shadowPos.z
+        );
+        return cShadowIntensity.y + dot(inLight, vec4(cShadowIntensity.x));
+    #elif defined(VSM_SHADOW)
+        vec2 samples = texture2D(sShadowMap, shadowPos.xy / shadowPos.w).rg; 
+        return cShadowIntensity.y + cShadowIntensity.x * Chebyshev(samples, shadowPos.z / shadowPos.w);
+    #endif
+}
+#endif
 
 #ifdef POINTLIGHT
 float GetPointShadow(vec3 lightVec)
@@ -225,18 +305,30 @@ float GetDirShadow(const vec4 iShadowPos[NUMCASCADES], float depth)
 #endif
 
 #ifndef GL_ES
-float GetDirShadowDeferred(vec4 projWorldPos, float depth)
+float GetDirShadowDeferred(vec4 projWorldPos, vec3 normal, float depth)
 {
     vec4 shadowPos;
 
-    if (depth < cShadowSplits.x)
-        shadowPos = projWorldPos * cLightMatricesPS[0];
-    else if (depth < cShadowSplits.y)
-        shadowPos = projWorldPos * cLightMatricesPS[1];
-    else if (depth < cShadowSplits.z)
-        shadowPos = projWorldPos * cLightMatricesPS[2];
-    else
-        shadowPos = projWorldPos * cLightMatricesPS[3];
+    #ifdef NORMALOFFSET
+        float cosAngle = clamp(1.0 - dot(normal, cLightDirPS), 0.0, 1.0);
+        if (depth < cShadowSplits.x)
+            shadowPos = vec4(projWorldPos.xyz + cosAngle * cNormalOffsetScalePS.x * normal, 1.0) * cLightMatricesPS[0];
+        else if (depth < cShadowSplits.y)
+            shadowPos = vec4(projWorldPos.xyz + cosAngle * cNormalOffsetScalePS.y * normal, 1.0) * cLightMatricesPS[1];
+        else if (depth < cShadowSplits.z)
+            shadowPos = vec4(projWorldPos.xyz + cosAngle * cNormalOffsetScalePS.z * normal, 1.0) * cLightMatricesPS[2];
+        else
+            shadowPos = vec4(projWorldPos.xyz + cosAngle * cNormalOffsetScalePS.w * normal, 1.0) * cLightMatricesPS[3];
+    #else
+        if (depth < cShadowSplits.x)
+            shadowPos = projWorldPos * cLightMatricesPS[0];
+        else if (depth < cShadowSplits.y)
+            shadowPos = projWorldPos * cLightMatricesPS[1];
+        else if (depth < cShadowSplits.z)
+            shadowPos = projWorldPos * cLightMatricesPS[2];
+        else
+            shadowPos = projWorldPos * cLightMatricesPS[3];
+    #endif
 
     return GetDirShadowFade(GetShadow(shadowPos), depth);
 }
@@ -255,16 +347,23 @@ float GetShadow(vec4 iShadowPos[NUMCASCADES], float depth)
 }
 
 #ifndef GL_ES
-float GetShadowDeferred(vec4 projWorldPos, float depth)
+float GetShadowDeferred(vec4 projWorldPos, vec3 normal, float depth)
 {
-    #if defined(DIRLIGHT)
-        return GetDirShadowDeferred(projWorldPos, depth);
-    #elif defined(SPOTLIGHT)
-        vec4 shadowPos = projWorldPos * cLightMatricesPS[1];
-        return GetShadow(shadowPos);
+    #ifdef DIRLIGHT
+        return GetDirShadowDeferred(projWorldPos, normal, depth);
     #else
-        vec3 shadowPos = projWorldPos.xyz - cLightPosPS.xyz;
-        return GetPointShadow(shadowPos);
+        #ifdef NORMALOFFSET
+            float cosAngle = clamp(1.0 - dot(normal, normalize(cLightPosPS - projWorldPos.xyz)), 0.0, 1.0);
+            projWorldPos.xyz += cosAngle * cNormalOffsetScalePS.x * normal;
+        #endif
+
+        #ifdef SPOTLIGHT
+            vec4 shadowPos = projWorldPos * cLightMatricesPS[1];
+            return GetShadow(shadowPos);
+        #else
+            vec3 shadowPos = projWorldPos.xyz - cLightPosPS.xyz;
+            return GetPointShadow(shadowPos);
+        #endif
     #endif
 }
 #endif

+ 6 - 2
Resources/CoreData/Shaders/GLSL/LitParticle.glsl

@@ -11,7 +11,11 @@ varying vec4 vWorldPos;
 #endif
 #ifdef PERPIXEL
     #ifdef SHADOW
-        varying vec4 vShadowPos[NUMCASCADES];
+        #ifndef GL_ES
+            varying vec4 vShadowPos[NUMCASCADES];
+        #else
+            varying highp vec4 vShadowPos[NUMCASCADES];
+        #endif
     #endif
     #ifdef SPOTLIGHT
         varying vec4 vSpotPos;
@@ -42,7 +46,7 @@ void VS()
         #ifdef SHADOW
             // Shadow projection: transform from world space to shadow space
             for (int i = 0; i < NUMCASCADES; i++)
-                vShadowPos[i] = GetShadowPos(i, projWorldPos);
+                vShadowPos[i] = GetShadowPos(i, vec3(0, 0, 0), projWorldPos);
         #endif
 
         #ifdef SPOTLIGHT

+ 11 - 7
Resources/CoreData/Shaders/GLSL/LitSolid.glsl

@@ -18,7 +18,11 @@ varying vec4 vWorldPos;
 #endif
 #ifdef PERPIXEL
     #ifdef SHADOW
-        varying vec4 vShadowPos[NUMCASCADES];
+        #ifndef GL_ES
+            varying vec4 vShadowPos[NUMCASCADES];
+        #else
+            varying highp vec4 vShadowPos[NUMCASCADES];
+        #endif
     #endif
     #ifdef SPOTLIGHT
         varying vec4 vSpotPos;
@@ -65,12 +69,12 @@ void VS()
         #ifdef SHADOW
             // Shadow projection: transform from world space to shadow space
             for (int i = 0; i < NUMCASCADES; i++)
-                vShadowPos[i] = GetShadowPos(i, projWorldPos);
+                vShadowPos[i] = GetShadowPos(i, vNormal, projWorldPos);
         #endif
 
         #ifdef SPOTLIGHT
             // Spotlight projection: transform from world space to projector texture coordinates
-            vSpotPos =  projWorldPos * cLightMatrices[0];
+            vSpotPos = projWorldPos * cLightMatrices[0];
         #endif
     
         #ifdef POINTLIGHT
@@ -82,7 +86,7 @@ void VS()
             // If using lightmap, disregard zone ambient light
             // If using AO, calculate ambient in the PS
             vVertexLight = vec3(0.0, 0.0, 0.0);
-            vTexCoord2 = iTexCoord2;
+            vTexCoord2 = iTexCoord1;
         #else
             vVertexLight = GetAmbient(GetZonePos(worldPos));
         #endif
@@ -168,7 +172,7 @@ void PS()
         #endif
 
         #ifdef AMBIENT
-            finalColor += cAmbientColor * diffColor.rgb;
+            finalColor += cAmbientColor.rgb * diffColor.rgb;
             finalColor += cMatEmissiveColor;
             gl_FragColor = vec4(GetFog(finalColor, fogFactor), diffColor.a);
         #else
@@ -188,7 +192,7 @@ void PS()
         vec3 finalColor = vVertexLight * diffColor.rgb;
         #ifdef AO
             // If using AO, the vertex light ambient is black, calculate occluded ambient here
-            finalColor += texture2D(sEmissiveMap, vTexCoord2).rgb * cAmbientColor * diffColor.rgb;
+            finalColor += texture2D(sEmissiveMap, vTexCoord2).rgb * cAmbientColor.rgb * diffColor.rgb;
         #endif
 
         #ifdef ENVCUBEMAP
@@ -212,7 +216,7 @@ void PS()
         vec3 finalColor = vVertexLight * diffColor.rgb;
         #ifdef AO
             // If using AO, the vertex light ambient is black, calculate occluded ambient here
-            finalColor += texture2D(sEmissiveMap, vTexCoord2).rgb * cAmbientColor * diffColor.rgb;
+            finalColor += texture2D(sEmissiveMap, vTexCoord2).rgb * cAmbientColor.rgb * diffColor.rgb;
         #endif
         
         #ifdef MATERIAL

+ 33 - 0
Resources/CoreData/Shaders/GLSL/PBR.glsl

@@ -0,0 +1,33 @@
+#include "BRDF.glsl"
+#ifdef COMPILEPS
+
+	//Return the PBR BRDF value
+	// lightDir  = the vector to the light
+	// lightVev  = normalised lightDir
+	// toCamera  = vector to the camera
+	// normal    = surface normal of the pixel
+	// roughness = roughness of the pixel
+	// diffColor = the rgb color of the pixel
+	// specColor = the rgb specular color of the pixel
+	vec3 GetBRDF(vec3 lightDir, vec3 lightVec, vec3 toCamera, vec3 normal, float roughness, vec3 diffColor, vec3 specColor)
+	{
+        vec3 Hn = normalize(toCamera + lightDir);
+        float vdh = clamp((dot(toCamera, Hn)), M_EPSILON, 1.0);
+        float ndh = clamp((dot(normal, Hn)), M_EPSILON, 1.0);
+        float ndl = clamp((dot(normal, lightVec)), M_EPSILON, 1.0);
+        float ndv = clamp((dot(normal, toCamera)), M_EPSILON, 1.0);
+
+        vec3 diffuseFactor = Diffuse(diffColor, roughness, ndv, ndl, vdh);
+        vec3 specularFactor = vec3(0.0, 0.0, 0.0);
+
+        #ifdef SPECULAR
+            vec3 fresnelTerm = Fresnel(specColor, vdh) ;
+            float distTerm = Distribution(ndh, roughness);
+            float visTerm = Visibility(ndl, ndv, roughness);
+
+            specularFactor = fresnelTerm * distTerm * visTerm  / M_PI;
+        #endif
+
+        return diffuseFactor + specularFactor;
+	}
+#endif

+ 117 - 0
Resources/CoreData/Shaders/GLSL/PBRDeferred.glsl

@@ -0,0 +1,117 @@
+#include "Uniforms.glsl"
+#include "Samplers.glsl"
+#include "Transform.glsl"
+#include "ScreenPos.glsl"
+#include "Lighting.glsl"
+#include "Constants.glsl"
+#include "PBR.glsl"
+#line 40007
+
+#ifdef DIRLIGHT
+    varying vec2 vScreenPos;
+#else
+    varying vec4 vScreenPos;
+#endif
+varying vec3 vFarRay;
+#ifdef ORTHO
+    varying vec3 vNearRay;
+#endif
+
+void VS()
+{
+    mat4 modelMatrix = iModelMatrix;
+    vec3 worldPos = GetWorldPos(modelMatrix);
+    gl_Position = GetClipPos(worldPos);
+    #ifdef DIRLIGHT
+        vScreenPos = GetScreenPosPreDiv(gl_Position);
+        vFarRay = GetFarRay(gl_Position);
+        #ifdef ORTHO
+            vNearRay = GetNearRay(gl_Position);
+        #endif
+    #else
+        vScreenPos = GetScreenPos(gl_Position);
+        vFarRay = GetFarRay(gl_Position) * gl_Position.w;
+        #ifdef ORTHO
+            vNearRay = GetNearRay(gl_Position) * gl_Position.w;
+        #endif
+    #endif
+}
+
+
+void PS()
+{
+    // If rendering a directional light quad, optimize out the w divide
+    #ifdef DIRLIGHT
+        vec4 depthInput = texture2D(sDepthBuffer, vScreenPos);
+        #ifdef HWDEPTH
+            float depth = ReconstructDepth(depthInput.r);
+        #else
+            float depth = DecodeDepth(depthInput.rgb);
+        #endif
+        #ifdef ORTHO
+            vec3 worldPos = mix(vNearRay, vFarRay, depth);
+        #else
+            vec3 worldPos = vFarRay * depth;
+        #endif
+        vec4 albedoInput = texture2D(sAlbedoBuffer, vScreenPos);
+        vec4 normalInput = texture2D(sNormalBuffer, vScreenPos);
+        vec4 specularInput = texture2D(sSpecMap, vScreenPos);
+    #else
+        vec4 depthInput = texture2DProj(sDepthBuffer, vScreenPos);
+        #ifdef HWDEPTH
+            float depth = ReconstructDepth(depthInput.r);
+        #else
+            float depth = DecodeDepth(depthInput.rgb);
+        #endif
+        #ifdef ORTHO
+            vec3 worldPos = mix(vNearRay, vFarRay, depth) / vScreenPos.w;
+        #else
+            vec3 worldPos = vFarRay * depth / vScreenPos.w;
+        #endif
+        vec4 albedoInput = texture2DProj(sAlbedoBuffer, vScreenPos);
+        vec4 normalInput = texture2DProj(sNormalBuffer, vScreenPos);
+        vec4 specularInput = texture2DProj(sSpecMap, vScreenPos);
+    #endif
+
+    // Position acquired via near/far ray is relative to camera. Bring position to world space
+    vec3 eyeVec = -worldPos;
+    worldPos += cCameraPosPS;
+
+    vec3 normal = normalInput.rgb;
+    float roughness = length(normal);
+    normal = normalize(normal);
+
+    vec3 specColor = specularInput.rgb;
+
+    vec4 projWorldPos = vec4(worldPos, 1.0);
+
+    vec3 lightDir;
+    float atten = GetAtten(normal, worldPos, lightDir);
+
+    float shadow = 1;
+    #ifdef SHADOW
+        shadow *= GetShadowDeferred(projWorldPos, normal, depth);
+    #endif
+
+    #if defined(SPOTLIGHT)
+        vec4 spotPos = projWorldPos * cLightMatricesPS[0];
+        vec3 lightColor = spotPos.w > 0.0 ? texture2DProj(sLightSpotMap, spotPos).rgb * cLightColor.rgb : vec3(0.0);
+    #elif defined(CUBEMASK)
+        mat3 lightVecRot = mat3(cLightMatricesPS[0][0].xyz, cLightMatricesPS[0][1].xyz, cLightMatricesPS[0][2].xyz);
+        vec3 lightColor = textureCube(sLightCubeMap, (worldPos - cLightPosPS.xyz) * lightVecRot).rgb * cLightColor.rgb;
+    #else
+        vec3 lightColor = cLightColor.rgb;
+    #endif
+
+    vec3 toCamera = normalize(eyeVec);
+    vec3 lightVec = normalize(lightDir);
+
+    float ndl = clamp(abs(dot(normal, lightVec)), M_EPSILON, 1.0);
+
+
+    vec3 BRDF = GetBRDF(lightDir, lightVec, toCamera, normal, roughness, albedoInput.rgb, specColor);
+
+    gl_FragColor.a = 1.0;
+    gl_FragColor.rgb = BRDF * lightColor * (atten * shadow) / M_PI;
+
+}

+ 252 - 0
Resources/CoreData/Shaders/GLSL/PBRLitSolid.glsl

@@ -0,0 +1,252 @@
+#include "Uniforms.glsl"
+#include "Samplers.glsl"
+#include "Transform.glsl"
+#include "ScreenPos.glsl"
+#include "Lighting.glsl"
+#include "Constants.glsl"
+#include "Fog.glsl"
+#include "PBR.glsl"
+#include "IBL.glsl"
+#line 30010
+
+#if defined(NORMALMAP) || defined(IBL)
+    varying vec4 vTexCoord;
+    varying vec4 vTangent;
+#else
+    varying vec2 vTexCoord;
+#endif
+varying vec3 vNormal;
+varying vec4 vWorldPos;
+#ifdef VERTEXCOLOR
+    varying vec4 vColor;
+#endif
+#ifdef PERPIXEL
+    #ifdef SHADOW
+        #ifndef GL_ES
+            varying vec4 vShadowPos[NUMCASCADES];
+        #else
+            varying highp vec4 vShadowPos[NUMCASCADES];
+        #endif
+    #endif
+    #ifdef SPOTLIGHT
+        varying vec4 vSpotPos;
+    #endif
+    #ifdef POINTLIGHT
+        varying vec3 vCubeMaskVec;
+    #endif
+#else
+    varying vec3 vVertexLight;
+    varying vec4 vScreenPos;
+    #ifdef ENVCUBEMAP
+        varying vec3 vReflectionVec;
+    #endif
+    #if defined(LIGHTMAP) || defined(AO)
+        varying vec2 vTexCoord2;
+    #endif
+#endif
+
+void VS()
+{
+    mat4 modelMatrix = iModelMatrix;
+    vec3 worldPos = GetWorldPos(modelMatrix);
+    gl_Position = GetClipPos(worldPos);
+    vNormal = GetWorldNormal(modelMatrix);
+    vWorldPos = vec4(worldPos, GetDepth(gl_Position));
+
+    #ifdef VERTEXCOLOR
+        vColor = iColor;
+    #endif
+
+    #if defined(NORMALMAP) || defined(DIRBILLBOARD) || defined(IBL)
+        vec3 tangent = GetWorldTangent(modelMatrix);
+        vec3 bitangent = cross(tangent, vNormal) * iTangent.w;
+        vTexCoord = vec4(GetTexCoord(iTexCoord), bitangent.xy);
+        vTangent = vec4(tangent, bitangent.z);
+    #else
+        vTexCoord = GetTexCoord(iTexCoord);
+    #endif
+
+    #ifdef PERPIXEL
+        // Per-pixel forward lighting
+        vec4 projWorldPos = vec4(worldPos, 1.0);
+
+        #ifdef SHADOW
+            // Shadow projection: transform from world space to shadow space
+            for (int i = 0; i < NUMCASCADES; i++)
+                vShadowPos[i] = GetShadowPos(i, vNormal, projWorldPos);
+        #endif
+
+        #ifdef SPOTLIGHT
+            // Spotlight projection: transform from world space to projector texture coordinates
+            vSpotPos = projWorldPos * cLightMatrices[0];
+        #endif
+
+        #ifdef POINTLIGHT
+            vCubeMaskVec = (worldPos - cLightPos.xyz) * mat3(cLightMatrices[0][0].xyz, cLightMatrices[0][1].xyz, cLightMatrices[0][2].xyz);
+        #endif
+    #else
+        // Ambient & per-vertex lighting
+        #if defined(LIGHTMAP) || defined(AO)
+            // If using lightmap, disregard zone ambient light
+            // If using AO, calculate ambient in the PS
+            vVertexLight = vec3(0.0, 0.0, 0.0);
+            vTexCoord2 = iTexCoord1;
+        #else
+            vVertexLight = GetAmbient(GetZonePos(worldPos));
+        #endif
+
+        #ifdef NUMVERTEXLIGHTS
+            for (int i = 0; i < NUMVERTEXLIGHTS; ++i)
+                vVertexLight += GetVertexLight(i, worldPos, vNormal) * cVertexLights[i * 3].rgb;
+        #endif
+
+        vScreenPos = GetScreenPos(gl_Position);
+
+        #ifdef ENVCUBEMAP
+            vReflectionVec = worldPos - cCameraPos;
+        #endif
+    #endif
+}
+
+void PS()
+{
+    // Get material diffuse albedo
+    #ifdef DIFFMAP
+        vec4 diffInput = texture2D(sDiffMap, vTexCoord.xy);
+        #ifdef ALPHAMASK
+            if (diffInput.a < 0.5)
+                discard;
+        #endif
+        vec4 diffColor = cMatDiffColor * diffInput;
+    #else
+        vec4 diffColor = cMatDiffColor;
+    #endif
+
+    #ifdef VERTEXCOLOR
+        diffColor *= vColor;
+    #endif
+
+    #ifdef METALLIC
+        vec4 roughMetalSrc = texture2D(sSpecMap, vTexCoord.xy);
+
+        float roughness = roughMetalSrc.r + cRoughness;
+        float metalness = roughMetalSrc.g + cMetallic;
+    #else
+        float roughness = cRoughness;
+        float metalness = cMetallic;
+    #endif
+
+    roughness *= roughness;
+
+    roughness = clamp(roughness, ROUGHNESS_FLOOR, 1.0);
+    metalness = clamp(metalness, METALNESS_FLOOR, 1.0);
+
+    vec3 specColor = mix(0.08 * cMatSpecColor.rgb, diffColor.rgb, metalness);
+    diffColor.rgb = diffColor.rgb - diffColor.rgb * metalness;
+
+    // Get normal
+    #if defined(NORMALMAP) || defined(DIRBILLBOARD) || defined(IBL)
+        vec3 tangent = vTangent.xyz;
+        vec3 bitangent = vec3(vTexCoord.zw, vTangent.w);
+        mat3 tbn = mat3(tangent, bitangent, vNormal);
+    #endif
+
+    #ifdef NORMALMAP
+        vec3 nn = DecodeNormal(texture2D(sNormalMap, vTexCoord.xy));
+        //nn.rg *= 2.0;
+        vec3 normal = normalize(tbn * nn);
+    #else
+        vec3 normal = normalize(vNormal);
+    #endif
+
+    // Get fog factor
+    #ifdef HEIGHTFOG
+        float fogFactor = GetHeightFogFactor(vWorldPos.w, vWorldPos.y);
+    #else
+        float fogFactor = GetFogFactor(vWorldPos.w);
+    #endif
+
+    #if defined(PERPIXEL)
+        // Per-pixel forward lighting
+        vec3 lightColor;
+        vec3 lightDir;
+        vec3 finalColor;
+
+        float atten = GetAtten(normal, vWorldPos.xyz, lightDir);
+        float shadow = 1.0;
+        #ifdef SHADOW
+            shadow = GetShadow(vShadowPos, vWorldPos.w);
+        #endif
+
+        #if defined(SPOTLIGHT)
+            lightColor = vSpotPos.w > 0.0 ? texture2DProj(sLightSpotMap, vSpotPos).rgb * cLightColor.rgb : vec3(0.0, 0.0, 0.0);
+        #elif defined(CUBEMASK)
+            lightColor = textureCube(sLightCubeMap, vCubeMaskVec).rgb * cLightColor.rgb;
+        #else
+            lightColor = cLightColor.rgb;
+        #endif
+        vec3 toCamera = normalize(cCameraPosPS - vWorldPos.xyz);
+        vec3 lightVec = normalize(lightDir);
+        float ndl = clamp((dot(normal, lightVec)), M_EPSILON, 1.0);
+
+        vec3 BRDF = GetBRDF(lightDir, lightVec, toCamera, normal, roughness, diffColor.rgb, specColor);
+
+        finalColor.rgb = BRDF * lightColor * (atten * shadow) / M_PI;
+
+        #ifdef AMBIENT
+            finalColor += cAmbientColor.rgb * diffColor.rgb;
+            finalColor += cMatEmissiveColor;
+            gl_FragColor = vec4(GetFog(finalColor, fogFactor), diffColor.a);
+        #else
+            gl_FragColor = vec4(GetLitFog(finalColor, fogFactor), diffColor.a);
+        #endif
+    #elif defined(DEFERRED)
+        // Fill deferred G-buffer
+        const vec3 spareData = vec3(0,0,0); // Can be used to pass more data to deferred renderer
+        gl_FragData[0] = vec4(specColor, spareData.r);
+        gl_FragData[1] = vec4(diffColor.rgb, spareData.g);
+        gl_FragData[2] = vec4(normal * roughness, spareData.b);
+        gl_FragData[3] = vec4(EncodeDepth(vWorldPos.w), 0.0);
+    #else
+        // Ambient & per-vertex lighting
+        vec3 finalColor = vVertexLight * diffColor.rgb;
+        #ifdef AO
+            // If using AO, the vertex light ambient is black, calculate occluded ambient here
+            finalColor += texture2D(sEmissiveMap, vTexCoord2).rgb * cAmbientColor.rgb * diffColor.rgb;
+        #endif
+
+        #ifdef MATERIAL
+            // Add light pre-pass accumulation result
+            // Lights are accumulated at half intensity. Bring back to full intensity now
+            vec4 lightInput = 2.0 * texture2DProj(sLightBuffer, vScreenPos);
+            vec3 lightSpecColor = lightInput.a * lightInput.rgb / max(GetIntensity(lightInput.rgb), 0.001);
+
+            finalColor += lightInput.rgb * diffColor.rgb + lightSpecColor * specColor;
+        #endif
+
+        vec3 toCamera = normalize(vWorldPos.xyz - cCameraPosPS);
+        vec3 reflection = normalize(reflect(toCamera, normal));
+
+        vec3 cubeColor = vVertexLight.rgb;
+
+        #ifdef IBL
+          vec3 iblColor = ImageBasedLighting(reflection, tangent, bitangent, normal, toCamera, diffColor.rgb, specColor.rgb, roughness, cubeColor);
+          float gamma = 0.0;
+          finalColor.rgb += iblColor;
+        #endif
+
+        #ifdef ENVCUBEMAP
+            finalColor += cMatEnvMapColor * textureCube(sEnvCubeMap, reflect(vReflectionVec, normal)).rgb;
+        #endif
+        #ifdef LIGHTMAP
+            finalColor += texture2D(sEmissiveMap, vTexCoord2).rgb * diffColor.rgb;
+        #endif
+        #ifdef EMISSIVEMAP
+            finalColor += cMatEmissiveColor * texture2D(sEmissiveMap, vTexCoord.xy).rgb;
+        #else
+            finalColor += cMatEmissiveColor;
+        #endif
+
+        gl_FragColor = vec4(GetFog(finalColor, fogFactor), diffColor.a);
+    #endif
+}

+ 0 - 6
Resources/CoreData/Shaders/GLSL/PostProcess.glsl

@@ -11,13 +11,7 @@ vec2 Noise(vec2 coord)
 // Adapted: http://callumhay.blogspot.com/2010/09/gaussian-blur-shader-glsl.html
 vec4 GaussianBlur(int blurKernelSize, vec2 blurDir, vec2 blurRadius, float sigma, sampler2D texSampler, vec2 texCoord)
 {
-
-#if defined(GL_ES)
-    // hardcoded for GL_ES to avoid loop comparison issue below
-    const int blurKernelSizeHalfSize = 3 / 2;
-#else
     int blurKernelSizeHalfSize = blurKernelSize / 2;
-#endif
 
     // Incremental Gaussian Coefficent Calculation (See GPU Gems 3 pp. 877 - 889)
     vec3 gaussCoeff;

+ 6 - 2
Resources/CoreData/Shaders/GLSL/PrepassLight.glsl

@@ -63,6 +63,10 @@ void PS()
         vec4 normalInput = texture2DProj(sNormalBuffer, vScreenPos);
     #endif
 
+    // Position acquired via near/far ray is relative to camera. Bring position to world space
+    vec3 eyeVec = -worldPos;
+    worldPos += cCameraPosPS;
+
     vec3 normal = normalize(normalInput.rgb * 2.0 - 1.0);
     vec4 projWorldPos = vec4(worldPos, 1.0);
     vec3 lightColor;
@@ -72,7 +76,7 @@ void PS()
     float diff = 0.5 * GetDiffuse(normal, worldPos, lightDir);
 
     #ifdef SHADOW
-        diff *= GetShadowDeferred(projWorldPos, depth);
+        diff *= GetShadowDeferred(projWorldPos, normal, depth);
     #endif
     
     #if defined(SPOTLIGHT)
@@ -86,7 +90,7 @@ void PS()
     #endif
 
     #ifdef SPECULAR
-        float spec = lightColor.g * GetSpecular(normal, -worldPos, lightDir, normalInput.a * 255.0);
+        float spec = lightColor.g * GetSpecular(normal, eyeVec, lightDir, normalInput.a * 255.0);
         gl_FragColor = diff * vec4(lightColor, spec * cLightColor.a);
     #else
         gl_FragColor = diff * vec4(lightColor, 0.0);

+ 6 - 2
Resources/CoreData/Shaders/GLSL/Samplers.glsl

@@ -15,13 +15,17 @@ uniform samplerCube sLightCubeMap;
     uniform sampler2D sNormalBuffer;
     uniform sampler2D sDepthBuffer;
     uniform sampler2D sLightBuffer;
-    uniform sampler2DShadow sShadowMap;
+    #ifdef VSM_SHADOW
+        uniform sampler2D sShadowMap;
+    #else
+        uniform sampler2DShadow sShadowMap;
+    #endif
     uniform samplerCube sFaceSelectCubeMap;
     uniform samplerCube sIndirectionCubeMap;
     uniform samplerCube sZoneCubeMap;
     uniform sampler3D sZoneVolumeMap;
 #else
-    uniform sampler2D sShadowMap;
+    uniform highp sampler2D sShadowMap;
 #endif
 
 #ifdef GL3

+ 10 - 3
Resources/CoreData/Shaders/GLSL/ScreenPos.glsl

@@ -1,4 +1,11 @@
 #ifdef COMPILEVS
+mat3 GetCameraRot()
+{
+    return mat3(cViewInv[0][0], cViewInv[0][1], cViewInv[0][2],
+        cViewInv[1][0], cViewInv[1][1], cViewInv[1][2],
+        cViewInv[2][0], cViewInv[2][1], cViewInv[2][2]);
+}
+
 vec4 GetScreenPos(vec4 clipPos)
 {
     return vec4(
@@ -36,7 +43,7 @@ vec3 GetFarRay(vec4 clipPos)
         clipPos.y / clipPos.w * cFrustumSize.y,
         cFrustumSize.z);
 
-    return viewRay * cCameraRot;
+    return viewRay * GetCameraRot();
 }
 
 vec3 GetNearRay(vec4 clipPos)
@@ -45,7 +52,7 @@ vec3 GetNearRay(vec4 clipPos)
         clipPos.x / clipPos.w * cFrustumSize.x,
         clipPos.y / clipPos.w * cFrustumSize.y,
         0.0);
-    
-    return (viewRay * cCameraRot) * cDepthMode.x;
+
+    return (viewRay * GetCameraRot()) * cDepthMode.x;
 }
 #endif

+ 17 - 4
Resources/CoreData/Shaders/GLSL/Shadow.glsl

@@ -2,23 +2,36 @@
 #include "Samplers.glsl"
 #include "Transform.glsl"
 
-varying vec2 vTexCoord;
+#ifdef VSM_SHADOW
+    varying vec3 vTexCoord;
+#else
+    varying vec2 vTexCoord;
+#endif
 
 void VS()
 {
     mat4 modelMatrix = iModelMatrix;
     vec3 worldPos = GetWorldPos(modelMatrix);
     gl_Position = GetClipPos(worldPos);
-    vTexCoord = GetTexCoord(iTexCoord);
+    #ifdef VSM_SHADOW
+        vTexCoord = vec3(GetTexCoord(iTexCoord), gl_Position.z / gl_Position.w * 0.5 + 0.5);
+    #else
+        vTexCoord = GetTexCoord(iTexCoord);
+    #endif
 }
 
 void PS()
 {
     #ifdef ALPHAMASK
-        float alpha = texture2D(sDiffMap, vTexCoord).a;
+        float alpha = texture2D(sDiffMap, vTexCoord.xy).a;
         if (alpha < 0.5)
             discard;
     #endif
 
-    gl_FragColor = vec4(1.0);
+    #ifdef VSM_SHADOW
+        float depth = vTexCoord.z;
+        gl_FragColor = vec4(depth, depth * depth, 1.0, 1.0);
+    #else
+        gl_FragColor = vec4(1.0);
+    #endif
 }

+ 34 - 0
Resources/CoreData/Shaders/GLSL/ShadowBlur.glsl

@@ -0,0 +1,34 @@
+#include "Uniforms.glsl"
+#include "Samplers.glsl"
+#include "Transform.glsl"
+#include "ScreenPos.glsl"
+
+#ifdef COMPILEPS
+uniform vec2 cBlurOffsets;
+#endif
+
+varying vec2 vScreenPos;
+
+void VS()
+{
+    mat4 modelMatrix = iModelMatrix;
+    vec3 worldPos = GetWorldPos(modelMatrix);
+    gl_Position = GetClipPos(worldPos);
+    vScreenPos = GetScreenPosPreDiv(gl_Position);
+}
+
+void PS()
+{
+    vec2 color = vec2(0.0);
+    
+    color += 0.015625 * texture2D(sDiffMap, vScreenPos + vec2(-3.0) * cBlurOffsets).rg;
+    color += 0.09375 * texture2D(sDiffMap, vScreenPos + vec2(-2.0) * cBlurOffsets).rg;
+    color += 0.234375 * texture2D(sDiffMap, vScreenPos + vec2(-1.0) * cBlurOffsets).rg;
+    color += 0.3125 * texture2D(sDiffMap, vScreenPos).rg;
+    color += 0.234375 * texture2D(sDiffMap, vScreenPos + vec2(1.0) * cBlurOffsets).rg;
+    color += 0.09375 * texture2D(sDiffMap, vScreenPos + vec2(2.0) * cBlurOffsets).rg;
+    color += 0.015625 * texture2D(sDiffMap, vScreenPos + vec2(3.0) * cBlurOffsets).rg;
+    
+    gl_FragColor = vec4(color, 0.0, 0.0);
+}
+

+ 5 - 7
Resources/CoreData/Shaders/GLSL/Skybox.glsl

@@ -9,17 +9,15 @@ void VS()
     mat4 modelMatrix = iModelMatrix;
     vec3 worldPos = GetWorldPos(modelMatrix);
     gl_Position = GetClipPos(worldPos);
-
-    #ifndef GL_ES
     gl_Position.z = gl_Position.w;
-    #else
-    // On OpenGL ES force Z slightly in front of far plane to avoid clipping artifacts due to inaccuracy
-    gl_Position.z = 0.999 * gl_Position.w;
-    #endif
     vTexCoord = iPos.xyz;
 }
 
 void PS()
 {
-    gl_FragColor = cMatDiffColor * textureCube(sDiffCubeMap, vTexCoord);
+    vec4 sky = cMatDiffColor * textureCube(sDiffCubeMap, vTexCoord);
+    #ifdef HDRSCALE
+        sky = pow(sky + clamp((cAmbientColor.a - 1.0) * 0.1, 0.0, 0.25), max(vec4(cAmbientColor.a), 1.0)) * clamp(cAmbientColor.a, 0.0, 1.0);
+    #endif
+    gl_FragColor = sky;
 }

+ 22 - 0
Resources/CoreData/Shaders/GLSL/Skydome.glsl

@@ -0,0 +1,22 @@
+#include "Uniforms.glsl"
+#include "Samplers.glsl"
+#include "Transform.glsl"
+
+varying vec2 vTexCoord;
+
+uniform mat4 gl_ModelViewMatrix;
+uniform mat4 gl_ProjectionMatrix;
+
+void VS()
+{
+    mat4 modelMatrix = iModelMatrix;
+    vec3 worldPos = GetWorldPos(modelMatrix);
+    gl_Position = GetClipPos(worldPos);
+    gl_Position.z = gl_Position.w;
+    vTexCoord = iTexCoord.xy;
+}
+
+void PS()
+{   
+    gl_FragColor = texture2D(sDiffMap, vTexCoord);       
+}

+ 8 - 4
Resources/CoreData/Shaders/GLSL/TerrainBlend.glsl

@@ -17,7 +17,11 @@ varying vec3 vNormal;
 varying vec4 vWorldPos;
 #ifdef PERPIXEL
     #ifdef SHADOW
-        varying vec4 vShadowPos[NUMCASCADES];
+        #ifndef GL_ES
+            varying vec4 vShadowPos[NUMCASCADES];
+        #else
+            varying highp vec4 vShadowPos[NUMCASCADES];
+        #endif
     #endif
     #ifdef SPOTLIGHT
         varying vec4 vSpotPos;
@@ -64,7 +68,7 @@ void VS()
         #ifdef SHADOW
             // Shadow projection: transform from world space to shadow space
             for (int i = 0; i < NUMCASCADES; i++)
-                vShadowPos[i] = GetShadowPos(i, projWorldPos);
+                vShadowPos[i] = GetShadowPos(i, vNormal, projWorldPos);
         #endif
 
         #ifdef SPOTLIGHT
@@ -81,7 +85,7 @@ void VS()
             // If using lightmap, disregard zone ambient light
             // If using AO, calculate ambient in the PS
             vVertexLight = vec3(0.0, 0.0, 0.0);
-            vTexCoord2 = iTexCoord2;
+            vTexCoord2 = iTexCoord1;
         #else
             vVertexLight = GetAmbient(GetZonePos(worldPos));
         #endif
@@ -152,7 +156,7 @@ void PS()
         #endif
 
         #ifdef AMBIENT
-            finalColor += cAmbientColor * diffColor.rgb;
+            finalColor += cAmbientColor.rgb * diffColor.rgb;
             finalColor += cMatEmissiveColor;
             gl_FragColor = vec4(GetFog(finalColor, fogFactor), diffColor.a);
         #else

+ 79 - 9
Resources/CoreData/Shaders/GLSL/Transform.glsl

@@ -10,17 +10,18 @@ attribute vec4 iPos;
 attribute vec3 iNormal;
 attribute vec4 iColor;
 attribute vec2 iTexCoord;
-attribute vec2 iTexCoord2;
+attribute vec2 iTexCoord1;
 attribute vec4 iTangent;
 attribute vec4 iBlendWeights;
 attribute vec4 iBlendIndices;
 attribute vec3 iCubeTexCoord;
-attribute vec4 iCubeTexCoord2;
-#ifndef GL_ES
-    attribute vec4 iInstanceMatrix1;
-    attribute vec4 iInstanceMatrix2;
-    attribute vec4 iInstanceMatrix3;
+attribute vec4 iCubeTexCoord1;
+#ifdef INSTANCED
+    attribute vec4 iTexCoord4;
+    attribute vec4 iTexCoord5;
+    attribute vec4 iTexCoord6;
 #endif
+attribute float iObjectIndex;
 
 #ifdef SKINNED
 mat4 GetSkinMatrix(vec4 blendWeights, vec4 blendIndices)
@@ -38,7 +39,7 @@ mat4 GetSkinMatrix(vec4 blendWeights, vec4 blendIndices)
 mat4 GetInstanceMatrix()
 {
     const vec4 lastColumn = vec4(0.0, 0.0, 0.0, 1.0);
-    return mat4(iInstanceMatrix1, iInstanceMatrix2, iInstanceMatrix3, lastColumn);
+    return mat4(iTexCoord4, iTexCoord5, iTexCoord6, lastColumn);
 }
 #endif
 
@@ -86,6 +87,63 @@ vec3 GetBillboardNormal()
 }
 #endif
 
+#ifdef DIRBILLBOARD
+mat3 GetFaceCameraRotation(vec3 position, vec3 direction)
+{
+    vec3 cameraDir = normalize(position - cCameraPos);
+    vec3 front = normalize(direction);
+    vec3 right = normalize(cross(front, cameraDir));
+    vec3 up = normalize(cross(front, right));
+
+    return mat3(
+        right.x, up.x, front.x,
+        right.y, up.y, front.y,
+        right.z, up.z, front.z
+    );
+}
+
+vec3 GetBillboardPos(vec4 iPos, vec3 iDirection, mat4 modelMatrix)
+{
+    vec3 worldPos = (iPos * modelMatrix).xyz;
+    return worldPos + vec3(iTexCoord1.x, 0.0, iTexCoord1.y) * GetFaceCameraRotation(worldPos, iDirection);
+}
+
+vec3 GetBillboardNormal(vec4 iPos, vec3 iDirection, mat4 modelMatrix)
+{
+    vec3 worldPos = (iPos * modelMatrix).xyz;
+    return vec3(0.0, 1.0, 0.0) * GetFaceCameraRotation(worldPos, iDirection);
+}
+#endif
+
+#ifdef TRAILFACECAM
+vec3 GetTrailPos(vec4 iPos, vec3 iFront, float iScale, mat4 modelMatrix)
+{
+    vec3 up = normalize(cCameraPos - iPos.xyz);
+    vec3 right = normalize(cross(iFront, up));
+    return (vec4((iPos.xyz + right * iScale), 1.0) * modelMatrix).xyz;
+}
+
+vec3 GetTrailNormal(vec4 iPos)
+{
+    return normalize(cCameraPos - iPos.xyz);
+}
+#endif
+
+#ifdef TRAILBONE
+vec3 GetTrailPos(vec4 iPos, vec3 iParentPos, float iScale, mat4 modelMatrix)
+{
+    vec3 right = iParentPos - iPos.xyz;
+    return (vec4((iPos.xyz + right * iScale), 1.0) * modelMatrix).xyz;
+}
+
+vec3 GetTrailNormal(vec4 iPos, vec3 iParentPos, vec3 iForward)
+{
+    vec3 left = normalize(iPos.xyz - iParentPos);
+    vec3 up = normalize(cross(normalize(iForward), left));
+    return up;
+}
+#endif
+
 #if defined(SKINNED)
     #define iModelMatrix GetSkinMatrix(iBlendWeights, iBlendIndices)
 #elif defined(INSTANCED)
@@ -97,7 +155,13 @@ vec3 GetBillboardNormal()
 vec3 GetWorldPos(mat4 modelMatrix)
 {
     #if defined(BILLBOARD)
-        return GetBillboardPos(iPos, iTexCoord2, modelMatrix);
+        return GetBillboardPos(iPos, iTexCoord1, modelMatrix);
+    #elif defined(DIRBILLBOARD)
+        return GetBillboardPos(iPos, iNormal, modelMatrix);
+    #elif defined(TRAILFACECAM)
+        return GetTrailPos(iPos, iTangent.xyz, iTangent.w, modelMatrix);
+    #elif defined(TRAILBONE)
+        return GetTrailPos(iPos, iTangent.xyz, iTangent.w, modelMatrix);
     #else
         return (iPos * modelMatrix).xyz;
     #endif
@@ -107,6 +171,12 @@ vec3 GetWorldNormal(mat4 modelMatrix)
 {
     #if defined(BILLBOARD)
         return GetBillboardNormal();
+    #elif defined(DIRBILLBOARD)
+        return GetBillboardNormal(iPos, iNormal, modelMatrix);
+    #elif defined(TRAILFACECAM)
+        return GetTrailNormal(iPos);
+    #elif defined(TRAILBONE)
+        return GetTrailNormal(iPos, iTangent.xyz, iNormal);
     #else
         return normalize(iNormal * GetNormalMatrix(modelMatrix));
     #endif
@@ -136,4 +206,4 @@ out vec4 fragData[1];
 #define gl_FragData fragData
 #endif
 
-#endif
+#endif

+ 29 - 10
Resources/CoreData/Shaders/GLSL/Uniforms.glsl

@@ -6,13 +6,12 @@
 // OpenGL 2 uniforms (no constant buffers)
 
 #ifdef COMPILEVS
-          
+
 // Vertex shader uniforms
 uniform vec3 cAmbientStartColor;
 uniform vec3 cAmbientEndColor;
 uniform mat3 cBillboardRot;
 uniform vec3 cCameraPos;
-uniform mat3 cCameraRot;
 uniform float cNearClip;
 uniform float cFarClip;
 uniform vec4 cDepthMode;
@@ -20,9 +19,12 @@ uniform vec3 cFrustumSize;
 uniform float cDeltaTime;
 uniform float cElapsedTime;
 uniform vec4 cGBufferOffsets;
-uniform vec3 cLightDir;
 uniform vec4 cLightPos;
+uniform vec3 cLightDir;
+uniform vec4 cNormalOffsetScale;
 uniform mat4 cModel;
+uniform mat4 cView;
+uniform mat4 cViewInv;
 uniform mat4 cViewProj;
 uniform vec4 cUOffset;
 uniform vec4 cVOffset;
@@ -30,7 +32,7 @@ uniform mat4 cZone;
 #if !defined(GL_ES) || defined(WEBGL)
     uniform mat4 cLightMatrices[4];
 #else
-    uniform mat4 cLightMatrices[2];
+    uniform highp mat4 cLightMatrices[2];
 #endif
 #ifdef SKINNED
     uniform vec4 cSkinMatrices[MAXBONES*3];
@@ -50,7 +52,7 @@ uniform mat4 cZone;
     precision mediump float;
 #endif
 
-uniform vec3 cAmbientColor;
+uniform vec4 cAmbientColor;
 uniform vec3 cCameraPosPS;
 uniform float cDeltaTimePS;
 uniform vec4 cDepthReconstruct;
@@ -59,12 +61,17 @@ uniform vec4 cFogParams;
 uniform vec3 cFogColor;
 uniform vec2 cGBufferInvSize;
 uniform vec4 cLightColor;
-uniform vec3 cLightDirPS;
 uniform vec4 cLightPosPS;
+uniform vec3 cLightDirPS;
+uniform vec4 cNormalOffsetScalePS;
 uniform vec4 cMatDiffColor;
 uniform vec3 cMatEmissiveColor;
 uniform vec3 cMatEnvMapColor;
 uniform vec4 cMatSpecColor;
+#ifdef PBR
+    uniform float cRoughness;
+    uniform float cMetallic;
+#endif
 uniform float cNearClipPS;
 uniform float cFarClipPS;
 uniform vec4 cShadowCubeAdjust;
@@ -73,7 +80,9 @@ uniform vec2 cShadowIntensity;
 uniform vec2 cShadowMapInvSize;
 uniform vec4 cShadowSplits;
 uniform mat4 cLightMatricesPS[4];
-
+#ifdef VSM_SHADOW
+uniform vec2 cVSMShadowParams;
+#endif
 #endif
 
 #else
@@ -91,12 +100,13 @@ uniform FrameVS
 uniform CameraVS
 {
     vec3 cCameraPos;
-    mat3 cCameraRot;
     float cNearClip;
     float cFarClip;
     vec4 cDepthMode;
     vec3 cFrustumSize;
     vec4 cGBufferOffsets;
+    mat4 cView;
+    mat4 cViewInv;
     mat4 cViewProj;
     vec4 cClipPlane;
 };
@@ -110,8 +120,9 @@ uniform ZoneVS
 
 uniform LightVS
 {
-    vec3 cLightDir;
     vec4 cLightPos;
+    vec3 cLightDir;
+    vec4 cNormalOffsetScale;
 #ifdef NUMVERTEXLIGHTS
     vec4 cVertexLights[4 * 3];
 #else
@@ -160,7 +171,7 @@ uniform CameraPS
 
 uniform ZonePS
 {
-    vec3 cAmbientColor;
+    vec4 cAmbientColor;
     vec4 cFogParams;
     vec3 cFogColor;
 };
@@ -170,12 +181,16 @@ uniform LightPS
     vec4 cLightColor;
     vec4 cLightPosPS;
     vec3 cLightDirPS;
+    vec4 cNormalOffsetScalePS;
     vec4 cShadowCubeAdjust;
     vec4 cShadowDepthFade;
     vec2 cShadowIntensity;
     vec2 cShadowMapInvSize;
     vec4 cShadowSplits;
     mat4 cLightMatricesPS[4];
+#ifdef VSM_SHADOW
+    vec2 cVSMShadowParams;
+#endif
 };
 
 #ifndef CUSTOM_MATERIAL_CBUFFER
@@ -185,6 +200,10 @@ uniform MaterialPS
     vec3 cMatEmissiveColor;
     vec3 cMatEnvMapColor;
     vec4 cMatSpecColor;
+    #ifdef PBR
+        float cRoughness;
+        float cMetallic;
+    #endif
 };
 #endif
 

+ 4 - 0
Resources/CoreData/Shaders/GLSL/Unlit.glsl

@@ -20,7 +20,11 @@ void VS()
 
     #ifdef VERTEXCOLOR
         vColor = iColor;
+        //#ifdef TRAIL
+        //    vColor = vec4(normalize(cCameraPos), 1.0);
+        //#endif
     #endif
+
 }
 
 void PS()

+ 23 - 0
Resources/CoreData/Shaders/GLSL/Urho2D.glsl

@@ -0,0 +1,23 @@
+#include "Uniforms.glsl"
+#include "Samplers.glsl"
+#include "Transform.glsl"
+
+varying vec2 vTexCoord;
+varying vec4 vColor;
+
+void VS()
+{
+    mat4 modelMatrix = iModelMatrix;
+    vec3 worldPos = GetWorldPos(modelMatrix);
+    gl_Position = GetClipPos(worldPos);
+    
+    vTexCoord = iTexCoord;
+    vColor = iColor;
+}
+
+void PS()
+{
+    vec4 diffColor = cMatDiffColor * vColor;
+    vec4 diffInput = texture2D(sDiffMap, vTexCoord);
+    gl_FragColor = diffColor * diffInput;
+}

+ 14 - 3
Resources/CoreData/Shaders/GLSL/Vegetation.glsl

@@ -16,9 +16,16 @@ uniform vec2 cWindWorldSpacing;
 #endif
 varying vec3 vNormal;
 varying vec4 vWorldPos;
+#ifdef VERTEXCOLOR
+    varying vec4 vColor;
+#endif
 #ifdef PERPIXEL
     #ifdef SHADOW
-        varying vec4 vShadowPos[NUMCASCADES];
+        #ifndef GL_ES
+            varying vec4 vShadowPos[NUMCASCADES];
+        #else
+            varying highp vec4 vShadowPos[NUMCASCADES];
+        #endif
     #endif
     #ifdef SPOTLIGHT
         varying vec4 vSpotPos;
@@ -52,6 +59,10 @@ void VS()
     vNormal = GetWorldNormal(modelMatrix);
     vWorldPos = vec4(worldPos, GetDepth(gl_Position));
 
+    #ifdef VERTEXCOLOR
+        vColor = iColor;
+    #endif
+
     #ifdef NORMALMAP
         vec3 tangent = GetWorldTangent(modelMatrix);
         vec3 bitangent = cross(tangent, vNormal) * iTangent.w;
@@ -68,7 +79,7 @@ void VS()
         #ifdef SHADOW
             // Shadow projection: transform from world space to shadow space
             for (int i = 0; i < NUMCASCADES; i++)
-                vShadowPos[i] = GetShadowPos(i, projWorldPos);
+                vShadowPos[i] = GetShadowPos(i, vNormal, projWorldPos);
         #endif
 
         #ifdef SPOTLIGHT
@@ -85,7 +96,7 @@ void VS()
             // If using lightmap, disregard zone ambient light
             // If using AO, calculate ambient in the PS
             vVertexLight = vec3(0.0, 0.0, 0.0);
-            vTexCoord2 = iTexCoord2;
+            vTexCoord2 = iTexCoord1;
         #else
             vVertexLight = GetAmbient(GetZonePos(worldPos));
         #endif

+ 135 - 0
Resources/CoreData/Shaders/HLSL/BRDF.hlsl

@@ -0,0 +1,135 @@
+#ifdef COMPILEPS
+  #ifdef PBR
+
+    // Following BRDF methods are based upon research Frostbite EA
+    //[Lagrade et al. 2014, "Moving Frostbite to Physically Based Rendering"]
+    
+    //Schlick Fresnel
+    //specular  = the rgb specular color value of the pixel
+    //VdotH     = the dot product of the camera view direction and the half vector 
+    float3 SchlickFresnel(float3 specular, float VdotH)
+    {
+        return specular + (float3(1.0, 1.0, 1.0) - specular) * pow(1.0 - VdotH, 5.0);
+    }
+
+    //Schlick Gaussian Fresnel 
+    //specular  = the rgb specular color value of the pixel
+    //VdotH     = the dot product of the camera view direction and the half vector 
+    float3 SchlickGaussianFresnel(in float3 specular, in float VdotH)
+    {
+        float sphericalGaussian = pow(2.0, (-5.55473 * VdotH - 6.98316) * VdotH);
+        return specular + (float3(1.0, 1.0, 1.0) - specular) * sphericalGaussian;
+    }
+
+    //Get Fresnel
+    //specular  = the rgb specular color value of the pixel
+    //VdotH     = the dot product of the camera view direction and the half vector 
+    float3 Fresnel(float3 specular, float VdotH)
+    {
+        return SchlickFresnel(specular, VdotH);
+    }
+
+    // Smith GGX corrected Visibility
+    // NdotL        = the dot product of the normal and direction to the light
+    // NdotV        = the dot product of the normal and the camera view direction
+    // roughness    = the roughness of the pixel
+    float SmithGGXSchlickVisibility(float NdotL, float NdotV, float roughness)
+    {
+        float rough2 = roughness * roughness;
+        float lambdaV = NdotL  * sqrt((-NdotV * rough2 + NdotV) * NdotV + rough2);   
+        float lambdaL = NdotV  * sqrt((-NdotL * rough2 + NdotL) * NdotL + rough2);
+    
+        return 0.5 / (lambdaV + lambdaL);
+    }
+
+    // Get Visibility
+    // NdotL        = the dot product of the normal and direction to the light
+    // NdotV        = the dot product of the normal and the camera view direction
+    // roughness    = the roughness of the pixel
+    float Visibility(float NdotL, float NdotV, float roughness)
+    {
+        return SmithGGXSchlickVisibility(NdotL, NdotV, roughness);
+    }
+
+    // GGX Distribution
+    // NdotH        = the dot product of the normal and the half vector
+    // roughness    = the roughness of the pixel
+    float GGXDistribution(float NdotH, float roughness)
+    {
+        float rough2 = roughness * roughness;
+        float tmp =  (NdotH * rough2 - NdotH) * NdotH + 1;
+        return rough2 / (tmp * tmp);
+    }
+
+    // Blinn Distribution
+    // NdotH        = the dot product of the normal and the half vector
+    // roughness    = the roughness of the pixel
+    float BlinnPhongDistribution(in float NdotH, in float roughness)
+    {
+        const float specPower = max((2.0 / (roughness * roughness)) - 2.0, 1e-4f); // Calculate specular power from roughness
+        return pow(saturate(NdotH), specPower);
+    }
+
+    // Beckmann Distribution
+    // NdotH        = the dot product of the normal and the half vector
+    // roughness    = the roughness of the pixel
+    float BeckmannDistribution(in float NdotH, in float roughness)
+    {
+        const float rough2 = roughness * roughness;
+        const float roughnessA = 1.0 / (4.0 * rough2 * pow(NdotH, 4.0));
+        const float roughnessB = NdotH * NdotH - 1.0;
+        const float roughnessC = rough2 * NdotH * NdotH;
+        return roughnessA * exp(roughnessB / roughnessC);
+    }
+
+    // Get Distribution
+    // NdotH        = the dot product of the normal and the half vector
+    // roughness    = the roughness of the pixel
+    float Distribution(float NdotH, float roughness)
+    {
+        return GGXDistribution(NdotH, roughness);
+    }
+
+    // Lambertian Diffuse
+    // diffuseColor = the rgb color value of the pixel
+    // roughness    = the roughness of the pixel
+    // NdotV        = the normal dot with the camera view direction
+    // NdotL        = the normal dot with the light direction
+    // VdotH        = the camera view direction dot with the half vector
+    float3 LambertianDiffuse(float3 diffuseColor, float NdotL)
+    {
+        return diffuseColor * NdotL;
+    }
+
+    // Burley Diffuse
+    // diffuseColor = the rgb color value of the pixel
+    // roughness    = the roughness of the pixel
+    // NdotV        = the normal dot with the camera view direction
+    // NdotL        = the normal dot with the light direction
+    // VdotH        = the camera view direction dot with the half vector
+    float3 BurleyDiffuse(float3 diffuseColor, float roughness, float NdotV, float NdotL, float VdotH)
+    {
+        const float energyBias = lerp(0, 0.5, roughness);
+        const float energyFactor = lerp(1.0, 1.0 / 1.51, roughness);
+        const float fd90 = energyBias + 2.0 * VdotH * VdotH * roughness;
+        const float f0 = 1.0;
+        const float lightScatter = f0 + (fd90 - f0) * pow(1.0f - NdotL, 5.0f);
+        const float viewScatter = f0 + (fd90 - f0) * pow(1.0f - NdotV, 5.0f);
+
+        return diffuseColor * lightScatter * viewScatter * energyFactor;
+    }
+
+    //Get Diffuse
+    // diffuseColor = the rgb color value of the pixel
+    // roughness    = the roughness of the pixel
+    // NdotV        = the normal dot with the camera view direction
+    // NdotL        = the normal dot with the light direction
+    // VdotH        = the camera view direction dot with the half vector
+    float3 Diffuse(float3 diffuseColor, float roughness, float NdotV, float NdotL, float VdotH)
+    {
+        //return LambertianDiffuse(diffuseColor, NdotL);
+        return BurleyDiffuse(diffuseColor, roughness, NdotV, NdotL, VdotH);
+    }
+
+  #endif
+#endif

+ 8 - 2
Resources/CoreData/Shaders/HLSL/Basic.hlsl

@@ -14,11 +14,17 @@ void VS(float4 iPos : POSITION,
         int4 iBlendIndices : BLENDINDICES,
     #endif
     #ifdef INSTANCED
-        float4x3 iModelInstance : TEXCOORD2,
+        float4x3 iModelInstance : TEXCOORD4,
     #endif
-    #ifdef BILLBOARD
+    #if defined(BILLBOARD) || defined(DIRBILLBOARD)
         float2 iSize : TEXCOORD1,
     #endif
+    #if defined(DIRBILLBOARD) || defined(TRAILBONE)
+        float3 iNormal : NORMAL,
+    #endif
+    #if defined(TRAILFACECAM) || defined(TRAILBONE)
+        float4 iTangent : TANGENT,
+    #endif
     #ifdef DIFFMAP
         out float2 oTexCoord : TEXCOORD0,
     #endif

+ 9 - 9
Resources/CoreData/Shaders/HLSL/Bloom.hlsl

@@ -8,8 +8,8 @@
 // D3D9 uniforms
 uniform float cBloomThreshold;
 uniform float2 cBloomMix;
-uniform float2 cHBlurOffsets;
-uniform float2 cHBlurInvSize;
+uniform float2 cBlurHOffsets;
+uniform float2 cBlurHInvSize;
 
 #else
 
@@ -17,14 +17,14 @@ uniform float2 cHBlurInvSize;
 #ifdef COMPILEVS
 cbuffer CustomVS : register(b6)
 {
-    float2 cHBlurOffsets;
+    float2 cBlurHOffsets;
 }
 #else
 cbuffer CustomPS : register(b6)
 {
     float cBloomThreshold;
     float2 cBloomMix;
-    float2 cHBlurInvSize;
+    float2 cBlurHInvSize;
 }
 #endif
 
@@ -54,7 +54,7 @@ void VS(float4 iPos : POSITION,
     float4x3 modelMatrix = iModelMatrix;
     float3 worldPos = GetWorldPos(modelMatrix);
     oPos = GetClipPos(worldPos);
-    oTexCoord = GetQuadTexCoord(oPos) + cHBlurOffsets;
+    oTexCoord = GetQuadTexCoord(oPos) + cBlurHOffsets;
     oScreenPos = GetScreenPosPreDiv(oPos);
 }
 
@@ -67,17 +67,17 @@ void PS(float2 iTexCoord : TEXCOORD0,
     oColor = float4((rgb - cBloomThreshold) / (1.0 - cBloomThreshold), 1.0);
     #endif
 
-    #ifdef HBLUR
+    #ifdef BLURH
     float3 rgb = 0.0;
     for (int i = 0; i < 5; ++i)
-        rgb += Sample2D(DiffMap, iTexCoord + (float2(offsets[i], 0.0)) * cHBlurInvSize).rgb * weights[i];
+        rgb += Sample2D(DiffMap, iTexCoord + (float2(offsets[i], 0.0)) * cBlurHInvSize).rgb * weights[i];
     oColor = float4(rgb, 1.0);
     #endif
 
-    #ifdef VBLUR
+    #ifdef BLURV
     float3 rgb = 0.0;
     for (int i = 0; i < 5; ++i)
-        rgb += Sample2D(DiffMap, iTexCoord + (float2(0.0, offsets[i])) * cHBlurInvSize).rgb * weights[i];
+        rgb += Sample2D(DiffMap, iTexCoord + (float2(0.0, offsets[i])) * cBlurHInvSize).rgb * weights[i];
     oColor = float4(rgb, 1.0);
     #endif
 

+ 22 - 26
Resources/CoreData/Shaders/HLSL/Blur.hlsl

@@ -11,9 +11,9 @@ uniform float2 cBlurHOffsets;
 uniform float2 cBlurHInvSize;
 
 void VS(float4 iPos : POSITION,
-    out float4 oPos : POSITION,
     out float2 oTexCoord : TEXCOORD0,
-    out float2 oScreenPos : TEXCOORD1)
+    out float2 oScreenPos : TEXCOORD1,
+    out float4 oPos : OUTPOSITION)
 {
     float4x3 modelMatrix = iModelMatrix;
     float3 worldPos = GetWorldPos(modelMatrix);
@@ -26,39 +26,35 @@ void PS(float2 iTexCoord : TEXCOORD0,
     float2 iScreenPos : TEXCOORD1,
     out float4 oColor : OUTCOLOR0)
 {
-
-#ifndef D3D11
-    #ifdef BLUR3
-        oColor = GaussianBlur(3, cBlurDir, cBlurHInvSize * cBlurRadius, cBlurSigma, sDiffMap, iTexCoord);
-    #endif
-
-    #ifdef BLUR5
-        oColor = GaussianBlur(5, cBlurDir, cBlurHInvSize * cBlurRadius, cBlurSigma, sDiffMap, iTexCoord);
-    #endif
-
-    #ifdef BLUR7
-        oColor = GaussianBlur(7, cBlurDir, cBlurHInvSize * cBlurRadius, cBlurSigma, sDiffMap, iTexCoord);
-    #endif
-
-    #ifdef BLUR9
-        oColor = GaussianBlur(9, cBlurDir, cBlurHInvSize * cBlurRadius, cBlurSigma, sDiffMap, iTexCoord);
-    #endif
-
-#else
     #ifdef BLUR3
-        oColor = GaussianBlur(3, cBlurDir, cBlurHInvSize * cBlurRadius, cBlurSigma, tDiffMap, sDiffMap, iTexCoord);
+        #ifndef D3D11 
+            oColor = GaussianBlur(3, cBlurDir, cBlurHInvSize * cBlurRadius, cBlurSigma, sDiffMap, iTexCoord);
+        #else
+            oColor = GaussianBlur(3, cBlurDir, cBlurHInvSize * cBlurRadius, cBlurSigma, tDiffMap, sDiffMap, iTexCoord);
+        #endif
     #endif
 
     #ifdef BLUR5
-        oColor = GaussianBlur(5, cBlurDir, cBlurHInvSize * cBlurRadius, cBlurSigma, tDiffMap, sDiffMap, iTexCoord);
+        #ifndef D3D11
+            oColor = GaussianBlur(5, cBlurDir, cBlurHInvSize * cBlurRadius, cBlurSigma, sDiffMap, iTexCoord);
+        #else
+            oColor = GaussianBlur(5, cBlurDir, cBlurHInvSize * cBlurRadius, cBlurSigma, tDiffMap, sDiffMap, iTexCoord);
+        #endif
     #endif
 
     #ifdef BLUR7
-        oColor = GaussianBlur(7, cBlurDir, cBlurHInvSize * cBlurRadius, cBlurSigma, tDiffmap, sDiffMap, iTexCoord);
+        #ifndef D3D11
+            oColor = GaussianBlur(7, cBlurDir, cBlurHInvSize * cBlurRadius, cBlurSigma, sDiffMap, iTexCoord);
+        #else
+            oColor = GaussianBlur(7, cBlurDir, cBlurHInvSize * cBlurRadius, cBlurSigma, tDiffMap, sDiffMap, iTexCoord);
+        #endif
     #endif
 
     #ifdef BLUR9
-        oColor = GaussianBlur(9, cBlurDir, cBlurHInvSize * cBlurRadius, cBlurSigma, tDiffMap, sDiffMap, iTexCoord);
+        #ifndef D3D11
+            oColor = GaussianBlur(9, cBlurDir, cBlurHInvSize * cBlurRadius, cBlurSigma, sDiffMap, iTexCoord);
+        #else
+            oColor = GaussianBlur(9, cBlurDir, cBlurHInvSize * cBlurRadius, cBlurSigma, tDiffMap, sDiffMap, iTexCoord);
+        #endif
     #endif
-#endif
 }

+ 7 - 0
Resources/CoreData/Shaders/HLSL/Constants.hlsl

@@ -0,0 +1,7 @@
+#define M_PI 3.14159265358979323846
+#define M_EPSILON 0.0001
+
+#ifdef PBR
+#define ROUGHNESS_FLOOR 0.003
+#define METALNESS_FLOOR 0.03
+#endif

+ 7 - 3
Resources/CoreData/Shaders/HLSL/DeferredLight.hlsl

@@ -72,7 +72,11 @@ void PS(
         float4 albedoInput = Sample2DProj(AlbedoBuffer, iScreenPos);
         float4 normalInput = Sample2DProj(NormalBuffer, iScreenPos);
     #endif
-    
+
+    // Position acquired via near/far ray is relative to camera. Bring position to world space
+    float3 eyeVec = -worldPos;
+    worldPos += cCameraPosPS;
+
     float3 normal = normalize(normalInput.rgb * 2.0 - 1.0);
     float4 projWorldPos = float4(worldPos, 1.0);
     float3 lightColor;
@@ -81,7 +85,7 @@ void PS(
     float diff = GetDiffuse(normal, worldPos, lightDir);
 
     #ifdef SHADOW
-        diff *= GetShadowDeferred(projWorldPos, depth);
+        diff *= GetShadowDeferred(projWorldPos, normal, depth);
     #endif
 
     #if defined(SPOTLIGHT)
@@ -94,7 +98,7 @@ void PS(
     #endif
 
     #ifdef SPECULAR
-        float spec = GetSpecular(normal, -worldPos, lightDir, normalInput.a * 255.0);
+        float spec = GetSpecular(normal, eyeVec, lightDir, normalInput.a * 255.0);
         oColor = diff * float4(lightColor * (albedoInput.rgb + spec * cLightColor.a * albedoInput.aaa), 0.0);
     #else
         oColor = diff * float4(lightColor * albedoInput.rgb, 0.0);

+ 9 - 2
Resources/CoreData/Shaders/HLSL/Depth.hlsl

@@ -8,12 +8,19 @@ void VS(float4 iPos : POSITION,
         int4 iBlendIndices : BLENDINDICES,
     #endif
     #ifdef INSTANCED
-        float4x3 iModelInstance : TEXCOORD2,
+        float4x3 iModelInstance : TEXCOORD4,
+    #endif
+    #ifndef NOUV
+        float2 iTexCoord : TEXCOORD0,
     #endif
-    float2 iTexCoord : TEXCOORD0,
     out float3 oTexCoord : TEXCOORD0,
     out float4 oPos : OUTPOSITION)
 {
+    // Define a 0,0 UV coord if not expected from the vertex data
+    #ifdef NOUV
+    float2 iTexCoord = float2(0.0, 0.0);
+    #endif
+    
     float4x3 modelMatrix = iModelMatrix;
     float3 worldPos = GetWorldPos(modelMatrix);
     oPos = GetClipPos(worldPos);

+ 282 - 0
Resources/CoreData/Shaders/HLSL/IBL.hlsl

@@ -0,0 +1,282 @@
+#ifdef COMPILEPS
+
+    //  float3 ImportanceSampleSimple(in float2 Xi, in float roughness, in float3 T, in float3 B, in float3 N)
+    // {
+    //     const float a = roughness * roughness;
+    //     const float3x3 tbn = float3x3(T, B, N);
+    //     #ifdef IBLFAST
+    //         const float blurFactor = 0.0;
+    //     #else
+    //         const float blurFactor = 5.0;
+    //     #endif
+    //     const float3 Xi3 = lerp(float3(0,0,1), normalize(float3(Xi.xy * blurFactor % 1.0 , 1.0)), a);
+    //     const float3 XiWS = mul(Xi3, tbn);
+    //     return normalize(N + XiWS);
+    // }
+
+    // // Karis '13
+    // float3 ImportanceSampleGGX(in float2 Xi, in float roughness, in float3 T, in float3 B, in float3 N)
+    // {
+    //     float a = roughness * roughness;
+    //     float Phi = 2.0 * M_PI * Xi.x;
+    //     float CosTheta = (sqrt((1.0 - Xi.y) / (1.0 + (a*a - 1.0) * Xi.y)));
+    //     float SinTheta = sqrt(1.0 - CosTheta * CosTheta);
+    //     float3 H = 0;
+    //     H.x = SinTheta * cos(Phi);
+    //     H.y = SinTheta * sin(Phi);
+    //     H.z = CosTheta;
+
+    //     float3 UpVector = abs(N.z) < 0.999 ? float3(0, 0, 1) : float3(1, 0, 0);
+    //     float3 TangentX = normalize(cross(UpVector, N));
+    //     float3 TangentY = cross(N, TangentX);
+    //     // Tangent to world space
+    //     return TangentX * H.x + TangentY * H.y + N * H.z;
+    // }
+
+    // #ifdef IBLFAST
+    //     #define IMPORTANCE_SAMPLES 1
+    // #else
+    //     #define IMPORTANCE_SAMPLES 16
+    // #endif
+
+    // #define IMPORTANCE_KERNEL_SIZE 16
+    // static const float2 IMPORTANCE_KERNEL[IMPORTANCE_KERNEL_SIZE] =
+    // {
+    //     float2(-0.0780436, 0.0558389),
+    //     float2(0.034318, -0.0635879),
+    //     float2(0.00230821, 0.0807279),
+    //     float2(0.0124638, 0.117585),
+    //     float2(0.093943, -0.0944602),
+    //     float2(0.139348, -0.109816),
+    //     float2(-0.181872, -0.129649),
+    //     float2(0.240066, -0.0494057),
+    //     float2(0.115965, -0.0374714),
+    //     float2(-0.294819, -0.100726),
+    //     float2(-0.149652, 0.37459),
+    //     float2(0.261695, -0.292813),
+    //     float2(-0.37944, -0.425145),
+    //     float2(0.628994, -0.189387),
+    //     float2(-0.331257, -0.646864),
+    //     float2(-0.467004, 0.439687),
+    // };
+
+    // float GetMipFromRougness(float roughness)
+    // {
+    //     const float smoothness = 1.0 - roughness;
+    //     return (1.0 - smoothness * smoothness) * 10.0;
+    // }
+
+    // /// Perform importance sampling
+    // ///     reflectVec: calculated vector of reflection
+    // ///     wsNormal: world-space normal of the surface
+    // ///     toCamera: direction from the pixel to the camera
+    // ///     specular: specular color
+    // ///     roughness: surface roughness
+    // ///     reflectionCubeColor: output color for diffuse
+
+    // // Implementation based on Epics 2013 course notes
+    // float3 ImportanceSampling(in float3 reflectVec, in float3 tangent, in float3 bitangent, in float3 wsNormal, in float3 toCamera,  in float3 diffColor, in float3 specColor, in float roughness, inout float3 reflectionCubeColor)
+    // {
+    //     reflectionCubeColor = 1.0;
+
+    //     const float3 reflectSpec = normalize(GetSpecularDominantDir(wsNormal, reflectVec, roughness));
+
+    //     const float3 V = normalize(-toCamera);
+    //     const float3 N = normalize(wsNormal);
+    //     const float ndv = saturate(abs(dot(N, V)));
+
+    //     const float specMipLevel = GetMipFromRougness(roughness);
+
+    //     float3 accumulatedColor = float3(0,0,0);
+    //     for (int i = 0; i < IMPORTANCE_SAMPLES; ++i)
+    //     {
+    //         float3 kd = 1.0;
+    //         float3 diffuseFactor = 0.0;
+    //         float3 specularFactor = 0.0;
+
+    //         {
+    //             // Diffuse IBL
+    //             const float rough = 1.0;
+    //             const float mipLevel = 9.0;
+
+    //             const float3 H = ImportanceSampleSimple(IMPORTANCE_KERNEL[i], rough, tangent, bitangent, N);
+    //             const float3 L = 2.0 * dot( V, H ) * H - V;
+
+    //             const float vdh = saturate(abs(dot(V, H)));
+    //             const float ndh = saturate(abs(dot(N, H)));
+    //             const float ndl = saturate(abs(dot(N, L)));
+
+    //             const float3 sampledColor = SampleCubeLOD(ZoneCubeMap, float4(L, mipLevel));
+
+    //             const float3 diffuseTerm = Diffuse(diffColor, rough, ndv, ndl, vdh);
+    //             const float3 lightTerm = sampledColor;
+
+    //             diffuseFactor = lightTerm * diffuseTerm;
+    //         }
+
+    //         {
+    //             // Specular IBL
+    //             const float rough = roughness;
+    //             const float mipLevel = specMipLevel;
+
+    //             const float3 H = ImportanceSampleSimple(IMPORTANCE_KERNEL[i], rough, tangent, bitangent, N);
+    //             const float3 L = 2.0 * dot( V, H ) * H - V;
+    //             const float3 sampledColor = SampleCubeLOD(ZoneCubeMap, float4(L, mipLevel));
+
+    //             const float vdh = saturate(abs(dot(V, H)));
+    //             const float ndh = saturate(abs(dot(N, H)));
+    //             const float ndl = saturate(abs(dot(N, L)));
+
+    //             const float3 fresnelTerm = Fresnel(specColor, vdh);
+    //             const float distTerm = 1.0;//Distribution(ndh_, roughness);
+    //             const float visTerm = Visibility(ndl, ndv, rough);
+    //             const float3 lightTerm = sampledColor * ndl;
+
+    //             const float pdf = ndl > 0.05 ? ImportanceSamplePDF(distTerm, ndh, vdh) : 4.0; // reduce artifacts at extreme grazing angles
+
+    //             const float3 specularTerm = SpecularBRDF(distTerm, fresnelTerm, visTerm, ndl, ndv);
+
+    //             // Energy conservation:
+    //             // Specular conservation:
+    //             specularFactor = lightTerm * specularTerm / pdf;
+    //             specularFactor = max(saturate(normalize(specularFactor) * (length(sampledColor * specColor))), specularFactor);
+
+    //             // Diffuse conservation:
+    //             kd = 1.0 - specularFactor;
+    //         }
+
+    //         accumulatedColor += specularFactor + diffuseFactor * kd;
+    //     }
+
+    //     return (accumulatedColor / IMPORTANCE_SAMPLES);
+    // }
+
+
+    // float3 ImportanceSamplingSimple(in float3 reflectVec, in float3 tangent, in float3 bitangent, in float3 wsNormal, in float3 toCamera,  in float3 diffColor, in float3 specColor, in float roughness, inout float3 reflectionCubeColor)
+    // {
+    //     reflectionCubeColor = 1.0;
+
+    //     reflectVec = normalize(GetSpecularDominantDir(wsNormal, reflectVec, roughness));
+
+    //     const float3 Hn = normalize(-toCamera + wsNormal);
+    //     const float ndv = saturate(dot(-toCamera, wsNormal));
+    //     const float vdh = saturate(dot(-toCamera, Hn));
+    //     const float ndh = saturate(dot(wsNormal, Hn));
+
+    //     float3 accumulatedColor = float3(0,0,0);
+    //     for (int i = 0; i < IMPORTANCE_SAMPLES; ++i)
+    //     {
+    //         float3 kd = 1.0;
+    //         float3 diffuseFactor = 0.0;
+    //         float3 specularFactor = 0.0;
+
+    //         {
+    //             // Diffuse IBL
+    //             const float rough = 1.0;
+    //             const float mipLevel = 9.0;
+
+    //             const float3 perturb = ImportanceSampleGGX(IMPORTANCE_KERNEL[i].xy, rough, tangent, bitangent, wsNormal);
+    //             const float3 sampleVec = wsNormal + perturb; //perturb by the sample vector
+
+    //             const float3 sampledColor = SampleCubeLOD(ZoneCubeMap, float4(sampleVec, mipLevel));
+    //             const float ndl = saturate(dot(sampleVec, wsNormal));
+
+    //             const float3 diffuseTerm = Diffuse(diffColor, rough, ndv, ndl, vdh);
+    //             const float3 lightTerm = sampledColor;
+
+    //             diffuseFactor = lightTerm * diffuseTerm;
+    //         }
+
+    //         {
+    //             // Specular IBL
+    //             const float rough = roughness;
+    //             const float mipLevel =  GetMipFromRougness(rough);
+
+    //             const float3 perturb = ImportanceSampleGGX(IMPORTANCE_KERNEL[i].xy, rough, tangent, bitangent, reflectVec);
+    //             const float3 sampleVec = reflectVec + perturb; //perturb by the sample vector
+
+    //             const float3 sampledColor = SampleCubeLOD(ZoneCubeMap, float4(sampleVec, mipLevel));
+    //             const float ndl = saturate(dot(sampleVec, wsNormal));
+
+    //             const float3 fresnelTerm = SchlickFresnel(specColor, ndh) ;
+    //             const float distTerm = 1.0; //Optimization, this term is mathematically cancelled out  //Distribution(ndh, roughness);
+    //             const float visTerm = SmithGGXVisibility(ndl, ndv, rough);
+    //             const float3 lightTerm = sampledColor * ndl;
+
+    //             const float pdf = 1.0;//ImportanceSamplePDF(distTerm, ndh, vdh);
+
+    //             specularFactor = lightTerm * SpecularBRDF(distTerm, fresnelTerm, visTerm, ndl, ndv) / pdf;
+    //             specularFactor *= pdf * ndv * (4.0 * ndl * ndv); // hacks
+    //             kd = (1.0 - saturate(specularFactor)); //energy conservation
+    //         }
+
+    //         accumulatedColor += specularFactor + diffuseFactor * kd;
+    //     }
+
+    //     return accumulatedColor / IMPORTANCE_SAMPLES;
+    // }
+
+    /// Determine reflection vector based on surface roughness, rougher uses closer to the normal and smoother uses closer to the reflection vector
+    ///     normal: surface normal
+    ///     reflection: vector of reflection off of the surface
+    ///     roughness: surface roughness
+    float3 GetSpecularDominantDir(float3 normal, float3 reflection, float roughness)
+    {
+        const float smoothness = 1.0 - roughness;
+        const float lerpFactor = smoothness * (sqrt(smoothness) + roughness);
+        return lerp(normal, reflection, lerpFactor);
+    }
+
+    float GetMipFromRougness(float roughness)
+    {
+        const float smoothness = 1.0 - roughness;
+        return (1.0 - smoothness * smoothness) * 10.0;
+    }
+
+
+    float3 EnvBRDFApprox (float3 SpecularColor, float Roughness, float NoV)
+    {
+        const float4 c0 = float4(-1, -0.0275, -0.572, 0.022 );
+        const float4 c1 = float4(1, 0.0425, 1.0, -0.04 );
+        float4 r = Roughness * c0 + c1;
+        float a004 = min( r.x * r.x, exp2( -9.28 * NoV ) ) * r.x + r.y;
+        float2 AB = float2( -1.04, 1.04 ) * a004 + r.zw;
+        return SpecularColor * AB.x + AB.y;
+    }
+
+    /// Calculate IBL contributation
+    ///     reflectVec: reflection vector for cube sampling
+    ///     wsNormal: surface normal in word space
+    ///     toCamera: normalized direction from surface point to camera
+    ///     roughness: surface roughness
+    ///     ambientOcclusion: ambient occlusion
+    float3 ImageBasedLighting(in float3 reflectVec, in float3 tangent, in float3 bitangent, in float3 wsNormal, in float3 toCamera, in float3 diffColor, in float3 specColor, in float roughness, inout float3 reflectionCubeColor)
+    {
+        reflectVec = GetSpecularDominantDir(wsNormal, reflectVec, roughness);
+        const float ndv = saturate(dot(-toCamera, wsNormal));
+
+        // PMREM Mipmapmode https://seblagarde.wordpress.com/2012/06/10/amd-cubemapgen-for-physically-based-rendering/
+        //const float GlossScale = 16.0;
+        //const float GlossBias = 5.0;
+        const float mipSelect = roughness * 9.0;// exp2(GlossScale * roughness + GlossBias) - exp2(GlossBias);
+
+        float3 cube = SampleCubeLOD(ZoneCubeMap, float4(reflectVec, mipSelect)).rgb;
+        float3 cubeD = SampleCubeLOD(ZoneCubeMap, float4(wsNormal, 9.0)).rgb;
+        // Fake the HDR texture
+        float brightness = clamp(cAmbientColor.a, 0.0, 1.0);
+        float darknessCutoff = clamp((cAmbientColor.a - 1.0) * 0.1, 0.0, 0.25);
+
+        const float hdrMaxBrightness = 5.0;
+        float3 hdrCube = pow(cube + darknessCutoff, max(1.0, cAmbientColor.a));
+        hdrCube += max(0.0, hdrCube - 1.0) * hdrMaxBrightness;
+
+        float3 hdrCubeD = pow(cubeD + darknessCutoff, max(1.0, cAmbientColor.a));
+        hdrCubeD += max(0.0, hdrCubeD - 1.0) * hdrMaxBrightness;
+
+        const float3 environmentSpecular = EnvBRDFApprox(specColor, roughness, ndv);
+        const float3 environmentDiffuse = EnvBRDFApprox(diffColor, 1.0, ndv);
+
+        return (hdrCube * environmentSpecular + hdrCubeD * environmentDiffuse) * brightness;
+        //return ImportanceSampling(reflectVec, tangent, bitangent, wsNormal, toCamera, diffColor, specColor, roughness, reflectionCubeColor);
+    }
+#endif

+ 148 - 47
Resources/CoreData/Shaders/HLSL/Lighting.hlsl

@@ -18,7 +18,11 @@ float GetVertexLight(int index, float3 worldPos, float3 normal)
     // Directional light
     if (invRange == 0.0)
     {
-        float NdotL = max(dot(normal, lightDir), 0.0);
+        #ifdef TRANSLUCENT
+            float NdotL = abs(dot(normal, lightDir));
+        #else
+            float NdotL = max(dot(normal, lightDir), 0.0);
+        #endif
         return NdotL;
     }
     // Point/spot light
@@ -27,7 +31,11 @@ float GetVertexLight(int index, float3 worldPos, float3 normal)
         float3 lightVec = (lightPos - worldPos) * invRange;
         float lightDist = length(lightVec);
         float3 localDir = lightVec / lightDist;
-        float NdotL = max(dot(normal, localDir), 0.0);
+        #ifdef TRANSLUCENT
+            float NdotL = abs(dot(normal, localDir));
+        #else
+            float NdotL = max(dot(normal, localDir), 0.0);
+        #endif
         float atten = saturate(1.0 - lightDist * lightDist);
         float spotEffect = dot(localDir, lightDir);
         float spotAtten = saturate((spotEffect - cutoff) * invCutoff);
@@ -70,18 +78,37 @@ float GetVertexLightVolumetric(int index, float3 worldPos)
     #define NUMCASCADES 1
 #endif
 
-void GetShadowPos(float4 projWorldPos, out float4 shadowPos[NUMCASCADES])
+void GetShadowPos(float4 projWorldPos, float3 normal, out float4 shadowPos[NUMCASCADES])
 {
     // Shadow projection: transform from world space to shadow space
-    #if defined(DIRLIGHT)
-        shadowPos[0] = mul(projWorldPos, cLightMatrices[0]);
-        shadowPos[1] = mul(projWorldPos, cLightMatrices[1]);
-        shadowPos[2] = mul(projWorldPos, cLightMatrices[2]);
-        shadowPos[3] = mul(projWorldPos, cLightMatrices[3]);
-    #elif defined(SPOTLIGHT)
-        shadowPos[0] = mul(projWorldPos, cLightMatrices[1]);
+    #ifdef NORMALOFFSET
+        #ifdef DIRLIGHT
+            float cosAngle = saturate(1.0 - dot(normal, cLightDir));
+        #else
+            float cosAngle = saturate(1.0 - dot(normal, normalize(cLightPos - projWorldPos.xyz)));
+        #endif
+
+        #if defined(DIRLIGHT)
+            shadowPos[0] = mul(float4(projWorldPos.xyz + cosAngle * cNormalOffsetScale.x * normal, 1.0), cLightMatrices[0]);
+            shadowPos[1] = mul(float4(projWorldPos.xyz + cosAngle * cNormalOffsetScale.y * normal, 1.0), cLightMatrices[1]);
+            shadowPos[2] = mul(float4(projWorldPos.xyz + cosAngle * cNormalOffsetScale.z * normal, 1.0), cLightMatrices[2]);
+            shadowPos[3] = mul(float4(projWorldPos.xyz + cosAngle * cNormalOffsetScale.w * normal, 1.0), cLightMatrices[3]);
+        #elif defined(SPOTLIGHT)
+            shadowPos[0] = mul(float4(projWorldPos.xyz + cosAngle * cNormalOffsetScale.x * normal, 1.0), cLightMatrices[1]);
+        #else
+            shadowPos[0] = float4(projWorldPos.xyz + cosAngle * cNormalOffsetScale.x * normal - cLightPos.xyz, 0.0);
+        #endif
     #else
-        shadowPos[0] = float4(projWorldPos.xyz - cLightPos.xyz, 0.0);
+        #if defined(DIRLIGHT)
+            shadowPos[0] = mul(projWorldPos, cLightMatrices[0]);
+            shadowPos[1] = mul(projWorldPos, cLightMatrices[1]);
+            shadowPos[2] = mul(projWorldPos, cLightMatrices[2]);
+            shadowPos[3] = mul(projWorldPos, cLightMatrices[3]);
+        #elif defined(SPOTLIGHT)
+            shadowPos[0] = mul(projWorldPos, cLightMatrices[1]);
+        #else
+            shadowPos[0] = float4(projWorldPos.xyz - cLightPos.xyz, 0.0);
+        #endif
     #endif
 }
 #endif
@@ -91,13 +118,36 @@ void GetShadowPos(float4 projWorldPos, out float4 shadowPos[NUMCASCADES])
 float GetDiffuse(float3 normal, float3 worldPos, out float3 lightDir)
 {
     #ifdef DIRLIGHT
+        lightDir = cLightDirPS;
+        #ifdef TRANSLUCENT
+            return abs(dot(normal, lightDir));
+        #else
+            return saturate(dot(normal, lightDir));
+        #endif
+    #else
+        float3 lightVec = (cLightPosPS.xyz - worldPos) * cLightPosPS.w;
+        float lightDist = length(lightVec);
+        lightDir = lightVec / lightDist;
+        #ifdef TRANSLUCENT
+            return abs(dot(normal, lightDir)) * Sample2D(LightRampMap, float2(lightDist, 0.0)).r;
+        #else
+            return saturate(dot(normal, lightDir)) * Sample2D(LightRampMap, float2(lightDist, 0.0)).r;
+        #endif
+    #endif
+}
+
+float GetAtten(float3 normal, float3 worldPos, out float3 lightDir)
+{
+     #ifdef DIRLIGHT
         lightDir = cLightDirPS;
         return saturate(dot(normal, lightDir));
     #else
         float3 lightVec = (cLightPosPS.xyz - worldPos) * cLightPosPS.w;
         float lightDist = length(lightVec);
+        float falloff = pow(saturate(1.0 - pow(lightDist / 1.0, 4.0)), 2.0) / (pow(lightDist, 2.0) + 1.0);
+
         lightDir = lightVec / lightDist;
-        return saturate(dot(normal, lightDir)) * Sample2D(LightRampMap, float2(lightDist, 0.0)).r;
+        return saturate(dot(normal, lightDir)) * falloff;
     #endif
 }
 
@@ -131,15 +181,55 @@ float GetIntensity(float3 color)
     #define NUMCASCADES 1
 #endif
 
+#ifdef VSM_SHADOW
+float ReduceLightBleeding(float min, float p_max)  
+{  
+    return clamp((p_max - min) / (1.0 - min), 0.0, 1.0);  
+}
+
+float Chebyshev(float2 Moments, float depth)  
+{  
+    //One-tailed inequality valid if depth > Moments.x  
+    float p = float(depth <= Moments.x);  
+    //Compute variance.  
+    float Variance = Moments.y - (Moments.x * Moments.x); 
+
+    float minVariance = cVSMShadowParams.x;
+    Variance = max(Variance, minVariance);  
+    //Compute probabilistic upper bound.  
+    float d = depth - Moments.x;  
+    float p_max = Variance / (Variance + d*d); 
+    // Prevent light bleeding
+    p_max = ReduceLightBleeding(cVSMShadowParams.y, p_max);
+
+    return max(p, p_max);
+}
+#endif
+
 float GetShadow(float4 shadowPos)
 {
-    #ifdef D3D11
-        shadowPos.xyz /= shadowPos.w;
-    #endif
-
-    #ifndef LQSHADOW
+    #if defined(SIMPLE_SHADOW)
+        // Take one sample
+        #ifdef D3D11
+            shadowPos.xyz /= shadowPos.w;
+        #endif
+        float inLight = SampleShadow(ShadowMap, shadowPos).r;
+        #ifndef SHADOWCMP
+            return cShadowIntensity.y + cShadowIntensity.x * inLight;
+        #else
+            #ifndef POINTLIGHT
+                return cShadowIntensity.y + cShadowIntensity.x * (inLight * shadowPos.w > shadowPos.z);
+            #else
+                return cShadowIntensity.y + cShadowIntensity.x * (inLight > shadowPos.z);
+            #endif
+        #endif
+    
+    #elif defined(PCF_SHADOW)
         // Take four samples and average them
         // Note: in case of sampling a point light cube shadow, we optimize out the w divide as it has already been performed
+        #ifdef D3D11
+            shadowPos.xyz /= shadowPos.w;
+        #endif
         #if !defined(POINTLIGHT) && !defined(D3D11)
             float2 offsets = cShadowMapInvSize * shadowPos.w;
         #else
@@ -164,18 +254,10 @@ float GetShadow(float4 shadowPos)
                 return cShadowIntensity.y + dot(inLight > shadowPos.z, cShadowIntensity.x);
             #endif
         #endif
-    #else
-        // Take one sample
-        float inLight = SampleShadow(ShadowMap, shadowPos).r;
-        #ifndef SHADOWCMP
-            return cShadowIntensity.y + cShadowIntensity.x * inLight;
-        #else
-            #ifndef POINTLIGHT
-                return cShadowIntensity.y + cShadowIntensity.x * (inLight * shadowPos.w > shadowPos.z);
-            #else
-                return cShadowIntensity.y + cShadowIntensity.x * (inLight > shadowPos.z);
-            #endif
-        #endif
+    
+    #elif defined(VSM_SHADOW)
+        float2 samples = Sample2D(ShadowMap, shadowPos.xy / shadowPos.w).rg;
+        return cShadowIntensity.y + cShadowIntensity.x * Chebyshev(samples, shadowPos.z/shadowPos.w);
     #endif
 }
 
@@ -223,19 +305,31 @@ float GetDirShadow(const float4 iShadowPos[NUMCASCADES], float depth)
     return GetDirShadowFade(GetShadow(shadowPos), depth);
 }
 
-float GetDirShadowDeferred(float4 projWorldPos, float depth)
+float GetDirShadowDeferred(float4 projWorldPos, float3 normal, float depth)
 {
     float4 shadowPos;
 
-    if (depth < cShadowSplits.x)
-        shadowPos = mul(projWorldPos, cLightMatricesPS[0]);
-    else if (depth < cShadowSplits.y)
-        shadowPos = mul(projWorldPos, cLightMatricesPS[1]);
-    else if (depth < cShadowSplits.z)
-        shadowPos = mul(projWorldPos, cLightMatricesPS[2]);
-    else
-        shadowPos = mul(projWorldPos, cLightMatricesPS[3]);
-
+    #ifdef NORMALOFFSET
+        float cosAngle = saturate(1.0 - dot(normal, cLightDirPS));
+        if (depth < cShadowSplits.x)
+            shadowPos = mul(float4(projWorldPos.xyz + cosAngle * cNormalOffsetScalePS.x * normal, 1.0), cLightMatricesPS[0]);
+        else if (depth < cShadowSplits.y)
+            shadowPos = mul(float4(projWorldPos.xyz + cosAngle * cNormalOffsetScalePS.y * normal, 1.0), cLightMatricesPS[1]);
+        else if (depth < cShadowSplits.z)
+            shadowPos = mul(float4(projWorldPos.xyz + cosAngle * cNormalOffsetScalePS.z * normal, 1.0), cLightMatricesPS[2]);
+        else
+            shadowPos = mul(float4(projWorldPos.xyz + cosAngle * cNormalOffsetScalePS.w * normal, 1.0), cLightMatricesPS[3]);
+    #else
+        if (depth < cShadowSplits.x)
+            shadowPos = mul(projWorldPos, cLightMatricesPS[0]);
+        else if (depth < cShadowSplits.y)
+            shadowPos = mul(projWorldPos, cLightMatricesPS[1]);
+        else if (depth < cShadowSplits.z)
+            shadowPos = mul(projWorldPos, cLightMatricesPS[2]);
+        else
+            shadowPos = mul(projWorldPos, cLightMatricesPS[3]);
+    #endif
+    
     return GetDirShadowFade(GetShadow(shadowPos), depth);
 }
 #endif
@@ -251,16 +345,23 @@ float GetShadow(float4 iShadowPos[NUMCASCADES], float depth)
     #endif
 }
 
-float GetShadowDeferred(float4 projWorldPos, float depth)
+float GetShadowDeferred(float4 projWorldPos, float3 normal, float depth)
 {
-    #if defined(DIRLIGHT)
-        return GetDirShadowDeferred(projWorldPos, depth);
-    #elif defined(SPOTLIGHT)
-        float4 shadowPos = mul(projWorldPos, cLightMatricesPS[1]);
-        return GetShadow(shadowPos);
+    #ifdef DIRLIGHT
+        return GetDirShadowDeferred(projWorldPos, normal, depth);
     #else
-        float3 shadowPos = projWorldPos.xyz - cLightPosPS.xyz;
-        return GetPointShadow(shadowPos);
+        #ifdef NORMALOFFSET
+            float cosAngle = saturate(1.0 - dot(normal, normalize(cLightPosPS - projWorldPos.xyz)));
+            projWorldPos.xyz += cosAngle * cNormalOffsetScalePS.x * normal;
+        #endif
+
+        #ifdef SPOTLIGHT
+            float4 shadowPos = mul(projWorldPos, cLightMatricesPS[1]);
+            return GetShadow(shadowPos);
+        #else
+            float3 shadowPos = projWorldPos.xyz - cLightPosPS.xyz;
+            return GetPointShadow(shadowPos);
+        #endif
     #endif
 }
 #endif

+ 8 - 5
Resources/CoreData/Shaders/HLSL/LitParticle.hlsl

@@ -5,7 +5,7 @@
 #include "Fog.hlsl"
 
 void VS(float4 iPos : POSITION,
-    #ifndef BILLBOARD
+    #if !defined(BILLBOARD) && !defined(TRAILFACECAM)
         float3 iNormal : NORMAL,
     #endif
     #ifndef NOUV
@@ -19,11 +19,14 @@ void VS(float4 iPos : POSITION,
         int4 iBlendIndices : BLENDINDICES,
     #endif
     #ifdef INSTANCED
-        float4x3 iModelInstance : TEXCOORD2,
+        float4x3 iModelInstance : TEXCOORD4,
     #endif
-    #ifdef BILLBOARD
+    #if defined(BILLBOARD) || defined(DIRBILLBOARD)
         float2 iSize : TEXCOORD1,
     #endif
+    #if defined(TRAILFACECAM) || defined(TRAILBONE)
+        float4 iTangent : TANGENT,
+    #endif
     out float2 oTexCoord : TEXCOORD0,
     out float4 oWorldPos : TEXCOORD3,
     #if PERPIXEL
@@ -72,7 +75,7 @@ void VS(float4 iPos : POSITION,
 
         #ifdef SHADOW
             // Shadow projection: transform from world space to shadow space
-            GetShadowPos(projWorldPos, oShadowPos);
+            GetShadowPos(projWorldPos, float3(0, 0, 0), oShadowPos);
         #endif
 
         #ifdef SPOTLIGHT
@@ -103,7 +106,7 @@ void PS(float2 iTexCoord : TEXCOORD0,
         #ifdef SPOTLIGHT
             float4 iSpotPos : TEXCOORD5,
         #endif
-        #ifdef CUBEMASK
+        #ifdef POINTLIGHT
             float3 iCubeMaskVec : TEXCOORD5,
         #endif
     #else

+ 34 - 49
Resources/CoreData/Shaders/HLSL/LitSolid.hlsl

@@ -6,7 +6,7 @@
 #include "Fog.hlsl"
 
 void VS(float4 iPos : POSITION,
-    #ifndef BILLBOARD
+    #if !defined(BILLBOARD) && !defined(TRAILFACECAM)
         float3 iNormal : NORMAL,
     #endif
     #ifndef NOUV
@@ -18,7 +18,7 @@ void VS(float4 iPos : POSITION,
     #if defined(LIGHTMAP) || defined(AO)
         float2 iTexCoord2 : TEXCOORD1,
     #endif
-    #ifdef NORMALMAP
+    #if defined(NORMALMAP) || defined(TRAILFACECAM) || defined(TRAILBONE)
         float4 iTangent : TANGENT,
     #endif
     #ifdef SKINNED
@@ -26,9 +26,9 @@ void VS(float4 iPos : POSITION,
         int4 iBlendIndices : BLENDINDICES,
     #endif
     #ifdef INSTANCED
-        float4x3 iModelInstance : TEXCOORD2,
+        float4x3 iModelInstance : TEXCOORD4,
     #endif
-    #ifdef BILLBOARD
+    #if defined(BILLBOARD) || defined(DIRBILLBOARD)
         float2 iSize : TEXCOORD1,
     #endif
     #ifndef NORMALMAP
@@ -101,7 +101,7 @@ void VS(float4 iPos : POSITION,
 
         #ifdef SHADOW
             // Shadow projection: transform from world space to shadow space
-            GetShadowPos(projWorldPos, oShadowPos);
+            GetShadowPos(projWorldPos, oNormal, oShadowPos);
         #endif
 
         #ifdef SPOTLIGHT
@@ -152,7 +152,7 @@ void PS(
         #ifdef SPOTLIGHT
             float4 iSpotPos : TEXCOORD5,
         #endif
-        #ifdef CUBEMASK
+        #ifdef POINTLIGHT
             float3 iCubeMaskVec : TEXCOORD5,
         #endif
     #else
@@ -225,43 +225,33 @@ void PS(
         float3 lightColor;
         float3 finalColor;
 
-        #if defined(LIGHTMAP) && defined(SHADOW)
-            float diff = 1-GetShadow(iShadowPos, iWorldPos.w);
+        float diff = GetDiffuse(normal, iWorldPos.xyz, lightDir);
 
-            finalColor = diff * diffColor.rgb * cAmbientColor;
+        #ifdef SHADOW
+            diff *= GetShadow(iShadowPos, iWorldPos.w);
+        #endif
 
-            oColor = float4(GetLitFog(finalColor, fogFactor), diffColor.a);
-		#elif defined(LIGHTMAP)            
-            oColor = float4(0.0, 0.0, 0.0, 0.0);
+        #if defined(SPOTLIGHT)
+            lightColor = iSpotPos.w > 0.0 ? Sample2DProj(LightSpotMap, iSpotPos).rgb * cLightColor.rgb : 0.0;
+        #elif defined(CUBEMASK)
+            lightColor = SampleCube(LightCubeMap, iCubeMaskVec).rgb * cLightColor.rgb;
         #else
-            float diff = GetDiffuse(normal, iWorldPos.xyz, lightDir);
-
-            #ifdef SHADOW
-                diff *= GetShadow(iShadowPos, iWorldPos.w);
-            #endif
-
-            #if defined(SPOTLIGHT)
-                lightColor = iSpotPos.w > 0.0 ? Sample2DProj(LightSpotMap, iSpotPos).rgb * cLightColor.rgb : 0.0;
-            #elif defined(CUBEMASK)
-                lightColor = SampleCube(LightCubeMap, iCubeMaskVec).rgb * cLightColor.rgb;
-            #else
-                lightColor = cLightColor.rgb;
-            #endif
-        
-            #ifdef SPECULAR
-                float spec = GetSpecular(normal, cCameraPosPS - iWorldPos.xyz, lightDir, cMatSpecColor.a);
-                finalColor = diff * lightColor * (diffColor.rgb + spec * specColor * cLightColor.a);
-            #else
-                finalColor = diff * lightColor * diffColor.rgb;
-            #endif
+            lightColor = cLightColor.rgb;
+        #endif
+    
+        #ifdef SPECULAR
+            float spec = GetSpecular(normal, cCameraPosPS - iWorldPos.xyz, lightDir, cMatSpecColor.a);
+            finalColor = diff * lightColor * (diffColor.rgb + spec * specColor * cLightColor.a);
+        #else
+            finalColor = diff * lightColor * diffColor.rgb;
+        #endif
 
-            #ifdef AMBIENT
-                finalColor += cAmbientColor * diffColor.rgb;
-                finalColor += cMatEmissiveColor;
-                oColor = float4(GetFog(finalColor, fogFactor), diffColor.a);
-            #else
-                oColor = float4(GetLitFog(finalColor, fogFactor), diffColor.a);
-            #endif
+        #ifdef AMBIENT
+            finalColor += cAmbientColor.rgb * diffColor.rgb;
+            finalColor += cMatEmissiveColor;
+            oColor = float4(GetFog(finalColor, fogFactor), diffColor.a);
+        #else
+            oColor = float4(GetLitFog(finalColor, fogFactor), diffColor.a);
         #endif
     #elif defined(PREPASS)
         // Fill light pre-pass G-Buffer
@@ -277,7 +267,7 @@ void PS(
         float3 finalColor = iVertexLight * diffColor.rgb;
         #ifdef AO
             // If using AO, the vertex light ambient is black, calculate occluded ambient here
-            finalColor += Sample2D(EmissiveMap, iTexCoord2).rgb * cAmbientColor * diffColor.rgb;
+            finalColor += Sample2D(EmissiveMap, iTexCoord2).rgb * cAmbientColor.rgb * diffColor.rgb;
         #endif
         #ifdef ENVCUBEMAP
             finalColor += cMatEnvMapColor * SampleCube(EnvCubeMap, reflect(iReflectionVec, normal)).rgb;
@@ -300,7 +290,7 @@ void PS(
         float3 finalColor = iVertexLight * diffColor.rgb;
         #ifdef AO
             // If using AO, the vertex light ambient is black, calculate occluded ambient here
-            finalColor += Sample2D(EmissiveMap, iTexCoord2).rgb * cAmbientColor * diffColor.rgb;
+            finalColor += Sample2D(EmissiveMap, iTexCoord2).rgb * cAmbientColor.rgb * diffColor.rgb;
         #endif
 
         #ifdef MATERIAL
@@ -312,16 +302,11 @@ void PS(
             finalColor += lightInput.rgb * diffColor.rgb + lightSpecColor * specColor;
         #endif
 
+        #ifdef ENVCUBEMAP
+            finalColor += cMatEnvMapColor * SampleCube(EnvCubeMap, reflect(iReflectionVec, normal)).rgb;
+        #endif
         #ifdef LIGHTMAP
             finalColor += Sample2D(EmissiveMap, iTexCoord2).rgb * diffColor.rgb;
-			
-			#ifdef ENVCUBEMAP
-				finalColor += cMatEnvMapColor * SampleCube(EnvCubeMap, reflect(iReflectionVec, normal)).rgb * Sample2D(EmissiveMap, iTexCoord2).rgb;
-			#endif
-		#else
-			#ifdef ENVCUBEMAP
-				finalColor += cMatEnvMapColor * SampleCube(EnvCubeMap, reflect(iReflectionVec, normal)).rgb;
-			#endif
         #endif
         #ifdef EMISSIVEMAP
             finalColor += cMatEmissiveColor * Sample2D(EmissiveMap, iTexCoord.xy).rgb;

+ 34 - 0
Resources/CoreData/Shaders/HLSL/PBR.hlsl

@@ -0,0 +1,34 @@
+#include "BRDF.hlsl"
+#ifdef COMPILEPS
+
+	//Return the PBR BRDF value
+	// lightDir  = the vector to the light
+	// lightVev  = normalised lightDir
+	// toCamera  = vector to the camera
+	// normal    = surface normal of the pixel
+	// roughness = roughness of the pixel
+	// diffColor = the rgb color of the pixel
+	// specColor = the rgb specular color of the pixel
+	float3 GetBRDF(float3 lightDir, float3 lightVec, float3 toCamera, float3 normal, float roughness, float3 diffColor, float3 specColor)
+	{
+
+        const float3 Hn = normalize(toCamera + lightDir);
+        const float vdh = clamp((dot(toCamera, Hn)), M_EPSILON, 1.0);
+        const float ndh = clamp((dot(normal, Hn)), M_EPSILON, 1.0);
+        const float ndl = clamp((dot(normal, lightVec)), M_EPSILON, 1.0);
+        const float ndv = clamp((dot(normal, toCamera)), M_EPSILON, 1.0);
+
+        const float3 diffuseFactor = Diffuse(diffColor, roughness, ndv, ndl, vdh);
+        float3 specularFactor = 0;
+
+        #ifdef SPECULAR
+            const float3 fresnelTerm = Fresnel(specColor, vdh) ;
+            const float distTerm = Distribution(ndh, roughness);
+            const float visTerm = Visibility(ndl, ndv, roughness);
+
+            specularFactor = distTerm * visTerm * fresnelTerm / M_PI;
+        #endif
+
+        return diffuseFactor + specularFactor;
+	}
+#endif

+ 120 - 0
Resources/CoreData/Shaders/HLSL/PBRDeferred.hlsl

@@ -0,0 +1,120 @@
+#include "Uniforms.hlsl"
+#include "Samplers.hlsl"
+#include "Transform.hlsl"
+#include "ScreenPos.hlsl"
+#include "Lighting.hlsl"
+#include "Constants.hlsl"
+#include "PBR.hlsl"
+#line 9
+
+void VS(float4 iPos : POSITION,
+    #ifdef DIRLIGHT
+        out float2 oScreenPos : TEXCOORD0,
+    #else
+        out float4 oScreenPos : TEXCOORD0,
+    #endif
+    out float3 oFarRay : TEXCOORD1,
+    #ifdef ORTHO
+        out float3 oNearRay : TEXCOORD2,
+    #endif
+    out float4 oPos : OUTPOSITION)
+{
+    float4x3 modelMatrix = iModelMatrix;
+    float3 worldPos = GetWorldPos(modelMatrix);
+    oPos = GetClipPos(worldPos);
+    #ifdef DIRLIGHT
+        oScreenPos = GetScreenPosPreDiv(oPos);
+        oFarRay = GetFarRay(oPos);
+        #ifdef ORTHO
+            oNearRay = GetNearRay(oPos);
+        #endif
+    #else
+        oScreenPos = GetScreenPos(oPos);
+        oFarRay = GetFarRay(oPos) * oPos.w;
+        #ifdef ORTHO
+            oNearRay = GetNearRay(oPos) * oPos.w;
+        #endif
+    #endif
+}
+
+void PS(
+    #ifdef DIRLIGHT
+        float2 iScreenPos : TEXCOORD0,
+    #else
+        float4 iScreenPos : TEXCOORD0,
+    #endif
+    float3 iFarRay : TEXCOORD1,
+    #ifdef ORTHO
+        float3 iNearRay : TEXCOORD2,
+    #endif
+
+    float2 iFragPos : VPOS,
+    out float4 oColor : OUTCOLOR0)
+{
+    // If rendering a directional light quad, optimize out the w divide
+    #ifdef DIRLIGHT
+        float3 depth = Sample2DLod0(DepthBuffer, iScreenPos).r;
+        #ifdef HWDEPTH
+            depth = ReconstructDepth(depth);
+        #endif
+        #ifdef ORTHO
+            float3 worldPos = lerp(iNearRay, iFarRay, depth);
+        #else
+            float3 worldPos = iFarRay * depth;
+        #endif
+        const float4 albedoInput = Sample2DLod0(AlbedoBuffer, iScreenPos);
+        const float4 normalInput = Sample2DLod0(NormalBuffer, iScreenPos);
+        const float4 specularInput = Sample2DLod0(SpecMap, iScreenPos);
+    #else
+        float depth = Sample2DProj(DepthBuffer, iScreenPos).r;
+        #ifdef HWDEPTH
+            depth = ReconstructDepth(depth);
+        #endif
+        #ifdef ORTHO
+            float3 worldPos = lerp(iNearRay, iFarRay, depth) / iScreenPos.w;
+        #else
+            float3 worldPos = iFarRay * depth / iScreenPos.w;
+        #endif
+        const float4 albedoInput = Sample2DProj(AlbedoBuffer, iScreenPos);
+        const float4 normalInput = Sample2DProj(NormalBuffer, iScreenPos);
+        const float4 specularInput = Sample2DProj(SpecMap, iScreenPos);
+    #endif
+
+    // Position acquired via near/far ray is relative to camera. Bring position to world space
+    float3 eyeVec = -worldPos;
+    worldPos += cCameraPosPS;
+
+    float3 normal = normalInput.rgb;
+    const float roughness = length(normal);
+    normal = normalize(normal);
+
+    const float3 specColor = specularInput.rgb;
+
+    const float4 projWorldPos = float4(worldPos, 1.0);
+
+    float3 lightDir;
+    float atten = GetAtten(normal, worldPos, lightDir);
+
+    float shadow = 1;
+    #ifdef SHADOW
+        shadow *= GetShadowDeferred(projWorldPos, normal, depth);
+    #endif
+
+    #if defined(SPOTLIGHT)
+        const float4 spotPos = mul(projWorldPos, cLightMatricesPS[0]);
+        const float3 lightColor = spotPos.w > 0.0 ? Sample2DProj(LightSpotMap, spotPos).rgb * cLightColor.rgb : 0.0;
+    #elif defined(CUBEMASK)
+        const float3 lightColor = texCUBE(sLightCubeMap, mul(worldPos - cLightPosPS.xyz, (float3x3)cLightMatricesPS[0])).rgb * cLightColor.rgb;
+    #else
+        const float3 lightColor = cLightColor.rgb;
+    #endif
+
+    const float3 toCamera = normalize(eyeVec);
+    const float3 lightVec = normalize(lightDir);
+    const float ndl = clamp(abs(dot(normal, lightVec)), M_EPSILON, 1.0);
+
+    float3 BRDF = GetBRDF(lightDir, lightVec, toCamera, normal, roughness, albedoInput.rgb, specColor);
+
+    oColor.a = 1;
+    oColor.rgb  = BRDF * lightColor * shadow * atten / M_PI;
+}

+ 337 - 0
Resources/CoreData/Shaders/HLSL/PBRLitSolid.hlsl

@@ -0,0 +1,337 @@
+#include "Uniforms.hlsl"
+#include "Samplers.hlsl"
+#include "Transform.hlsl"
+#include "ScreenPos.hlsl"
+#include "Lighting.hlsl"
+#include "Constants.hlsl"
+#include "Fog.hlsl"
+#include "PBR.hlsl"
+#include "IBL.hlsl"
+
+void VS(float4 iPos : POSITION,
+    #if !defined(BILLBOARD) && !defined(TRAILFACECAM)
+        float3 iNormal : NORMAL,
+    #endif
+    #ifndef NOUV
+        float2 iTexCoord : TEXCOORD0,
+    #endif
+    #ifdef VERTEXCOLOR
+        float4 iColor : COLOR0,
+    #endif
+    #if defined(LIGHTMAP) || defined(AO)
+        float2 iTexCoord2 : TEXCOORD1,
+    #endif
+    #if defined(NORMALMAP)|| defined(IBL) || defined(TRAILFACECAM) || defined(TRAILBONE)
+        float4 iTangent : TANGENT,
+    #endif
+    #ifdef SKINNED
+        float4 iBlendWeights : BLENDWEIGHT,
+        int4 iBlendIndices : BLENDINDICES,
+    #endif
+    #ifdef INSTANCED
+        float4x3 iModelInstance : TEXCOORD4,
+    #endif
+    #if defined(BILLBOARD) || defined(DIRBILLBOARD)
+        float2 iSize : TEXCOORD1,
+    #endif
+    #if defined(NORMALMAP) || defined(IBL)
+        out float4 oTexCoord : TEXCOORD0,
+        out float4 oTangent : TEXCOORD3,
+    #else
+        out float2 oTexCoord : TEXCOORD0,
+    #endif
+    out float3 oNormal : TEXCOORD1,
+    out float4 oWorldPos : TEXCOORD2,
+    #ifdef PERPIXEL
+        #ifdef SHADOW
+            out float4 oShadowPos[NUMCASCADES] : TEXCOORD4,
+        #endif
+        #ifdef SPOTLIGHT
+            out float4 oSpotPos : TEXCOORD5,
+        #endif
+        #ifdef POINTLIGHT
+            out float3 oCubeMaskVec : TEXCOORD5,
+        #endif
+    #else
+        out float3 oVertexLight : TEXCOORD4,
+        out float4 oScreenPos : TEXCOORD5,
+        #ifdef ENVCUBEMAP
+            out float3 oReflectionVec : TEXCOORD6,
+        #endif
+        #if defined(LIGHTMAP) || defined(AO)
+            out float2 oTexCoord2 : TEXCOORD7,
+        #endif
+    #endif
+    #ifdef VERTEXCOLOR
+        out float4 oColor : COLOR0,
+    #endif
+    #if defined(D3D11) && defined(CLIPPLANE)
+        out float oClip : SV_CLIPDISTANCE0,
+    #endif
+    out float4 oPos : OUTPOSITION)
+{
+    // Define a 0,0 UV coord if not expected from the vertex data
+    #ifdef NOUV
+        const float2 iTexCoord = float2(0.0, 0.0);
+    #endif
+
+    const float4x3 modelMatrix = iModelMatrix;
+    const float3 worldPos = GetWorldPos(modelMatrix);
+    oPos = GetClipPos(worldPos);
+    oNormal = GetWorldNormal(modelMatrix);
+    oWorldPos = float4(worldPos, GetDepth(oPos));
+
+    #if defined(D3D11) && defined(CLIPPLANE)
+        oClip = dot(oPos, cClipPlane);
+    #endif
+
+    #ifdef VERTEXCOLOR
+        oColor = iColor;
+    #endif
+
+    #if defined(NORMALMAP) || defined(IBL)
+        const float3 tangent = GetWorldTangent(modelMatrix);
+        const float3 bitangent = cross(tangent, oNormal) * iTangent.w;
+        oTexCoord = float4(GetTexCoord(iTexCoord), bitangent.xy);
+        oTangent = float4(tangent, bitangent.z);
+    #else
+        oTexCoord = GetTexCoord(iTexCoord);
+    #endif
+
+    #ifdef PERPIXEL
+        // Per-pixel forward lighting
+        const float4 projWorldPos = float4(worldPos.xyz, 1.0);
+
+        #ifdef SHADOW
+            // Shadow projection: transform from world space to shadow space
+            GetShadowPos(projWorldPos, oNormal, oShadowPos);
+        #endif
+
+        #ifdef SPOTLIGHT
+            // Spotlight projection: transform from world space to projector texture coordinates
+            oSpotPos = mul(projWorldPos, cLightMatrices[0]);
+        #endif
+
+        #ifdef POINTLIGHT
+            oCubeMaskVec = mul(worldPos - cLightPos.xyz, (float3x3)cLightMatrices[0]);
+        #endif
+    #else
+        // Ambient & per-vertex lighting
+        #if defined(LIGHTMAP) || defined(AO)
+            // If using lightmap, disregard zone ambient light
+            // If using AO, calculate ambient in the PS
+            oVertexLight = float3(0.0, 0.0, 0.0);
+            oTexCoord2 = iTexCoord2;
+        #else
+            oVertexLight = GetAmbient(GetZonePos(worldPos));
+        #endif
+
+        #ifdef NUMVERTEXLIGHTS
+            for (int i = 0; i < NUMVERTEXLIGHTS; ++i)
+                oVertexLight += GetVertexLight(i, worldPos, oNormal) * cVertexLights[i * 3].rgb;
+        #endif
+
+        oScreenPos = GetScreenPos(oPos);
+
+        #ifdef ENVCUBEMAP
+            oReflectionVec = worldPos - cCameraPos;
+        #endif
+    #endif
+}
+
+void PS(
+    #if defined(NORMALMAP) || defined(IBL)
+        float4 iTexCoord : TEXCOORD0,
+        float4 iTangent : TEXCOORD3,
+    #else
+        float2 iTexCoord : TEXCOORD0,
+    #endif
+    float3 iNormal : TEXCOORD1,
+    float4 iWorldPos : TEXCOORD2,
+    #ifdef PERPIXEL
+        #ifdef SHADOW
+            float4 iShadowPos[NUMCASCADES] : TEXCOORD4,
+        #endif
+        #ifdef SPOTLIGHT
+            float4 iSpotPos : TEXCOORD5,
+        #endif
+        #ifdef POINTLIGHT
+            float3 iCubeMaskVec : TEXCOORD5,
+        #endif
+    #else
+        float3 iVertexLight : TEXCOORD4,
+        float4 iScreenPos : TEXCOORD5,
+        #ifdef ENVCUBEMAP
+            float3 iReflectionVec : TEXCOORD6,
+        #endif
+        #if defined(LIGHTMAP) || defined(AO)
+            float2 iTexCoord2 : TEXCOORD7,
+        #endif
+    #endif
+    #ifdef VERTEXCOLOR
+        float4 iColor : COLOR0,
+    #endif
+    #if defined(D3D11) && defined(CLIPPLANE)
+        float iClip : SV_CLIPDISTANCE0,
+    #endif
+    #ifdef PREPASS
+        out float4 oDepth : OUTCOLOR1,
+    #endif
+    #ifdef DEFERRED
+        out float4 oAlbedo : OUTCOLOR1,
+        out float4 oNormal : OUTCOLOR2,
+        out float4 oDepth : OUTCOLOR3,
+        #ifndef D3D11
+            float2 iFragPos : VPOS,
+        #else
+            float4 iFragPos : SV_Position,
+        #endif
+    #endif
+    out float4 oColor : OUTCOLOR0)
+{
+    // Get material diffuse albedo
+    #ifdef DIFFMAP
+        const float4 diffInput = Sample2D(DiffMap, iTexCoord.xy);
+        #ifdef ALPHAMASK
+            if (diffInput.a < 0.5)
+                discard;
+        #endif
+        float4 diffColor = cMatDiffColor * diffInput;
+    #else
+        float4 diffColor = cMatDiffColor;
+    #endif
+
+    #ifdef VERTEXCOLOR
+        diffColor *= iColor;
+    #endif
+
+    // Get material specular albedo
+    #ifdef METALLIC // METALNESS
+        float4 roughMetalSrc = Sample2D(RoughMetalFresnel, iTexCoord.xy);
+
+        float roughness = roughMetalSrc.r + cRoughness;
+        float metalness = roughMetalSrc.g + cMetallic;
+    #else
+        float roughness = cRoughness;
+        float metalness = cMetallic;
+    #endif
+
+    roughness *= roughness;
+
+    roughness = clamp(roughness, ROUGHNESS_FLOOR, 1.0);
+    metalness = clamp(metalness, METALNESS_FLOOR, 1.0);
+
+    float3 specColor = lerp(0.08 * cMatSpecColor.rgb, diffColor.rgb, metalness);
+    specColor *= cMatSpecColor.rgb;
+    diffColor.rgb = diffColor.rgb - diffColor.rgb * metalness; // Modulate down the diffuse
+
+    // Get normal
+    #if defined(NORMALMAP) || defined(DIRBILLBOARD) || defined(IBL)
+        const float3 tangent = normalize(iTangent.xyz);
+        const float3 bitangent = normalize(float3(iTexCoord.zw, iTangent.w));
+        const float3x3 tbn = float3x3(tangent, bitangent, iNormal);
+    #endif
+
+    #ifdef NORMALMAP
+        const float3 nn = DecodeNormal(Sample2D(NormalMap, iTexCoord.xy));
+        //nn.rg *= 2.0;
+        const float3 normal = normalize(mul(nn, tbn));
+    #else
+        const float3 normal = normalize(iNormal);
+    #endif
+
+    // Get fog factor
+    #ifdef HEIGHTFOG
+        const float fogFactor = GetHeightFogFactor(iWorldPos.w, iWorldPos.y);
+    #else
+        const float fogFactor = GetFogFactor(iWorldPos.w);
+    #endif
+
+    #if defined(PERPIXEL)
+        // Per-pixel forward lighting
+        float3 lightDir;
+        float3 lightColor;
+        float3 finalColor;
+
+        float atten = GetAtten(normal, iWorldPos.xyz, lightDir);
+
+        float shadow = 1.0;
+
+        #ifdef SHADOW
+            shadow *= GetShadow(iShadowPos, iWorldPos.w);
+        #endif
+
+        #if defined(SPOTLIGHT)
+            lightColor = iSpotPos.w > 0.0 ? Sample2DProj(LightSpotMap, iSpotPos).rgb * cLightColor.rgb : 0.0;
+        #elif defined(CUBEMASK)
+            lightColor = SampleCube(LightCubeMap, iCubeMaskVec).rgb * cLightColor.rgb;
+        #else
+            lightColor = cLightColor.rgb;
+        #endif
+
+        const float3 toCamera = normalize(cCameraPosPS - iWorldPos.xyz);
+
+        const float3 lightVec = normalize(lightDir);
+        const float ndl = clamp((dot(normal, lightVec)), M_EPSILON, 1.0);
+
+
+        float3 BRDF = GetBRDF(lightDir, lightVec, toCamera, normal, roughness, diffColor.rgb, specColor);
+        finalColor.rgb = BRDF * lightColor * (atten * shadow) / M_PI;
+
+        #ifdef AMBIENT
+            finalColor += cAmbientColor.rgb * diffColor.rgb;
+            finalColor += cMatEmissiveColor;
+            oColor = float4(GetFog(finalColor, fogFactor), diffColor.a);
+        #else
+            oColor = float4(GetLitFog(finalColor, fogFactor), diffColor.a);
+        #endif
+    #elif defined(DEFERRED)
+        // Fill deferred G-buffer
+        const float3 spareData = 0; // Can be used to pass more data to deferred renderer
+        oColor = float4(specColor, spareData.r);
+        oAlbedo = float4(diffColor.rgb, spareData.g);
+        oNormal = float4(normalize(normal) * roughness, spareData.b);
+        oDepth = iWorldPos.w;
+    #else
+        // Ambient & per-vertex lighting
+        float3 finalColor = iVertexLight * diffColor.rgb;
+        #ifdef AO
+            // If using AO, the vertex light ambient is black, calculate occluded ambient here
+            finalColor += Sample2D(EmissiveMap, iTexCoord2).rgb * cAmbientColor.rgb * diffColor.rgb;
+        #endif
+
+        #ifdef MATERIAL
+            // Add light pre-pass accumulation result
+            // Lights are accumulated at half intensity. Bring back to full intensity now
+            float4 lightInput = 2.0 * Sample2DProj(LightBuffer, iScreenPos);
+            float3 lightSpecColor = lightInput.a * lightInput.rgb / max(GetIntensity(lightInput.rgb), 0.001);
+
+            finalColor += lightInput.rgb * diffColor.rgb + lightSpecColor * specColor;
+        #endif
+
+        const float3 toCamera = normalize(iWorldPos.xyz - cCameraPosPS);
+
+        const float3 reflection = normalize(reflect(toCamera, normal));
+        float3 cubeColor = iVertexLight.rgb;
+
+        #ifdef IBL
+            const float3 iblColor = ImageBasedLighting(reflection, tangent, bitangent, normal, toCamera, diffColor, specColor, roughness, cubeColor);
+            const float gamma = 0;
+            finalColor += iblColor;
+        #endif
+
+        #ifdef ENVCUBEMAP
+            finalColor += cMatEnvMapColor * SampleCube(EnvCubeMap, reflect(iReflectionVec, normal)).rgb;
+        #endif
+        #ifdef LIGHTMAP
+            finalColor += Sample2D(EmissiveMap, iTexCoord2).rgb * diffColor.rgb;
+        #endif
+        #ifdef EMISSIVEMAP
+            finalColor += cMatEmissiveColor * Sample2D(EmissiveMap, iTexCoord.xy).rgb;
+        #else
+            finalColor += cMatEmissiveColor;
+        #endif
+
+        oColor = float4(GetFog(finalColor, fogFactor), diffColor.a);
+    #endif
+}

+ 6 - 2
Resources/CoreData/Shaders/HLSL/PrepassLight.hlsl

@@ -71,6 +71,10 @@ void PS(
         float4 normalInput = Sample2DProj(NormalBuffer, iScreenPos);
     #endif
 
+    // Position acquired via near/far ray is relative to camera. Bring position to world space
+    float3 eyeVec = -worldPos;
+    worldPos += cCameraPosPS;
+
     float3 normal = normalize(normalInput.rgb * 2.0 - 1.0);
     float4 projWorldPos = float4(worldPos, 1.0);
     float3 lightColor;
@@ -80,7 +84,7 @@ void PS(
     float diff = 0.5 * GetDiffuse(normal, worldPos, lightDir);
 
     #ifdef SHADOW
-        diff *= GetShadowDeferred(projWorldPos, depth);
+        diff *= GetShadowDeferred(projWorldPos, normal, depth);
     #endif
 
     #if defined(SPOTLIGHT)
@@ -93,7 +97,7 @@ void PS(
     #endif
 
     #ifdef SPECULAR
-        float spec = lightColor.g * GetSpecular(normal, -worldPos, lightDir, normalInput.a * 255.0);
+        float spec = lightColor.g * GetSpecular(normal, eyeVec, lightDir, normalInput.a * 255.0);
         oColor = diff * float4(lightColor, spec * cLightColor.a);
     #else
         oColor = diff * float4(lightColor, 0.0);

+ 10 - 1
Resources/CoreData/Shaders/HLSL/Samplers.hlsl

@@ -4,6 +4,7 @@
 #define Sample2DProj(tex, uv) t##tex.Sample(s##tex, uv.xy / uv.w)
 #define Sample2DLod0(tex, uv) t##tex.SampleLevel(s##tex, uv, 0.0)
 #define SampleCube(tex, uv) t##tex.Sample(s##tex, uv)
+#define SampleCubeLOD(tex, uv) t##tex.SampleLevel(s##tex, uv.xyz, uv.w)
 #define SampleShadow(tex, uv) t##tex.SampleCmpLevelZero(s##tex, uv.xy, uv.z)
 #endif
 
@@ -18,6 +19,7 @@ sampler2D sAlbedoBuffer : register(s0);
 sampler2D sNormalMap : register(s1);
 sampler2D sNormalBuffer : register(s1);
 sampler2D sSpecMap : register(s2);
+sampler2D sRoughMetalFresnel : register(s2); //R: Roughness, G: Metal
 sampler2D sEmissiveMap : register(s3);
 sampler2D sEnvMap : register(s4);
 sampler3D sVolumeMap : register(s5);
@@ -37,6 +39,7 @@ sampler3D sZoneVolumeMap : register(s15);
 #define Sample2DProj(tex, uv) tex2Dproj(s##tex, uv)
 #define Sample2DLod0(tex, uv) tex2Dlod(s##tex, float4(uv, 0.0, 0.0))
 #define SampleCube(tex, uv) texCUBE(s##tex, uv)
+#define SampleCubeLOD(tex, uv) texCUBElod(s##tex, uv)
 #define SampleShadow(tex, uv) tex2Dproj(s##tex, uv)
 
 #else
@@ -49,6 +52,7 @@ Texture2D tAlbedoBuffer : register(t0);
 Texture2D tNormalMap : register(t1);
 Texture2D tNormalBuffer : register(t1);
 Texture2D tSpecMap : register(t2);
+Texture2D tRoughMetalFresnel : register(t2); //R: Roughness, G: Metal
 Texture2D tEmissiveMap : register(t3);
 Texture2D tEnvMap : register(t4);
 Texture3D tVolumeMap : register(t5);
@@ -70,6 +74,7 @@ SamplerState sAlbedoBuffer : register(s0);
 SamplerState sNormalMap : register(s1);
 SamplerState sNormalBuffer : register(s1);
 SamplerState sSpecMap : register(s2);
+SamplerState sRoughMetalFresnel : register(s2); //R: Roughness, G: Metal 
 SamplerState sEmissiveMap : register(s3);
 SamplerState sEnvMap : register(s4);
 SamplerState sVolumeMap : register(s5);
@@ -77,7 +82,11 @@ SamplerState sEnvCubeMap : register(s4);
 SamplerState sLightRampMap : register(s8);
 SamplerState sLightSpotMap : register(s9);
 SamplerState sLightCubeMap : register(s9);
-SamplerComparisonState sShadowMap : register(s10);
+#ifdef VSM_SHADOW
+    SamplerState sShadowMap : register(s10);
+#else
+    SamplerComparisonState sShadowMap : register(s10);
+#endif
 SamplerState sFaceSelectCubeMap : register(s11);
 SamplerState sIndirectionCubeMap : register(s12);
 SamplerState sDepthBuffer : register(s13);

+ 9 - 2
Resources/CoreData/Shaders/HLSL/ScreenPos.hlsl

@@ -1,4 +1,11 @@
 #ifdef COMPILEVS
+float3x3 GetCameraRot()
+{
+    return float3x3(cViewInv[0][0], cViewInv[0][1], cViewInv[0][2],
+        cViewInv[1][0], cViewInv[1][1], cViewInv[1][2],
+        cViewInv[2][0], cViewInv[2][1], cViewInv[2][2]);
+}
+
 float4 GetScreenPos(float4 clipPos)
 {
     return float4(
@@ -36,7 +43,7 @@ float3 GetFarRay(float4 clipPos)
         clipPos.y / clipPos.w * cFrustumSize.y,
         cFrustumSize.z);
 
-    return mul(viewRay, cCameraRot);
+    return mul(viewRay, GetCameraRot());
 }
 
 float3 GetNearRay(float4 clipPos)
@@ -46,6 +53,6 @@ float3 GetNearRay(float4 clipPos)
         clipPos.y / clipPos.w * cFrustumSize.y,
         0.0);
 
-    return mul(viewRay, cCameraRot) * cDepthMode.z;
+    return mul(viewRay, GetCameraRot()) * cDepthMode.z;
 }
 #endif

+ 31 - 7
Resources/CoreData/Shaders/HLSL/Shadow.hlsl

@@ -8,27 +8,51 @@ void VS(float4 iPos : POSITION,
         int4 iBlendIndices : BLENDINDICES,
     #endif
     #ifdef INSTANCED
-        float4x3 iModelInstance : TEXCOORD2,
+        float4x3 iModelInstance : TEXCOORD4,
+    #endif
+    #ifndef NOUV
+        float2 iTexCoord : TEXCOORD0,
+    #endif
+    #ifdef VSM_SHADOW
+        out float3 oTexCoord : TEXCOORD0,
+    #else
+        out float2 oTexCoord : TEXCOORD0,
     #endif
-    float2 iTexCoord : TEXCOORD0,
-    out float2 oTexCoord : TEXCOORD0,
     out float4 oPos : OUTPOSITION)
 {
+    // Define a 0,0 UV coord if not expected from the vertex data
+    #ifdef NOUV
+    float2 iTexCoord = float2(0.0, 0.0);
+    #endif
+
     float4x3 modelMatrix = iModelMatrix;
     float3 worldPos = GetWorldPos(modelMatrix);
     oPos = GetClipPos(worldPos);
-    oTexCoord = GetTexCoord(iTexCoord);
+    #ifdef VSM_SHADOW
+        oTexCoord = float3(GetTexCoord(iTexCoord), oPos.z/oPos.w);
+    #else
+        oTexCoord = GetTexCoord(iTexCoord);
+    #endif
 }
 
 void PS(
-    float2 iTexCoord : TEXCOORD0,
+    #ifdef VSM_SHADOW
+        float3 iTexCoord : TEXCOORD0,
+    #else
+        float2 iTexCoord : TEXCOORD0,
+    #endif
     out float4 oColor : OUTCOLOR0)
 {
     #ifdef ALPHAMASK
-        float alpha = Sample2D(DiffMap, iTexCoord).a;
+        float alpha = Sample2D(DiffMap, iTexCoord.xy).a;
         if (alpha < 0.5)
             discard;
     #endif
 
-    oColor = 1.0;
+    #ifdef VSM_SHADOW
+        float depth = iTexCoord.z;
+        oColor = float4(depth, depth * depth, 1.0, 1.0);
+    #else
+        oColor = 1.0;
+    #endif
 }

+ 48 - 0
Resources/CoreData/Shaders/HLSL/ShadowBlur.hlsl

@@ -0,0 +1,48 @@
+#include "Uniforms.hlsl"
+#include "Samplers.hlsl"
+#include "Transform.hlsl"
+#include "ScreenPos.hlsl"
+
+#ifndef D3D11
+
+// D3D9 uniforms
+uniform float2 cBlurOffsets;
+
+#else
+
+#ifdef COMPILEPS
+// D3D11 constant buffers
+cbuffer CustomPS : register(b6)
+{
+    float2 cBlurOffsets;
+}
+#endif
+
+#endif
+
+void VS(float4 iPos : POSITION,
+    out float2 oScreenPos : TEXCOORD0,
+    out float4 oPos : OUTPOSITION)
+{
+    float4x3 modelMatrix = iModelMatrix;
+    float3 worldPos = GetWorldPos(modelMatrix);
+    oPos = GetClipPos(worldPos);
+    oScreenPos = GetScreenPosPreDiv(oPos);
+}
+
+void PS(float2 iScreenPos : TEXCOORD0,
+    out float4 oColor : OUTCOLOR0)
+{  
+    float2 color = 0.0;
+
+    color += 0.015625 * Sample2D(DiffMap, iScreenPos - 3.0 * cBlurOffsets).rg;
+    color += 0.09375 * Sample2D(DiffMap, iScreenPos - 2.0 * cBlurOffsets).rg;
+    color += 0.234375 * Sample2D(DiffMap, iScreenPos - cBlurOffsets).rg;
+    color += 0.3125 * Sample2D(DiffMap, iScreenPos).rg;
+    color += 0.234375 * Sample2D(DiffMap, iScreenPos + cBlurOffsets).rg;
+    color += 0.09375 * Sample2D(DiffMap, iScreenPos + 2.0 * cBlurOffsets).rg;
+    color += 0.015625 * Sample2D(DiffMap, iScreenPos + 3.0 * cBlurOffsets).rg;
+
+    oColor = float4(color, 0.0, 0.0);
+}
+

+ 6 - 2
Resources/CoreData/Shaders/HLSL/Skybox.hlsl

@@ -9,7 +9,7 @@ void VS(float4 iPos : POSITION,
     float4x3 modelMatrix = iModelMatrix;
     float3 worldPos = GetWorldPos(modelMatrix);
     oPos = GetClipPos(worldPos);
-    
+
     oPos.z = oPos.w;
     oTexCoord = iPos.xyz;
 }
@@ -17,5 +17,9 @@ void VS(float4 iPos : POSITION,
 void PS(float3 iTexCoord : TEXCOORD0,
     out float4 oColor : OUTCOLOR0)
 {
-    oColor = cMatDiffColor * SampleCube(DiffCubeMap, iTexCoord);
+    float4 sky = cMatDiffColor * SampleCube(DiffCubeMap, iTexCoord);
+    #ifdef HDRSCALE
+        sky = pow(sky + clamp((cAmbientColor.a - 1.0) * 0.1, 0.0, 0.25), max(cAmbientColor.a, 1.0)) * clamp(cAmbientColor.a, 0.0, 1.0);
+    #endif
+    oColor = sky;
 }

+ 22 - 0
Resources/CoreData/Shaders/HLSL/Skydome.hlsl

@@ -0,0 +1,22 @@
+#include "Uniforms.hlsl"
+#include "Samplers.hlsl"
+#include "Transform.hlsl"
+
+void VS(float4 iPos : POSITION, 
+    float2 iTexCoord: TEXCOORD0,
+    out float2 oTexCoord : TEXCOORD0, 
+    out float4 oPos : OUTPOSITION)
+{
+    float4x3 modelMatrix = iModelMatrix;
+    float3 worldPos = GetWorldPos(modelMatrix);
+    oPos = GetClipPos(worldPos);
+    
+    oPos.z = oPos.w;
+    oTexCoord = iTexCoord;
+}
+
+void PS(float2 iTexCoord : TEXCOORD0, 
+        out float4 oColor : OUTCOLOR0)
+{
+    oColor = cMatDiffColor * Sample2D(DiffMap, iTexCoord);
+}

+ 8 - 5
Resources/CoreData/Shaders/HLSL/TerrainBlend.hlsl

@@ -46,11 +46,14 @@ void VS(float4 iPos : POSITION,
         int4 iBlendIndices : BLENDINDICES,
     #endif
     #ifdef INSTANCED
-        float4x3 iModelInstance : TEXCOORD2,
+        float4x3 iModelInstance : TEXCOORD4,
     #endif
-    #ifdef BILLBOARD
+    #if defined(BILLBOARD) || defined(DIRBILLBOARD)
         float2 iSize : TEXCOORD1,
     #endif
+    #if defined(TRAILFACECAM) || defined(TRAILBONE)
+        float4 iTangent : TANGENT,
+    #endif
     out float2 oTexCoord : TEXCOORD0,
     out float3 oNormal : TEXCOORD1,
     out float4 oWorldPos : TEXCOORD2,
@@ -92,7 +95,7 @@ void VS(float4 iPos : POSITION,
 
         #ifdef SHADOW
             // Shadow projection: transform from world space to shadow space
-            GetShadowPos(projWorldPos, oShadowPos);
+            GetShadowPos(projWorldPos, oNormal, oShadowPos);
         #endif
 
         #ifdef SPOTLIGHT
@@ -127,7 +130,7 @@ void PS(float2 iTexCoord : TEXCOORD0,
         #ifdef SPOTLIGHT
             float4 iSpotPos : TEXCOORD5,
         #endif
-        #ifdef CUBEMASK
+        #ifdef POINTLIGHT
             float3 iCubeMaskVec : TEXCOORD5,
         #endif
     #else
@@ -198,7 +201,7 @@ void PS(float2 iTexCoord : TEXCOORD0,
         #endif
 
         #ifdef AMBIENT
-            finalColor += cAmbientColor * diffColor.rgb;
+            finalColor += cAmbientColor.rgb * diffColor.rgb;
             finalColor += cMatEmissiveColor;
             oColor = float4(GetFog(finalColor, fogFactor), diffColor.a);
         #else

+ 71 - 2
Resources/CoreData/Shaders/HLSL/Transform.hlsl

@@ -48,6 +48,63 @@ float3 GetBillboardNormal()
 }
 #endif
 
+#ifdef DIRBILLBOARD
+float3x3 GetFaceCameraRotation(float3 position, float3 direction)
+{
+    float3 cameraDir = normalize(position - cCameraPos);
+    float3 front = normalize(direction);
+    float3 right = normalize(cross(front, cameraDir));
+    float3 up = normalize(cross(front, right));
+
+    return float3x3(
+        right.x, right.y, right.z,
+        up.x, up.y, up.z,
+        front.x, front.y, front.z
+    );
+}
+
+float3 GetBillboardPos(float4 iPos, float2 iSize, float3 iDirection, float4x3 modelMatrix)
+{
+    float3 worldPos = mul(iPos, modelMatrix);
+    return worldPos + mul(float3(iSize.x, 0.0, iSize.y), GetFaceCameraRotation(worldPos, iDirection));
+}
+
+float3 GetBillboardNormal(float4 iPos, float3 iDirection, float4x3 modelMatrix)
+{
+    float3 worldPos = mul(iPos, modelMatrix);
+    return mul(float3(0.0, 1.0, 0.0), GetFaceCameraRotation(worldPos, iDirection));
+}
+#endif
+
+#ifdef TRAILFACECAM
+float3 GetTrailPos(float4 iPos, float3 iFront, float iScale, float4x3 modelMatrix)
+{
+    float3 up = normalize(cCameraPos - iPos.xyz);
+    float3 left = normalize(cross(iFront, up));
+    return (mul(float4((iPos.xyz + left * iScale), 1.0), modelMatrix)).xyz;
+}
+
+float3 GetTrailNormal(float4 iPos)
+{
+    return normalize(cCameraPos - iPos.xyz);
+}
+#endif
+
+#ifdef TRAILBONE
+float3 GetTrailPos(float4 iPos, float3 iParentPos, float iScale, float4x3 modelMatrix)
+{
+    float3 right = iParentPos - iPos.xyz;
+    return (mul(float4((iPos.xyz + right * iScale), 1.0), modelMatrix)).xyz;
+}
+
+float3 GetTrailNormal(float4 iPos, float3 iParentPos, float3 iForward)
+{
+    float3 left = normalize(iPos.xyz - iParentPos);
+    float3 up = -normalize(cross(normalize(iForward), left));
+    return up;
+}
+#endif
+
 #if defined(SKINNED)
     #define iModelMatrix GetSkinMatrix(iBlendWeights, iBlendIndices);
 #elif defined(INSTANCED)
@@ -56,14 +113,26 @@ float3 GetBillboardNormal()
     #define iModelMatrix cModel
 #endif
 
-#ifdef BILLBOARD
+#if defined(BILLBOARD)
     #define GetWorldPos(modelMatrix) GetBillboardPos(iPos, iSize, modelMatrix)
+#elif defined(DIRBILLBOARD)
+    #define GetWorldPos(modelMatrix) GetBillboardPos(iPos, iSize, iNormal, modelMatrix)
+#elif defined(TRAILFACECAM)
+    #define GetWorldPos(modelMatrix) GetTrailPos(iPos, iTangent.xyz, iTangent.w, modelMatrix)
+#elif defined(TRAILBONE)
+    #define GetWorldPos(modelMatrix) GetTrailPos(iPos, iTangent.xyz, iTangent.w, modelMatrix)
 #else
     #define GetWorldPos(modelMatrix) mul(iPos, modelMatrix)
 #endif
 
-#ifdef BILLBOARD
+#if defined(BILLBOARD)
     #define GetWorldNormal(modelMatrix) GetBillboardNormal()
+#elif defined(DIRBILLBOARD)
+    #define GetWorldNormal(modelMatrix) GetBillboardNormal(iPos, iNormal, modelMatrix)
+#elif defined(TRAILFACECAM)
+    #define GetWorldNormal(modelMatrix) GetTrailNormal(iPos)
+#elif defined(TRAILBONE)
+    #define GetWorldNormal(modelMatrix) GetTrailNormal(iPos, iTangent.xyz, iNormal)
 #else
     #define GetWorldNormal(modelMatrix) normalize(mul(iNormal, (float3x3)modelMatrix))
 #endif

+ 24 - 6
Resources/CoreData/Shaders/HLSL/Uniforms.hlsl

@@ -11,7 +11,6 @@ uniform float3 cAmbientEndColor;
 uniform float3x3 cBillboardRot;
 #endif
 uniform float3 cCameraPos;
-uniform float3x3 cCameraRot;
 uniform float cNearClip;
 uniform float cFarClip;
 uniform float4 cDepthMode;
@@ -19,9 +18,12 @@ uniform float cDeltaTime;
 uniform float cElapsedTime;
 uniform float3 cFrustumSize;
 uniform float4 cGBufferOffsets;
-uniform float3 cLightDir;
 uniform float4 cLightPos;
+uniform float3 cLightDir;
+uniform float4 cNormalOffsetScale;
 uniform float4x3 cModel;
+uniform float4x3 cView;
+uniform float4x3 cViewInv;
 uniform float4x4 cViewProj;
 uniform float4 cUOffset;
 uniform float4 cVOffset;
@@ -39,7 +41,7 @@ uniform float4x3 cZone;
 #ifdef COMPILEPS
 
 // Pixel shader uniforms
-uniform float3 cAmbientColor;
+uniform float4 cAmbientColor;
 uniform float3 cCameraPosPS;
 uniform float cDeltaTimePS;
 uniform float4 cDepthReconstruct;
@@ -50,10 +52,15 @@ uniform float2 cGBufferInvSize;
 uniform float4 cLightColor;
 uniform float4 cLightPosPS;
 uniform float3 cLightDirPS;
+uniform float4 cNormalOffsetScalePS;
 uniform float4 cMatDiffColor;
 uniform float3 cMatEmissiveColor;
 uniform float3 cMatEnvMapColor;
 uniform float4 cMatSpecColor;
+#ifdef PBR
+    uniform float cRoughness;
+    uniform float cMetallic;
+#endif
 uniform float cNearClipPS;
 uniform float cFarClipPS;
 uniform float4 cShadowCubeAdjust;
@@ -62,6 +69,9 @@ uniform float2 cShadowIntensity;
 uniform float2 cShadowMapInvSize;
 uniform float4 cShadowSplits;
 uniform float4x4 cLightMatricesPS[4];
+#ifdef VSM_SHADOW
+uniform float2 cVSMShadowParams;
+#endif
 #endif
 
 #else
@@ -80,12 +90,13 @@ cbuffer FrameVS : register(b0)
 cbuffer CameraVS : register(b1)
 {
     float3 cCameraPos;
-    float3x3 cCameraRot;
     float cNearClip;
     float cFarClip;
     float4 cDepthMode;
     float3 cFrustumSize;
     float4 cGBufferOffsets;
+    float4x3 cView;
+    float4x3 cViewInv;
     float4x4 cViewProj;
     float4 cClipPlane;
 }
@@ -99,8 +110,9 @@ cbuffer ZoneVS : register(b2)
 
 cbuffer LightVS : register(b3)
 {
-    float3 cLightDir;
     float4 cLightPos;
+    float3 cLightDir;
+    float4 cNormalOffsetScale;
 #ifdef NUMVERTEXLIGHTS
     float4 cVertexLights[4 * 3];
 #else
@@ -148,7 +160,7 @@ cbuffer CameraPS : register(b1)
 
 cbuffer ZonePS : register(b2)
 {
-    float3 cAmbientColor;
+    float4 cAmbientColor;
     float4 cFogParams;
     float3 cFogColor;
 }
@@ -158,11 +170,13 @@ cbuffer LightPS : register(b3)
     float4 cLightColor;
     float4 cLightPosPS;
     float3 cLightDirPS;
+    float4 cNormalOffsetScalePS;
     float4 cShadowCubeAdjust;
     float4 cShadowDepthFade;
     float2 cShadowIntensity;
     float2 cShadowMapInvSize;
     float4 cShadowSplits;
+    float2 cVSMShadowParams;
     float4x4 cLightMatricesPS[4];
 }
 
@@ -173,6 +187,10 @@ cbuffer MaterialPS : register(b4)
     float3 cMatEmissiveColor;
     float3 cMatEnvMapColor;
     float4 cMatSpecColor;
+    #ifdef PBR
+        float cRoughness;
+        float cMetallic;
+    #endif
 }
 #endif
 

+ 9 - 3
Resources/CoreData/Shaders/HLSL/Unlit.hlsl

@@ -15,11 +15,17 @@ void VS(float4 iPos : POSITION,
         int4 iBlendIndices : BLENDINDICES,
     #endif
     #ifdef INSTANCED
-        float4x3 iModelInstance : TEXCOORD2,
+        float4x3 iModelInstance : TEXCOORD4,
     #endif
-    #ifdef BILLBOARD
+    #if defined(BILLBOARD) || defined(DIRBILLBOARD)
         float2 iSize : TEXCOORD1,
     #endif
+    #if defined(DIRBILLBOARD) || defined(TRAILBONE)
+        float3 iNormal : NORMAL,
+    #endif
+    #if defined(TRAILFACECAM) || defined(TRAILBONE)
+        float4 iTangent : TANGENT,
+    #endif
     out float2 oTexCoord : TEXCOORD0,
     out float4 oWorldPos : TEXCOORD2,
     #ifdef VERTEXCOLOR
@@ -103,4 +109,4 @@ void PS(float2 iTexCoord : TEXCOORD0,
     #else
         oColor = float4(GetFog(diffColor.rgb, fogFactor), diffColor.a);
     #endif
-}
+}

+ 27 - 0
Resources/CoreData/Shaders/HLSL/Urho2D.hlsl

@@ -0,0 +1,27 @@
+#include "Uniforms.hlsl"
+#include "Samplers.hlsl"
+#include "Transform.hlsl"
+
+void VS(float4 iPos : POSITION,
+    float2 iTexCoord : TEXCOORD0,
+    float4 iColor : COLOR0,
+    out float4 oColor : COLOR0,
+    out float2 oTexCoord : TEXCOORD0,
+    out float4 oPos : OUTPOSITION)
+{
+    float4x3 modelMatrix = iModelMatrix;
+    float3 worldPos = GetWorldPos(modelMatrix);
+    oPos = GetClipPos(worldPos);
+
+    oColor = iColor;
+    oTexCoord = iTexCoord;
+}
+
+void PS(float4 iColor : COLOR0,
+        float2 iTexCoord : TEXCOORD0,
+        out float4 oColor : OUTCOLOR0)
+{
+    float4 diffColor = cMatDiffColor * iColor;
+    float4 diffInput = Sample2D(DiffMap, iTexCoord);
+    oColor = diffColor * diffInput;
+}

+ 43 - 8
Resources/CoreData/Shaders/HLSL/Vegetation.hlsl

@@ -5,18 +5,41 @@
 #include "Lighting.hlsl"
 #include "Fog.hlsl"
 
+#ifndef D3D11
+
+// D3D9 uniforms
 uniform float cWindHeightFactor;
 uniform float cWindHeightPivot;
 uniform float cWindPeriod;
 uniform float2 cWindWorldSpacing;
 
+#else
+
+// D3D11 constant buffer
+cbuffer CustomVS : register(b6)
+{
+    float cWindHeightFactor;
+    float cWindHeightPivot;
+    float cWindPeriod;
+    float2 cWindWorldSpacing;
+}
+
+#endif
+
 void VS(float4 iPos : POSITION,
-    float3 iNormal : NORMAL,
-    float2 iTexCoord : TEXCOORD0,
+    #if !defined(BILLBOARD) && !defined(TRAILFACECAM)
+        float3 iNormal : NORMAL,
+    #endif
+    #ifndef NOUV
+        float2 iTexCoord : TEXCOORD0,
+    #endif
+    #ifdef VERTEXCOLOR
+        float4 iColor : COLOR0,
+    #endif
     #if defined(LIGHTMAP) || defined(AO)
         float2 iTexCoord2 : TEXCOORD1,
     #endif
-    #ifdef NORMALMAP
+    #if defined(NORMALMAP) || defined(TRAILFACECAM) || defined(TRAILBONE)
         float4 iTangent : TANGENT,
     #endif
     #ifdef SKINNED
@@ -24,9 +47,9 @@ void VS(float4 iPos : POSITION,
         int4 iBlendIndices : BLENDINDICES,
     #endif
     #ifdef INSTANCED
-        float4x3 iModelInstance : TEXCOORD2,
+        float4x3 iModelInstance : TEXCOORD4,
     #endif
-    #ifdef BILLBOARD
+    #if defined(BILLBOARD) || defined(DIRBILLBOARD)
         float2 iSize : TEXCOORD1,
     #endif
     #ifndef NORMALMAP
@@ -57,11 +80,19 @@ void VS(float4 iPos : POSITION,
             out float2 oTexCoord2 : TEXCOORD7,
         #endif
     #endif
+    #ifdef VERTEXCOLOR
+        out float4 oColor : COLOR0,
+    #endif
     #if defined(D3D11) && defined(CLIPPLANE)
         out float oClip : SV_CLIPDISTANCE0,
     #endif
     out float4 oPos : OUTPOSITION)
 {
+    // Define a 0,0 UV coord if not expected from the vertex data
+    #ifdef NOUV
+    float2 iTexCoord = float2(0.0, 0.0);
+    #endif
+
     float4x3 modelMatrix = iModelMatrix;
     float3 worldPos = GetWorldPos(modelMatrix);
     float height = worldPos.y - cModel._m31;
@@ -78,7 +109,11 @@ void VS(float4 iPos : POSITION,
     #if defined(D3D11) && defined(CLIPPLANE)
         oClip = dot(oPos, cClipPlane);
     #endif
-    
+
+    #ifdef VERTEXCOLOR
+        oColor = iColor;
+    #endif
+
     #ifdef NORMALMAP
         float3 tangent = GetWorldTangent(modelMatrix);
         float3 bitangent = cross(tangent, oNormal) * iTangent.w;
@@ -94,7 +129,7 @@ void VS(float4 iPos : POSITION,
 
         #ifdef SHADOW
             // Shadow projection: transform from world space to shadow space
-            GetShadowPos(projWorldPos, oShadowPos);
+            GetShadowPos(projWorldPos, oNormal, oShadowPos);
         #endif
 
         #ifdef SPOTLIGHT
@@ -103,7 +138,7 @@ void VS(float4 iPos : POSITION,
         #endif
 
         #ifdef POINTLIGHT
-            oCubeMaskVec = mul(cLightPos.xyz - worldPos, (float3x3)cLightMatrices[0]);
+            oCubeMaskVec = mul(worldPos - cLightPos.xyz, (float3x3)cLightMatrices[0]);
         #endif
     #else
         // Ambient & per-vertex lighting

+ 18 - 2
Resources/CoreData/Shaders/HLSL/VegetationDepth.hlsl

@@ -2,22 +2,38 @@
 #include "Samplers.hlsl"
 #include "Transform.hlsl"
 
+#ifndef D3D11
+
+// D3D9 uniforms
 uniform float cWindHeightFactor;
 uniform float cWindHeightPivot;
 uniform float cWindPeriod;
 uniform float2 cWindWorldSpacing;
 
+#else
+
+// D3D11 constant buffer
+cbuffer CustomVS : register(b6)
+{
+    float cWindHeightFactor;
+    float cWindHeightPivot;
+    float cWindPeriod;
+    float2 cWindWorldSpacing;
+}
+
+#endif
+
 void VS(float4 iPos : POSITION,
     #ifdef SKINNED
         float4 iBlendWeights : BLENDWEIGHT,
         int4 iBlendIndices : BLENDINDICES,
     #endif
     #ifdef INSTANCED
-        float4x3 iModelInstance : TEXCOORD2,
+        float4x3 iModelInstance : TEXCOORD4,
     #endif
     float2 iTexCoord : TEXCOORD0,
     out float3 oTexCoord : TEXCOORD0,
-    out float4 oPos : POSITION)
+    out float4 oPos : OUTPOSITION)
 {
     float4x3 modelMatrix = iModelMatrix;
     float3 worldPos = GetWorldPos(modelMatrix);

+ 18 - 2
Resources/CoreData/Shaders/HLSL/VegetationShadow.hlsl

@@ -2,22 +2,38 @@
 #include "Samplers.hlsl"
 #include "Transform.hlsl"
 
+#ifndef D3D11
+
+// D3D9 uniforms
 uniform float cWindHeightFactor;
 uniform float cWindHeightPivot;
 uniform float cWindPeriod;
 uniform float2 cWindWorldSpacing;
 
+#else
+
+// D3D11 constant buffer
+cbuffer CustomVS : register(b6)
+{
+    float cWindHeightFactor;
+    float cWindHeightPivot;
+    float cWindPeriod;
+    float2 cWindWorldSpacing;
+}
+
+#endif
+
 void VS(float4 iPos : POSITION,
     #ifdef SKINNED
         float4 iBlendWeights : BLENDWEIGHT,
         int4 iBlendIndices : BLENDINDICES,
     #endif
     #ifdef INSTANCED
-        float4x3 iModelInstance : TEXCOORD2,
+        float4x3 iModelInstance : TEXCOORD4,
     #endif
     float2 iTexCoord : TEXCOORD0,
     out float2 oTexCoord : TEXCOORD0,
-    out float4 oPos : POSITION)
+    out float4 oPos : OUTPOSITION)
 {
     float4x3 modelMatrix = iModelMatrix;
     float3 worldPos = GetWorldPos(modelMatrix);

+ 3 - 0
Resources/CoreData/Shaders/HLSL/Water.hlsl

@@ -36,6 +36,9 @@ cbuffer CustomPS : register(b6)
 void VS(float4 iPos : POSITION,
     float3 iNormal: NORMAL,
     float2 iTexCoord : TEXCOORD0,
+    #ifdef INSTANCED
+        float4x3 iModelInstance : TEXCOORD4,
+    #endif
     out float4 oScreenPos : TEXCOORD0,
     out float2 oReflectUV : TEXCOORD1,
     out float2 oWaterUV : TEXCOORD2,

+ 10 - 0
Resources/CoreData/Techniques/DiffAlphaMaskTranslucent.xml

@@ -0,0 +1,10 @@
+<technique vs="LitSolid" ps="LitSolid" vsdefines="TRANSLUCENT" psdefines="DIFFMAP ALPHAMASK TRANSLUCENT" alphamask="true" >
+    <pass name="base" />
+    <pass name="litbase" psdefines="AMBIENT" />
+    <pass name="light" depthtest="equal" depthwrite="false" blend="add" />
+    <pass name="prepass" psdefines="PREPASS" />
+    <pass name="material" psdefines="MATERIAL" depthtest="equal" depthwrite="false" />
+    <pass name="deferred" psdefines="DEFERRED" />
+    <pass name="depth" vs="Depth" ps="Depth" psdefines="ALPHAMASK" />
+    <pass name="shadow" vs="Shadow" ps="Shadow" psdefines="ALPHAMASK" />
+</technique>

+ 5 - 0
Resources/CoreData/Techniques/DiffAlphaTranslucent.xml

@@ -0,0 +1,5 @@
+<technique vs="LitSolid" ps="LitSolid" vsdefines="TRANSLUCENT" psdefines="DIFFMAP TRANSLUCENT">
+    <pass name="alpha" depthwrite="false" blend="alpha" />
+    <pass name="litalpha" depthwrite="false" blend="addalpha" />
+    <pass name="shadow" vs="Shadow" ps="Shadow" />
+</technique>

+ 1 - 1
Resources/CoreData/Techniques/DiffLightMap.xml

@@ -1,6 +1,6 @@
 <technique vs="LitSolid" ps="LitSolid" psdefines="DIFFMAP">
     <pass name="base" vsdefines="LIGHTMAP" psdefines="LIGHTMAP" />
-    <pass name="light" vsdefines="LIGHTMAP" psdefines="LIGHTMAP" depthtest="equal" depthwrite="false" blend="subtract" />
+    <pass name="light" depthtest="equal" depthwrite="false" blend="add" />
     <pass name="prepass" psdefines="PREPASS" />
     <pass name="material" vsdefines="LIGHTMAP" psdefines="MATERIAL LIGHTMAP" depthtest="equal" depthwrite="false" />
     <pass name="deferred" vsdefines="LIGHTMAP" psdefines="DEFERRED LIGHTMAP" />

+ 10 - 0
Resources/CoreData/Techniques/DiffNormalAlphaMaskTranslucent.xml

@@ -0,0 +1,10 @@
+<technique vs="LitSolid" ps="LitSolid" vsdefines="TRANSLUCENT" psdefines="DIFFMAP ALPHAMASK TRANSLUCENT" alphamask="true">
+    <pass name="base" />
+    <pass name="litbase" vsdefines="NORMALMAP" psdefines="AMBIENT NORMALMAP" />
+    <pass name="light" vsdefines="NORMALMAP" psdefines="NORMALMAP" depthtest="equal" depthwrite="false" blend="add" />
+    <pass name="prepass" vsdefines="NORMALMAP" psdefines="PREPASS NORMALMAP" />
+    <pass name="material" psdefines="MATERIAL" depthtest="equal" depthwrite="false" />
+    <pass name="deferred" vsdefines="NORMALMAP" psdefines="DEFERRED NORMALMAP" />
+    <pass name="depth" vs="Depth" ps="Depth" psdefines="ALPHAMASK" />
+    <pass name="shadow" vs="Shadow" ps="Shadow" psdefines="ALPHAMASK" />
+</technique>

+ 5 - 0
Resources/CoreData/Techniques/DiffNormalAlphaTranslucent.xml

@@ -0,0 +1,5 @@
+<technique vs="LitSolid" ps="LitSolid" vsdefines="TRANSLUCENT" psdefines="DIFFMAP TRANSLUCENT">
+    <pass name="alpha" depthwrite="false" blend="alpha" />
+    <pass name="litalpha" vsdefines="NORMALMAP" psdefines="NORMALMAP" depthwrite="false" blend="addalpha" />
+    <pass name="shadow" vs="Shadow" ps="Shadow" />
+</technique>

+ 10 - 0
Resources/CoreData/Techniques/DiffNormalPackedAlphaMaskTranslucent.xml

@@ -0,0 +1,10 @@
+<technique vs="LitSolid" ps="LitSolid" vsdefines="TRANSLUCENT" psdefines="DIFFMAP ALPHAMASK TRANSLUCENT" alphamask="true">
+    <pass name="base" />
+    <pass name="litbase" vsdefines="NORMALMAP" psdefines="AMBIENT NORMALMAP PACKEDNORMAL" />
+    <pass name="light" vsdefines="NORMALMAP" psdefines="NORMALMAP PACKEDNORMAL" depthtest="equal" depthwrite="false" blend="add" />
+    <pass name="prepass" vsdefines="NORMALMAP" psdefines="PREPASS NORMALMAP PACKEDNORMAL" />
+    <pass name="material" psdefines="MATERIAL" depthtest="equal" depthwrite="false" />
+    <pass name="deferred" vsdefines="NORMALMAP" psdefines="DEFERRED NORMALMAP PACKEDNORMAL" />
+    <pass name="depth" vs="Depth" ps="Depth" psdefines="ALPHAMASK" />
+    <pass name="shadow" vs="Shadow" ps="Shadow" psdefines="ALPHAMASK" />
+</technique>

+ 5 - 0
Resources/CoreData/Techniques/DiffNormalPackedAlphaTranslucent.xml

@@ -0,0 +1,5 @@
+<technique vs="LitSolid" ps="LitSolid" vsdefines="TRANSLUCENT" psdefines="DIFFMAP TRANSLUCENT">
+    <pass name="alpha" depthwrite="false" blend="alpha" />
+    <pass name="litalpha" vsdefines="NORMALMAP" psdefines="NORMALMAP PACKEDNORMAL" depthwrite="false" blend="addalpha" />
+    <pass name="shadow" vs="Shadow" ps="Shadow" />
+</technique>

+ 3 - 0
Resources/CoreData/Techniques/DiffSkyboxHDRScale.xml

@@ -0,0 +1,3 @@
+<technique vs="Skybox" ps="Skybox" psdefines="HDRSCALE">
+    <pass name="postopaque" depthwrite="false" />
+</technique>

+ 3 - 0
Resources/CoreData/Techniques/DiffSkydome.xml

@@ -0,0 +1,3 @@
+<technique vs="Skydome" ps="Skydome">
+    <pass name="postopaque" depthwrite="false" />
+</technique>

+ 8 - 0
Resources/CoreData/Techniques/PBR/DiffNormalSpecEmissive.xml

@@ -0,0 +1,8 @@
+<technique vs="PBRLitSolid" ps="PBRLitSolid" psdefines="DIFFMAP NORMALMAP SPECMAP EMISSIVEMAP">
+    <pass name="base" />
+    <pass name="light" depthtest="equal" depthwrite="false" blend="add" />>
+    <pass name="material" psdefines="MATERIAL" depthtest="equal" depthwrite="false" />
+    <pass name="deferred" psdefines="DEFERRED" />
+    <pass name="depth" vs="Depth" ps="Depth" />
+    <pass name="shadow" vs="Shadow" ps="Shadow" />
+</technique>

+ 5 - 0
Resources/CoreData/Techniques/PBR/DiffNormalSpecEmissiveAlpha.xml

@@ -0,0 +1,5 @@
+<technique vs="PBRLitSolid" ps="PBRLitSolid" psdefines="DIFFMAP SPECMAP EMISSIVEMAP NORMALMAP">
+    <pass name="alpha" depthwrite="false" blend="alpha" />
+    <pass name="litalpha" depthwrite="false" blend="addalpha" />
+    <pass name="shadow" vs="Shadow" ps="Shadow" />
+</technique>

+ 8 - 0
Resources/CoreData/Techniques/PBR/PBRDiff.xml

@@ -0,0 +1,8 @@
+<technique vs="PBRLitSolid" ps="PBRLitSolid" vsdefines="IBL" psdefines="DIFFMAP PBR IBL">
+    <pass name="base" />
+    <pass name="light" depthtest="equal" depthwrite="false" blend="add" />
+    <pass name="material" psdefines="MATERIAL" depthtest="equal" depthwrite="false" />
+    <pass name="deferred" psdefines="DEFERRED" blend="add" />
+    <pass name="depth" vs="Depth" ps="Depth" />
+    <pass name="shadow" vs="Shadow" ps="Shadow" />
+</technique>

+ 5 - 0
Resources/CoreData/Techniques/PBR/PBRDiffAlpha.xml

@@ -0,0 +1,5 @@
+<technique vs="PBRLitSolid" ps="PBRLitSolid" vsdefines="IBL" psdefines="DIFFMAP PBR IBL">
+    <pass name="alpha" depthwrite="false" blend="alpha" />
+    <pass name="litalpha" depthwrite="false" blend="addalpha" />
+    <pass name="shadow" vs="Shadow" ps="Shadow" />
+</technique>

+ 8 - 0
Resources/CoreData/Techniques/PBR/PBRDiffNormal.xml

@@ -0,0 +1,8 @@
+<technique vs="PBRLitSolid" ps="PBRLitSolid" vsdefines="IBL" psdefines="DIFFMAP NORMALMAP PBR IBL">
+    <pass name="base" />
+    <pass name="light" depthtest="equal" depthwrite="false" blend="add" />
+    <pass name="material" psdefines="MATERIAL" depthtest="equal" depthwrite="false" />
+    <pass name="deferred" psdefines="DEFERRED" blend="add" />
+    <pass name="depth" vs="Depth" ps="Depth" />
+    <pass name="shadow" vs="Shadow" ps="Shadow" />
+</technique>

+ 5 - 0
Resources/CoreData/Techniques/PBR/PBRDiffNormalAlpha.xml

@@ -0,0 +1,5 @@
+<technique vs="PBRLitSolid" ps="PBRLitSolid" vsdefines="IBL" psdefines="DIFFMAP NORMALMAP PBR IBL">
+    <pass name="alpha" depthwrite="false" blend="alpha" />
+    <pass name="litalpha" depthwrite="false" blend="addalpha" />
+    <pass name="shadow" vs="Shadow" ps="Shadow" />
+</technique>

+ 7 - 0
Resources/CoreData/Techniques/PBR/PBRDiffNormalEmissive.xml

@@ -0,0 +1,7 @@
+<technique vs="PBRLitSolid" ps="PBRLitSolid"  vsdefines="IBL" psdefines="DIFFMAP NORMALMAP EMISSIVEMAP PBR IBL">
+    <pass name="light" depthtest="equal" depthwrite="false" blend="add" />
+    <pass name="material" psdefines="MATERIAL" depthtest="equal" depthwrite="false" />
+    <pass name="deferred" psdefines="DEFERRED" blend="add" />
+    <pass name="depth" vs="Depth" ps="Depth" />
+    <pass name="shadow" vs="Shadow" ps="Shadow" />
+</technique>

+ 5 - 0
Resources/CoreData/Techniques/PBR/PBRDiffNormalEmissiveAlpha.xml

@@ -0,0 +1,5 @@
+<technique vs="PBRLitSolid" ps="PBRLitSolid"  vsdefines="IBL" psdefines="DIFFMAP NORMALMAP EMISSIVEMAP PBR IBL">
+    <pass name="alpha" depthwrite="false" blend="alpha" />
+    <pass name="litalpha" depthwrite="false" blend="addalpha" />
+    <pass name="shadow" vs="Shadow" ps="Shadow" />
+</technique>

+ 8 - 0
Resources/CoreData/Techniques/PBR/PBRMetallicRoughDiffNormalSpec.xml

@@ -0,0 +1,8 @@
+<technique vs="PBRLitSolid" ps="PBRLitSolid" vsdefines="IBL" psdefines="NORMALMAP DIFFMAP METALLIC ROUGHNESS PBR IBL">
+    <pass name="base" />
+    <pass name="light" depthtest="equal" depthwrite="false" blend="add" />
+    <pass name="material" psdefines="MATERIAL" depthtest="equal" depthwrite="false" />
+    <pass name="deferred" psdefines="DEFERRED" blend="add"/>
+    <pass name="depth" vs="Depth" ps="Depth" />
+    <pass name="shadow" vs="Shadow" ps="Shadow" />
+</technique>

+ 8 - 0
Resources/CoreData/Techniques/PBR/PBRMetallicRoughDiffNormalSpecEmissive.xml

@@ -0,0 +1,8 @@
+<technique vs="PBRLitSolid" ps="PBRLitSolid" vsdefines="IBL" psdefines="DIFFMAP NORMALMAP EMISSIVEMAP METALLIC ROUGHNESS PBR IBL">
+    <pass name="base" />
+    <pass name="light" depthtest="equal" depthwrite="false" blend="add" />
+    <pass name="material" psdefines="MATERIAL" depthtest="equal" depthwrite="false" />
+    <pass name="deferred" psdefines="DEFERRED" blend="add"/>
+    <pass name="depth" vs="Depth" ps="Depth" />
+    <pass name="shadow" vs="Shadow" ps="Shadow" />
+</technique>

+ 5 - 0
Resources/CoreData/Techniques/PBR/PBRMetallicRoughDiffNormalSpecEmissiveAlpha.xml

@@ -0,0 +1,5 @@
+<technique vs="PBRLitSolid" ps="PBRLitSolid" vsdefines="IBL" psdefines="DIFFMAP NORMALMAP EMISSIVEMAP PBR IBL METALLIC ROUGHNESS">
+    <pass name="alpha" depthwrite="false" blend="alpha" />
+    <pass name="litalpha" depthwrite="false" blend="addalpha" />
+    <pass name="shadow" vs="Shadow" ps="Shadow" />
+</technique>

+ 8 - 0
Resources/CoreData/Techniques/PBR/PBRMetallicRoughDiffSpec.xml

@@ -0,0 +1,8 @@
+<technique vs="PBRLitSolid" ps="PBRLitSolid" vsdefines="IBL" psdefines="DIFFMAP PBR IBL METALLIC ROUGHNESS">
+    <pass name="base"/>
+    <pass name="light" depthtest="equal" depthwrite="false" blend="add" />
+    <pass name="material" psdefines="MATERIAL" depthtest="equal" depthwrite="false" />
+    <pass name="deferred" psdefines="DEFERRED" blend="add" />
+    <pass name="depth" vs="Depth" ps="Depth" />
+    <pass name="shadow" vs="Shadow" ps="Shadow" />
+</technique>

+ 5 - 0
Resources/CoreData/Techniques/PBR/PBRMetallicRoughDiffSpecAlpha.xml

@@ -0,0 +1,5 @@
+<technique vs="PBRLitSolid" ps="PBRLitSolid" vsdefines="IBL" psdefines="DIFFMAP PBR IBL METALLIC ROUGHNESS">
+    <pass name="alpha" depthwrite="false" blend="alpha" />
+    <pass name="litalpha" depthwrite="false" blend="addalpha" />
+    <pass name="shadow" vs="Shadow" ps="Shadow" />
+</technique>

+ 9 - 0
Resources/CoreData/Techniques/PBR/PBRNoTexture.xml

@@ -0,0 +1,9 @@
+<technique vs="PBRLitSolid" ps="PBRLitSolid" vsdefines="NOUV PBR IBL" psdefines="PBR IBL">
+    <pass name="base" />
+    <pass name="light" depthtest="equal" depthwrite="false" blend="add" />
+    <pass name="prepass" psdefines="PREPASS" />
+    <pass name="material" psdefines="MATERIAL" depthtest="equal" depthwrite="false" />
+    <pass name="deferred" psdefines="DEFERRED" />
+    <pass name="depth" vs="Depth" ps="Depth" />
+    <pass name="shadow" vs="Shadow" ps="Shadow" />
+</technique>

+ 5 - 0
Resources/CoreData/Techniques/PBR/PBRNoTextureAlpha.xml

@@ -0,0 +1,5 @@
+<technique vs="PBRLitSolid" ps="PBRLitSolid" vsdefines="NOUV IBL" psdefines="PBR IBL">
+    <pass name="alpha"  depthwrite="false" blend="alpha" />
+    <pass name="litalpha" depthwrite="false" blend="addalpha" />
+    <pass name="shadow" vs="Shadow" ps="Shadow" />
+</technique>

+ 0 - 1
Resources/CoreData/Textures/LUTIdentity.png


+ 0 - 2
Script/AtomicNET/AtomicNET/Core/Constants.cs

@@ -9,8 +9,6 @@ namespace AtomicEngine
     {
         public const string LIBNAME = "AtomicNETNative.dll";
 
-        // Atomic2D
-        public const float PIXEL_SIZE = 0.01f;
     }
 
 }

+ 2 - 1
Script/Packages/Atomic/Atomic2D.json

@@ -3,7 +3,7 @@
 	"sources" : ["Source/Atomic/Atomic2D"],
 	"includes" : ["<Atomic/Graphics/Texture2D.h>", "<Atomic/Scene/Node.h>", "<Atomic/Graphics/Material.h>"],
 	"classes" : [ "SpriteSheet2D", "Sprite2D", "Drawable2D", "StaticSprite2D", "AnimationSet2D", "AnimatedSprite2D",
-				 "CollisionShape2D", "CollisionBox2D", "RigidBody2D", "Animation2D", "CollisionChain2D",
+				 "CollisionShape2D", "CollisionBox2D", "RigidBody2D", "CollisionChain2D",
 				 "CollisionCircle2D", "CollisionEdge2D", "CollisionPolygon2D",
 				 "Constraint2D", "ConstraintDistance2D", "ConstraintFriction2D", "ConstraintGear2D",
 				 "ConstraintMotor2D", "ConstraintMouse2D", "ConstraintPrismatic2D", "ConstraintPulley2D",
@@ -12,6 +12,7 @@
 				 "TileMap2D", "PropertySet2D", "Tile2D", "TileMapObject2D", "TileMapLayer2D",
 				 "TmxLayer2D", "TmxTileLayer2D", "TmxObjectGroup2D", "TmxImageLayer2D", "TmxFile2D",
 				 "Light2DGroup", "Light2D", "DirectionalLight2D", "PositionalLight2D", "PointLight2D"],
+	"jsmodulepreamble" : ["using namespace Atomic::Spriter;"],			 
 	"overloads" : {
 		"AnimatedSprite2D" : {
 			"SetAnimation" : ["String", "LoopMode2D"]

+ 0 - 43
Script/Packages/Atomic/Atomic3D.json

@@ -1,43 +0,0 @@
-{
-	"name" : "Atomic3D",
-	"sources" : ["Source/Atomic/Atomic3D"],
-	"requires" : ["3D"],
-	"includes" : ["<Atomic/Container/ArrayPtr.h>","<Atomic/Scene/Scene.h>", "<Atomic/Atomic3D/Animation.h>", "<Atomic/Graphics/OcclusionBuffer.h>",
-			      "<Atomic/Scene/ValueAnimation.h>", "<Atomic/Graphics/Material.h>", "<Atomic/Resource/Image.h>", "<Atomic/Graphics/VertexBuffer.h>"],
-	"classes" : ["Model",
-				 "StaticModel",
-				 "Animation", "AnimatedModel", "AnimationController", "AnimationState", "Billboard", "BillboardSet", "CustomGeometry",
-				 "DecalSet", "ParticleEffect", "ParticleEmitter",
-				 "Skybox", "StaticModelGroup", "Terrain", "TerrainPatch"],
-	"overloads" : {
-		"StaticModel" : {
-			"SetMaterial" : ["Material"]
-		},
-		"AnimationState" : {
-			"AnimationState" : ["AnimatedModel", "Animation"]
-		},
-		"CustomGeometry" : {
-			"SetMaterial" : ["Material"]
-		}
-
-	},
-	"typescript_decl" : {
-		"StaticModel" : [
-			"setMaterialIndex(index:number, material:Material);"
-		],
-		"CustomGeometry" : [
-			"setMaterialIndex(index:number, material:Material);"
-		]
-	},
-
-	"haxe_decl" : {
-		"StaticModel" : [
-			"function setMaterialIndex(index:UInt, material:Material):Void;"
-		],
-		"CustomGeometry" : [
-			"function setMaterialIndex(index:UInt, material:Material):Void;"
-		]
-	}
-
-
-}

+ 30 - 2
Script/Packages/Atomic/Graphics.json

@@ -1,14 +1,20 @@
 {
 	"name" : "Graphics",
 	"sources" : ["Source/Atomic/Graphics"],
-	"includes" : ["<Atomic/Scene/Scene.h>", "<Atomic/Graphics/OcclusionBuffer.h>", "<Atomic/Scene/ValueAnimation.h>"],
+	"includes" : ["<Atomic/Scene/Scene.h>", "<Atomic/Graphics/OcclusionBuffer.h>", "<Atomic/Scene/ValueAnimation.h>",
+							  "<Atomic/Container/ArrayPtr.h>", "<Atomic/Graphics/Animation.h>",
+							 "<Atomic/Graphics/Material.h>", "<Atomic/Resource/Image.h>", "<Atomic/Graphics/VertexBuffer.h>"],
 	"classes" : ["Graphics", "Texture", "Texture2D", "Material", "Drawable",
 				 "Viewport", "Renderer", "Octree", "Zone", "Camera", "Light", "RenderPath",
 				 "DebugRenderer",
 				 "RenderSurface", "Shader", "ShaderPrecache", "ShaderVariation",
 				 "Pass", "Technique",
 				 "Texture3D", "TextureCube", "View",
-			 	 "VertexBuffer"],
+			 	 "VertexBuffer", "Model",
+ 				 "StaticModel",
+ 				 "Animation", "AnimatedModel", "AnimationController", "AnimationState", "Billboard", "BillboardSet", "CustomGeometry",
+ 				 "DecalSet", "ParticleEffect", "ParticleEmitter",
+ 				 "Skybox", "StaticModelGroup", "Terrain", "TerrainPatch"],
 	"overloads" : {
 		"Viewport" : {
 			"Viewport" : ["Context", "Scene", "Camera", "RenderPath"],
@@ -20,8 +26,18 @@
 		"Graphics" : {
 			"SetWindowPosition" : ["int", "int"],
 			"Draw" : ["PrimitiveType", "unsigned", "unsigned"]
+		},
+		"StaticModel" : {
+			"SetMaterial" : ["Material"]
+		},
+		"AnimationState" : {
+			"AnimationState" : ["AnimatedModel", "Animation"]
+		},
+		"CustomGeometry" : {
+			"SetMaterial" : ["Material"]
 		}
 
+
 	},
 	"typescript_decl" : {
 
@@ -33,6 +49,12 @@
 			"getShadowCascade():Number[];",
 			"setShadowCascade(split1:number, split2:number, split3:number, split4:number, fadeStart:number, biasAutoAdjust?:number);",
 			"setShadowCascadeParameter(index:number, value:number);"
+		],
+		"StaticModel" : [
+			"setMaterialIndex(index:number, material:Material);"
+		],
+		"CustomGeometry" : [
+			"setMaterialIndex(index:number, material:Material);"
 		]
 
 	},
@@ -42,6 +64,12 @@
 			"function getShadowCascade():Array<Float>;",
 			"function setShadowCascade(split1:Float, split2:Float, split3:Float, split4:Float, fadeStart:Float, ?biasAutoAdjust:Float):Void;",
 			"function setShadowCascadeParameter(index:Int, value:Float):Void;"
+		],
+		"StaticModel" : [
+			"function setMaterialIndex(index:UInt, material:Material):Void;"
+		],
+		"CustomGeometry" : [
+			"function setMaterialIndex(index:UInt, material:Material):Void;"
 		]
 
 	}

+ 1 - 1
Script/Packages/Atomic/Package.json

@@ -2,7 +2,7 @@
 {
 	"name" : "Atomic",
 	"namespace" : "Atomic",
-	"modules" : ["Container", "Math", "Core", "Scene", "Graphics", "Atomic3D", "Atomic2D", "Audio",
+	"modules" : ["Container", "Math", "Core", "Scene", "Graphics", "Atomic2D", "Audio",
 		"Physics", "Navigation", "Input", "UI", "Resource", "Network", "IO",
 		"Engine", "Script", "Javascript", "Environment", "Web", "IPC"],
 		"moduleExclude" : {

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