Browse Source

Merge pull request #90 from AtomicGameEngine/Updates

New Direct3D11 and OpenGL3 renderers, rendering API optimizations and cleanups, additional Navigation subsystem capabilities, 2D optimizations, etc
JoshEngebretson 10 years ago
parent
commit
43f8416e97
100 changed files with 1956 additions and 1267 deletions
  1. 15 1
      CMake/Modules/AtomicWindows.cmake
  2. 1 1
      CMakeLists.txt
  3. 1 0
      Data/AtomicPlayer/Resources/CoreData/RenderPaths/DeferredHWDepth.xml
  4. 5 1
      Data/AtomicPlayer/Resources/CoreData/Shaders/GLSL/Atomic2D.glsl
  5. 2 2
      Data/AtomicPlayer/Resources/CoreData/Shaders/GLSL/Bloom.glsl
  6. 23 15
      Data/AtomicPlayer/Resources/CoreData/Shaders/GLSL/Depth.glsl
  7. 2 2
      Data/AtomicPlayer/Resources/CoreData/Shaders/GLSL/LitParticle.glsl
  8. 15 6
      Data/AtomicPlayer/Resources/CoreData/Shaders/GLSL/LitSolid.glsl
  9. 0 8
      Data/AtomicPlayer/Resources/CoreData/Shaders/GLSL/PostProcess.glsl
  10. 2 2
      Data/AtomicPlayer/Resources/CoreData/Shaders/GLSL/PrepassLight.glsl
  11. 27 10
      Data/AtomicPlayer/Resources/CoreData/Shaders/GLSL/Samplers.glsl
  12. 2 2
      Data/AtomicPlayer/Resources/CoreData/Shaders/GLSL/ScreenPos.glsl
  13. 2 2
      Data/AtomicPlayer/Resources/CoreData/Shaders/GLSL/Shadow.glsl
  14. 6 1
      Data/AtomicPlayer/Resources/CoreData/Shaders/GLSL/Text.glsl
  15. 43 28
      Data/AtomicPlayer/Resources/CoreData/Shaders/GLSL/Tonemap.glsl
  16. 132 6
      Data/AtomicPlayer/Resources/CoreData/Shaders/GLSL/Uniforms.glsl
  17. 3 3
      Data/AtomicPlayer/Resources/CoreData/Shaders/GLSL/Unlit.glsl
  18. 3 3
      Data/AtomicPlayer/Resources/CoreData/Shaders/GLSL/VegetationDepth.glsl
  19. 34 11
      Data/AtomicPlayer/Resources/CoreData/Shaders/HLSL/AutoExposure.hlsl
  20. 14 4
      Data/AtomicPlayer/Resources/CoreData/Shaders/HLSL/Basic.hlsl
  21. 30 8
      Data/AtomicPlayer/Resources/CoreData/Shaders/HLSL/Bloom.hlsl
  22. 62 9
      Data/AtomicPlayer/Resources/CoreData/Shaders/HLSL/BloomHDR.hlsl
  23. 21 1
      Data/AtomicPlayer/Resources/CoreData/Shaders/HLSL/Blur.hlsl
  24. 17 0
      Data/AtomicPlayer/Resources/CoreData/Shaders/HLSL/ClearFramebuffer.hlsl
  25. 9 5
      Data/AtomicPlayer/Resources/CoreData/Shaders/HLSL/ColorCorrection.hlsl
  26. 3 3
      Data/AtomicPlayer/Resources/CoreData/Shaders/HLSL/CopyFramebuffer.hlsl
  27. 9 9
      Data/AtomicPlayer/Resources/CoreData/Shaders/HLSL/DeferredLight.hlsl
  28. 27 12
      Data/AtomicPlayer/Resources/CoreData/Shaders/HLSL/Depth.hlsl
  29. 50 44
      Data/AtomicPlayer/Resources/CoreData/Shaders/HLSL/FXAA3.hlsl
  30. 4 4
      Data/AtomicPlayer/Resources/CoreData/Shaders/HLSL/Fog.hlsl
  31. 4 4
      Data/AtomicPlayer/Resources/CoreData/Shaders/HLSL/GreyScale.hlsl
  32. 6 6
      Data/AtomicPlayer/Resources/CoreData/Shaders/HLSL/Light2D.hlsl
  33. 38 58
      Data/AtomicPlayer/Resources/CoreData/Shaders/HLSL/Lighting.hlsl
  34. 25 6
      Data/AtomicPlayer/Resources/CoreData/Shaders/HLSL/LitParticle.hlsl
  35. 59 33
      Data/AtomicPlayer/Resources/CoreData/Shaders/HLSL/LitSolid.hlsl
  36. 23 1
      Data/AtomicPlayer/Resources/CoreData/Shaders/HLSL/PostProcess.hlsl
  37. 7 7
      Data/AtomicPlayer/Resources/CoreData/Shaders/HLSL/PrepassLight.hlsl
  38. 93 42
      Data/AtomicPlayer/Resources/CoreData/Shaders/HLSL/Samplers.hlsl
  39. 3 3
      Data/AtomicPlayer/Resources/CoreData/Shaders/HLSL/ScreenPos.hlsl
  40. 9 8
      Data/AtomicPlayer/Resources/CoreData/Shaders/HLSL/Shadow2D.hlsl
  41. 4 4
      Data/AtomicPlayer/Resources/CoreData/Shaders/HLSL/Skybox.hlsl
  42. 2 2
      Data/AtomicPlayer/Resources/CoreData/Shaders/HLSL/Stencil.hlsl
  43. 52 21
      Data/AtomicPlayer/Resources/CoreData/Shaders/HLSL/TerrainBlend.hlsl
  44. 27 15
      Data/AtomicPlayer/Resources/CoreData/Shaders/HLSL/Text.hlsl
  45. 22 6
      Data/AtomicPlayer/Resources/CoreData/Shaders/HLSL/Tonemap.hlsl
  46. 26 0
      Data/AtomicPlayer/Resources/CoreData/Shaders/HLSL/Transform.hlsl
  47. 126 5
      Data/AtomicPlayer/Resources/CoreData/Shaders/HLSL/Uniforms.hlsl
  48. 25 8
      Data/AtomicPlayer/Resources/CoreData/Shaders/HLSL/Unlit.hlsl
  49. 8 1
      Data/AtomicPlayer/Resources/CoreData/Shaders/HLSL/Vegetation.hlsl
  50. 38 5
      Data/AtomicPlayer/Resources/CoreData/Shaders/HLSL/VegetationDepth.hlsl
  51. 1 1
      Data/AtomicPlayer/Resources/CoreData/Techniques/Diff.xml
  52. 1 1
      Data/AtomicPlayer/Resources/CoreData/Techniques/DiffNormalAO.xml
  53. 1 1
      Data/AtomicPlayer/Resources/CoreData/Techniques/DiffNormalEmissive.xml
  54. 1 1
      Data/AtomicPlayer/Resources/CoreData/Techniques/DiffNormalPackedAO.xml
  55. 1 1
      Data/AtomicPlayer/Resources/CoreData/Techniques/DiffNormalPackedEmissive.xml
  56. 1 1
      Data/AtomicPlayer/Resources/CoreData/Techniques/DiffNormalPackedSpecAO.xml
  57. 1 1
      Data/AtomicPlayer/Resources/CoreData/Techniques/DiffNormalPackedSpecEmissive.xml
  58. 1 1
      Data/AtomicPlayer/Resources/CoreData/Techniques/DiffNormalSpecAO.xml
  59. 10 0
      Data/AtomicPlayer/Resources/CoreData/Techniques/DiffNormalSpecEmissive.xml
  60. 1 1
      Data/AtomicPlayer/Resources/CoreData/Techniques/DiffVColAdd.xml
  61. 1 1
      Data/AtomicPlayer/Resources/CoreData/Techniques/NoTextureAO.xml
  62. 1 1
      Data/AtomicPlayer/Resources/CoreData/Techniques/NoTextureAddAlpha.xml
  63. 1 1
      Data/AtomicPlayer/Resources/CoreData/Techniques/NoTextureAlpha.xml
  64. 1 1
      Data/AtomicPlayer/Resources/CoreData/Techniques/NoTextureEnvCube.xml
  65. 1 1
      Data/AtomicPlayer/Resources/CoreData/Techniques/NoTextureNormal.xml
  66. 1 1
      Data/AtomicPlayer/Resources/CoreData/Techniques/NoTextureNormalAlpha.xml
  67. 1 1
      Data/AtomicPlayer/Resources/CoreData/Techniques/NoTextureNormalPackedAlpha.xml
  68. 1 1
      Data/AtomicPlayer/Resources/CoreData/Techniques/NoTextureUnlit.xml
  69. 1 1
      Data/AtomicPlayer/Resources/CoreData/Techniques/NoTextureUnlitAlpha.xml
  70. 1 1
      Data/AtomicPlayer/Resources/CoreData/Techniques/NoTextureUnlitVCol.xml
  71. 10 0
      Data/AtomicPlayer/Resources/CoreData/Techniques/NoTextureVCol.xml
  72. 1 1
      Data/AtomicPlayer/Resources/CoreData/Techniques/NoTextureVColAdd.xml
  73. 1 1
      Data/AtomicPlayer/Resources/CoreData/Techniques/NoTextureVColAddAlpha.xml
  74. 1 1
      Data/AtomicPlayer/Resources/CoreData/Techniques/NoTextureVColMultiply.xml
  75. 12 20
      Data/AtomicPlayer/Resources/CoreData/Techniques/TerrainBlend.xml
  76. 3 5
      Source/Atomic/Atomic2D/AnimatedSprite2D.h
  77. 17 97
      Source/Atomic/Atomic2D/Drawable2D.cpp
  78. 26 40
      Source/Atomic/Atomic2D/Drawable2D.h
  79. 20 11
      Source/Atomic/Atomic2D/Light2D.cpp
  80. 8 2
      Source/Atomic/Atomic2D/Light2D.h
  81. 64 24
      Source/Atomic/Atomic2D/ParticleEmitter2D.cpp
  82. 13 3
      Source/Atomic/Atomic2D/ParticleEmitter2D.h
  83. 202 187
      Source/Atomic/Atomic2D/Renderer2D.cpp
  84. 45 27
      Source/Atomic/Atomic2D/Renderer2D.h
  85. 56 1
      Source/Atomic/Atomic2D/Sprite2D.cpp
  86. 8 1
      Source/Atomic/Atomic2D/Sprite2D.h
  87. 109 83
      Source/Atomic/Atomic2D/StaticSprite2D.cpp
  88. 23 3
      Source/Atomic/Atomic2D/StaticSprite2D.h
  89. 3 3
      Source/Atomic/Atomic3D/AnimatedModel.cpp
  90. 2 2
      Source/Atomic/Atomic3D/DecalSet.cpp
  91. 2 0
      Source/Atomic/Atomic3D/Model.h
  92. 2 2
      Source/Atomic/Atomic3D/ParticleEmitter.cpp
  93. 10 12
      Source/Atomic/Atomic3D/StaticModel.cpp
  94. 5 1
      Source/Atomic/CMakeLists.txt
  95. 0 191
      Source/Atomic/Container/HashTable.h
  96. 21 1
      Source/Atomic/Container/Str.cpp
  97. 10 2
      Source/Atomic/Container/Str.h
  98. 1 1
      Source/Atomic/Core/Object.h
  99. 14 11
      Source/Atomic/Core/ProcessUtils.cpp
  100. 77 77
      Source/Atomic/Core/StringUtils.cpp

+ 15 - 1
CMake/Modules/AtomicWindows.cmake

@@ -8,7 +8,21 @@ set (D3DCOMPILER_47_DLL ${CMAKE_SOURCE_DIR}/Build/Windows/Binaries/x64/D3DCompil
 
 add_definitions(-DATOMIC_PLATFORM_WINDOWS -D_CRT_SECURE_NO_WARNINGS -DATOMIC_TBUI)
 
-list (APPEND ATOMIC_LINK_LIBRARIES MojoShader user32 gdi32 winmm imm32 ole32 oleaut32 version uuid d3d9 d3dcompiler Ws2_32)
+list (APPEND ATOMIC_LINK_LIBRARIES MojoShader user32 gdi32 winmm imm32 ole32 oleaut32 version uuid Ws2_32)
+
+if (ATOMIC_D3D11)
+
+    add_definitions(-DATOMIC_D3D11)
+
+    list (APPEND ATOMIC_LINK_LIBRARIES d3d11 d3dcompiler dxguid)
+
+else()
+
+    list (APPEND ATOMIC_LINK_LIBRARIES  d3d9 d3dcompiler)
+
+endif()
+
+
 
 # compile with static runtime
 set(CompilerFlags CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE CMAKE_C_FLAGS CMAKE_C_FLAGS_DEBUG CMAKE_C_FLAGS_RELEASE)

+ 1 - 1
CMakeLists.txt

@@ -26,7 +26,7 @@ endif()
 
 if (NOT EMSCRIPTEN)
     add_definitions( -DATOMIC_NETWORK)
-    set (ATOMIC_LINK_LIBRARIES ${ATOMIC_LINK_LIBRARIES} SDL Civetweb Recast Detour kNet )
+    set (ATOMIC_LINK_LIBRARIES ${ATOMIC_LINK_LIBRARIES} SDL Civetweb Recast Detour DetourCrowd DetourTileCache kNet )
 endif()
 
 if (MSVC)

+ 1 - 0
Data/AtomicPlayer/Resources/CoreData/RenderPaths/DeferredHWDepth.xml

@@ -3,6 +3,7 @@
     <rendertarget name="normal" sizedivisor="1 1" format="rgba" />
     <rendertarget name="depth" sizedivisor="1 1" format="readabledepth" />
     <command type="clear" color="fog" depth="1.0" stencil="0" depthstencil="depth" />
+    <command type="clear" color="0 0 0 0" output="albedo" depthstencil="depth" />
     <command type="scenepass" pass="deferred" marktostencil="true" vertexlights="true" metadata="gbuffer" depthstencil="depth">
         <output index="0" name="viewport" />
         <output index="1" name="albedo" />

+ 5 - 1
Data/AtomicPlayer/Resources/CoreData/Shaders/GLSL/Atomic2D.glsl

@@ -43,7 +43,11 @@ void PS()
         gl_FragColor = diffColor * diffInput;
     #endif
     #ifdef ALPHAMAP
-        float alphaInput = texture2D(sDiffMap, vTexCoord).a;
+        #ifdef GL3
+            float alphaInput = texture2D(sDiffMap, vTexCoord).r;
+        #else
+            float alphaInput = texture2D(sDiffMap, vTexCoord).a;
+        #endif
         gl_FragColor = vec4(diffColor.rgb, diffColor.a * alphaInput);
     #endif
 }

+ 2 - 2
Data/AtomicPlayer/Resources/CoreData/Shaders/GLSL/Bloom.glsl

@@ -78,11 +78,11 @@ void PS()
     #endif
 
     #if defined(SPOTLIGHT)
-        vec4 spotPos = cLightMatricesPS[0] * projWorldPos;
+        vec4 spotPos = projWorldPos * cLightMatricesPS[0];
         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);
-        lightColor = textureCube(sLightCubeMap, lightVecRot * (worldPos - cLightPosPS.xyz)).rgb * cLightColor.rgb;
+        lightColor = textureCube(sLightCubeMap, (worldPos - cLightPosPS.xyz) * lightVecRot).rgb * cLightColor.rgb;
     #else
         lightColor = cLightColor.rgb;
     #endif

+ 23 - 15
Data/AtomicPlayer/Resources/CoreData/Shaders/GLSL/Depth.glsl

@@ -69,9 +69,9 @@ float GetVertexLightVolumetric(int index, vec3 worldPos)
 vec4 GetShadowPos(int index, vec4 projWorldPos)
 {
     #if defined(DIRLIGHT)
-        return cLightMatrices[index] * projWorldPos;
+        return projWorldPos * cLightMatrices[index];
     #elif defined(SPOTLIGHT)
-        return cLightMatrices[1] * projWorldPos;
+        return projWorldPos * cLightMatrices[1];
     #else
         return vec4(projWorldPos.xyz - cLightPos.xyz, 1.0);
     #endif
@@ -135,16 +135,24 @@ float GetShadow(vec4 shadowPos)
             #else
                 vec2 offsets = cShadowMapInvSize;
             #endif
-            vec4 inLight = vec4(
-                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
-            );
-            return cShadowIntensity.y + dot(inLight, vec4(cShadowIntensity.x));
+            #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
         #else
             // Take one sample
-            float inLight = shadow2DProj(sShadowMap, shadowPos).r;
+            #ifndef GL3
+                float inLight = shadow2DProj(sShadowMap, shadowPos).r;
+            #else
+                float inLight = textureProj(sShadowMap, shadowPos);
+            #endif
             return cShadowIntensity.y + cShadowIntensity.x * inLight;
         #endif
     #else
@@ -222,13 +230,13 @@ float GetDirShadowDeferred(vec4 projWorldPos, float depth)
     vec4 shadowPos;
 
     if (depth < cShadowSplits.x)
-        shadowPos = cLightMatricesPS[0] * projWorldPos;
+        shadowPos = projWorldPos * cLightMatricesPS[0];
     else if (depth < cShadowSplits.y)
-        shadowPos = cLightMatricesPS[1] * projWorldPos;
+        shadowPos = projWorldPos * cLightMatricesPS[1];
     else if (depth < cShadowSplits.z)
-        shadowPos = cLightMatricesPS[2] * projWorldPos;
+        shadowPos = projWorldPos * cLightMatricesPS[2];
     else
-        shadowPos = cLightMatricesPS[3] * projWorldPos;
+        shadowPos = projWorldPos * cLightMatricesPS[3];
 
     return GetDirShadowFade(GetShadow(shadowPos), depth);
 }
@@ -252,7 +260,7 @@ float GetShadowDeferred(vec4 projWorldPos, float depth)
     #if defined(DIRLIGHT)
         return GetDirShadowDeferred(projWorldPos, depth);
     #elif defined(SPOTLIGHT)
-        vec4 shadowPos = cLightMatricesPS[1] * projWorldPos;
+        vec4 shadowPos = projWorldPos * cLightMatricesPS[1];
         return GetShadow(shadowPos);
     #else
         vec3 shadowPos = projWorldPos.xyz - cLightPosPS.xyz;

+ 2 - 2
Data/AtomicPlayer/Resources/CoreData/Shaders/GLSL/LitParticle.glsl

@@ -47,11 +47,11 @@ void VS()
 
         #ifdef SPOTLIGHT
             // Spotlight projection: transform from world space to projector texture coordinates
-            vSpotPos = cLightMatrices[0] * projWorldPos;
+            vSpotPos = projWorldPos * cLightMatrices[0];
         #endif
     
         #ifdef POINTLIGHT
-            vCubeMaskVec = mat3(cLightMatrices[0][0].xyz, cLightMatrices[0][1].xyz, cLightMatrices[0][2].xyz) * (worldPos - cLightPos.xyz);
+            vCubeMaskVec = (worldPos - cLightPos.xyz) * mat3(cLightMatrices[0][0].xyz, cLightMatrices[0][1].xyz, cLightMatrices[0][2].xyz);
         #endif
     #else
         // Ambient & per-vertex lighting

+ 15 - 6
Data/AtomicPlayer/Resources/CoreData/Shaders/GLSL/LitSolid.glsl

@@ -13,6 +13,9 @@
 #endif
 varying vec3 vNormal;
 varying vec4 vWorldPos;
+#ifdef VERTEXCOLOR
+    varying vec4 vColor;
+#endif
 #ifdef PERPIXEL
     #ifdef SHADOW
         varying vec4 vShadowPos[NUMCASCADES];
@@ -42,6 +45,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;
@@ -63,11 +70,11 @@ void VS()
 
         #ifdef SPOTLIGHT
             // Spotlight projection: transform from world space to projector texture coordinates
-            vSpotPos = cLightMatrices[0] * projWorldPos;
+            vSpotPos =  projWorldPos * cLightMatrices[0];
         #endif
     
         #ifdef POINTLIGHT
-            vCubeMaskVec = mat3(cLightMatrices[0][0].xyz, cLightMatrices[0][1].xyz, cLightMatrices[0][2].xyz) * (worldPos - cLightPos.xyz);
+            vCubeMaskVec = (worldPos - cLightPos.xyz) * mat3(cLightMatrices[0][0].xyz, cLightMatrices[0][1].xyz, cLightMatrices[0][2].xyz);
         #endif
     #else
         // Ambient & per-vertex lighting
@@ -75,7 +82,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 = GetLightMapTexCoord(iTexCoord2);
+            vTexCoord2 = iTexCoord2;
         #else
             vVertexLight = GetAmbient(GetZonePos(worldPos));
         #endif
@@ -106,6 +113,10 @@ void PS()
     #else
         vec4 diffColor = cMatDiffColor;
     #endif
+
+    #ifdef VERTEXCOLOR
+        diffColor *= vColor;
+    #endif
     
     // Get material specular albedo
     #ifdef SPECMAP
@@ -217,9 +228,7 @@ void PS()
             finalColor += cMatEnvMapColor * textureCube(sEnvCubeMap, reflect(vReflectionVec, normal)).rgb;
         #endif
         #ifdef LIGHTMAP
-            // Lightmap with HDR encoded in alpha
-            vec4 lightMapColor = texture2D(sEmissiveMap, vTexCoord2);
-            finalColor += lightMapColor.rgb * lightMapColor.a * 8.0 * diffColor.rgb;
+            finalColor += texture2D(sEmissiveMap, vTexCoord2).rgb * diffColor.rgb;
         #endif
         #ifdef EMISSIVEMAP
             finalColor += cMatEmissiveColor * texture2D(sEmissiveMap, vTexCoord.xy).rgb;

+ 0 - 8
Data/AtomicPlayer/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;
@@ -70,7 +64,6 @@ vec3 Uncharted2Tonemap(vec3 x)
    return ((x*(A*x+C*B)+D*E)/(x*(A*x+B)+D*F))-E/F;
 }
 
-#if !defined(GL_ES)
 vec3 ColorCorrection(vec3 color, sampler3D lut)
 {
     float lutSize = 16.0;
@@ -78,7 +71,6 @@ vec3 ColorCorrection(vec3 color, sampler3D lut)
     float offset = 1.0 / (2.0 * lutSize);
     return texture3D(lut, clamp(color, 0.0, 1.0) * scale + offset).rgb;
 }
-#endif
 
 const float Gamma = 2.2;
 const float InverseGamma = 1.0 / 2.2;

+ 2 - 2
Data/AtomicPlayer/Resources/CoreData/Shaders/GLSL/PrepassLight.glsl

@@ -76,11 +76,11 @@ void PS()
     #endif
     
     #if defined(SPOTLIGHT)
-        vec4 spotPos = cLightMatricesPS[0] * projWorldPos;
+        vec4 spotPos = projWorldPos * cLightMatricesPS[0];
         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);
-        lightColor = textureCube(sLightCubeMap, lightVecRot * (worldPos - cLightPosPS.xyz)).rgb * cLightColor.rgb;
+        lightColor = textureCube(sLightCubeMap, (worldPos - cLightPosPS.xyz) * lightVecRot).rgb * cLightColor.rgb;
     #else
         lightColor = cLightColor.rgb;
     #endif

+ 27 - 10
Data/AtomicPlayer/Resources/CoreData/Shaders/GLSL/Samplers.glsl

@@ -24,6 +24,13 @@ uniform samplerCube sLightCubeMap;
     uniform sampler2D sShadowMap;
 #endif
 
+#ifdef GL3
+#define texture2D texture
+#define texture2DProj textureProj
+#define texture3D texture
+#define textureCube texture
+#endif
+
 vec3 DecodeNormal(vec4 normalInput)
 {
     #ifdef PACKEDNORMAL
@@ -38,20 +45,30 @@ vec3 DecodeNormal(vec4 normalInput)
 
 vec3 EncodeDepth(float depth)
 {
-    vec3 ret;
-    depth *= 255.0;
-    ret.x = floor(depth);
-    depth = (depth - ret.x) * 255.0;
-    ret.y = floor(depth);
-    ret.z = (depth - ret.y);
-    ret.xy *= 1.0 / 255.0;
-    return ret;
+    #ifndef GL3
+        vec3 ret;
+        depth *= 255.0;
+        ret.x = floor(depth);
+        depth = (depth - ret.x) * 255.0;
+        ret.y = floor(depth);
+        ret.z = (depth - ret.y);
+        ret.xy *= 1.0 / 255.0;
+        return ret;
+    #else
+        // OpenGL 3 can use different MRT formats, so no need for encoding
+        return vec3(depth, 0.0, 0.0);
+    #endif
 }
 
 float DecodeDepth(vec3 depth)
 {
-    const vec3 dotValues = vec3(1.0, 1.0 / 255.0, 1.0 / (255.0 * 255.0));
-    return dot(depth, dotValues);
+    #ifndef GL3
+        const vec3 dotValues = vec3(1.0, 1.0 / 255.0, 1.0 / (255.0 * 255.0));
+        return dot(depth, dotValues);
+    #else
+        // OpenGL 3 can use different MRT formats, so no need for encoding
+        return depth.r;
+    #endif
 }
 
 float ReconstructDepth(float hwDepth)

+ 2 - 2
Data/AtomicPlayer/Resources/CoreData/Shaders/GLSL/ScreenPos.glsl

@@ -36,7 +36,7 @@ vec3 GetFarRay(vec4 clipPos)
         clipPos.y / clipPos.w * cFrustumSize.y,
         cFrustumSize.z);
 
-    return cCameraRot * viewRay;
+    return viewRay * cCameraRot;
 }
 
 vec3 GetNearRay(vec4 clipPos)
@@ -46,6 +46,6 @@ vec3 GetNearRay(vec4 clipPos)
         clipPos.y / clipPos.w * cFrustumSize.y,
         0.0);
     
-    return (cCameraRot * viewRay) * cDepthMode.x;
+    return (viewRay * cCameraRot) * cDepthMode.x;
 }
 #endif

+ 2 - 2
Data/AtomicPlayer/Resources/CoreData/Shaders/GLSL/Shadow.glsl

@@ -69,11 +69,11 @@ void VS()
 
         #ifdef SPOTLIGHT
             // Spotlight projection: transform from world space to projector texture coordinates
-            vSpotPos = cLightMatrices[0] * projWorldPos;
+            vSpotPos = projWorldPos * cLightMatrices[0];
         #endif
     
         #ifdef POINTLIGHT
-            vCubeMaskVec = mat3(cLightMatrices[0][0].xyz, cLightMatrices[0][1].xyz, cLightMatrices[0][2].xyz) * (worldPos - cLightPos.xyz);
+            vCubeMaskVec = (worldPos - cLightPos.xyz) * mat3(cLightMatrices[0][0].xyz, cLightMatrices[0][1].xyz, cLightMatrices[0][2].xyz);
         #endif
     #else
         // Ambient & per-vertex lighting

+ 6 - 1
Data/AtomicPlayer/Resources/CoreData/Shaders/GLSL/Text.glsl

@@ -54,6 +54,11 @@ void PS()
         gl_FragColor.a = vColor.a * smoothstep(0.5, 0.505, distance);
     }
 #else
-    gl_FragColor.a = vColor.a * texture2D(sDiffMap, vTexCoord).a;
+    // Non-SDF font will likely be monochrome, in which case the alpha channel will be on the R channel on OpenGL 3
+    #ifdef GL3
+        gl_FragColor.a = vColor.a * texture2D(sDiffMap, vTexCoord).r;
+    #else
+        gl_FragColor.a = vColor.a * texture2D(sDiffMap, vTexCoord).a;
+    #endif
 #endif
 }

+ 43 - 28
Data/AtomicPlayer/Resources/CoreData/Shaders/GLSL/Tonemap.glsl

@@ -1,4 +1,11 @@
 #ifdef COMPILEVS
+
+// Silence GLSL 150 deprecation warnings
+#ifdef GL3
+#define attribute in
+#define varying out
+#endif
+
 attribute vec4 iPos;
 attribute vec3 iNormal;
 attribute vec4 iColor;
@@ -45,24 +52,21 @@ vec2 GetTexCoord(vec2 texCoord)
     return vec2(dot(texCoord, cUOffset.xy) + cUOffset.w, dot(texCoord, cVOffset.xy) + cVOffset.w);
 }
 
-vec2 GetLightMapTexCoord(vec2 texCoord)
-{
-    return vec2(texCoord.x * cLMOffset.x + cLMOffset.z, texCoord.y * cLMOffset.y + cLMOffset.w);
-}
-
 vec4 GetClipPos(vec3 worldPos)
 {
-    vec4 ret = cViewProj * vec4(worldPos, 1.0);
+    vec4 ret = vec4(worldPos, 1.0) * cViewProj;
     // While getting the clip coordinate, also automatically set gl_ClipVertex for user clip planes
-    #ifndef GL_ES
-    gl_ClipVertex = ret;
+    #if !defined(GL_ES) && !defined(GL3)
+        gl_ClipVertex = ret;
+    #elif defined(GL3)
+        gl_ClipDistance[0] = dot(cClipPlane, ret);
     #endif
     return ret;
 }
 
 float GetZonePos(vec3 worldPos)
 {
-    return clamp((cZone * vec4(worldPos, 1.0)).z, 0.0, 1.0);
+    return clamp((vec4(worldPos, 1.0) * cZone).z, 0.0, 1.0);
 }
 
 float GetDepth(vec4 clipPos)
@@ -70,18 +74,18 @@ float GetDepth(vec4 clipPos)
     return dot(clipPos.zw, cDepthMode.zw);
 }
 
+#ifdef BILLBOARD
 vec3 GetBillboardPos(vec4 iPos, vec2 iSize, mat4 modelMatrix)
 {
-    return (modelMatrix * iPos).xyz + cBillboardRot * vec3(iSize.x, iSize.y, 0.0);
+    return (iPos * modelMatrix).xyz + vec3(iSize.x, iSize.y, 0.0) * cBillboardRot;
 }
 
 vec3 GetBillboardNormal()
 {
-    return vec3(-cBillboardRot[2][0], -cBillboardRot[2][1], -cBillboardRot[2][2]);
+    return vec3(-cBillboardRot[0][2], -cBillboardRot[1][2], -cBillboardRot[2][2]);
 }
+#endif
 
-// Note: the skinning/instancing model matrix is a transpose, so the matrix multiply order must be swapped
-// (see GetWorldPos(), GetWorldNormal() and GetWorldTangent() below)
 #if defined(SKINNED)
     #define iModelMatrix GetSkinMatrix(iBlendWeights, iBlendIndices)
 #elif defined(INSTANCED)
@@ -92,33 +96,44 @@ vec3 GetBillboardNormal()
 
 vec3 GetWorldPos(mat4 modelMatrix)
 {
-    #if defined(SKINNED) || defined(INSTANCED)
-        return (iPos * modelMatrix).xyz;
-    #elif defined(BILLBOARD)
+    #if defined(BILLBOARD)
         return GetBillboardPos(iPos, iTexCoord2, modelMatrix);
     #else
-        return (modelMatrix * iPos).xyz;
+        return (iPos * modelMatrix).xyz;
     #endif
 }
 
 vec3 GetWorldNormal(mat4 modelMatrix)
 {
-    #if defined(SKINNED) || defined(INSTANCED)
-        return normalize(iNormal * GetNormalMatrix(modelMatrix));
-    #elif defined(BILLBOARD)
+    #if defined(BILLBOARD)
         return GetBillboardNormal();
     #else
-        return normalize(GetNormalMatrix(modelMatrix) * iNormal);
+        return normalize(iNormal * GetNormalMatrix(modelMatrix));
     #endif
 }
 
 vec3 GetWorldTangent(mat4 modelMatrix)
-{   
-    mat3 normalMatrix = GetNormalMatrix(modelMatrix);
-    #if defined(SKINNED) || defined(INSTANCED)
-        return normalize(iTangent.xyz * normalMatrix);
-    #else
-        return normalize(normalMatrix * iTangent.xyz);
-    #endif
+{
+    return normalize(iTangent.xyz * GetNormalMatrix(modelMatrix));
 }
+
+#else
+
+// Silence GLSL 150 deprecation warnings
+#ifdef GL3
+#define varying in
+
+// \todo: should not hardcode the number of MRT outputs according to defines
+#if defined(DEFERRED)
+out vec4 fragData[4];
+#elif defined(PREPASS)
+out vec4 fragData[2];
+#else
+out vec4 fragData[1];
 #endif
+
+#define gl_FragColor fragData[0]
+#define gl_FragData fragData
+#endif
+
+#endif

+ 132 - 6
Data/AtomicPlayer/Resources/CoreData/Shaders/GLSL/Uniforms.glsl

@@ -1,4 +1,13 @@
+// Use of constant buffers on OpenGL 3 commented out for now as it seems to be slower in practice
+//#define USE_CBUFFERS
+
+#if !defined(GL3) || !defined(USE_CBUFFERS)
+
+// OpenGL 2 uniforms (no constant buffers)
+
 #ifdef COMPILEVS
+          
+// Vertex shader uniforms
 uniform vec3 cAmbientStartColor;
 uniform vec3 cAmbientEndColor;
 uniform mat3 cBillboardRot;
@@ -17,7 +26,6 @@ uniform mat4 cModel;
 uniform mat4 cViewProj;
 uniform vec4 cUOffset;
 uniform vec4 cVOffset;
-uniform vec4 cLMOffset;
 uniform mat4 cZone;
 #if !defined(GL_ES) || defined(WEBGL)
     uniform mat4 cLightMatrices[4];
@@ -25,18 +33,19 @@ uniform mat4 cZone;
     uniform mat4 cLightMatrices[2];
 #endif
 #ifdef SKINNED
-    #ifdef RPI
-        uniform vec4 cSkinMatrices[32*3];
-    #else
-        uniform vec4 cSkinMatrices[64*3];
-    #endif
+    uniform vec4 cSkinMatrices[MAXBONES*3];
 #endif
 #ifdef NUMVERTEXLIGHTS
     uniform vec4 cVertexLights[4*3];
 #endif
+#ifdef GL3
+    uniform vec4 cClipPlane;
+#endif
 #endif
 
 #ifdef COMPILEPS
+
+// Fragment shader uniforms
 #ifdef GL_ES
     precision mediump float;
 #endif
@@ -64,4 +73,121 @@ uniform vec2 cShadowIntensity;
 uniform vec2 cShadowMapInvSize;
 uniform vec4 cShadowSplits;
 uniform mat4 cLightMatricesPS[4];
+
+#endif
+
+#else
+
+// OpenGL 3 uniforms (using constant buffers)
+
+#ifdef COMPILEVS
+
+uniform FrameVS
+{
+    float cDeltaTime;
+    float cElapsedTime;
+};
+
+uniform CameraVS
+{
+    vec3 cCameraPos;
+    mat3 cCameraRot;
+    float cNearClip;
+    float cFarClip;
+    vec4 cDepthMode;
+    vec3 cFrustumSize;
+    vec4 cGBufferOffsets;
+    mat4 cViewProj;
+    vec4 cClipPlane;
+};
+
+uniform ZoneVS
+{
+    vec3 cAmbientStartColor;
+    vec3 cAmbientEndColor;
+    mat4 cZone;
+};
+
+uniform LightVS
+{
+    vec3 cLightDir;
+    vec4 cLightPos;
+#ifdef NUMVERTEXLIGHTS
+    vec4 cVertexLights[4 * 3];
+#else
+    mat4 cLightMatrices[4];
+#endif
+};
+
+#ifndef CUSTOM_MATERIAL_CBUFFER
+uniform MaterialVS
+{
+    vec4 cUOffset;
+    vec4 cVOffset;
+};
+#endif
+
+uniform ObjectVS
+{
+    mat4 cModel;
+#ifdef BILLBOARD
+    mat3 cBillboardRot;
+#endif
+#ifdef SKINNED
+    uniform vec4 cSkinMatrices[MAXBONES*3];
+#endif
+};
+
+#endif
+
+#ifdef COMPILEPS
+
+// Pixel shader uniforms
+uniform FramePS
+{
+    float cDeltaTimePS;
+    float cElapsedTimePS;
+};
+
+uniform CameraPS
+{
+    vec3 cCameraPosPS;
+    vec4 cDepthReconstruct;
+    vec2 cGBufferInvSize;
+    float cNearClipPS;
+    float cFarClipPS;
+};
+
+uniform ZonePS
+{
+    vec3 cAmbientColor;
+    vec4 cFogParams;
+    vec3 cFogColor;
+};
+
+uniform LightPS
+{
+    vec4 cLightColor;
+    vec4 cLightPosPS;
+    vec3 cLightDirPS;
+    vec4 cShadowCubeAdjust;
+    vec4 cShadowDepthFade;
+    vec2 cShadowIntensity;
+    vec2 cShadowMapInvSize;
+    vec4 cShadowSplits;
+    mat4 cLightMatricesPS[4];
+};
+
+#ifndef CUSTOM_MATERIAL_CBUFFER
+uniform MaterialPS
+{
+    vec4 cMatDiffColor;
+    vec3 cMatEmissiveColor;
+    vec3 cMatEnvMapColor;
+    vec4 cMatSpecColor;
+};
+#endif
+
+#endif
+
 #endif

+ 3 - 3
Data/AtomicPlayer/Resources/CoreData/Shaders/GLSL/Unlit.glsl

@@ -41,7 +41,7 @@ void VS()
 {
     mat4 modelMatrix = iModelMatrix;
     vec3 worldPos = GetWorldPos(modelMatrix);
-    float height = worldPos.y - cModel[3][1];
+    float height = worldPos.y - cModel[1][3];
 
     float windStrength = max(height - cWindHeightPivot, 0.0) * cWindHeightFactor;
     float windPeriod = cElapsedTime * cWindPeriod + dot(worldPos.xz, cWindWorldSpacing);
@@ -73,11 +73,11 @@ void VS()
 
         #ifdef SPOTLIGHT
             // Spotlight projection: transform from world space to projector texture coordinates
-            vSpotPos = cLightMatrices[0] * projWorldPos;
+            vSpotPos = projWorldPos * cLightMatrices[0];
         #endif
     
         #ifdef POINTLIGHT
-            vCubeMaskVec = mat3(cLightMatrices[0][0].xyz, cLightMatrices[0][1].xyz, cLightMatrices[0][2].xyz) * (worldPos - cLightPos.xyz);
+            vCubeMaskVec = (worldPos - cLightPos.xyz) * mat3(cLightMatrices[0][0].xyz, cLightMatrices[0][1].xyz, cLightMatrices[0][2].xyz);
         #endif
     #else
         // Ambient & per-vertex lighting

+ 3 - 3
Data/AtomicPlayer/Resources/CoreData/Shaders/GLSL/VegetationDepth.glsl

@@ -7,7 +7,7 @@ void VS(float4 iPos : POSITION,
     float4 iColor : COLOR0,
     out float4 oColor : COLOR0,
     out float2 oTexCoord : TEXCOORD0,
-    out float4 oPos : POSITION)
+    out float4 oPos : OUTPOSITION)
 {
     float4x3 modelMatrix = iModelMatrix;
     float3 worldPos = GetWorldPos(modelMatrix);
@@ -19,9 +19,9 @@ void VS(float4 iPos : POSITION,
 
 void PS(float4 iColor : COLOR0,
         float2 iTexCoord : TEXCOORD0,
-        out float4 oColor : COLOR0)
+        out float4 oColor : OUTCOLOR0)
 {
     float4 diffColor = cMatDiffColor * iColor;
-    float4 diffInput = tex2D(sDiffMap, iTexCoord);
+    float4 diffInput = Sample2D(DiffMap, iTexCoord);
     oColor = diffColor * diffInput;
 }

+ 34 - 11
Data/AtomicPlayer/Resources/CoreData/Shaders/HLSL/AutoExposure.hlsl

@@ -16,20 +16,31 @@ uniform float2 cLum64InvSize;
 uniform float2 cLum16InvSize;
 uniform float2 cLum4InvSize;
 
+#ifndef D3D11
 float GatherAvgLum(sampler2D texSampler, float2 texCoord, float2 texelSize)
+#else
+float GatherAvgLum(Texture2D tex, SamplerState texSampler, float2 texCoord, float2 texelSize)
+#endif
 {
     float lumAvg = 0.0;
+    #ifndef D3D11
     lumAvg += tex2D(texSampler, texCoord + float2(0.0, 0.0) * texelSize).r;
     lumAvg += tex2D(texSampler, texCoord + float2(0.0, 2.0) * texelSize).r;
     lumAvg += tex2D(texSampler, texCoord + float2(2.0, 2.0) * texelSize).r;
     lumAvg += tex2D(texSampler, texCoord + float2(2.0, 0.0) * texelSize).r;
+    #else
+    lumAvg += tex.Sample(texSampler, texCoord + float2(0.0, 0.0) * texelSize).r;
+    lumAvg += tex.Sample(texSampler, texCoord + float2(0.0, 2.0) * texelSize).r;
+    lumAvg += tex.Sample(texSampler, texCoord + float2(2.0, 2.0) * texelSize).r;
+    lumAvg += tex.Sample(texSampler, texCoord + float2(2.0, 0.0) * texelSize).r;
+    #endif
     return lumAvg / 4.0;
 }
 
 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);
@@ -58,38 +69,50 @@ void VS(float4 iPos : POSITION,
 
 void PS(float2 iTexCoord : TEXCOORD0,
     float2 iScreenPos : TEXCOORD1,
-    out float4 oColor : COLOR0)
+    out float4 oColor : OUTCOLOR0)
 {
     #ifdef LUMINANCE64
     float logLumSum = 0.0;
-    logLumSum += log(dot(tex2D(sDiffMap, iTexCoord + float2(0.0, 0.0) * cHDR128InvSize).rgb, LumWeights) + 1e-5);
-    logLumSum += log(dot(tex2D(sDiffMap, iTexCoord + float2(0.0, 2.0) * cHDR128InvSize).rgb, LumWeights) + 1e-5);
-    logLumSum += log(dot(tex2D(sDiffMap, iTexCoord + float2(2.0, 2.0) * cHDR128InvSize).rgb, LumWeights) + 1e-5);
-    logLumSum += log(dot(tex2D(sDiffMap, iTexCoord + float2(2.0, 0.0) * cHDR128InvSize).rgb, LumWeights) + 1e-5);
+    logLumSum += log(dot(Sample2D(DiffMap, iTexCoord + float2(0.0, 0.0) * cHDR128InvSize).rgb, LumWeights) + 1e-5);
+    logLumSum += log(dot(Sample2D(DiffMap, iTexCoord + float2(0.0, 2.0) * cHDR128InvSize).rgb, LumWeights) + 1e-5);
+    logLumSum += log(dot(Sample2D(DiffMap, iTexCoord + float2(2.0, 2.0) * cHDR128InvSize).rgb, LumWeights) + 1e-5);
+    logLumSum += log(dot(Sample2D(DiffMap, iTexCoord + float2(2.0, 0.0) * cHDR128InvSize).rgb, LumWeights) + 1e-5);
     oColor = logLumSum;
     #endif
 
     #ifdef LUMINANCE16
+    #ifndef D3D11
     oColor = GatherAvgLum(sDiffMap, iTexCoord, cLum64InvSize);
+    #else
+    oColor = GatherAvgLum(tDiffMap, sDiffMap, iTexCoord, cLum64InvSize);
+    #endif
     #endif
 
     #ifdef LUMINANCE4
+    #ifndef D3D11
     oColor = GatherAvgLum(sDiffMap, iTexCoord, cLum16InvSize);
+    #else
+    oColor = GatherAvgLum(tDiffMap, sDiffMap, iTexCoord, cLum16InvSize);
+    #endif
     #endif
 
     #ifdef LUMINANCE1
+    #ifndef D3D11
     oColor = exp(GatherAvgLum(sDiffMap, iTexCoord, cLum4InvSize) / 16.0);
+    #else
+    oColor = exp(GatherAvgLum(tDiffMap, sDiffMap, iTexCoord, cLum4InvSize) / 16.0);
+    #endif
     #endif
 
     #ifdef ADAPTLUMINANCE
-    float adaptedLum = tex2D(sDiffMap, iTexCoord).r;
-    float lum = clamp(tex2D(sNormalMap, iTexCoord).r, cAutoExposureLumRange.x, cAutoExposureLumRange.y);
+    float adaptedLum = Sample2D(DiffMap, iTexCoord).r;
+    float lum = clamp(Sample2D(NormalMap, iTexCoord).r, cAutoExposureLumRange.x, cAutoExposureLumRange.y);
     oColor = adaptedLum + (lum - adaptedLum) * (1.0 - exp(-cDeltaTimePS * cAutoExposureAdaptRate));
     #endif
 
     #ifdef EXPOSE
-    float3 color = tex2D(sDiffMap, iScreenPos).rgb;
-    float adaptedLum = tex2D(sNormalMap, iTexCoord).r;
+    float3 color = Sample2D(DiffMap, iScreenPos).rgb;
+    float adaptedLum = Sample2D(NormalMap, iTexCoord).r;
     oColor = float4(color * (cAutoExposureMiddleGrey / adaptedLum), 1.0);
     #endif
 }

+ 14 - 4
Data/AtomicPlayer/Resources/CoreData/Shaders/HLSL/Basic.hlsl

@@ -23,12 +23,19 @@ void VS(float4 iPos : POSITION,
     #ifdef DIFFMAP
         out float2 oTexCoord : TEXCOORD0,
     #endif
-    out float4 oPos : POSITION)
+    #if defined(D3D11) && defined(CLIPPLANE)
+        out float oClip : SV_CLIPDISTANCE0,
+    #endif
+    out float4 oPos : OUTPOSITION)
 {
     float4x3 modelMatrix = iModelMatrix;
     float3 worldPos = GetWorldPos(modelMatrix);
     oPos = GetClipPos(worldPos);
 
+    #if defined(D3D11) && defined(CLIPPLANE)
+        oClip = dot(oPos, cClipPlane);
+    #endif
+
     #ifdef VERTEXCOLOR
         oColor = iColor;
     #endif
@@ -44,7 +51,10 @@ void PS(
     #if defined(DIFFMAP) || defined(ALPHAMAP)
         float2 iTexCoord : TEXCOORD0,
     #endif
-    out float4 oColor : COLOR0)
+    #if defined(D3D11) && defined(CLIPPLANE)
+        float iClip : SV_CLIPDISTANCE0,
+    #endif    
+    out float4 oColor : OUTCOLOR0)
 {
     float4 diffColor = cMatDiffColor;
 
@@ -56,7 +66,7 @@ void PS(
         oColor = diffColor;
     #endif
     #ifdef DIFFMAP
-        float4 diffInput = tex2D(sDiffMap, iTexCoord);
+        float4 diffInput = Sample2D(DiffMap, iTexCoord);
         #ifdef ALPHAMASK
             if (diffInput.a < 0.5)
                 discard;
@@ -64,7 +74,7 @@ void PS(
         oColor = diffColor * diffInput;
     #endif
     #ifdef ALPHAMAP
-        float alphaInput = tex2D(sDiffMap, iTexCoord).a;
+        float alphaInput = Sample2D(DiffMap, iTexCoord).a;
         oColor = float4(diffColor.rgb, diffColor.a * alphaInput);
     #endif
 }

+ 30 - 8
Data/AtomicPlayer/Resources/CoreData/Shaders/HLSL/Bloom.hlsl

@@ -3,11 +3,33 @@
 #include "Samplers.hlsl"
 #include "ScreenPos.hlsl"
 
+#ifndef D3D11
+
+// D3D9 uniforms
 uniform float cBloomThreshold;
 uniform float2 cBloomMix;
 uniform float2 cHBlurOffsets;
 uniform float2 cHBlurInvSize;
 
+#else
+
+// D3D11 constant buffers
+#ifdef COMPILEVS
+cbuffer CustomVS : register(b6)
+{
+    float2 cHBlurOffsets;
+}
+#else
+cbuffer CustomPS : register(b6)
+{
+    float cBloomThreshold;
+    float2 cBloomMix;
+    float2 cHBlurInvSize;
+}
+#endif
+
+#endif
+
 static const float offsets[5] = {
     2.0,
     1.0,
@@ -25,9 +47,9 @@ static const float weights[5] = {
 };
 
 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);
@@ -38,30 +60,30 @@ void VS(float4 iPos : POSITION,
 
 void PS(float2 iTexCoord : TEXCOORD0,
     float2 iScreenPos : TEXCOORD1,
-    out float4 oColor : COLOR0)
+    out float4 oColor : OUTCOLOR0)
 {
     #ifdef BRIGHT
-    float3 rgb = tex2D(sDiffMap, iScreenPos).rgb;
+    float3 rgb = Sample2D(DiffMap, iScreenPos).rgb;
     oColor = float4((rgb - cBloomThreshold) / (1.0 - cBloomThreshold), 1.0);
     #endif
 
     #ifdef HBLUR
     float3 rgb = 0.0;
     for (int i = 0; i < 5; ++i)
-        rgb += tex2D(sDiffMap, iTexCoord + (float2(offsets[i], 0.0)) * cHBlurInvSize).rgb * weights[i];
+        rgb += Sample2D(DiffMap, iTexCoord + (float2(offsets[i], 0.0)) * cHBlurInvSize).rgb * weights[i];
     oColor = float4(rgb, 1.0);
     #endif
 
     #ifdef VBLUR
     float3 rgb = 0.0;
     for (int i = 0; i < 5; ++i)
-        rgb += tex2D(sDiffMap, iTexCoord + (float2(0.0, offsets[i])) * cHBlurInvSize).rgb * weights[i];
+        rgb += Sample2D(DiffMap, iTexCoord + (float2(0.0, offsets[i])) * cHBlurInvSize).rgb * weights[i];
     oColor = float4(rgb, 1.0);
     #endif
 
     #ifdef COMBINE
-    float3 original = tex2D(sDiffMap, iScreenPos).rgb * cBloomMix.x;
-    float3 bloom = tex2D(sNormalMap, iTexCoord).rgb  * cBloomMix.y;
+    float3 original = Sample2D(DiffMap, iScreenPos).rgb * cBloomMix.x;
+    float3 bloom = Sample2D(NormalMap, iTexCoord).rgb  * cBloomMix.y;
     // Prevent oversaturation
     original *= saturate(1.0 - bloom);
     oColor = float4(original + bloom, 1.0);

+ 62 - 9
Data/AtomicPlayer/Resources/CoreData/Shaders/HLSL/BloomHDR.hlsl

@@ -4,6 +4,9 @@
 #include "ScreenPos.hlsl"
 #include "PostProcess.hlsl"
 
+#ifndef D3D11
+
+// D3D9 uniforms
 uniform float cBloomHDRThreshold;
 uniform float2 cBloomHDRBlurDir;
 uniform float cBloomHDRBlurRadius;
@@ -18,12 +21,40 @@ uniform float2 cBright4InvSize;
 uniform float2 cBright8InvSize;
 uniform float2 cBright16InvSize;
 
+#else
+
+// D3D11 constant buffers
+#ifdef COMPILEVS
+cbuffer CustomVS : register(b6)
+{
+    float2 cBright2Offsets;
+    float2 cBright4Offsets;
+    float2 cBright8Offsets;
+    float2 cBright16Offsets;
+}
+#else
+cbuffer CustomPS : register(b6)
+{
+    float cBloomHDRThreshold;
+    float2 cBloomHDRBlurDir;
+    float cBloomHDRBlurRadius;
+    float cBloomHDRBlurSigma;
+    float2 cBloomHDRMix;
+    float2 cBright2InvSize;
+    float2 cBright4InvSize;
+    float2 cBright8InvSize;
+    float2 cBright16InvSize;
+}
+#endif
+
+#endif
+
 static const int BlurKernelSize = 5;
 
 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);
@@ -68,13 +99,15 @@ void VS(float4 iPos : POSITION,
 
 void PS(float2 iTexCoord : TEXCOORD0,
     float2 iScreenPos : TEXCOORD1,
-    out float4 oColor : COLOR0)
+    out float4 oColor : OUTCOLOR0)
 {
     #ifdef BRIGHT
-    float3 color = tex2D(sDiffMap, iScreenPos).rgb;
+    float3 color = Sample2D(DiffMap, iScreenPos).rgb;
     oColor = float4(max(color - cBloomHDRThreshold, 0.0), 1.0);
     #endif
 
+    #ifndef D3D11
+
     #ifdef BLUR16
     oColor = GaussianBlur(BlurKernelSize, cBloomHDRBlurDir, cBright16InvSize * cBloomHDRBlurRadius, cBloomHDRBlurSigma, sDiffMap, iTexCoord);
     #endif
@@ -90,22 +123,42 @@ void PS(float2 iTexCoord : TEXCOORD0,
     #ifdef BLUR2
     oColor = GaussianBlur(BlurKernelSize, cBloomHDRBlurDir, cBright2InvSize * cBloomHDRBlurRadius, cBloomHDRBlurSigma, sDiffMap, iTexCoord);
     #endif
+    
+    #else
+
+    #ifdef BLUR16
+    oColor = GaussianBlur(BlurKernelSize, cBloomHDRBlurDir, cBright16InvSize * cBloomHDRBlurRadius, cBloomHDRBlurSigma, tDiffMap, sDiffMap, iTexCoord);
+    #endif
+
+    #ifdef BLUR8
+    oColor = GaussianBlur(BlurKernelSize, cBloomHDRBlurDir, cBright8InvSize * cBloomHDRBlurRadius, cBloomHDRBlurSigma, tDiffMap, sDiffMap, iTexCoord);
+    #endif
+
+    #ifdef BLUR4
+    oColor = GaussianBlur(BlurKernelSize, cBloomHDRBlurDir, cBright4InvSize * cBloomHDRBlurRadius, cBloomHDRBlurSigma, tDiffMap, sDiffMap, iTexCoord);
+    #endif
+
+    #ifdef BLUR2
+    oColor = GaussianBlur(BlurKernelSize, cBloomHDRBlurDir, cBright2InvSize * cBloomHDRBlurRadius, cBloomHDRBlurSigma, tDiffMap, sDiffMap, iTexCoord);
+    #endif
+    
+    #endif
 
     #ifdef COMBINE16
-    oColor = tex2D(sDiffMap, iScreenPos) + tex2D(sNormalMap, iTexCoord);
+    oColor = Sample2D(DiffMap, iScreenPos) + Sample2D(NormalMap, iTexCoord);
     #endif
 
     #ifdef COMBINE8
-    oColor = tex2D(sDiffMap, iScreenPos) + tex2D(sNormalMap, iTexCoord);
+    oColor = Sample2D(DiffMap, iScreenPos) + Sample2D(NormalMap, iTexCoord);
     #endif
 
     #ifdef COMBINE4
-    oColor = tex2D(sDiffMap, iScreenPos) + tex2D(sNormalMap, iTexCoord);
+    oColor = Sample2D(DiffMap, iScreenPos) + Sample2D(NormalMap, iTexCoord);
     #endif
 
     #ifdef COMBINE2
-    float3 color = tex2D(sDiffMap, iScreenPos).rgb * cBloomHDRMix.x;
-    float3 bloom = tex2D(sNormalMap, iTexCoord).rgb * cBloomHDRMix.y;
+    float3 color = Sample2D(DiffMap, iScreenPos).rgb * cBloomHDRMix.x;
+    float3 bloom = Sample2D(NormalMap, iTexCoord).rgb * cBloomHDRMix.y;
     oColor = float4(color + bloom, 1.0);
     #endif
 }

+ 21 - 1
Data/AtomicPlayer/Resources/CoreData/Shaders/HLSL/Blur.hlsl

@@ -24,8 +24,10 @@ void VS(float4 iPos : POSITION,
 
 void PS(float2 iTexCoord : TEXCOORD0,
     float2 iScreenPos : TEXCOORD1,
-    out float4 oColor : COLOR0)
+    out float4 oColor : OUTCOLOR0)
 {
+
+#ifndef D3D11
     #ifdef BLUR3
         oColor = GaussianBlur(3, cBlurDir, cBlurHInvSize * cBlurRadius, cBlurSigma, sDiffMap, iTexCoord);
     #endif
@@ -41,4 +43,22 @@ void PS(float2 iTexCoord : TEXCOORD0,
     #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);
+    #endif
+
+    #ifdef BLUR5
+        oColor = GaussianBlur(5, cBlurDir, cBlurHInvSize * cBlurRadius, cBlurSigma, tDiffMap, sDiffMap, iTexCoord);
+    #endif
+
+    #ifdef BLUR7
+        oColor = GaussianBlur(7, cBlurDir, cBlurHInvSize * cBlurRadius, cBlurSigma, tDiffmap, sDiffMap, iTexCoord);
+    #endif
+
+    #ifdef BLUR9
+        oColor = GaussianBlur(9, cBlurDir, cBlurHInvSize * cBlurRadius, cBlurSigma, tDiffMap, sDiffMap, iTexCoord);
+    #endif
+#endif
 }

+ 17 - 0
Data/AtomicPlayer/Resources/CoreData/Shaders/HLSL/ClearFramebuffer.hlsl

@@ -0,0 +1,17 @@
+#include "Uniforms.hlsl"
+#include "Samplers.hlsl"
+#include "Transform.hlsl"
+#include "ScreenPos.hlsl"
+
+void VS(float4 iPos : POSITION,
+    out float4 oPos : OUTPOSITION)
+{
+    float4x3 modelMatrix = iModelMatrix;
+    float3 worldPos = GetWorldPos(modelMatrix);
+    oPos = GetClipPos(worldPos);
+}
+
+void PS(out float4 oColor : OUTCOLOR0)
+{
+    oColor = cMatDiffColor;
+}

+ 9 - 5
Data/AtomicPlayer/Resources/CoreData/Shaders/HLSL/ColorCorrection.hlsl

@@ -5,8 +5,8 @@
 #include "PostProcess.hlsl"
 
 void VS(float4 iPos : POSITION,
-    out float4 oPos : POSITION,
-    out float2 oScreenPos : TEXCOORD0)
+    out float2 oScreenPos : TEXCOORD0,
+    out float4 oPos : OUTPOSITION)
 {
     float4x3 modelMatrix = iModelMatrix;
     float3 worldPos = GetWorldPos(modelMatrix);
@@ -15,8 +15,12 @@ void VS(float4 iPos : POSITION,
 }
 
 void PS(float2 iScreenPos : TEXCOORD0,
-    out float4 oColor : COLOR0)
+    out float4 oColor : OUTCOLOR0)
 {
-    float3 color = tex2D(sDiffMap, iScreenPos).rgb;
-    oColor = float4(ColorCorrection(color, sVolumeMap), 1.0);
+    float3 color = Sample2D(DiffMap, iScreenPos).rgb;
+    #ifndef D3D11
+        oColor = float4(ColorCorrection(color, sVolumeMap), 1.0);
+    #else
+        oColor = float4(ColorCorrection(color, tVolumeMap, sVolumeMap), 1.0);
+    #endif
 }

+ 3 - 3
Data/AtomicPlayer/Resources/CoreData/Shaders/HLSL/CopyFramebuffer.hlsl

@@ -5,7 +5,7 @@
 
 void VS(float4 iPos : POSITION,
     out float2 oScreenPos : TEXCOORD0,
-    out float4 oPos : POSITION)
+    out float4 oPos : OUTPOSITION)
 {
     float4x3 modelMatrix = iModelMatrix;
     float3 worldPos = GetWorldPos(modelMatrix);
@@ -14,7 +14,7 @@ void VS(float4 iPos : POSITION,
 }
 
 void PS(float2 iScreenPos : TEXCOORD0,
-    out float4 oColor : COLOR0)
+    out float4 oColor : OUTCOLOR0)
 {
-    oColor = tex2D(sDiffMap, iScreenPos);
+    oColor = Sample2D(DiffMap, iScreenPos);
 }

+ 9 - 9
Data/AtomicPlayer/Resources/CoreData/Shaders/HLSL/DeferredLight.hlsl

@@ -14,7 +14,7 @@ void VS(float4 iPos : POSITION,
     #ifdef ORTHO
         out float3 oNearRay : TEXCOORD2,
     #endif
-    out float4 oPos : POSITION)
+    out float4 oPos : OUTPOSITION)
 {
     float4x3 modelMatrix = iModelMatrix;
     float3 worldPos = GetWorldPos(modelMatrix);
@@ -44,11 +44,11 @@ void PS(
     #ifdef ORTHO
         float3 iNearRay : TEXCOORD2,
     #endif
-    out float4 oColor : COLOR0)
+    out float4 oColor : OUTCOLOR0)
 {
     // If rendering a directional light quad, optimize out the w divide
     #ifdef DIRLIGHT
-        float depth = Sample(sDepthBuffer, iScreenPos).r;
+        float depth = Sample2DLod0(DepthBuffer, iScreenPos).r;
         #ifdef HWDEPTH
             depth = ReconstructDepth(depth);
         #endif
@@ -57,10 +57,10 @@ void PS(
         #else
             float3 worldPos = iFarRay * depth;
         #endif
-        float4 albedoInput = Sample(sAlbedoBuffer, iScreenPos);
-        float4 normalInput = Sample(sNormalBuffer, iScreenPos);
+        float4 albedoInput = Sample2DLod0(AlbedoBuffer, iScreenPos);
+        float4 normalInput = Sample2DLod0(NormalBuffer, iScreenPos);
     #else
-        float depth = tex2Dproj(sDepthBuffer, iScreenPos).r;
+        float depth = Sample2DProj(DepthBuffer, iScreenPos).r;
         #ifdef HWDEPTH
             depth = ReconstructDepth(depth);
         #endif
@@ -69,8 +69,8 @@ void PS(
         #else
             float3 worldPos = iFarRay * depth / iScreenPos.w;
         #endif
-        float4 albedoInput = tex2Dproj(sAlbedoBuffer, iScreenPos);
-        float4 normalInput = tex2Dproj(sNormalBuffer, iScreenPos);
+        float4 albedoInput = Sample2DProj(AlbedoBuffer, iScreenPos);
+        float4 normalInput = Sample2DProj(NormalBuffer, iScreenPos);
     #endif
     
     float3 normal = normalize(normalInput.rgb * 2.0 - 1.0);
@@ -86,7 +86,7 @@ void PS(
 
     #if defined(SPOTLIGHT)
         float4 spotPos = mul(projWorldPos, cLightMatricesPS[0]);
-        lightColor = spotPos.w > 0.0 ? tex2Dproj(sLightSpotMap, spotPos).rgb * cLightColor.rgb : 0.0;
+        lightColor = spotPos.w > 0.0 ? Sample2DProj(LightSpotMap, spotPos).rgb * cLightColor.rgb : 0.0;
     #elif defined(CUBEMASK)
         lightColor = texCUBE(sLightCubeMap, mul(worldPos - cLightPosPS.xyz, (float3x3)cLightMatricesPS[0])).rgb * cLightColor.rgb;
     #else

+ 27 - 12
Data/AtomicPlayer/Resources/CoreData/Shaders/HLSL/Depth.hlsl

@@ -11,11 +11,26 @@
 #include "Transform.hlsl"
 #include "ScreenPos.hlsl"
 
+#ifndef D3D11
+
+// D3D9 uniforms
 uniform float4 cFXAAParams;
 
+#else
+
+// D3D11 constant buffers
+#ifdef COMPILEPS
+cbuffer CustomPS : register(b6)
+{
+    float4 cFXAAParams;
+}
+#endif
+
+#endif
+
 void VS(float4 iPos : POSITION,
-    out float4 oPos : POSITION,
-    out float2 oScreenPos : TEXCOORD0)
+    out float2 oScreenPos : TEXCOORD0,
+    out float4 oPos : OUTPOSITION)
 {
     float4x3 modelMatrix = iModelMatrix;
     float3 worldPos = GetWorldPos(modelMatrix);
@@ -24,7 +39,7 @@ void VS(float4 iPos : POSITION,
 }
 
 void PS(float2 iScreenPos : TEXCOORD0,
-    out float4 oColor : COLOR0)
+    out float4 oColor : OUTCOLOR0)
 {
     float FXAA_SUBPIX_SHIFT = 1.0/4.0; // Not used
     float FXAA_SPAN_MAX = 8.0;
@@ -33,11 +48,11 @@ void PS(float2 iScreenPos : TEXCOORD0,
 
     float2 posOffset = cGBufferInvSize.xy * cFXAAParams.x;
 
-    float3 rgbNW = Sample(sDiffMap, iScreenPos + float2(-posOffset.x, -posOffset.y)).rgb;
-    float3 rgbNE = Sample(sDiffMap, iScreenPos + float2(posOffset.x, -posOffset.y)).rgb;
-    float3 rgbSW = Sample(sDiffMap, iScreenPos + float2(-posOffset.x, posOffset.y)).rgb;
-    float3 rgbSE = Sample(sDiffMap, iScreenPos + float2(posOffset.x, posOffset.y)).rgb;
-    float3 rgbM  = Sample(sDiffMap, iScreenPos).rgb;
+    float3 rgbNW = Sample2DLod0(DiffMap, iScreenPos + float2(-posOffset.x, -posOffset.y)).rgb;
+    float3 rgbNE = Sample2DLod0(DiffMap, iScreenPos + float2(posOffset.x, -posOffset.y)).rgb;
+    float3 rgbSW = Sample2DLod0(DiffMap, iScreenPos + float2(-posOffset.x, posOffset.y)).rgb;
+    float3 rgbSE = Sample2DLod0(DiffMap, iScreenPos + float2(posOffset.x, posOffset.y)).rgb;
+    float3 rgbM  = Sample2DLod0(DiffMap, iScreenPos).rgb;
 
     float3 luma = float3(0.299, 0.587, 0.114);
     float lumaNW = dot(rgbNW, luma);
@@ -66,11 +81,11 @@ void PS(float2 iScreenPos : TEXCOORD0,
         dir *= cFXAAParams.z;
     
         float3 rgbA = (1.0/2.0) * (
-            Sample(sDiffMap, iScreenPos + dir * (1.0/3.0 - 0.5)).xyz +
-            Sample(sDiffMap, iScreenPos + dir * (2.0/3.0 - 0.5)).xyz);
+            Sample2DLod0(DiffMap, iScreenPos + dir * (1.0/3.0 - 0.5)).xyz +
+            Sample2DLod0(DiffMap, iScreenPos + dir * (2.0/3.0 - 0.5)).xyz);
         float3 rgbB = rgbA * (1.0/2.0) + (1.0/4.0) * (
-            Sample(sDiffMap, iScreenPos + dir * (0.0/3.0 - 0.5)).xyz +
-            Sample(sDiffMap, iScreenPos + dir * (3.0/3.0 - 0.5)).xyz);
+            Sample2DLod0(DiffMap, iScreenPos + dir * (0.0/3.0 - 0.5)).xyz +
+            Sample2DLod0(DiffMap, iScreenPos + dir * (3.0/3.0 - 0.5)).xyz);
         float lumaB = dot(rgbB, luma);
         
         float3 rgbOut;

+ 50 - 44
Data/AtomicPlayer/Resources/CoreData/Shaders/HLSL/FXAA3.hlsl

@@ -49,6 +49,7 @@
 #include "Transform.hlsl"
 #include "ScreenPos.hlsl"
 
+#ifdef COMPILEPS
 /*============================================================================
                         FXAA QUALITY - TUNING KNOBS
 ------------------------------------------------------------------------------
@@ -296,10 +297,15 @@ float CalcLuma(float3 rgb)
 
 /*--------------------------------------------------------------------------*/
 
-#define FxaaTexTop(t, p) float4(tex2Dlod(t, float4(p, 0.0, 0.0)).rgb, 1.0)
-
-#define LumaTop(t, p) CalcLuma(tex2Dlod(t, float4(p, 0.0, 0.0)).rgb)
-#define LumaOff(t, p, o, r) CalcLuma(tex2Dlod(t, float4(p + (o * r), 0, 0)).rgb)
+#ifndef D3D11
+#define FxaaTexTop(tex, p) float4(tex2Dlod(s##tex, float4(p, 0.0, 0.0)).rgb, 1.0)
+#define LumaTop(tex, p) CalcLuma(tex2Dlod(s##tex, float4(p, 0.0, 0.0)).rgb)
+#define LumaOff(tex, p, o, r) CalcLuma(tex2Dlod(s##tex, float4(p + (o * r), 0, 0)).rgb)
+#else
+#define FxaaTexTop(tex, p) float4(t##tex.SampleLevel(s##tex, p, 0.0).rgb, 1.0)
+#define LumaTop(tex, p) CalcLuma(t##tex.SampleLevel(s##tex, p, 0.0).rgb)
+#define LumaOff(tex, p, o, r) CalcLuma(t##tex.SampleLevel(s##tex, p + (o * r), 0.0).rgb)
+#endif
 
 /*============================================================================
 
@@ -316,7 +322,7 @@ float4 FxaaPixelShader(
     // {rgb_} = color in linear or perceptual color space
     // if (FXAA_GREEN_AS_LUMA == 0)
     //     {__a} = luma in perceptual color space (not linear)
-    sampler2D tex,
+    //sampler2D tex,
     //
     // Only used on FXAA Quality.
     // This must be from a constant/uniform.
@@ -367,13 +373,13 @@ float4 FxaaPixelShader(
     posM.x = pos.x;
     posM.y = pos.y;
     
-    float4 rgbyM = FxaaTexTop(tex, posM);
+    float4 rgbyM = FxaaTexTop(DiffMap, posM);
     rgbyM.y = CalcLuma(rgbyM.rgb);
     #define lumaM rgbyM.y
-    float lumaS = LumaOff(tex, posM, float2( 0, 1), fxaaQualityRcpFrame.xy);
-    float lumaE = LumaOff(tex, posM, float2( 1, 0), fxaaQualityRcpFrame.xy);
-    float lumaN = LumaOff(tex, posM, float2( 0,-1), fxaaQualityRcpFrame.xy);
-    float lumaW = LumaOff(tex, posM, float2(-1, 0), fxaaQualityRcpFrame.xy);
+    float lumaS = LumaOff(DiffMap, posM, float2( 0, 1), fxaaQualityRcpFrame.xy);
+    float lumaE = LumaOff(DiffMap, posM, float2( 1, 0), fxaaQualityRcpFrame.xy);
+    float lumaN = LumaOff(DiffMap, posM, float2( 0,-1), fxaaQualityRcpFrame.xy);
+    float lumaW = LumaOff(DiffMap, posM, float2(-1, 0), fxaaQualityRcpFrame.xy);
 /*--------------------------------------------------------------------------*/
     float maxSM = max(lumaS, lumaM);
     float minSM = min(lumaS, lumaM);
@@ -389,12 +395,12 @@ float4 FxaaPixelShader(
     bool earlyExit = range < rangeMaxClamped;
 /*--------------------------------------------------------------------------*/
     if(earlyExit)
-        return FxaaTexTop(tex, pos);
+        return FxaaTexTop(DiffMap, pos);
 /*--------------------------------------------------------------------------*/
-    float lumaNW = LumaOff(tex, posM, float2(-1,-1), fxaaQualityRcpFrame.xy);
-    float lumaSE = LumaOff(tex, posM, float2( 1, 1), fxaaQualityRcpFrame.xy);
-    float lumaNE = LumaOff(tex, posM, float2( 1,-1), fxaaQualityRcpFrame.xy);
-    float lumaSW = LumaOff(tex, posM, float2(-1, 1), fxaaQualityRcpFrame.xy);
+    float lumaNW = LumaOff(DiffMap, posM, float2(-1,-1), fxaaQualityRcpFrame.xy);
+    float lumaSE = LumaOff(DiffMap, posM, float2( 1, 1), fxaaQualityRcpFrame.xy);
+    float lumaNE = LumaOff(DiffMap, posM, float2( 1,-1), fxaaQualityRcpFrame.xy);
+    float lumaSW = LumaOff(DiffMap, posM, float2(-1, 1), fxaaQualityRcpFrame.xy);
 /*--------------------------------------------------------------------------*/
     float lumaNS = lumaN + lumaS;
     float lumaWE = lumaW + lumaE;
@@ -452,9 +458,9 @@ float4 FxaaPixelShader(
     posP.x = posB.x + offNP.x * FXAA_QUALITY_P0;
     posP.y = posB.y + offNP.y * FXAA_QUALITY_P0;
     float subpixD = ((-2.0)*subpixC) + 3.0;
-    float lumaEndN = LumaTop(tex, posN);
+    float lumaEndN = LumaTop(DiffMap, posN);
     float subpixE = subpixC * subpixC;
-    float lumaEndP = LumaTop(tex, posP);
+    float lumaEndP = LumaTop(DiffMap, posP);
 /*--------------------------------------------------------------------------*/
     if(!pairN) lumaNN = lumaSS;
     float gradientScaled = gradient * 1.0/4.0;
@@ -473,8 +479,8 @@ float4 FxaaPixelShader(
     if(!doneP) posP.y += offNP.y * FXAA_QUALITY_P1;
 /*--------------------------------------------------------------------------*/
     if(doneNP) {
-        if(!doneN) lumaEndN = LumaTop(tex, posN.xy);
-        if(!doneP) lumaEndP = LumaTop(tex, posP.xy);
+        if(!doneN) lumaEndN = LumaTop(DiffMap, posN.xy);
+        if(!doneP) lumaEndP = LumaTop(DiffMap, posP.xy);
         if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;
         if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;
         doneN = abs(lumaEndN) >= gradientScaled;
@@ -487,8 +493,8 @@ float4 FxaaPixelShader(
 /*--------------------------------------------------------------------------*/
         #if (FXAA_QUALITY_PS > 3)
         if(doneNP) {
-            if(!doneN) lumaEndN = LumaTop(tex, posN.xy);
-            if(!doneP) lumaEndP = LumaTop(tex, posP.xy);
+            if(!doneN) lumaEndN = LumaTop(DiffMap, posN.xy);
+            if(!doneP) lumaEndP = LumaTop(DiffMap, posP.xy);
             if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;
             if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;
             doneN = abs(lumaEndN) >= gradientScaled;
@@ -501,8 +507,8 @@ float4 FxaaPixelShader(
 /*--------------------------------------------------------------------------*/
             #if (FXAA_QUALITY_PS > 4)
             if(doneNP) {
-                if(!doneN) lumaEndN = LumaTop(tex, posN.xy);
-                if(!doneP) lumaEndP = LumaTop(tex, posP.xy);
+                if(!doneN) lumaEndN = LumaTop(DiffMap, posN.xy);
+                if(!doneP) lumaEndP = LumaTop(DiffMap, posP.xy);
                 if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;
                 if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;
                 doneN = abs(lumaEndN) >= gradientScaled;
@@ -515,8 +521,8 @@ float4 FxaaPixelShader(
 /*--------------------------------------------------------------------------*/
                 #if (FXAA_QUALITY_PS > 5)
                 if(doneNP) {
-                    if(!doneN) lumaEndN = LumaTop(tex, posN.xy);
-                    if(!doneP) lumaEndP = LumaTop(tex, posP.xy);
+                    if(!doneN) lumaEndN = LumaTop(DiffMap, posN.xy);
+                    if(!doneP) lumaEndP = LumaTop(DiffMap, posP.xy);
                     if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;
                     if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;
                     doneN = abs(lumaEndN) >= gradientScaled;
@@ -529,8 +535,8 @@ float4 FxaaPixelShader(
 /*--------------------------------------------------------------------------*/
                     #if (FXAA_QUALITY_PS > 6)
                     if(doneNP) {
-                        if(!doneN) lumaEndN = LumaTop(tex, posN.xy);
-                        if(!doneP) lumaEndP = LumaTop(tex, posP.xy);
+                        if(!doneN) lumaEndN = LumaTop(DiffMap, posN.xy);
+                        if(!doneP) lumaEndP = LumaTop(DiffMap, posP.xy);
                         if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;
                         if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;
                         doneN = abs(lumaEndN) >= gradientScaled;
@@ -543,8 +549,8 @@ float4 FxaaPixelShader(
 /*--------------------------------------------------------------------------*/
                         #if (FXAA_QUALITY_PS > 7)
                         if(doneNP) {
-                            if(!doneN) lumaEndN = LumaTop(tex, posN.xy);
-                            if(!doneP) lumaEndP = LumaTop(tex, posP.xy);
+                            if(!doneN) lumaEndN = LumaTop(DiffMap, posN.xy);
+                            if(!doneP) lumaEndP = LumaTop(DiffMap, posP.xy);
                             if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;
                             if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;
                             doneN = abs(lumaEndN) >= gradientScaled;
@@ -557,8 +563,8 @@ float4 FxaaPixelShader(
 /*--------------------------------------------------------------------------*/
     #if (FXAA_QUALITY_PS > 8)
     if(doneNP) {
-        if(!doneN) lumaEndN = LumaTop(tex, posN.xy);
-        if(!doneP) lumaEndP = LumaTop(tex, posP.xy);
+        if(!doneN) lumaEndN = LumaTop(DiffMap, posN.xy);
+        if(!doneP) lumaEndP = LumaTop(DiffMap, posP.xy);
         if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;
         if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;
         doneN = abs(lumaEndN) >= gradientScaled;
@@ -571,8 +577,8 @@ float4 FxaaPixelShader(
 /*--------------------------------------------------------------------------*/
         #if (FXAA_QUALITY_PS > 9)
         if(doneNP) {
-            if(!doneN) lumaEndN = LumaTop(tex, posN.xy);
-            if(!doneP) lumaEndP = LumaTop(tex, posP.xy);
+            if(!doneN) lumaEndN = LumaTop(DiffMap, posN.xy);
+            if(!doneP) lumaEndP = LumaTop(DiffMap, posP.xy);
             if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;
             if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;
             doneN = abs(lumaEndN) >= gradientScaled;
@@ -585,8 +591,8 @@ float4 FxaaPixelShader(
 /*--------------------------------------------------------------------------*/
             #if (FXAA_QUALITY_PS > 10)
             if(doneNP) {
-                if(!doneN) lumaEndN = LumaTop(tex, posN.xy);
-                if(!doneP) lumaEndP = LumaTop(tex, posP.xy);
+                if(!doneN) lumaEndN = LumaTop(DiffMap, posN.xy);
+                if(!doneP) lumaEndP = LumaTop(DiffMap, posP.xy);
                 if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;
                 if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;
                 doneN = abs(lumaEndN) >= gradientScaled;
@@ -599,8 +605,8 @@ float4 FxaaPixelShader(
 /*--------------------------------------------------------------------------*/
                 #if (FXAA_QUALITY_PS > 11)
                 if(doneNP) {
-                    if(!doneN) lumaEndN = LumaTop(tex, posN.xy);
-                    if(!doneP) lumaEndP = LumaTop(tex, posP.xy);
+                    if(!doneN) lumaEndN = LumaTop(DiffMap, posN.xy);
+                    if(!doneP) lumaEndP = LumaTop(DiffMap, posP.xy);
                     if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;
                     if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;
                     doneN = abs(lumaEndN) >= gradientScaled;
@@ -613,8 +619,8 @@ float4 FxaaPixelShader(
 /*--------------------------------------------------------------------------*/
                     #if (FXAA_QUALITY_PS > 12)
                     if(doneNP) {
-                        if(!doneN) lumaEndN = LumaTop(tex, posN.xy);
-                        if(!doneP) lumaEndP = LumaTop(tex, posP.xy);
+                        if(!doneN) lumaEndN = LumaTop(DiffMap, posN.xy);
+                        if(!doneP) lumaEndP = LumaTop(DiffMap, posP.xy);
                         if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;
                         if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;
                         doneN = abs(lumaEndN) >= gradientScaled;
@@ -678,9 +684,10 @@ float4 FxaaPixelShader(
     float pixelOffsetSubpix = max(pixelOffsetGood, subpixH);
     if(!horzSpan) posM.x += pixelOffsetSubpix * lengthSign;
     if( horzSpan) posM.y += pixelOffsetSubpix * lengthSign;
-    return FxaaTexTop(tex, posM);
+    return FxaaTexTop(DiffMap, posM);
 }
 /*==========================================================================*/
+#endif
 
 /*============================================================================
 
@@ -689,8 +696,8 @@ float4 FxaaPixelShader(
 ============================================================================*/
 
 void VS(float4 iPos : POSITION,
-    out float4 oPos : POSITION,
-    out float2 oScreenPos : TEXCOORD0)
+    out float2 oScreenPos : TEXCOORD0,
+    out float4 oPos : OUTPOSITION)
 {
     float4x3 modelMatrix = iModelMatrix;
     float3 worldPos = GetWorldPos(modelMatrix);
@@ -699,13 +706,12 @@ void VS(float4 iPos : POSITION,
 }
 
 void PS(float2 iScreenPos : TEXCOORD0,
-    out float4 oColor : COLOR0)
+    out float4 oColor : OUTCOLOR0)
 {
     float2 rcpFrame = float2(cGBufferInvSize.x, cGBufferInvSize.y);
 
     oColor = FxaaPixelShader(
         iScreenPos,                         // float2 pos,
-        sDiffMap,                           // sampler2D tex,
         rcpFrame,                           // float2 fxaaQualityRcpFrame,
         0.75f,                              // float fxaaQualitySubpix,
         0.166f,                             // float fxaaQualityEdgeThreshold,

+ 4 - 4
Data/AtomicPlayer/Resources/CoreData/Shaders/HLSL/Fog.hlsl

@@ -5,8 +5,8 @@
 #include "PostProcess.hlsl"
 
 void VS(float4 iPos : POSITION,
-    out float4 oPos : POSITION,
-    out float2 oScreenPos : TEXCOORD0)
+    out float2 oScreenPos : TEXCOORD0,
+    out float4 oPos : OUTPOSITION)
 {
     float4x3 modelMatrix = iModelMatrix;
     float3 worldPos = GetWorldPos(modelMatrix);
@@ -15,8 +15,8 @@ void VS(float4 iPos : POSITION,
 }
 
 void PS(float2 iScreenPos : TEXCOORD0,
-    out float4 oColor : COLOR0)
+    out float4 oColor : OUTCOLOR0)
 {
-    float3 color = tex2D(sDiffMap, iScreenPos).rgb;
+    float3 color = Sample2D(DiffMap, iScreenPos).rgb;
     oColor = float4(ToInverseGamma(color), 1.0);
 }

+ 4 - 4
Data/AtomicPlayer/Resources/CoreData/Shaders/HLSL/GreyScale.hlsl

@@ -5,8 +5,8 @@
 #include "Lighting.hlsl"
 
 void VS(float4 iPos : POSITION,
-    out float4 oPos : POSITION,
-    out float2 oScreenPos : TEXCOORD0)
+    out float2 oScreenPos : TEXCOORD0,
+    out float4 oPos : OUTPOSITION)
 {
     float4x3 modelMatrix = iModelMatrix;
     float3 worldPos = GetWorldPos(modelMatrix);
@@ -15,9 +15,9 @@ void VS(float4 iPos : POSITION,
 }
 
 void PS(float2 iScreenPos : TEXCOORD0,
-    out float4 oColor : COLOR0)
+    out float4 oColor : OUTCOLOR0)
 {
-    float3 rgb = tex2D(sDiffMap, iScreenPos).rgb;
+    float3 rgb = Sample2D(DiffMap, iScreenPos).rgb;
     float intensity = GetIntensity(rgb);
     oColor = float4(intensity, intensity, intensity, 1.0);
 }

+ 6 - 6
Data/AtomicPlayer/Resources/CoreData/Shaders/HLSL/Light2D.hlsl

@@ -3,10 +3,11 @@
 #include "Transform.hlsl"
 
 void VS(float4 iPos : POSITION,
-		float2 iTexCoord : TEXCOORD0,  
-		float4 iColor : COLOR0, 
-		out float4 oPos : POSITION, 
-		out float4 oColor : COLOR0)
+		float2 iTexCoord : TEXCOORD0,
+		float4 iColor : COLOR0,
+		out float4 oColor : COLOR0,
+		out float4 oPos : OUTPOSITION
+		)
 {
 
 	float4x3 modelMatrix = iModelMatrix;
@@ -15,8 +16,7 @@ void VS(float4 iPos : POSITION,
     oColor = iColor * iTexCoord.x;
 }
 
-void PS(float4 iColor : COLOR0, out float4 oColor : COLOR0)
+void PS(float4 iColor : COLOR0, out float4 oColor : OUTCOLOR0)
 {
 	oColor = iColor;
 }
-

+ 38 - 58
Data/AtomicPlayer/Resources/CoreData/Shaders/HLSL/Lighting.hlsl

@@ -65,11 +65,7 @@ float GetVertexLightVolumetric(int index, float3 worldPos)
 #ifdef SHADOW
 
 #ifdef DIRLIGHT
-    #ifdef SM3
-        #define NUMCASCADES 4
-    #else
-        #define NUMCASCADES 3
-    #endif
+    #define NUMCASCADES 4
 #else
     #define NUMCASCADES 1
 #endif
@@ -81,9 +77,7 @@ void GetShadowPos(float4 projWorldPos, out float4 shadowPos[NUMCASCADES])
         shadowPos[0] = mul(projWorldPos, cLightMatrices[0]);
         shadowPos[1] = mul(projWorldPos, cLightMatrices[1]);
         shadowPos[2] = mul(projWorldPos, cLightMatrices[2]);
-        #ifdef SM3
-            shadowPos[3] = mul(projWorldPos, cLightMatrices[3]);
-        #endif
+        shadowPos[3] = mul(projWorldPos, cLightMatrices[3]);
     #elif defined(SPOTLIGHT)
         shadowPos[0] = mul(projWorldPos, cLightMatrices[1]);
     #else
@@ -103,7 +97,7 @@ float GetDiffuse(float3 normal, float3 worldPos, out float3 lightDir)
         float3 lightVec = (cLightPosPS.xyz - worldPos) * cLightPosPS.w;
         float lightDist = length(lightVec);
         lightDir = lightVec / lightDist;
-        return saturate(dot(normal, lightDir)) * tex1D(sLightRampMap, lightDist).r;
+        return saturate(dot(normal, lightDir)) * Sample2D(LightRampMap, float2(lightDist, 0.0)).r;
     #endif
 }
 
@@ -114,14 +108,14 @@ float GetDiffuseVolumetric(float3 worldPos)
     #else
         float3 lightVec = (cLightPosPS.xyz - worldPos) * cLightPosPS.w;
         float lightDist = length(lightVec);
-        return tex1D(sLightRampMap, lightDist).r;
+        return Sample2D(LightRampMap, float2(lightDist, 0.0)).r;
     #endif
 }
 
 float GetSpecular(float3 normal, float3 eyeVec, float3 lightDir, float specularPower)
 {
     float3 halfVec = normalize(normalize(eyeVec) + lightDir);
-    return pow(dot(normal, halfVec), specularPower);
+    return saturate(pow(dot(normal, halfVec), specularPower));
 }
 
 float GetIntensity(float3 color)
@@ -132,30 +126,34 @@ float GetIntensity(float3 color)
 #ifdef SHADOW
 
 #ifdef DIRLIGHT
-    #ifdef SM3
-        #define NUMCASCADES 4
-    #else
-        #define NUMCASCADES 3
-    #endif
+    #define NUMCASCADES 4
 #else
     #define NUMCASCADES 1
 #endif
 
 float GetShadow(float4 shadowPos)
 {
+    #ifdef D3D11
+        shadowPos.xyz /= shadowPos.w;
+    #endif
+
     #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
+        #if !defined(POINTLIGHT) && !defined(D3D11)
             float2 offsets = cShadowMapInvSize * shadowPos.w;
         #else
             float2 offsets = cShadowMapInvSize;
         #endif
+        float4 shadowPos2 = float4(shadowPos.x + offsets.x, shadowPos.yzw);
+        float4 shadowPos3 = float4(shadowPos.x, shadowPos.y + offsets.y, shadowPos.zw);
+        float4 shadowPos4 = float4(shadowPos.xy + offsets.xy, shadowPos.zw);
+
         float4 inLight = float4(
-            tex2Dproj(sShadowMap, shadowPos).r,
-            tex2Dproj(sShadowMap, float4(shadowPos.x + offsets.x, shadowPos.yzw)).r,
-            tex2Dproj(sShadowMap, float4(shadowPos.x, shadowPos.y + offsets.y, shadowPos.zw)).r,
-            tex2Dproj(sShadowMap, float4(shadowPos.xy + offsets.xy, shadowPos.zw)).r
+            SampleShadow(ShadowMap, shadowPos).r,
+            SampleShadow(ShadowMap, shadowPos2).r,
+            SampleShadow(ShadowMap, shadowPos3).r,
+            SampleShadow(ShadowMap, shadowPos4).r
         );
         #ifndef SHADOWCMP
             return cShadowIntensity.y + dot(inLight, cShadowIntensity.x);
@@ -168,7 +166,7 @@ float GetShadow(float4 shadowPos)
         #endif
     #else
         // Take one sample
-        float inLight = tex2Dproj(sShadowMap, shadowPos).r;
+        float inLight = SampleShadow(ShadowMap, shadowPos).r;
         #ifndef SHADOWCMP
             return cShadowIntensity.y + cShadowIntensity.x * inLight;
         #else
@@ -184,7 +182,7 @@ float GetShadow(float4 shadowPos)
 #ifdef POINTLIGHT
 float GetPointShadow(float3 lightVec)
 {
-    float3 axis = texCUBE(sFaceSelectCubeMap, lightVec).rgb;
+    float3 axis = SampleCube(FaceSelectCubeMap, lightVec).rgb;
     float depth = abs(dot(lightVec, axis));
 
     // Expand the maximum component of the light vector to get full 0.0 - 1.0 UV range from the cube map,
@@ -194,7 +192,7 @@ float GetPointShadow(float3 lightVec)
     lightVec += factor * axis * lightVec;
 
     // Read the 2D UV coordinates, adjust according to shadow map size and add face offset
-    float4 indirectPos = texCUBE(sIndirectionCubeMap, lightVec);
+    float4 indirectPos = SampleCube(IndirectionCubeMap, lightVec);
     indirectPos.xy *= cShadowCubeAdjust.xy;
     indirectPos.xy += float2(cShadowCubeAdjust.z + indirectPos.z * 0.5, cShadowCubeAdjust.w + indirectPos.w);
 
@@ -213,23 +211,14 @@ float GetDirShadow(const float4 iShadowPos[NUMCASCADES], float depth)
 {
     float4 shadowPos;
 
-    #ifdef SM3
-        if (depth < cShadowSplits.x)
-            shadowPos = iShadowPos[0];
-        else if (depth < cShadowSplits.y)
-            shadowPos = iShadowPos[1];
-        else if (depth < cShadowSplits.z)
-            shadowPos = iShadowPos[2];
-        else
-            shadowPos = iShadowPos[3];
-    #else
-        if (depth < cShadowSplits.x)
-            shadowPos = iShadowPos[0];
-        else if (depth < cShadowSplits.y)
-            shadowPos = iShadowPos[1];
-        else
-            shadowPos = iShadowPos[2];
-    #endif
+    if (depth < cShadowSplits.x)
+        shadowPos = iShadowPos[0];
+    else if (depth < cShadowSplits.y)
+        shadowPos = iShadowPos[1];
+    else if (depth < cShadowSplits.z)
+        shadowPos = iShadowPos[2];
+    else
+        shadowPos = iShadowPos[3];
 
     return GetDirShadowFade(GetShadow(shadowPos), depth);
 }
@@ -238,23 +227,14 @@ float GetDirShadowDeferred(float4 projWorldPos, float depth)
 {
     float4 shadowPos;
 
-    #ifdef SM3
-        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]);
-    #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]);
-    #endif
+    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]);
 
     return GetDirShadowFade(GetShadow(shadowPos), depth);
 }

+ 25 - 6
Data/AtomicPlayer/Resources/CoreData/Shaders/HLSL/LitParticle.hlsl

@@ -5,8 +5,12 @@
 #include "Fog.hlsl"
 
 void VS(float4 iPos : POSITION,
-    float3 iNormal : NORMAL,
-    float2 iTexCoord : TEXCOORD0,
+    #ifndef BILLBOARD
+        float3 iNormal : NORMAL,
+    #endif
+    #ifndef NOUV
+        float2 iTexCoord : TEXCOORD0,
+    #endif
     #ifdef VERTEXCOLOR
         float4 iColor : COLOR0,
     #endif
@@ -38,14 +42,26 @@ void VS(float4 iPos : POSITION,
     #ifdef VERTEXCOLOR
         out float4 oColor : COLOR0,
     #endif
-    out float4 oPos : POSITION)
+    #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);
     oPos = GetClipPos(worldPos);
     oTexCoord = GetTexCoord(iTexCoord);
     oWorldPos = float4(worldPos, GetDepth(oPos));
 
+    #if defined(D3D11) && defined(CLIPPLANE)
+        oClip = dot(oPos, cClipPlane);
+    #endif
+
     #ifdef VERTEXCOLOR
         oColor = iColor;
     #endif
@@ -96,11 +112,14 @@ void PS(float2 iTexCoord : TEXCOORD0,
     #ifdef VERTEXCOLOR
         float4 iColor : COLOR0,
     #endif
-    out float4 oColor : COLOR0)
+    #if defined(D3D11) && defined(CLIPPLANE)
+        float iClip : SV_CLIPDISTANCE0,
+    #endif
+    out float4 oColor : OUTCOLOR0)
 {
     // Get material diffuse albedo
     #ifdef DIFFMAP
-        float4 diffInput = tex2D(sDiffMap, iTexCoord);
+        float4 diffInput = Sample2D(DiffMap, iTexCoord);
         #ifdef ALPHAMASK
             if (diffInput.a < 0.5)
                 discard;
@@ -133,7 +152,7 @@ void PS(float2 iTexCoord : TEXCOORD0,
         #endif
 
         #if defined(SPOTLIGHT)
-            lightColor = iSpotPos.w > 0.0 ? tex2Dproj(sLightSpotMap, iSpotPos).rgb * cLightColor.rgb : 0.0;
+            lightColor = iSpotPos.w > 0.0 ? Sample2DProj(LightSpotMap, iSpotPos).rgb * cLightColor.rgb : 0.0;
         #elif defined(CUBEMASK)
             lightColor = texCUBE(sLightCubeMap, iCubeMaskVec).rgb * cLightColor.rgb;
         #else

+ 59 - 33
Data/AtomicPlayer/Resources/CoreData/Shaders/HLSL/LitSolid.hlsl

@@ -5,14 +5,16 @@
 #include "Lighting.hlsl"
 #include "Fog.hlsl"
 
-// When rendering a shadowed point light, disable specular calculations on Shader Model 2 to avoid exceeding the instruction limit
-#if !defined(SM3) && defined(SHADOW) && defined(POINTLIGHT)
-    #undef SPECULAR
-#endif
-
 void VS(float4 iPos : POSITION,
-    float3 iNormal : NORMAL,
-    float2 iTexCoord : TEXCOORD0,
+    #ifndef BILLBOARD
+        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
@@ -57,14 +59,33 @@ void VS(float4 iPos : POSITION,
             out float2 oTexCoord2 : TEXCOORD7,
         #endif
     #endif
-    out float4 oPos : POSITION)
+    #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);
     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
+
     #ifdef NORMALMAP
         float3 tangent = GetWorldTangent(modelMatrix);
         float3 bitangent = cross(tangent, oNormal) * iTangent.w;
@@ -144,19 +165,25 @@ void PS(
             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 : COLOR1,
+        out float4 oDepth : OUTCOLOR1,
     #endif
     #ifdef DEFERRED
-        out float4 oAlbedo : COLOR1,
-        out float4 oNormal : COLOR2,
-        out float4 oDepth : COLOR3,
+        out float4 oAlbedo : OUTCOLOR1,
+        out float4 oNormal : OUTCOLOR2,
+        out float4 oDepth : OUTCOLOR3,
     #endif
-    out float4 oColor : COLOR0)
+    out float4 oColor : OUTCOLOR0)
 {
     // Get material diffuse albedo
     #ifdef DIFFMAP
-        float4 diffInput = tex2D(sDiffMap, iTexCoord.xy);
+        float4 diffInput = Sample2D(DiffMap, iTexCoord.xy);
         #ifdef ALPHAMASK
             if (diffInput.a < 0.5)
                 discard;
@@ -166,9 +193,13 @@ void PS(
         float4 diffColor = cMatDiffColor;
     #endif
 
+    #ifdef VERTEXCOLOR
+        diffColor *= iColor;
+    #endif
+
     // Get material specular albedo
     #ifdef SPECMAP
-        float3 specColor = cMatSpecColor.rgb * tex2D(sSpecMap, iTexCoord.xy).rgb;
+        float3 specColor = cMatSpecColor.rgb * Sample2D(SpecMap, iTexCoord.xy).rgb;
     #else
         float3 specColor = cMatSpecColor.rgb;
     #endif
@@ -176,12 +207,7 @@ void PS(
     // Get normal
     #ifdef NORMALMAP
         float3x3 tbn = float3x3(iTangent.xyz, float3(iTexCoord.zw, iTangent.w), iNormal);
-        // We may be running low on instructions on Shader Model 2, so skip normalize if necessary
-        #if defined(SM3) || !defined(SHADOW) || !defined(SPECULAR)
-            float3 normal = normalize(mul(DecodeNormal(tex2D(sNormalMap, iTexCoord.xy)), tbn));
-        #else
-            float3 normal = mul(DecodeNormal(tex2D(sNormalMap, iTexCoord.xy)), tbn);
-        #endif
+        float3 normal = normalize(mul(DecodeNormal(Sample2D(NormalMap, iTexCoord.xy)), tbn));
     #else
         float3 normal = normalize(iNormal);
     #endif
@@ -206,9 +232,9 @@ void PS(
         #endif
 
         #if defined(SPOTLIGHT)
-            lightColor = iSpotPos.w > 0.0 ? tex2Dproj(sLightSpotMap, iSpotPos).rgb * cLightColor.rgb : 0.0;
+            lightColor = iSpotPos.w > 0.0 ? Sample2DProj(LightSpotMap, iSpotPos).rgb * cLightColor.rgb : 0.0;
         #elif defined(CUBEMASK)
-            lightColor = texCUBE(sLightCubeMap, iCubeMaskVec).rgb * cLightColor.rgb;
+            lightColor = SampleCube(LightCubeMap, iCubeMaskVec).rgb * cLightColor.rgb;
         #else
             lightColor = cLightColor.rgb;
         #endif
@@ -241,16 +267,16 @@ void PS(
         float3 finalColor = iVertexLight * diffColor.rgb;
         #ifdef AO
             // If using AO, the vertex light ambient is black, calculate occluded ambient here
-            finalColor += tex2D(sEmissiveMap, iTexCoord2).rgb * cAmbientColor * diffColor.rgb;
+            finalColor += Sample2D(EmissiveMap, iTexCoord2).rgb * cAmbientColor * diffColor.rgb;
         #endif
         #ifdef ENVCUBEMAP
-            finalColor += cMatEnvMapColor * texCUBE(sEnvCubeMap, reflect(iReflectionVec, normal)).rgb;
+            finalColor += cMatEnvMapColor * SampleCube(EnvCubeMap, reflect(iReflectionVec, normal)).rgb;
         #endif
         #ifdef LIGHTMAP
-            finalColor += tex2D(sEmissiveMap, iTexCoord2).rgb * diffColor.rgb;
+            finalColor += Sample2D(EmissiveMap, iTexCoord2).rgb * diffColor.rgb;
         #endif
         #ifdef EMISSIVEMAP
-            finalColor += cMatEmissiveColor * tex2D(sEmissiveMap, iTexCoord.xy).rgb;
+            finalColor += cMatEmissiveColor * Sample2D(EmissiveMap, iTexCoord.xy).rgb;
         #else
             finalColor += cMatEmissiveColor;
         #endif
@@ -264,26 +290,26 @@ void PS(
         float3 finalColor = iVertexLight * diffColor.rgb;
         #ifdef AO
             // If using AO, the vertex light ambient is black, calculate occluded ambient here
-            finalColor += tex2D(sEmissiveMap, iTexCoord2).rgb * cAmbientColor * diffColor.rgb;
+            finalColor += Sample2D(EmissiveMap, iTexCoord2).rgb * cAmbientColor * 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 * tex2Dproj(sLightBuffer, iScreenPos);
-            float3 lightSpecColor = lightInput.a * (lightInput.rgb / GetIntensity(lightInput.rgb));
+            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
 
         #ifdef ENVCUBEMAP
-            finalColor += cMatEnvMapColor * texCUBE(sEnvCubeMap, reflect(iReflectionVec, normal)).rgb;
+            finalColor += cMatEnvMapColor * SampleCube(EnvCubeMap, reflect(iReflectionVec, normal)).rgb;
         #endif
         #ifdef LIGHTMAP
-            finalColor += tex2D(sEmissiveMap, iTexCoord2).rgb * diffColor.rgb;
+            finalColor += Sample2D(EmissiveMap, iTexCoord2).rgb * diffColor.rgb;
         #endif
         #ifdef EMISSIVEMAP
-            finalColor += cMatEmissiveColor * tex2D(sEmissiveMap, iTexCoord.xy).rgb;
+            finalColor += cMatEmissiveColor * Sample2D(EmissiveMap, iTexCoord.xy).rgb;
         #else
             finalColor += cMatEmissiveColor;
         #endif

+ 23 - 1
Data/AtomicPlayer/Resources/CoreData/Shaders/HLSL/PostProcess.hlsl

@@ -9,7 +9,11 @@ float2 Noise(float2 coord)
 }
 
 // Adapted: http://callumhay.blogspot.com/2010/09/gaussian-blur-shader-glsl.html
+#ifndef D3D11
 float4 GaussianBlur(int blurKernelSize, float2 blurDir, float2 blurRadius, float sigma, sampler2D texSampler, float2 texCoord)
+#else
+float4 GaussianBlur(int blurKernelSize, float2 blurDir, float2 blurRadius, float sigma, Texture2D tex, SamplerState texSampler, float2 texCoord)
+#endif
 {
     const int blurKernelHalfSize = blurKernelSize / 2;
 
@@ -23,14 +27,24 @@ float4 GaussianBlur(int blurKernelSize, float2 blurDir, float2 blurRadius, float
     float4 avgValue = float4(0.0, 0.0, 0.0, 0.0);
     float gaussCoeffSum = 0.0;
 
+    #ifndef D3D11
     avgValue += tex2D(texSampler, texCoord) * gaussCoeff.x;
+    #else
+    avgValue += tex.Sample(texSampler, texCoord) * gaussCoeff.x;
+    #endif
+
     gaussCoeffSum += gaussCoeff.x;
     gaussCoeff.xy *= gaussCoeff.yz;
 
     for (int i = 1; i <= blurKernelHalfSize; i++)
     {
+        #ifndef D3D11
         avgValue += tex2D(texSampler, texCoord - i * blurVec) * gaussCoeff.x;
         avgValue += tex2D(texSampler, texCoord + i * blurVec) * gaussCoeff.x;
+        #else
+        avgValue += tex.Sample(texSampler, texCoord - i * blurVec) * gaussCoeff.x;
+        avgValue += tex.Sample(texSampler, texCoord + i * blurVec) * gaussCoeff.x;
+        #endif
 
         gaussCoeffSum += 2.0 * gaussCoeff.x;
         gaussCoeff.xy *= gaussCoeff.yz;
@@ -64,12 +78,20 @@ float3 Uncharted2Tonemap(float3 x)
    return ((x*(A*x+C*B)+D*E)/(x*(A*x+B)+D*F))-E/F;
 }
 
+#ifndef D3D11
 float3 ColorCorrection(float3 color, sampler3D lut)
+#else
+float3 ColorCorrection(float3 color, Texture3D lut, SamplerState lutSampler)
+#endif
 {
     float lutSize = 16.0;
     float scale = (lutSize - 1.0) / lutSize;
     float offset = 1.0 / (2.0 * lutSize);
-    return tex3D(lut, clamp(color, 0.0, 1.0) * scale + offset).rgb;
+    #ifndef D3D11
+        return tex3D(lut, clamp(color, 0.0, 1.0) * scale + offset).rgb;
+    #else
+        return lut.Sample(lutSampler, clamp(color, 0.0, 1.0) * scale + offset).rgb;
+    #endif
 }
 
 static const float Gamma = 2.2;

+ 7 - 7
Data/AtomicPlayer/Resources/CoreData/Shaders/HLSL/PrepassLight.hlsl

@@ -14,7 +14,7 @@ void VS(float4 iPos : POSITION,
     #ifdef ORTHO
         out float3 oNearRay : TEXCOORD2,
     #endif
-    out float4 oPos : POSITION)
+    out float4 oPos : OUTPOSITION)
 {
     float4x3 modelMatrix = iModelMatrix;
     float3 worldPos = GetWorldPos(modelMatrix);
@@ -44,11 +44,11 @@ void PS(
     #ifdef ORTHO
         float3 iNearRay : TEXCOORD2,
     #endif
-    out float4 oColor : COLOR0)
+    out float4 oColor : OUTCOLOR0)
 {
     // If rendering a directional light quad, optimize out the w divide
     #ifdef DIRLIGHT
-        float depth = Sample(sDepthBuffer, iScreenPos).r;
+        float depth = Sample2DLod0(DepthBuffer, iScreenPos).r;
         #ifdef HWDEPTH
             depth = ReconstructDepth(depth);
         #endif
@@ -57,9 +57,9 @@ void PS(
         #else
             float3 worldPos = iFarRay * depth;
         #endif
-        float4 normalInput = Sample(sNormalBuffer, iScreenPos);
+        float4 normalInput = Sample2DLod0(NormalBuffer, iScreenPos);
     #else
-        float depth = tex2Dproj(sDepthBuffer, iScreenPos).r;
+        float depth = Sample2DProj(DepthBuffer, iScreenPos).r;
         #ifdef HWDEPTH
             depth = ReconstructDepth(depth);
         #endif
@@ -68,7 +68,7 @@ void PS(
         #else
             float3 worldPos = iFarRay * depth / iScreenPos.w;
         #endif
-        float4 normalInput = tex2Dproj(sNormalBuffer, iScreenPos);
+        float4 normalInput = Sample2DProj(NormalBuffer, iScreenPos);
     #endif
 
     float3 normal = normalize(normalInput.rgb * 2.0 - 1.0);
@@ -85,7 +85,7 @@ void PS(
 
     #if defined(SPOTLIGHT)
         float4 spotPos = mul(projWorldPos, cLightMatricesPS[0]);
-        lightColor = spotPos.w > 0.0 ? tex2Dproj(sLightSpotMap, spotPos).rgb * cLightColor.rgb : 0.0;
+        lightColor = spotPos.w > 0.0 ? Sample2DProj(LightSpotMap, spotPos).rgb * cLightColor.rgb : 0.0;
     #elif defined(CUBEMASK)
         lightColor = texCUBE(sLightCubeMap, mul(worldPos - cLightPosPS.xyz, (float3x3)cLightMatricesPS[0])).rgb * cLightColor.rgb;
     #else

+ 93 - 42
Data/AtomicPlayer/Resources/CoreData/Shaders/HLSL/Samplers.hlsl

@@ -1,53 +1,104 @@
 #ifdef COMPILEPS
-sampler2D sDiffMap : register(S0);
-samplerCUBE sDiffCubeMap : register(S0);
-sampler2D sAlbedoBuffer : register(S0);
-sampler2D sNormalMap : register(S1);
-sampler2D sNormalBuffer : register(S1);
-sampler2D sSpecMap : register(S2);
-sampler2D sEmissiveMap : register(S3);
-sampler2D sEnvMap : register(S4);
-samplerCUBE sEnvCubeMap : register(S4);
-sampler1D sLightRampMap : register(S5);
-sampler2D sLightSpotMap : register(S6);
-samplerCUBE sLightCubeMap : register(S6);
-sampler2D sShadowMap : register(S7);
-samplerCUBE sFaceSelectCubeMap : register(S8);
-samplerCUBE sIndirectionCubeMap : register(S9);
-sampler2D sDepthBuffer : register(S10);
-sampler2D sLightBuffer : register(S11);
-sampler3D sVolumeMap : register(S12);
-samplerCUBE sZoneCubeMap : register(S13);
-sampler3D sZoneVolumeMap : register(S13);
-
-float4 Sample(sampler2D map, float2 texCoord)
-{
-    // Use tex2Dlod if available to avoid divergence and allow branching
-    #ifdef SM3
-        return tex2Dlod(map, float4(texCoord, 0.0, 0.0));
-    #else
-        return tex2D(map, texCoord);
-    #endif
-}
+
+#ifndef D3D11
+
+// D3D9 samplers
+sampler2D sDiffMap : register(s0);
+samplerCUBE sDiffCubeMap : register(s0);
+sampler2D sAlbedoBuffer : register(s0);
+sampler2D sNormalMap : register(s1);
+sampler2D sNormalBuffer : register(s1);
+sampler2D sSpecMap : register(s2);
+sampler2D sEmissiveMap : register(s3);
+sampler2D sEnvMap : register(s4);
+sampler3D sVolumeMap : register(s5);
+samplerCUBE sEnvCubeMap : register(s4);
+sampler2D sLightRampMap : register(s8);
+sampler2D sLightSpotMap : register(s9);
+samplerCUBE sLightCubeMap : register(s9);
+sampler2D sShadowMap : register(s10);
+samplerCUBE sFaceSelectCubeMap : register(s11);
+samplerCUBE sIndirectionCubeMap : register(s12);
+sampler2D sDepthBuffer : register(s13);
+sampler2D sLightBuffer : register(s14);
+samplerCUBE sZoneCubeMap : register(s15);
+sampler3D sZoneVolumeMap : register(s15);
+
+#define Sample2D(tex, uv) tex2D(s##tex, uv)
+#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 SampleShadow(tex, uv) tex2Dproj(s##tex, uv)
+
+#else
+
+// D3D11 textures and samplers
+
+Texture2D tDiffMap : register(t0);
+TextureCube tDiffCubeMap : register(t0);
+Texture2D tAlbedoBuffer : register(t0);
+Texture2D tNormalMap : register(t1);
+Texture2D tNormalBuffer : register(t1);
+Texture2D tSpecMap : register(t2);
+Texture2D tEmissiveMap : register(t3);
+Texture2D tEnvMap : register(t4);
+Texture3D tVolumeMap : register(t5);
+TextureCube tEnvCubeMap : register(t4);
+Texture2D tLightRampMap : register(t8);
+Texture2D tLightSpotMap : register(t9);
+TextureCube tLightCubeMap : register(t9);
+Texture2D tShadowMap : register(t10);
+TextureCube tFaceSelectCubeMap : register(t11);
+TextureCube tIndirectionCubeMap : register(t12);
+Texture2D tDepthBuffer : register(t13);
+Texture2D tLightBuffer : register(t14);
+TextureCube tZoneCubeMap : register(t15);
+Texture3D tZoneVolumeMap : register(t15);
+
+SamplerState sDiffMap : register(s0);
+SamplerState sDiffCubeMap : register(s0);
+SamplerState sAlbedoBuffer : register(s0);
+SamplerState sNormalMap : register(s1);
+SamplerState sNormalBuffer : register(s1);
+SamplerState sSpecMap : register(s2);
+SamplerState sEmissiveMap : register(s3);
+SamplerState sEnvMap : register(s4);
+SamplerState sVolumeMap : register(s5);
+SamplerState sEnvCubeMap : register(s4);
+SamplerState sLightRampMap : register(s8);
+SamplerState sLightSpotMap : register(s9);
+SamplerState sLightCubeMap : register(s9);
+SamplerComparisonState sShadowMap : register(s10);
+SamplerState sFaceSelectCubeMap : register(s11);
+SamplerState sIndirectionCubeMap : register(s12);
+SamplerState sDepthBuffer : register(s13);
+SamplerState sLightBuffer : register(s14);
+SamplerState sZoneCubeMap : register(s15);
+SamplerState sZoneVolumeMap : register(s15);
+
+#define Sample2D(tex, uv) t##tex.Sample(s##tex, uv)
+#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 SampleShadow(tex, uv) t##tex.SampleCmpLevelZero(s##tex, uv.xy, uv.z)
+
+#endif
 
 float3 DecodeNormal(float4 normalInput)
 {
-    #ifdef PACKEDNORMAL
-        float3 normal;
-        normal.xy = normalInput.ag * 2.0 - 1.0;
-        #ifdef SM3
-            normal.z = sqrt(max(1.0 - dot(normal.xy, normal.xy), 0.0));
-        #else
-            normal.z = sqrt(1.0 - dot(normal.xy, normal.xy));
-        #endif
-        return normal;
-    #else
-        return normalInput.rgb * 2.0 - 1.0;
-    #endif
+#ifdef PACKEDNORMAL
+    float3 normal;
+    normal.xy = normalInput.ag * 2.0 - 1.0;
+    normal.z = sqrt(max(1.0 - dot(normal.xy, normal.xy), 0.0));
+    return normal;
+#else
+    return normalInput.rgb * 2.0 - 1.0;
+#endif
 }
 
 float ReconstructDepth(float hwDepth)
 {
     return dot(float2(hwDepth, cDepthReconstruct.y / (hwDepth - cDepthReconstruct.x)), cDepthReconstruct.zw);
 }
+
 #endif

+ 3 - 3
Data/AtomicPlayer/Resources/CoreData/Shaders/HLSL/ScreenPos.hlsl

@@ -12,7 +12,7 @@ void VS(float4 iPos : POSITION,
     #endif
     float2 iTexCoord : TEXCOORD0,
     out float2 oTexCoord : TEXCOORD0,
-    out float4 oPos : POSITION)
+    out float4 oPos : OUTPOSITION)
 {
     float4x3 modelMatrix = iModelMatrix;
     float3 worldPos = GetWorldPos(modelMatrix);
@@ -22,10 +22,10 @@ void VS(float4 iPos : POSITION,
 
 void PS(
     float2 iTexCoord : TEXCOORD0,
-    out float4 oColor : COLOR0)
+    out float4 oColor : OUTCOLOR0)
 {
     #ifdef ALPHAMASK
-        float alpha = tex2D(sDiffMap, iTexCoord).a;
+        float alpha = Sample2D(DiffMap, iTexCoord).a;
         if (alpha < 0.5)
             discard;
     #endif

+ 9 - 8
Data/AtomicPlayer/Resources/CoreData/Shaders/HLSL/Shadow2D.hlsl

@@ -8,7 +8,9 @@
 uniform float4 cShadowAmbient;
 #endif
 
-void VS(float4 iPos : POSITION, out float4 oPos : POSITION, out float2 oScreenPos : TEXCOORD0)
+void VS(float4 iPos : POSITION,
+       out float2 oScreenPos : TEXCOORD0,
+       out float4 oPos : OUTPOSITION)
 {
     float4x3 modelMatrix = iModelMatrix;
     float3 worldPos = GetWorldPos(modelMatrix);
@@ -16,13 +18,12 @@ void VS(float4 iPos : POSITION, out float4 oPos : POSITION, out float2 oScreenPo
     oScreenPos = GetScreenPosPreDiv(oPos);
 }
 
-void PS(float2 iScreenPos : TEXCOORD0, out float4 oColor : COLOR0)
+void PS(float2 iScreenPos : TEXCOORD0, out float4 oColor : OUTCOLOR0)
 {
-	float4 diffInput = tex2D(sDiffMap, iScreenPos);
-    float4 lightInput = tex2D(sEmissiveMap, iScreenPos);
-	oColor.rgb = (diffInput.rgb * (lightInput.rgb + cShadowAmbient.rgb) * (lightInput.a + cShadowAmbient.a));
-    oColor.a = 1.0;
-}
-
 
+    float4 diffInput = Sample2D(DiffMap, iScreenPos);
+    float4 lightInput = Sample2D(EmissiveMap, iScreenPos);
 
+	  oColor.rgb = (diffInput.rgb * (lightInput.rgb + cShadowAmbient.rgb) * (lightInput.a + cShadowAmbient.a));
+    oColor.a = 1.0;
+}

+ 4 - 4
Data/AtomicPlayer/Resources/CoreData/Shaders/HLSL/Skybox.hlsl

@@ -3,8 +3,8 @@
 #include "Transform.hlsl"
 
 void VS(float4 iPos : POSITION,
-    out float4 oPos : POSITION,
-    out float3 oTexCoord : TEXCOORD0)
+    out float3 oTexCoord : TEXCOORD0,
+    out float4 oPos : OUTPOSITION)
 {
     float4x3 modelMatrix = iModelMatrix;
     float3 worldPos = GetWorldPos(modelMatrix);
@@ -15,7 +15,7 @@ void VS(float4 iPos : POSITION,
 }
 
 void PS(float3 iTexCoord : TEXCOORD0,
-    out float4 oColor : COLOR0)
+    out float4 oColor : OUTCOLOR0)
 {
-    oColor = cMatDiffColor * texCUBE(sDiffCubeMap, iTexCoord);
+    oColor = cMatDiffColor * SampleCube(DiffCubeMap, iTexCoord);
 }

+ 2 - 2
Data/AtomicPlayer/Resources/CoreData/Shaders/HLSL/Stencil.hlsl

@@ -2,14 +2,14 @@
 #include "Transform.hlsl"
 
 void VS(float4 iPos : POSITION,
-    out float4 oPos : POSITION)
+    out float4 oPos : OUTPOSITION)
 {
     float4x3 modelMatrix = iModelMatrix;
     float3 worldPos = GetWorldPos(modelMatrix);
     oPos = GetClipPos(worldPos);
 }
 
-void PS(out float4 oColor : COLOR0)
+void PS(out float4 oColor : OUTCOLOR0)
 {
     oColor = 1.0;
 }

+ 52 - 21
Data/AtomicPlayer/Resources/CoreData/Shaders/HLSL/TerrainBlend.hlsl

@@ -5,17 +5,38 @@
 #include "Lighting.hlsl"
 #include "Fog.hlsl"
 
-// When rendering a shadowed point light, disable specular calculations on Shader Model 2 to avoid exceeding the instruction limit
-#if !defined(SM3) && defined(SHADOW) && defined(POINTLIGHT)
-    #undef SPECULAR
+#ifndef D3D11
+
+// D3D9 uniforms and samplers
+#ifdef COMPILEVS
+uniform float2 cDetailTiling;
+#else
+sampler2D sWeightMap0 : register(s0);
+sampler2D sDetailMap1 : register(s1);
+sampler2D sDetailMap2 : register(s2);
+sampler2D sDetailMap3 : register(s3);
 #endif
 
-sampler2D sWeightMap0 : register(S0);
-sampler2D sDetailMap1 : register(S1);
-sampler2D sDetailMap2 : register(S2);
-sampler2D sDetailMap3 : register(S3);
+#else
 
-uniform float2 cDetailTiling;
+// D3D11 constant buffers and samplers
+#ifdef COMPILEVS
+cbuffer CustomVS : register(b6)
+{
+    float2 cDetailTiling;
+}
+#else
+Texture2D tWeightMap0 : register(t0);
+Texture2D tDetailMap1 : register(t1);
+Texture2D tDetailMap2 : register(t2);
+Texture2D tDetailMap3 : register(t3);
+SamplerState sWeightMap0 : register(s0);
+SamplerState sDetailMap1 : register(s1);
+SamplerState sDetailMap2 : register(s2);
+SamplerState sDetailMap3 : register(s3);
+#endif
+
+#endif
 
 void VS(float4 iPos : POSITION,
     float3 iNormal : NORMAL,
@@ -48,7 +69,10 @@ void VS(float4 iPos : POSITION,
         out float3 oVertexLight : TEXCOORD4,
         out float4 oScreenPos : TEXCOORD5,
     #endif
-    out float4 oPos : POSITION)
+    #if defined(D3D11) && defined(CLIPPLANE)
+        out float oClip : SV_CLIPDISTANCE0,
+    #endif
+    out float4 oPos : OUTPOSITION)
 {
     float4x3 modelMatrix = iModelMatrix;
     float3 worldPos = GetWorldPos(modelMatrix);
@@ -58,6 +82,10 @@ void VS(float4 iPos : POSITION,
     oTexCoord = GetTexCoord(iTexCoord);
     oDetailTexCoord = cDetailTiling * oTexCoord;
 
+    #if defined(D3D11) && defined(CLIPPLANE)
+        oClip = dot(oPos, cClipPlane);
+    #endif
+
     #ifdef PERPIXEL
         // Per-pixel forward lighting
         float4 projWorldPos = float4(worldPos.xyz, 1.0);
@@ -106,24 +134,27 @@ void PS(float2 iTexCoord : TEXCOORD0,
         float3 iVertexLight : TEXCOORD4,
         float4 iScreenPos : TEXCOORD5,
     #endif
+    #if defined(D3D11) && defined(CLIPPLANE)
+        float iClip : SV_CLIPDISTANCE0,
+    #endif
     #ifdef PREPASS
-        out float4 oDepth : COLOR1,
+        out float4 oDepth : OUTCOLOR1,
     #endif
     #ifdef DEFERRED
-        out float4 oAlbedo : COLOR1,
-        out float4 oNormal : COLOR2,
-        out float4 oDepth : COLOR3,
+        out float4 oAlbedo : OUTCOLOR1,
+        out float4 oNormal : OUTCOLOR2,
+        out float4 oDepth : OUTCOLOR3,
     #endif
-    out float4 oColor : COLOR0)
+    out float4 oColor : OUTCOLOR0)
 {
     // Get material diffuse albedo
-    float3 weights = tex2D(sWeightMap0, iTexCoord).rgb;
+    float3 weights = Sample2D(WeightMap0, iTexCoord).rgb;
     float sumWeights = weights.r + weights.g + weights.b;
     weights /= sumWeights;
     float4 diffColor = cMatDiffColor * (
-        weights.r * tex2D(sDetailMap1, iDetailTexCoord) +
-        weights.g * tex2D(sDetailMap2, iDetailTexCoord) +
-        weights.b * tex2D(sDetailMap3, iDetailTexCoord)
+        weights.r * Sample2D(DetailMap1, iDetailTexCoord) +
+        weights.g * Sample2D(DetailMap2, iDetailTexCoord) +
+        weights.b * Sample2D(DetailMap3, iDetailTexCoord)
     );
 
     // Get material specular albedo
@@ -152,9 +183,9 @@ void PS(float2 iTexCoord : TEXCOORD0,
         #endif
     
         #if defined(SPOTLIGHT)
-            lightColor = iSpotPos.w > 0.0 ? tex2Dproj(sLightSpotMap, iSpotPos).rgb * cLightColor.rgb : 0.0;
+            lightColor = iSpotPos.w > 0.0 ? Sample2DProj(LightSpotMap, iSpotPos).rgb * cLightColor.rgb : 0.0;
         #elif defined(CUBEMASK)
-            lightColor = texCUBE(sLightCubeMap, iCubeMaskVec).rgb * cLightColor.rgb;
+            lightColor = SampleCube(LightCubeMap, iCubeMaskVec).rgb * cLightColor.rgb;
         #else
             lightColor = cLightColor.rgb;
         #endif
@@ -197,7 +228,7 @@ void PS(float2 iTexCoord : TEXCOORD0,
         #ifdef MATERIAL
             // Add light pre-pass accumulation result
             // Lights are accumulated at half intensity. Bring back to full intensity now
-            float4 lightInput = 2.0 * tex2Dproj(sLightBuffer, iScreenPos);
+            float4 lightInput = 2.0 * Sample2DProj(LightBuffer, iScreenPos);
             float3 lightSpecColor = lightInput.a * (lightInput.rgb / GetIntensity(lightInput.rgb));
 
             finalColor += lightInput.rgb * diffColor.rgb + lightSpecColor * specColor;

+ 27 - 15
Data/AtomicPlayer/Resources/CoreData/Shaders/HLSL/Text.hlsl

@@ -2,21 +2,33 @@
 #include "Samplers.hlsl"
 #include "Transform.hlsl"
 
-#ifdef TEXT_EFFECT_SHADOW
+#ifndef D3D11
+
+// D3D9 uniforms
 uniform float2 cShadowOffset;
 uniform float4 cShadowColor;
+uniform float4 cStrokeColor;
+
+#else
+
+#ifdef COMPILEPS
+// D3D11 constant buffers
+cbuffer CustomPS : register(b6)
+{
+    float2 cShadowOffset;
+    float4 cShadowColor;
+    float4 cStrokeColor;
+}
 #endif
 
-#ifdef TEXT_EFFECT_STROKE
-uniform float4 cStrokeColor;
 #endif
 
 void VS(float4 iPos : POSITION,
-        float4 iColor : COLOR0,
-        float2 iTexCoord : TEXCOORD0,
-        out float4 oPos : POSITION,
-        out float4 oColor : COLOR0,
-        out float2 oTexCoord : TEXCOORD0)
+    float2 iTexCoord : TEXCOORD0,
+    out float2 oTexCoord : TEXCOORD0,
+    float4 iColor : COLOR0,
+    out float4 oColor : COLOR0,
+    out float4 oPos : OUTPOSITION)
 {
     float4x3 modelMatrix = iModelMatrix;
     float3 worldPos = GetWorldPos(modelMatrix);
@@ -25,18 +37,18 @@ void VS(float4 iPos : POSITION,
     oTexCoord = iTexCoord;
 }
 
-void PS(float4 iColor : COLOR0,
-        float2 iTexCoord : TEXCOORD0,
-        out float4 oColor : COLOR0)
+void PS(float2 iTexCoord : TEXCOORD0,
+    float4 iColor : COLOR0,
+    out float4 oColor : OUTCOLOR0)
 {
     oColor.rgb = iColor.rgb;
 
 #ifdef SIGNED_DISTANCE_FIELD
-    float distance = tex2D(sDiffMap, iTexCoord).a;
+    float distance = Sample2D(DiffMap, iTexCoord).a;
     if (distance < 0.5f)
     {
     #ifdef TEXT_EFFECT_SHADOW
-        if (tex2D(sDiffMap, iTexCoord - cShadowOffset).a > 0.5f)
+        if (Sample2D(DiffMap, iTexCoord - cShadowOffset).a > 0.5f)
             oColor = cShadowColor;
         else
     #endif
@@ -50,13 +62,13 @@ void PS(float4 iColor : COLOR0,
     #endif
 
     #ifdef TEXT_EFFECT_SHADOW
-        if (tex2D(sDiffMap, iTexCoord + cShadowOffset).a < 0.5f)
+        if (Sample2D(DiffMap, iTexCoord + cShadowOffset).a < 0.5f)
             oColor.a = iColor.a;
         else
     #endif
         oColor.a = iColor.a * smoothstep(0.5f, 0.505f, distance);
     }
 #else
-    oColor.a = iColor.a * tex2D(sDiffMap, iTexCoord).a;
+    oColor.a = iColor.a * Sample2D(DiffMap, iTexCoord).a;
 #endif
 }

+ 22 - 6
Data/AtomicPlayer/Resources/CoreData/Shaders/HLSL/Tonemap.hlsl

@@ -4,12 +4,28 @@
 #include "ScreenPos.hlsl"
 #include "PostProcess.hlsl"
 
+#ifndef D3D11
+
+// D3D9 uniforms
 uniform float cTonemapExposureBias;
 uniform float cTonemapMaxWhite;
 
+#else
+
+#ifdef COMPILEPS
+// D3D11 constant buffers
+cbuffer CustomPS : register(b6)
+{
+    float cTonemapExposureBias;
+    float cTonemapMaxWhite;
+}
+#endif
+
+#endif
+
 void VS(float4 iPos : POSITION,
-    out float4 oPos : POSITION,
-    out float2 oScreenPos : TEXCOORD0)
+    out float2 oScreenPos : TEXCOORD0,
+    out float4 oPos : OUTPOSITION)
 {
     float4x3 modelMatrix = iModelMatrix;
     float3 worldPos = GetWorldPos(modelMatrix);
@@ -18,20 +34,20 @@ void VS(float4 iPos : POSITION,
 }
 
 void PS(float2 iScreenPos : TEXCOORD0,
-    out float4 oColor : COLOR0)
+    out float4 oColor : OUTCOLOR0)
 {
     #ifdef REINHARDEQ3
-    float3 color = ReinhardEq3Tonemap(max(tex2D(sDiffMap, iScreenPos).rgb * cTonemapExposureBias, 0.0));
+    float3 color = ReinhardEq3Tonemap(max(Sample2D(DiffMap, iScreenPos).rgb * cTonemapExposureBias, 0.0));
     oColor = float4(color, 1.0);
     #endif
 
     #ifdef REINHARDEQ4
-    float3 color = ReinhardEq4Tonemap(max(tex2D(sDiffMap, iScreenPos).rgb * cTonemapExposureBias, 0.0), cTonemapMaxWhite);
+    float3 color = ReinhardEq4Tonemap(max(Sample2D(DiffMap, iScreenPos).rgb * cTonemapExposureBias, 0.0), cTonemapMaxWhite);
     oColor = float4(color, 1.0);
     #endif
 
     #ifdef UNCHARTED2
-    float3 color = Uncharted2Tonemap(max(tex2D(sDiffMap, iScreenPos).rgb * cTonemapExposureBias, 0.0)) / 
+    float3 color = Uncharted2Tonemap(max(Sample2D(DiffMap, iScreenPos).rgb * cTonemapExposureBias, 0.0)) / 
         Uncharted2Tonemap(float3(cTonemapMaxWhite, cTonemapMaxWhite, cTonemapMaxWhite));
     oColor = float4(color, 1.0);
     #endif

+ 26 - 0
Data/AtomicPlayer/Resources/CoreData/Shaders/HLSL/Transform.hlsl

@@ -1,4 +1,11 @@
 #ifdef COMPILEVS
+
+#ifdef D3D11
+#define OUTPOSITION SV_POSITION
+#else
+#define OUTPOSITION POSITION
+#endif
+
 #ifdef SKINNED
 float4x3 GetSkinMatrix(float4 blendWeights, int4 blendIndices)
 {
@@ -29,6 +36,7 @@ float GetDepth(float4 clipPos)
     return dot(clipPos.zw, cDepthMode.zw);
 }
 
+#ifdef BILLBOARD
 float3 GetBillboardPos(float4 iPos, float2 iSize, float4x3 modelMatrix)
 {
     return mul(iPos, modelMatrix) + mul(float3(iSize.x, iSize.y, 0.0), cBillboardRot);
@@ -38,6 +46,7 @@ float3 GetBillboardNormal()
 {
     return float3(-cBillboardRot[2][0], -cBillboardRot[2][1], -cBillboardRot[2][2]);
 }
+#endif
 
 #if defined(SKINNED)
     #define iModelMatrix GetSkinMatrix(iBlendWeights, iBlendIndices);
@@ -61,3 +70,20 @@ float3 GetBillboardNormal()
 
 #define GetWorldTangent(modelMatrix) normalize(mul(iTangent.xyz, (float3x3)modelMatrix))
 #endif
+
+#ifdef COMPILEPS
+
+#ifdef D3D11
+#define OUTCOLOR0 SV_TARGET
+#define OUTCOLOR1 SV_TARGET1
+#define OUTCOLOR2 SV_TARGET2
+#define OUTCOLOR3 SV_TARGET3
+#else
+#define OUTCOLOR0 COLOR0
+#define OUTCOLOR1 COLOR1
+#define OUTCOLOR2 COLOR2
+#define OUTCOLOR3 COLOR3
+#endif
+
+#endif
+

+ 126 - 5
Data/AtomicPlayer/Resources/CoreData/Shaders/HLSL/Uniforms.hlsl

@@ -1,8 +1,15 @@
+#ifndef D3D11
+
+// D3D9 uniforms (no constant buffers)
+
 #ifdef COMPILEVS
+
 // Vertex shader uniforms
 uniform float3 cAmbientStartColor;
 uniform float3 cAmbientEndColor;
+#ifdef BILLBOARD
 uniform float3x3 cBillboardRot;
+#endif
 uniform float3 cCameraPos;
 uniform float3x3 cCameraRot;
 uniform float cNearClip;
@@ -19,16 +26,18 @@ uniform float4x4 cViewProj;
 uniform float4 cUOffset;
 uniform float4 cVOffset;
 uniform float4x3 cZone;
-uniform float4x4 cLightMatrices[4];
 #ifdef SKINNED
-    uniform float4x3 cSkinMatrices[64];
+    uniform float4x3 cSkinMatrices[MAXBONES];
 #endif
 #ifdef NUMVERTEXLIGHTS
     uniform float4 cVertexLights[4*3];
+#else
+    uniform float4x4 cLightMatrices[4];
 #endif
 #endif
 
 #ifdef COMPILEPS
+
 // Pixel shader uniforms
 uniform float3 cAmbientColor;
 uniform float3 cCameraPosPS;
@@ -52,9 +61,121 @@ uniform float4 cShadowDepthFade;
 uniform float2 cShadowIntensity;
 uniform float2 cShadowMapInvSize;
 uniform float4 cShadowSplits;
-#ifdef SM3
-    uniform float4x4 cLightMatricesPS[4];
+uniform float4x4 cLightMatricesPS[4];
+#endif
+
 #else
-    uniform float4x4 cLightMatricesPS[3];
+
+// D3D11 uniforms (using constant buffers)
+
+#ifdef COMPILEVS
+
+// Vertex shader uniforms
+cbuffer FrameVS : register(b0)
+{
+    float cDeltaTime;
+    float cElapsedTime;
+}
+
+cbuffer CameraVS : register(b1)
+{
+    float3 cCameraPos;
+    float3x3 cCameraRot;
+    float cNearClip;
+    float cFarClip;
+    float4 cDepthMode;
+    float3 cFrustumSize;
+    float4 cGBufferOffsets;
+    float4x4 cViewProj;
+    float4 cClipPlane;
+}
+
+cbuffer ZoneVS : register(b2)
+{
+    float3 cAmbientStartColor;
+    float3 cAmbientEndColor;
+    float4x3 cZone;
+}
+
+cbuffer LightVS : register(b3)
+{
+    float3 cLightDir;
+    float4 cLightPos;
+#ifdef NUMVERTEXLIGHTS
+    float4 cVertexLights[4 * 3];
+#else
+    float4x4 cLightMatrices[4];
 #endif
+}
+
+#ifndef CUSTOM_MATERIAL_CBUFFER
+cbuffer MaterialVS : register(b4)
+{
+    float4 cUOffset;
+    float4 cVOffset;
+}
+#endif
+
+cbuffer ObjectVS : register(b5)
+{
+    float4x3 cModel;
+#ifdef BILLBOARD
+    float3x3 cBillboardRot;
+#endif
+#ifdef SKINNED
+    uniform float4x3 cSkinMatrices[MAXBONES];
+#endif
+}
+#endif
+
+#ifdef COMPILEPS
+
+// Pixel shader uniforms
+cbuffer FramePS : register(b0)
+{
+    float cDeltaTimePS;
+    float cElapsedTimePS;
+}
+
+cbuffer CameraPS : register(b1)
+{
+    float3 cCameraPosPS;
+    float4 cDepthReconstruct;
+    float2 cGBufferInvSize;
+    float cNearClipPS;
+    float cFarClipPS;
+}
+
+cbuffer ZonePS : register(b2)
+{
+    float3 cAmbientColor;
+    float4 cFogParams;
+    float3 cFogColor;
+}
+
+cbuffer LightPS : register(b3)
+{
+    float4 cLightColor;
+    float4 cLightPosPS;
+    float3 cLightDirPS;
+    float4 cShadowCubeAdjust;
+    float4 cShadowDepthFade;
+    float2 cShadowIntensity;
+    float2 cShadowMapInvSize;
+    float4 cShadowSplits;
+    float4x4 cLightMatricesPS[4];
+}
+
+#ifndef CUSTOM_MATERIAL_CBUFFER
+cbuffer MaterialPS : register(b4)
+{
+    float4 cMatDiffColor;
+    float3 cMatEmissiveColor;
+    float3 cMatEnvMapColor;
+    float4 cMatSpecColor;
+}
+#endif
+
+#endif
+
 #endif

+ 25 - 8
Data/AtomicPlayer/Resources/CoreData/Shaders/HLSL/Unlit.hlsl

@@ -4,7 +4,9 @@
 #include "Fog.hlsl"
 
 void VS(float4 iPos : POSITION,
-    float2 iTexCoord : TEXCOORD0,
+    #ifndef NOUV
+        float2 iTexCoord : TEXCOORD0,
+    #endif
     #ifdef VERTEXCOLOR
         float4 iColor : COLOR0,
     #endif
@@ -23,14 +25,26 @@ void VS(float4 iPos : POSITION,
     #ifdef VERTEXCOLOR
         out float4 oColor : COLOR0,
     #endif
-    out float4 oPos : POSITION)
+    #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);
     oPos = GetClipPos(worldPos);
     oTexCoord = GetTexCoord(iTexCoord);
     oWorldPos = float4(worldPos, GetDepth(oPos));
 
+    #if defined(D3D11) && defined(CLIPPLANE)
+        oClip = dot(oPos, cClipPlane);
+    #endif
+    
     #ifdef VERTEXCOLOR
         oColor = iColor;
     #endif
@@ -41,19 +55,22 @@ void PS(float2 iTexCoord : TEXCOORD0,
     #ifdef VERTEXCOLOR
         float4 iColor : COLOR0,
     #endif
+    #if defined(D3D11) && defined(CLIPPLANE)
+        float iClip : SV_CLIPDISTANCE0,
+    #endif
     #ifdef PREPASS
-        out float4 oDepth : COLOR1,
+        out float4 oDepth : OUTCOLOR1,
     #endif
     #ifdef DEFERRED
-        out float4 oAlbedo : COLOR1,
-        out float4 oNormal : COLOR2,
-        out float4 oDepth : COLOR3,
+        out float4 oAlbedo : OUTCOLOR1,
+        out float4 oNormal : OUTCOLOR2,
+        out float4 oDepth : OUTCOLOR3,
     #endif
-    out float4 oColor : COLOR0)
+    out float4 oColor : OUTCOLOR0)
 {
     // Get material diffuse albedo
     #ifdef DIFFMAP
-        float4 diffColor = cMatDiffColor * tex2D(sDiffMap, iTexCoord);
+        float4 diffColor = cMatDiffColor * Sample2D(DiffMap, iTexCoord);
         #ifdef ALPHAMASK
             if (diffColor.a < 0.5)
                 discard;

+ 8 - 1
Data/AtomicPlayer/Resources/CoreData/Shaders/HLSL/Vegetation.hlsl

@@ -57,7 +57,10 @@ void VS(float4 iPos : POSITION,
             out float2 oTexCoord2 : TEXCOORD7,
         #endif
     #endif
-    out float4 oPos : POSITION)
+    #if defined(D3D11) && defined(CLIPPLANE)
+        out float oClip : SV_CLIPDISTANCE0,
+    #endif
+    out float4 oPos : OUTPOSITION)
 {
     float4x3 modelMatrix = iModelMatrix;
     float3 worldPos = GetWorldPos(modelMatrix);
@@ -72,6 +75,10 @@ void VS(float4 iPos : POSITION,
     oNormal = GetWorldNormal(modelMatrix);
     oWorldPos = float4(worldPos, GetDepth(oPos));
 
+    #if defined(D3D11) && defined(CLIPPLANE)
+        oClip = dot(oPos, cClipPlane);
+    #endif
+    
     #ifdef NORMALMAP
         float3 tangent = GetWorldTangent(modelMatrix);
         float3 bitangent = cross(tangent, oNormal) * iTangent.w;

+ 38 - 5
Data/AtomicPlayer/Resources/CoreData/Shaders/HLSL/VegetationDepth.hlsl

@@ -4,12 +4,35 @@
 #include "ScreenPos.hlsl"
 #include "Fog.hlsl"
 
+#ifndef D3D11
+
+// D3D9 uniforms
 uniform float2 cNoiseSpeed;
 uniform float cNoiseTiling;
 uniform float cNoiseStrength;
 uniform float cFresnelPower;
 uniform float3 cWaterTint;
 
+#else
+
+// D3D11 constant buffers
+#ifdef COMPILEVS
+cbuffer CustomVS : register(b6)
+{
+    float2 cNoiseSpeed;
+    float cNoiseTiling;
+}
+#else
+cbuffer CustomPS : register(b6)
+{
+    float cNoiseStrength;
+    float cFresnelPower;
+    float3 cWaterTint;
+}
+#endif
+
+#endif
+
 void VS(float4 iPos : POSITION,
     float3 iNormal: NORMAL,
     float2 iTexCoord : TEXCOORD0,
@@ -18,7 +41,10 @@ void VS(float4 iPos : POSITION,
     out float2 oWaterUV : TEXCOORD2,
     out float3 oNormal : TEXCOORD3,
     out float4 oEyeVec : TEXCOORD4,
-    out float4 oPos : POSITION)
+    #if defined(D3D11) && defined(CLIPPLANE)
+        out float oClip : SV_CLIPDISTANCE0,
+    #endif
+    out float4 oPos : OUTPOSITION)
 {
     float4x3 modelMatrix = iModelMatrix;
     float3 worldPos = GetWorldPos(modelMatrix);
@@ -31,6 +57,10 @@ void VS(float4 iPos : POSITION,
     oWaterUV = iTexCoord * cNoiseTiling + cElapsedTime * cNoiseSpeed;
     oNormal = GetWorldNormal(modelMatrix);
     oEyeVec = float4(cCameraPos - worldPos, GetDepth(oPos));
+
+    #if defined(D3D11) && defined(CLIPPLANE)
+        oClip = dot(oPos, cClipPlane);
+    #endif
 }
 
 void PS(
@@ -39,12 +69,15 @@ void PS(
     float2 iWaterUV : TEXCOORD2,
     float3 iNormal : TEXCOORD3,
     float4 iEyeVec : TEXCOORD4,
-    out float4 oColor : COLOR0)
+    #if defined(D3D11) && defined(CLIPPLANE)
+        float iClip : SV_CLIPDISTANCE0,
+    #endif
+    out float4 oColor : OUTCOLOR0)
 {
     float2 refractUV = iScreenPos.xy / iScreenPos.w;
     float2 reflectUV = iReflectUV.xy / iScreenPos.w;
 
-    float2 noise = (tex2D(sNormalMap, iWaterUV).rg - 0.5) * cNoiseStrength;
+    float2 noise = (Sample2D(NormalMap, iWaterUV).rg - 0.5) * cNoiseStrength;
     refractUV += noise;
     // Do not shift reflect UV coordinate upward, because it will reveal the clipping of geometry below water
     if (noise.y < 0.0)
@@ -52,8 +85,8 @@ void PS(
     reflectUV += noise;
 
     float fresnel = pow(1.0 - saturate(dot(normalize(iEyeVec.xyz), iNormal)), cFresnelPower);
-    float3 refractColor = tex2D(sEnvMap, refractUV).rgb * cWaterTint;
-    float3 reflectColor = tex2D(sDiffMap, reflectUV).rgb;
+    float3 refractColor = Sample2D(EnvMap, refractUV).rgb * cWaterTint;
+    float3 reflectColor = Sample2D(DiffMap, reflectUV).rgb;
     float3 finalColor = lerp(refractColor, reflectColor, fresnel);
 
     oColor = float4(GetFog(finalColor, GetFogFactor(iEyeVec.w)), 1.0);

+ 1 - 1
Data/AtomicPlayer/Resources/CoreData/Techniques/Diff.xml

@@ -1,6 +1,6 @@
 <technique vs="LitSolid" ps="LitSolid" psdefines="DIFFMAP">
     <pass name="base" />
-    <pass name="litbase" vsdefines="NORMALMAP" psdefines="AMBIENT NORMALMAP" sm3="true" />
+    <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" />

+ 1 - 1
Data/AtomicPlayer/Resources/CoreData/Techniques/DiffNormalAO.xml

@@ -1,6 +1,6 @@
 <technique vs="LitSolid" ps="LitSolid" psdefines="DIFFMAP ALPHAMASK" alphamask="true">
     <pass name="base" />
-    <pass name="litbase" vsdefines="NORMALMAP" psdefines="AMBIENT NORMALMAP" sm3="true" />
+    <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" />

+ 1 - 1
Data/AtomicPlayer/Resources/CoreData/Techniques/DiffNormalEmissive.xml

@@ -1,6 +1,6 @@
 <technique vs="LitSolid" ps="LitSolid" psdefines="DIFFMAP">
     <pass name="base" />
-    <pass name="litbase" vsdefines="NORMALMAP" psdefines="AMBIENT NORMALMAP PACKEDNORMAL" sm3="true" />
+    <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" />

+ 1 - 1
Data/AtomicPlayer/Resources/CoreData/Techniques/DiffNormalPackedAO.xml

@@ -1,6 +1,6 @@
 <technique vs="LitSolid" ps="LitSolid" psdefines="DIFFMAP ALPHAMASK" alphamask="true">
     <pass name="base" />
-    <pass name="litbase" vsdefines="NORMALMAP" psdefines="AMBIENT NORMALMAP PACKEDNORMAL" sm3="true" />
+    <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" />

+ 1 - 1
Data/AtomicPlayer/Resources/CoreData/Techniques/DiffNormalPackedEmissive.xml

@@ -1,6 +1,6 @@
 <technique vs="LitSolid" ps="LitSolid" psdefines="DIFFMAP">
     <pass name="base" />
-    <pass name="litbase" vsdefines="NORMALMAP" psdefines="AMBIENT NORMALMAP PACKEDNORMAL SPECMAP" sm3="true" />
+    <pass name="litbase" vsdefines="NORMALMAP" psdefines="AMBIENT NORMALMAP PACKEDNORMAL SPECMAP" />
     <pass name="light" vsdefines="NORMALMAP" psdefines="NORMALMAP PACKEDNORMAL SPECMAP" depthtest="equal" depthwrite="false" blend="add" />
     <pass name="prepass" vsdefines="NORMALMAP" psdefines="PREPASS NORMALMAP PACKEDNORMAL SPECMAP" />
     <pass name="material" psdefines="MATERIAL SPECMAP" depthtest="equal" depthwrite="false" />

+ 1 - 1
Data/AtomicPlayer/Resources/CoreData/Techniques/DiffNormalPackedSpecAO.xml

@@ -1,6 +1,6 @@
 <technique vs="LitSolid" ps="LitSolid" psdefines="DIFFMAP ALPHAMASK" alphamask="true">
     <pass name="base" />
-    <pass name="litbase" vsdefines="NORMALMAP" psdefines="AMBIENT NORMALMAP PACKEDNORMAL SPECMAP" sm3="true" />
+    <pass name="litbase" vsdefines="NORMALMAP" psdefines="AMBIENT NORMALMAP PACKEDNORMAL SPECMAP" />
     <pass name="light" vsdefines="NORMALMAP" psdefines="NORMALMAP PACKEDNORMAL SPECMAP" depthtest="equal" depthwrite="false" blend="add" />
     <pass name="prepass" vsdefines="NORMALMAP" psdefines="PREPASS NORMALMAP PACKEDNORMAL SPECMAP" />
     <pass name="material" psdefines="MATERIAL SPECMAP" depthtest="equal" depthwrite="false" />

+ 1 - 1
Data/AtomicPlayer/Resources/CoreData/Techniques/DiffNormalPackedSpecEmissive.xml

@@ -1,6 +1,6 @@
 <technique vs="LitSolid" ps="LitSolid" psdefines="DIFFMAP">
     <pass name="base" />
-    <pass name="litbase" vsdefines="NORMALMAP" psdefines="AMBIENT NORMALMAP SPECMAP" sm3="true" />
+    <pass name="litbase" vsdefines="NORMALMAP" psdefines="AMBIENT NORMALMAP SPECMAP" />
     <pass name="light" vsdefines="NORMALMAP" psdefines="NORMALMAP SPECMAP" depthtest="equal" depthwrite="false" blend="add" />
     <pass name="prepass" vsdefines="NORMALMAP" psdefines="PREPASS NORMALMAP SPECMAP" />
     <pass name="material" psdefines="MATERIAL SPECMAP" depthtest="equal" depthwrite="false" />

+ 1 - 1
Data/AtomicPlayer/Resources/CoreData/Techniques/DiffNormalSpecAO.xml

@@ -1,6 +1,6 @@
 <technique vs="LitSolid" ps="LitSolid" psdefines="DIFFMAP ALPHAMASK" alphamask="true">
     <pass name="base" />
-    <pass name="litbase" vsdefines="NORMALMAP" psdefines="AMBIENT NORMALMAP SPECMAP" sm3="true" />
+    <pass name="litbase" vsdefines="NORMALMAP" psdefines="AMBIENT NORMALMAP SPECMAP" />
     <pass name="light" vsdefines="NORMALMAP" psdefines="NORMALMAP SPECMAP" depthtest="equal" depthwrite="false" blend="add" />
     <pass name="prepass" vsdefines="NORMALMAP" psdefines="PREPASS NORMALMAP SPECMAP" />
     <pass name="material" psdefines="MATERIAL SPECMAP" depthtest="equal" depthwrite="false" />

+ 10 - 0
Data/AtomicPlayer/Resources/CoreData/Techniques/DiffNormalSpecEmissive.xml

@@ -0,0 +1,10 @@
+<technique vs="LitSolid" ps="LitSolid" vsdefines="VERTEXCOLOR" psdefines="DIFFMAP VERTEXCOLOR">
+    <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" />
+    <pass name="shadow" vs="Shadow" ps="Shadow" />
+</technique>

+ 1 - 1
Data/AtomicPlayer/Resources/CoreData/Techniques/DiffVColAdd.xml

@@ -1,4 +1,4 @@
-<technique vs="LitSolid" ps="LitSolid">
+<technique vs="LitSolid" ps="LitSolid" vsdefines="NOUV" >
     <pass name="base" />
     <pass name="litbase" psdefines="AMBIENT" />
     <pass name="light" depthtest="equal" depthwrite="false" blend="add" />

+ 1 - 1
Data/AtomicPlayer/Resources/CoreData/Techniques/NoTextureAO.xml

@@ -1,3 +1,3 @@
-<technique vs="Unlit" ps="Unlit">
+<technique vs="Unlit" ps="Unlit" vsdefines="NOUV" >
     <pass name="alpha" depthwrite="false" blend="add" />
 </technique>

+ 1 - 1
Data/AtomicPlayer/Resources/CoreData/Techniques/NoTextureAddAlpha.xml

@@ -1,3 +1,3 @@
-<technique vs="Unlit" ps="Unlit">
+<technique vs="Unlit" ps="Unlit" vsdefines="NOUV" >
     <pass name="alpha" depthwrite="false" blend="addalpha" />
 </technique>

+ 1 - 1
Data/AtomicPlayer/Resources/CoreData/Techniques/NoTextureAlpha.xml

@@ -1,4 +1,4 @@
-<technique vs="LitSolid" ps="LitSolid">
+<technique vs="LitSolid" ps="LitSolid" vsdefines="NOUV" >
     <pass name="alpha"  depthwrite="false" blend="alpha" />
     <pass name="litalpha" depthwrite="false" blend="addalpha" />
     <pass name="shadow" vs="Shadow" ps="Shadow" />

+ 1 - 1
Data/AtomicPlayer/Resources/CoreData/Techniques/NoTextureEnvCube.xml

@@ -1,3 +1,3 @@
-<technique vs="Unlit" ps="Unlit">
+<technique vs="Unlit" ps="Unlit" vsdefines="NOUV" >
     <pass name="alpha" depthwrite="false" blend="multiply" />
 </technique>

+ 1 - 1
Data/AtomicPlayer/Resources/CoreData/Techniques/NoTextureNormal.xml

@@ -1,6 +1,6 @@
 <technique vs="LitSolid" ps="LitSolid">
     <pass name="base" />
-    <pass name="litbase" vsdefines="NORMALMAP" psdefines="AMBIENT NORMALMAP" sm3="true" />
+    <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" />

+ 1 - 1
Data/AtomicPlayer/Resources/CoreData/Techniques/NoTextureNormalAlpha.xml

@@ -1,6 +1,6 @@
 <technique vs="LitSolid" ps="LitSolid">
     <pass name="base" />
-    <pass name="litbase" vsdefines="NORMALMAP" psdefines="AMBIENT NORMALMAP PACKEDNORMAL" sm3="true" />
+    <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" />

+ 1 - 1
Data/AtomicPlayer/Resources/CoreData/Techniques/NoTextureNormalPackedAlpha.xml

@@ -1,3 +1,3 @@
-<technique vs="Basic" ps="Basic">
+<technique vs="Basic" ps="Basic" vsdefines="NOUV" >
     <pass name="postalpha" depthtest="always" depthwrite="false" />
 </technique>

+ 1 - 1
Data/AtomicPlayer/Resources/CoreData/Techniques/NoTextureUnlit.xml

@@ -1,4 +1,4 @@
-<technique vs="Unlit" ps="Unlit">
+<technique vs="Unlit" ps="Unlit" vsdefines="NOUV" >
     <pass name="base" />
     <pass name="prepass" psdefines="PREPASS" />
     <pass name="material" />

+ 1 - 1
Data/AtomicPlayer/Resources/CoreData/Techniques/NoTextureUnlitAlpha.xml

@@ -1,3 +1,3 @@
-<technique vs="Unlit" ps="Unlit">
+<technique vs="Unlit" ps="Unlit" vsdefines="NOUV" >
     <pass name="alpha" depthwrite="false" blend="alpha" />
 </technique>

+ 1 - 1
Data/AtomicPlayer/Resources/CoreData/Techniques/NoTextureUnlitVCol.xml

@@ -1,4 +1,4 @@
-<technique vs="Unlit" ps="Unlit" vsdefines="VERTEXCOLOR" psdefines="VERTEXCOLOR">
+<technique vs="Unlit" ps="Unlit" vsdefines="VERTEXCOLOR NOUV" psdefines="VERTEXCOLOR">
     <pass name="base" />
     <pass name="prepass" psdefines="PREPASS" />
     <pass name="material" />

+ 10 - 0
Data/AtomicPlayer/Resources/CoreData/Techniques/NoTextureVCol.xml

@@ -0,0 +1,10 @@
+<technique vs="LitSolid" ps="LitSolid" vsdefines="NOUV VERTEXCOLOR" psdefines="VERTEXCOLOR" >
+    <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" />
+    <pass name="shadow" vs="Shadow" ps="Shadow" />
+</technique>

+ 1 - 1
Data/AtomicPlayer/Resources/CoreData/Techniques/NoTextureVColAdd.xml

@@ -1,3 +1,3 @@
-<technique vs="Unlit" ps="Unlit" vsdefines="VERTEXCOLOR" psdefines="VERTEXCOLOR">
+<technique vs="Unlit" ps="Unlit" vsdefines="VERTEXCOLOR NOUV" psdefines="VERTEXCOLOR">
     <pass name="alpha" depthwrite="false" blend="add" />
 </technique>

+ 1 - 1
Data/AtomicPlayer/Resources/CoreData/Techniques/NoTextureVColAddAlpha.xml

@@ -1,3 +1,3 @@
-<technique vs="Unlit" ps="Unlit" vsdefines="VERTEXCOLOR" psdefines="VERTEXCOLOR">
+<technique vs="Unlit" ps="Unlit" vsdefines="VERTEXCOLOR NOUV" psdefines="VERTEXCOLOR">
     <pass name="alpha" depthwrite="false" blend="addalpha" />
 </technique>

+ 1 - 1
Data/AtomicPlayer/Resources/CoreData/Techniques/NoTextureVColMultiply.xml

@@ -1,3 +1,3 @@
-<technique vs="Unlit" ps="Unlit" vsdefines="VERTEXCOLOR" psdefines="VERTEXCOLOR">
+<technique vs="Unlit" ps="Unlit" vsdefines="VERTEXCOLOR NOUV" psdefines="VERTEXCOLOR">
     <pass name="alpha" depthwrite="false" blend="multiply" />
 </technique>

+ 12 - 20
Data/AtomicPlayer/Resources/CoreData/Techniques/TerrainBlend.xml

@@ -21,13 +21,13 @@
 //
 
 #include "Precompiled.h"
-#include "../Atomic2D/AnimatedSprite2D.h"
-#include "../Atomic2D/Animation2D.h"
-#include "../Atomic2D/AnimationSet2D.h"
 #include "../Core/Context.h"
 #include "../Resource/ResourceCache.h"
 #include "../Scene/Scene.h"
 #include "../Scene/SceneEvents.h"
+#include "../Atomic2D/AnimatedSprite2D.h"
+#include "../Atomic2D/Animation2D.h"
+#include "../Atomic2D/AnimationSet2D.h"
 #include "../Atomic2D/Sprite2D.h"
 #include "../Atomic2D/StaticSprite2D.h"
 
@@ -222,7 +222,7 @@ void AnimatedSprite2D::OnWorldBoundingBoxUpdate()
     boundingBox_ = worldBoundingBox_.Transformed(node_->GetWorldTransform().Inverse());
 }
 
-void AnimatedSprite2D::OnLayerChanged()
+void AnimatedSprite2D::OnDrawOrderChanged()
 {
     for (unsigned i = 0; i < numTracks_; ++i)
     {
@@ -235,18 +235,6 @@ void AnimatedSprite2D::OnLayerChanged()
     }
 }
 
-void AnimatedSprite2D::OnBlendModeChanged()
-{
-    for (unsigned i = 0; i < numTracks_; ++i)
-    {
-        if (!trackNodes_[i])
-            continue;
-
-        StaticSprite2D* staticSprite = trackNodes_[i]->GetComponent<StaticSprite2D>();
-        staticSprite->SetBlendMode(blendMode_);
-    }
-}
-
 void AnimatedSprite2D::OnFlipChanged()
 {
     for (unsigned i = 0; i < numTracks_; ++i)
@@ -255,16 +243,17 @@ void AnimatedSprite2D::OnFlipChanged()
             continue;
 
         StaticSprite2D* staticSprite = trackNodes_[i]->GetComponent<StaticSprite2D>();
-        staticSprite->SetFlip(flipX_, flipY_);
+        if (staticSprite)
+            staticSprite->SetFlip(flipX_, flipY_);
     }
 
     // For editor paused mode
     UpdateAnimation(0.0f);
 }
 
-void AnimatedSprite2D::UpdateVertices()
+void AnimatedSprite2D::UpdateSourceBatches()
 {
-    verticesDirty_ = false;
+    sourceBatchesDirty_ = false;
 }
 
 void AnimatedSprite2D::SetAnimation(Animation2D* animation, LoopMode2D loopMode)
@@ -376,7 +365,7 @@ void AnimatedSprite2D::UpdateAnimation(float timeStep)
     {
         trackNodeInfos_[i].worldSpace = false;
         
-        const AnimationTrack2D& track = animation_->GetTrack(i);        
+        const AnimationTrack2D& track = animation_->GetTrack(i);
         const Vector<AnimationKeyFrame2D>& keyFrames = track.keyFrames_;
 
         // Time out of range
@@ -430,6 +419,9 @@ void AnimatedSprite2D::UpdateAnimation(float timeStep)
     for (unsigned i = 0; i < numTracks_; ++i)
     {
         Node* node = trackNodes_[i];
+        if (!node)
+            continue;
+
         TrackNodeInfo& nodeInfo = trackNodeInfos_[i];
 
         if (!nodeInfo.value.enabled_)

+ 3 - 5
Source/Atomic/Atomic2D/AnimatedSprite2D.h

@@ -91,12 +91,10 @@ protected:
     virtual void OnNodeSet(Node* node);
     /// Recalculate the world-space bounding box.
     virtual void OnWorldBoundingBoxUpdate();
-    /// Handle layer changed.
-    virtual void OnLayerChanged();
-    /// Handle blend mode changed.
-    virtual void OnBlendModeChanged();
+    /// Handle draw order changed.
+    virtual void OnDrawOrderChanged();
     /// Handle update vertices.
-    virtual void UpdateVertices();
+    virtual void UpdateSourceBatches();
     /// Handle flip changed.
     virtual void OnFlipChanged();
     /// Set animation.

+ 17 - 97
Source/Atomic/Atomic2D/Drawable2D.cpp

@@ -21,13 +21,13 @@
 //
 
 #include "Precompiled.h"
-#include "../Graphics/Camera.h"
 #include "../Core/Context.h"
-#include "../Atomic2D/Drawable2D.h"
+#include "../Graphics/Camera.h"
 #include "../Graphics/Material.h"
-#include "../Atomic2D/Renderer2D.h"
-#include "../Scene/Scene.h"
 #include "../Graphics/Texture2D.h"
+#include "../Scene/Scene.h"
+#include "../Atomic2D/Drawable2D.h"
+#include "../Atomic2D/Renderer2D.h"
 
 #include "../DebugNew.h"
 
@@ -35,14 +35,16 @@ namespace Atomic
 {
 
 const float PIXEL_SIZE = 0.01f;
-extern const char* blendModeNames[];
+
+SourceBatch2D::SourceBatch2D() : drawOrder_(0)
+{
+}
 
 Drawable2D::Drawable2D(Context* context) :
     Drawable(context, DRAWABLE_GEOMETRY2D),
     layer_(0),
     orderInLayer_(0),
-    blendMode_(BLEND_ALPHA),
-    verticesDirty_(true)
+    sourceBatchesDirty_(true)
 {
 }
 
@@ -56,8 +58,6 @@ void Drawable2D::RegisterObject(Context* context)
 {
     ACCESSOR_ATTRIBUTE("Layer", GetLayer, SetLayer, int, 0, AM_DEFAULT);
     ACCESSOR_ATTRIBUTE("Order in Layer", GetOrderInLayer, SetOrderInLayer, int, 0, AM_DEFAULT);
-    ENUM_ACCESSOR_ATTRIBUTE("Blend Mode", GetBlendMode, SetBlendMode, BlendMode, blendModeNames, BLEND_ALPHA, AM_DEFAULT);
-    COPY_BASE_ATTRIBUTES(Drawable);
 }
 
 void Drawable2D::OnSetEnabled()
@@ -77,11 +77,7 @@ void Drawable2D::SetLayer(int layer)
 
     layer_ = layer;
 
-    OnLayerChanged();
-
-    if (renderer_)
-        renderer_->MarkOrderDirty();
-
+    OnDrawOrderChanged();
     MarkNetworkUpdate();
 }
 
@@ -92,96 +88,28 @@ void Drawable2D::SetOrderInLayer(int orderInLayer)
 
     orderInLayer_ = orderInLayer;
     
-    OnLayerChanged();
-
-    if (renderer_)
-        renderer_->MarkOrderDirty();
-
-    MarkNetworkUpdate();
-}
-
-void Drawable2D::SetTexture(Texture2D* texture)
-{
-    if (texture == texture_)
-        return;
-
-    texture_ = texture;
-
-    verticesDirty_ = true;
-    material_ = 0;
-    if (renderer_)
-        renderer_->MarkMaterialDirty(this);
-
-    OnMarkedDirty(node_);
-
+    OnDrawOrderChanged();
     MarkNetworkUpdate();
 }
 
-void Drawable2D::SetBlendMode(BlendMode blendMode)
+const Vector<SourceBatch2D>& Drawable2D::GetSourceBatches()
 {
-    if (blendMode == blendMode_)
-        return;
+    if (sourceBatchesDirty_)
+        UpdateSourceBatches();
 
-    blendMode_ = blendMode;
-    material_ = 0;
-    if (renderer_)
-        renderer_->MarkMaterialDirty(this);
-
-    OnBlendModeChanged();
-
-    MarkNetworkUpdate();
-}
-
-void Drawable2D::SetCustomMaterial(Material* customMaterial)
-{
-    if (customMaterial == customMaterial_)
-        return;
-
-    customMaterial_ = customMaterial;
-    material_ = 0;
-    if (renderer_)
-        renderer_->MarkMaterialDirty(this);
-
-    MarkNetworkUpdate();
-}
-
-Texture2D* Drawable2D::GetTexture() const
-{
-    return texture_;
-}
-
-Material* Drawable2D::GetCustomMaterial() const
-{
-    return customMaterial_;
-}
-
-void Drawable2D::SetMaterial(Material* material)
-{
-    material_ = material;
-}
-
-Material* Drawable2D::GetMaterial() const
-{
-    return customMaterial_ ? customMaterial_ : material_;
-}
-
-const Vector<Vertex2D>& Drawable2D::GetVertices()
-{
-    if (verticesDirty_)
-        UpdateVertices();
-    return vertices_;
+    return sourceBatches_;
 }
 
 void Drawable2D::OnNodeSet(Node* node)
 {
     // Do not call Drawable::OnNodeSet(node)
-
     if (node)
     {
         Scene* scene = GetScene();
         if (scene)
         {
             renderer_ = scene->GetOrCreateComponent<Renderer2D>();
+
             if (IsEnabledEffective())
                 renderer_->AddDrawable(this);
         }
@@ -199,15 +127,7 @@ void Drawable2D::OnMarkedDirty(Node* node)
 {
     Drawable::OnMarkedDirty(node);
 
-    verticesDirty_ = true;
-}
-
-void Drawable2D::OnLayerChanged()
-{
-}
-
-void Drawable2D::OnBlendModeChanged()
-{
+    sourceBatchesDirty_ = true;
 }
 
 }

+ 26 - 40
Source/Atomic/Atomic2D/Drawable2D.h

@@ -43,7 +43,19 @@ struct Vertex2D
     Vector2 uv_;
 };
 
-static const unsigned MASK_VERTEX2D = MASK_POSITION | MASK_COLOR | MASK_TEXCOORD1;
+/// 2D source batch.
+struct SourceBatch2D
+{
+    /// Construct.
+    SourceBatch2D();
+
+    /// Draw order.
+    int drawOrder_;
+    /// Material.
+    SharedPtr<Material> material_;
+    /// Vertices.
+    Vector<Vertex2D> vertices_;
+};
 
 /// Pixel size (equal 0.01f).
 extern ATOMIC_API const float PIXEL_SIZE;
@@ -68,61 +80,35 @@ public:
     void SetLayer(int layer);
     /// Set order in layer.
     void SetOrderInLayer(int orderInLayer);
-    /// Set texture.
-    void SetTexture(Texture2D* texture);
-    /// Set blend mode.
-    void SetBlendMode(BlendMode mode);
-    /// Set custom material. 
-    void SetCustomMaterial(Material* customMaterial);
     
     /// Return layer.
     int GetLayer() const { return layer_; }
     /// Return order in layer.
     int GetOrderInLayer() const { return orderInLayer_; }
-    /// Return texture.
-    Texture2D* GetTexture() const;
-    /// Return blend mode.
-    BlendMode GetBlendMode() const { return blendMode_; }
-    /// Return custom material.
-    Material* GetCustomMaterial() const;
 
-    /// Set material (called by Renderer2D).
-    void SetMaterial(Material* material);
-    /// Return custom material or material (called by Renderer2D).
-    Material* GetMaterial() const;
-    /// Return all vertices (called by Renderer2D).
-    const Vector<Vertex2D>& GetVertices();
+    /// Return all source batches (called by Renderer2D).
+    const Vector<SourceBatch2D>& GetSourceBatches();
 
 protected:
     /// Handle node being assigned.
     virtual void OnNodeSet(Node* node);
     /// Handle node transform being dirtied.
     virtual void OnMarkedDirty(Node* node);
-    /// Handle layer changed.
-    virtual void OnLayerChanged();
-    /// Handle blend mode changed.
-    virtual void OnBlendModeChanged();
-    /// Update vertices.
-    virtual void UpdateVertices() = 0;
-    
-
+    /// Handle draw order changed.
+    virtual void OnDrawOrderChanged() = 0;
+    /// Update source batches.
+    virtual void UpdateSourceBatches() = 0;
+    /// Return draw order by layer and order in layer.
+    int GetDrawOrder() const { return (layer_ << 20) + (orderInLayer_ << 10); }
+  
     /// Layer.
     int layer_;
     /// Order in layer.
     int orderInLayer_;
-    /// Texture.
-    SharedPtr<Texture2D> texture_;
-    /// Blend mode.
-    BlendMode blendMode_;
-    /// Custom material.
-    SharedPtr<Material> customMaterial_;
-
-    /// Vertices.
-    Vector<Vertex2D> vertices_;
-    /// Vertices dirty flag.
-    bool verticesDirty_;
-    /// Material.
-    SharedPtr<Material> material_;
+    /// Source batches.
+    Vector<SourceBatch2D> sourceBatches_;
+    /// Source batches dirty flag.
+    bool sourceBatchesDirty_;
     /// Renderer2D.
     WeakPtr<Renderer2D> renderer_;
 };

+ 20 - 11
Source/Atomic/Atomic2D/Light2D.cpp

@@ -388,7 +388,7 @@ void PositionalLight2D::UpdateVertices()
     }
 }
 
-PointLight2D::PointLight2D(Context* context) : PositionalLight2D(context),    
+PointLight2D::PointLight2D(Context* context) : PositionalLight2D(context),
     radius_(1.0f)
 {
     lightType_ = LIGHT2D_POINT;
@@ -481,12 +481,13 @@ Light2DGroup::Light2DGroup(Context* context) : Drawable2D(context),
     ambientColor_(0, 0, 0, 0),
     frustum_(0)
 {
+    sourceBatches_.Resize(1);
     SubscribeToEvent(E_BEGINRENDERING, HANDLER(Light2DGroup, HandleBeginRendering));
     SubscribeToEvent(E_BEGINVIEWUPDATE, HANDLER(Light2DGroup, HandleBeginViewUpdate));
 }
 
 Light2DGroup::~Light2DGroup()
-{   
+{
     Renderer* renderer = GetSubsystem<Renderer>();
 
     if (renderer)
@@ -527,7 +528,7 @@ void Light2DGroup::HandleBeginViewUpdate(StringHash eventType, VariantMap& event
 
 void Light2DGroup::HandleBeginRendering(StringHash eventType, VariantMap& eventData)
 {
-    verticesDirty_ = true;
+    sourceBatchesDirty_ = true;
 }
 
 void Light2DGroup::OnWorldBoundingBoxUpdate()
@@ -536,24 +537,32 @@ void Light2DGroup::OnWorldBoundingBoxUpdate()
     worldBoundingBox_.Define(-M_LARGE_VALUE, M_LARGE_VALUE);
 }
 
-void Light2DGroup::UpdateVertices()
+void Light2DGroup::OnDrawOrderChanged()
+{
+    sourceBatches_[0].drawOrder_ = GetDrawOrder();
+}
+
+void Light2DGroup::UpdateSourceBatches()
 {
-    // This is the shadow map
-    if (!verticesDirty_)
+    if (!sourceBatchesDirty_)
         return;
 
-    vertices_.Clear();
+    Vector<Vertex2D>& vertices = sourceBatches_[0].vertices_;
+    vertices.Clear();
 
     for (Vector<WeakPtr<Light2D> >::Iterator itr = lights_.Begin(); itr != lights_.End(); itr++)
     {
         Light2D* light = *itr;
+
         if (!light->IsEnabled())
             continue;
+
         light->UpdateVertices();
-        light->AddVertices(vertices_);
+        light->AddVertices(vertices);
     }
 
-    verticesDirty_ = false;
+    sourceBatchesDirty_ = false;
+
 
 }
 
@@ -654,7 +663,7 @@ void Light2DGroup::CreateLight2DMaterial()
     light2DMaterial_->SetName("Light2DMaterial");
 
     Technique* tech = new Technique(context_);
-    Pass* pass = tech->CreatePass(PASS_LIGHT2D);
+    Pass* pass = tech->CreatePass("light2d");
     pass->SetBlendMode(BLEND_ADDALPHA);
     pass->SetDepthTestMode(CMP_ALWAYS);
 
@@ -666,7 +675,7 @@ void Light2DGroup::CreateLight2DMaterial()
     light2DMaterial_->SetTechnique(0, tech);
     light2DMaterial_->SetCullMode(CULL_NONE);
 
-    SetCustomMaterial(light2DMaterial_);
+    sourceBatches_[0].material_ = light2DMaterial_;
 
 }
 

+ 8 - 2
Source/Atomic/Atomic2D/Light2D.h

@@ -174,7 +174,7 @@ public:
     void AddLight(Light2D* light);
     Vector<WeakPtr<Light2D> >& GetLights() { return lights_; }
 
-    void SetDirty() { verticesDirty_ = true; }
+    void SetDirty() { /*verticesDirty_ = true;*/ }
 
     void SetAmbientColor(const Color& color);
     const Color& GetAmbientColor() { return ambientColor_; }
@@ -185,9 +185,15 @@ protected:
 
     /// Recalculate the world-space bounding box.
     void OnWorldBoundingBoxUpdate();
-    void UpdateVertices();
+
     void OnNodeSet(Node* node);
 
+    /// Handle draw order changed.
+    virtual void OnDrawOrderChanged();
+    /// Update source batches.
+    virtual void UpdateSourceBatches();
+
+
 private:
 
     Color ambientColor_;

+ 64 - 24
Source/Atomic/Atomic2D/ParticleEmitter2D.cpp

@@ -1,5 +1,5 @@
 //
-// Copyright (c) 2008-2014 the Urho3D project.
+// Copyright (c) 2008-2015 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
@@ -21,13 +21,15 @@
 //
 
 #include "Precompiled.h"
-#include "../Graphics/Camera.h"
 #include "../Core/Context.h"
-#include "../Atomic2D/ParticleEffect2D.h"
-#include "../Atomic2D/ParticleEmitter2D.h"
+#include "../Graphics/Camera.h"
+#include "../Graphics/Material.h"
 #include "../Resource/ResourceCache.h"
 #include "../Scene/Scene.h"
 #include "../Scene/SceneEvents.h"
+#include "../Atomic2D/ParticleEffect2D.h"
+#include "../Atomic2D/ParticleEmitter2D.h"
+#include "../Atomic2D/Renderer2D.h"
 #include "../Atomic2D/Sprite2D.h"
 
 #include "../DebugNew.h"
@@ -36,15 +38,18 @@ namespace Atomic
 {
 
 extern const char* ATOMIC2D_CATEGORY;
+extern const char* blendModeNames[];
 
 ParticleEmitter2D::ParticleEmitter2D(Context* context) :
     Drawable2D(context),
+    blendMode_(BLEND_ADDALPHA),
     numParticles_(0),
     emissionTime_(0.0f),
     emitParticleTime_(0.0f),
     boundingBoxMinPoint_(Vector3::ZERO),
     boundingBoxMaxPoint_(Vector3::ZERO)
 {
+    sourceBatches_.Resize(1);
 }
 
 ParticleEmitter2D::~ParticleEmitter2D()
@@ -56,9 +61,10 @@ void ParticleEmitter2D::RegisterObject(Context* context)
     context->RegisterFactory<ParticleEmitter2D>(ATOMIC2D_CATEGORY);
 
     ACCESSOR_ATTRIBUTE("Is Enabled", IsEnabled, SetEnabled, bool, true, AM_DEFAULT);
+    COPY_BASE_ATTRIBUTES(Drawable2D);
     MIXED_ACCESSOR_ATTRIBUTE("Particle Effect", GetParticleEffectAttr, SetParticleEffectAttr, ResourceRef, ResourceRef(ParticleEffect2D::GetTypeStatic()), AM_DEFAULT);
     MIXED_ACCESSOR_ATTRIBUTE("Sprite ", GetSpriteAttr, SetSpriteAttr, ResourceRef, ResourceRef(Sprite2D::GetTypeStatic()), AM_DEFAULT);
-    COPY_BASE_ATTRIBUTES(Drawable2D);
+    ENUM_ACCESSOR_ATTRIBUTE("Blend Mode", GetBlendMode, SetBlendMode, BlendMode, blendModeNames, BLEND_ALPHA, AM_DEFAULT);
 }
 
 void ParticleEmitter2D::OnSetEnabled()
@@ -100,8 +106,20 @@ void ParticleEmitter2D::SetSprite(Sprite2D* sprite)
         return;
 
     sprite_ = sprite;
+    UpdateMaterial();
 
-    SetTexture(sprite_ ? sprite_->GetTexture() : 0);
+    MarkNetworkUpdate();
+}
+
+void ParticleEmitter2D::SetBlendMode(BlendMode blendMode)
+{
+    if (blendMode == blendMode_)
+        return;
+
+    blendMode_ = blendMode;
+    UpdateMaterial();
+
+    MarkNetworkUpdate();
 }
 
 void ParticleEmitter2D::SetMaxParticles(unsigned maxParticles)
@@ -109,7 +127,7 @@ void ParticleEmitter2D::SetMaxParticles(unsigned maxParticles)
     maxParticles = Max(maxParticles, 1);
 
     particles_.Resize(maxParticles);
-    vertices_.Reserve(maxParticles * 4);
+    sourceBatches_[0].vertices_.Reserve(maxParticles * 4);
 
     numParticles_ = Min(maxParticles, numParticles_);
 }
@@ -169,30 +187,44 @@ void ParticleEmitter2D::OnWorldBoundingBoxUpdate()
     worldBoundingBox_ = boundingBox_;
 }
 
-void ParticleEmitter2D::UpdateVertices()
+void ParticleEmitter2D::OnDrawOrderChanged()
 {
-    if (!verticesDirty_)
+    sourceBatches_[0].drawOrder_ = GetDrawOrder();
+}
+
+void ParticleEmitter2D::UpdateSourceBatches()
+{
+    if (!sourceBatchesDirty_)
         return;
 
-    vertices_.Clear();
+    Vector<Vertex2D>& vertices = sourceBatches_[0].vertices_;
+    vertices.Clear();
 
-    Texture2D* texture = GetTexture();
-    if (!texture)
+    if (!sprite_)
         return;
 
-    const IntRect& rectangle_ = sprite_->GetRectangle();
-    if (rectangle_.Width() == 0 || rectangle_.Height() == 0)
+    Rect textureRect;
+    if (!sprite_->GetTextureRectangle(textureRect))
         return;
 
+    /*
+    V1---------V2
+    |         / |
+    |       /   |
+    |     /     |
+    |   /       |
+    | /         |
+    V0---------V3
+    */
     Vertex2D vertex0;
     Vertex2D vertex1;
     Vertex2D vertex2;
     Vertex2D vertex3;
 
-    vertex0.uv_ = Vector2(0.0f, 1.0f);
-    vertex1.uv_ = Vector2(0.0f, 0.0f);
-    vertex2.uv_ = Vector2(1.0f, 0.0f);
-    vertex3.uv_ = Vector2(1.0f, 1.0f);
+    vertex0.uv_ = textureRect.min_;
+    vertex1.uv_ = Vector2(textureRect.min_.x_, textureRect.max_.y_);
+    vertex2.uv_ = textureRect.max_;
+    vertex3.uv_ = Vector2(textureRect.max_.x_, textureRect.min_.y_);
 
     for (int i = 0; i < numParticles_; ++i)
     {
@@ -211,13 +243,21 @@ void ParticleEmitter2D::UpdateVertices()
 
         vertex0.color_ = vertex1.color_ = vertex2.color_  = vertex3.color_ = p.color_.ToUInt();
 
-        vertices_.Push(vertex0);
-        vertices_.Push(vertex1);
-        vertices_.Push(vertex2);
-        vertices_.Push(vertex3);
+        vertices.Push(vertex0);
+        vertices.Push(vertex1);
+        vertices.Push(vertex2);
+        vertices.Push(vertex3);
     }
 
-    verticesDirty_ = false;
+    sourceBatchesDirty_ = false;
+}
+
+void ParticleEmitter2D::UpdateMaterial()
+{
+    if (sprite_)
+        sourceBatches_[0].material_ = renderer_->GetMaterial(sprite_->GetTexture(), blendMode_);
+    else
+        sourceBatches_[0].material_ = 0;
 }
 
 void ParticleEmitter2D::HandleScenePostUpdate(StringHash eventType, VariantMap& eventData)
@@ -274,7 +314,7 @@ void ParticleEmitter2D::Update(float timeStep)
             emissionTime_ = Max(0.0f, emissionTime_ - timeStep);
     }
 
-    verticesDirty_ = true;
+    sourceBatchesDirty_ = true;
 
     OnMarkedDirty(node_);
 }

+ 13 - 3
Source/Atomic/Atomic2D/ParticleEmitter2D.h

@@ -1,5 +1,5 @@
 //
-// Copyright (c) 2008-2014 the Urho3D project.
+// Copyright (c) 2008-2015 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
@@ -92,6 +92,8 @@ public:
     void SetEffect(ParticleEffect2D* effect);
     /// Set sprite.
     void SetSprite(Sprite2D* sprite);
+    /// Set blend mode.
+    void SetBlendMode(BlendMode blendMode);
     /// Set max particles.
     void SetMaxParticles(unsigned maxParticles);
 
@@ -99,6 +101,8 @@ public:
     ParticleEffect2D* GetEffect() const;
     /// Return sprite.
     Sprite2D* GetSprite() const;
+    /// Return blend mode.
+    BlendMode GetBlendMode() const { return blendMode_; }
     /// Return max particles.
     unsigned GetMaxParticles() const { return particles_.Size(); }
 
@@ -116,8 +120,12 @@ private:
     virtual void OnNodeSet(Node* node);
     /// Recalculate the world-space bounding box.
     virtual void OnWorldBoundingBoxUpdate();
-    /// Update vertices.
-    virtual void UpdateVertices();
+    /// Handle draw order changed.
+    virtual void OnDrawOrderChanged();
+    /// Update source batches.
+    virtual void UpdateSourceBatches();
+    /// Update material.
+    void UpdateMaterial();
     /// Handle scene post update.
     void HandleScenePostUpdate(StringHash eventType, VariantMap& eventData);
     /// Update.
@@ -131,6 +139,8 @@ private:
     SharedPtr<ParticleEffect2D> effect_;
     /// Sprite.
     SharedPtr<Sprite2D> sprite_;
+    /// Blend mode.
+    BlendMode blendMode_;
     /// Num particles.
     int numParticles_;
     /// Emission time.

+ 202 - 187
Source/Atomic/Atomic2D/Renderer2D.cpp

@@ -21,24 +21,25 @@
 //
 
 #include "Precompiled.h"
-#include "../Graphics/Camera.h"
+#include "../Container/Sort.h"
 #include "../Core/Context.h"
-#include "../Atomic2D/Drawable2D.h"
+#include "../Core/Profiler.h"
+#include "../Core/WorkQueue.h"
+#include "../Graphics/Camera.h"
 #include "../Graphics/Geometry.h"
 #include "../Graphics/GraphicsEvents.h"
 #include "../Graphics/IndexBuffer.h"
-#include "../IO/Log.h"
 #include "../Graphics/Material.h"
-#include "../Scene/Node.h"
-#include "../Core/Profiler.h"
-#include "../Atomic2D/Renderer2D.h"
-#include "../Scene/Scene.h"
-#include "../Container/Sort.h"
+#include "../Graphics/OctreeQuery.h"
 #include "../Graphics/Technique.h"
 #include "../Graphics/Texture2D.h"
 #include "../Graphics/VertexBuffer.h"
 #include "../Graphics/View.h"
-#include "../Core/WorkQueue.h"
+#include "../IO/Log.h"
+#include "../Scene/Node.h"
+#include "../Scene/Scene.h"
+#include "../Atomic2D/Drawable2D.h"
+#include "../Atomic2D/Renderer2D.h"
 
 #include "../DebugNew.h"
 
@@ -47,15 +48,34 @@ namespace Atomic
 
 extern const char* blendModeNames[];
 
+static const unsigned MASK_VERTEX2D = MASK_POSITION | MASK_COLOR | MASK_TEXCOORD1;
+
+ViewBatchInfo2D::ViewBatchInfo2D() : vertexBufferUpdateFrameNumber_(0),
+    indexCount_(0),
+    vertexCount_(0),
+    batchUpdatedFrameNumber_(0), 
+    batchCount_(0)
+{
+}
+
 Renderer2D::Renderer2D(Context* context) :
     Drawable(context, DRAWABLE_GEOMETRY),
+    material_(new Material(context)),
     indexBuffer_(new IndexBuffer(context_)),
-    vertexBuffer_(new VertexBuffer(context_)),
-    orderDirty_(true),
     frustum_(0),
-    useTris_(false),
-    geometryCount_(0)
+    useTris_(false)
 {
+    material_->SetName("Atomic2D");
+
+    Technique* tech = new Technique(context_);
+    Pass* pass = tech->CreatePass("alpha");
+    pass->SetVertexShader("Atomic2D");
+    pass->SetPixelShader("Atomic2D");
+    pass->SetDepthWrite(false);
+
+    material_->SetTechnique(0, tech);
+    material_->SetCullMode(CULL_NONE);
+
     frame_.frameNumber_ = 0;
     SubscribeToEvent(E_BEGINVIEWUPDATE, HANDLER(Renderer2D, HandleBeginViewUpdate));
 }
@@ -69,37 +89,27 @@ void Renderer2D::RegisterObject(Context* context)
     context->RegisterFactory<Renderer2D>();
 }
 
-static inline bool CompareDrawable2Ds(Drawable2D* lhs, Drawable2D* rhs)
+static inline bool CompareRayQueryResults(RayQueryResult& lr, RayQueryResult& rr)
 {
+    Drawable2D* lhs = static_cast<Drawable2D*>(lr.drawable_);
+    Drawable2D* rhs = static_cast<Drawable2D*>(rr.drawable_);
     if (lhs->GetLayer() != rhs->GetLayer())
-        return lhs->GetLayer() < rhs->GetLayer();
+        return lhs->GetLayer() > rhs->GetLayer();
 
     if (lhs->GetOrderInLayer() != rhs->GetOrderInLayer())
-        return lhs->GetOrderInLayer() < rhs->GetOrderInLayer();
+        return lhs->GetOrderInLayer() > rhs->GetOrderInLayer();
 
-    Material* lhsUsedMaterial = lhs->GetMaterial();
-    Material* rhsUsedMaterial = rhs->GetMaterial();
-    if (lhsUsedMaterial && rhsUsedMaterial && lhsUsedMaterial != rhsUsedMaterial)
-        return lhsUsedMaterial->GetNameHash() < rhsUsedMaterial->GetNameHash();
-
-    return lhs->GetID() < rhs->GetID();
+    return lhs->GetID() > rhs->GetID();
 }
 
 void Renderer2D::ProcessRayQuery(const RayOctreeQuery& query, PODVector<RayQueryResult>& results)
 {
-    if (orderDirty_)
-    {
-        Sort(drawables_.Begin(), drawables_.End(), CompareDrawable2Ds);
-        orderDirty_ = false;
-    }
-
     unsigned resultSize = results.Size();
-    for (unsigned i = drawables_.Size() - 1; i < drawables_.Size(); --i)
-    {
+    for (unsigned i = 0; i < drawables_.Size(); ++i)
         drawables_[i]->ProcessRayQuery(query, results);
-        if (results.Size() != resultSize)
-            return;
-    }
+
+    if (results.Size() != resultSize)
+        Sort(results.Begin() + resultSize, results.End(), CompareRayQueryResults);
 }
 
 void Renderer2D::UpdateBatches(const FrameInfo& frame)
@@ -116,14 +126,19 @@ void Renderer2D::UpdateBatches(const FrameInfo& frame)
 
 void Renderer2D::UpdateGeometry(const FrameInfo& frame)
 {
-    unsigned& vertexCount = vertexCount_[frame.camera_];
-    unsigned& indexCount = indexCount_[frame.camera_];
+    unsigned indexCount = 0;
+    for (HashMap<Camera*, ViewBatchInfo2D>::ConstIterator i = viewBatchInfos_.Begin(); i != viewBatchInfos_.End(); ++i)
+    {
+        if (i->second_.batchUpdatedFrameNumber_ == frame_.frameNumber_)
+            indexCount = Max((int)indexCount, (int)i->second_.indexCount_);
+    }
 
     // Fill index buffer
     if (indexBuffer_->GetIndexCount() < indexCount || indexBuffer_->IsDataLost())
     {
-        bool largeIndices = vertexCount > 0xffff;
+        bool largeIndices = (indexCount * 4 / 6) > 0xffff;
         indexBuffer_->SetSize(indexCount, largeIndices);
+
         void* buffer = indexBuffer_->Lock(0, indexCount, true);
         if (buffer)
         {
@@ -131,6 +146,7 @@ void Renderer2D::UpdateGeometry(const FrameInfo& frame)
             if (largeIndices)
             {
                 unsigned* dest = reinterpret_cast<unsigned*>(buffer);
+
                 for (unsigned i = 0; i < quadCount; ++i)
                 {
                     unsigned base = i * (useTris_ ? 3 : 4);
@@ -178,29 +194,37 @@ void Renderer2D::UpdateGeometry(const FrameInfo& frame)
         }
     }
 
-    if (vertexBuffer_->GetVertexCount() < vertexCount)
-        vertexBuffer_->SetSize(vertexCount, MASK_VERTEX2D);
+    Camera* camera = frame.camera_;
+    ViewBatchInfo2D& viewBatchInfo = viewBatchInfos_[camera];
 
-    if (vertexCount)
+    if (viewBatchInfo.vertexBufferUpdateFrameNumber_ != frame_.frameNumber_)
     {
-        Vertex2D* dest = reinterpret_cast<Vertex2D*>(vertexBuffer_->Lock(0, vertexCount, true));
-        if (dest)
+        unsigned vertexCount = viewBatchInfo.vertexCount_;
+        VertexBuffer* vertexBuffer = viewBatchInfo.vertexBuffer_;
+        if (vertexBuffer->GetVertexCount() < vertexCount)
+            vertexBuffer->SetSize(vertexCount, MASK_VERTEX2D, true);
+
+        if (vertexCount)
         {
-            for (unsigned d = 0; d < drawables_.Size(); ++d)
+            Vertex2D* dest = reinterpret_cast<Vertex2D*>(vertexBuffer->Lock(0, vertexCount, true));
+            if (dest)
             {
-                if (!drawables_[d]->IsInView(frame) || drawables_[d]->GetVertices().Empty())
-                    continue;
+                const PODVector<const SourceBatch2D*>& sourceBatches = viewBatchInfo.sourceBatches_;
+                for (unsigned b = 0; b < sourceBatches.Size(); ++b)
+                {
+                    const Vector<Vertex2D>& vertices = sourceBatches[b]->vertices_;
+                    for (unsigned i = 0; i < vertices.Size(); ++i)
+                        dest[i] = vertices[i];
+                    dest += vertices.Size();
+                }
 
-                const Vector<Vertex2D>& vertices = drawables_[d]->GetVertices();
-                for (unsigned i = 0; i < vertices.Size(); ++i)
-                    dest[i] = vertices[i];
-                dest += vertices.Size();
+                vertexBuffer->Unlock();
             }
-
-            vertexBuffer_->Unlock();
+            else
+                LOGERROR("Failed to lock vertex buffer");
         }
-        else
-            LOGERROR("Failed to lock vertex buffer");
+
+        viewBatchInfo.vertexBufferUpdateFrameNumber_ = frame_.frameNumber_;
     }
 }
 
@@ -215,9 +239,6 @@ void Renderer2D::AddDrawable(Drawable2D* drawable)
         return;
 
     drawables_.Push(drawable);
-    materialDirtyDrawables_.Push(drawable);
-
-    orderDirty_ = true;
 }
 
 void Renderer2D::RemoveDrawable(Drawable2D* drawable)
@@ -226,24 +247,33 @@ void Renderer2D::RemoveDrawable(Drawable2D* drawable)
         return;
 
     drawables_.Remove(drawable);
+}
 
-    // Drawable may be on the dirty list multiple times; remove all instances
-    for (;;)
+Material* Renderer2D::GetMaterial(Texture2D* texture, BlendMode blendMode)
+{
+    if (!material_)
+        return 0;
+
+    if (!texture)
+        return material_;
+
+    HashMap<Texture2D*, HashMap<int, SharedPtr<Material> > >::Iterator t = cachedMaterials_.Find(texture);
+    if (t == cachedMaterials_.End())
     {
-        PODVector<Drawable2D*>::Iterator i = materialDirtyDrawables_.Find(drawable);
-        if (i != materialDirtyDrawables_.End())
-            materialDirtyDrawables_.Erase(i);
-        else
-            break;
+        SharedPtr<Material> newMaterial = CreateMaterial(texture, blendMode);
+        cachedMaterials_[texture][blendMode] = newMaterial;
+        return newMaterial;
     }
 
-    orderDirty_ = true;
-}
+    HashMap<int, SharedPtr<Material> >& materials = t->second_;
+    HashMap<int, SharedPtr<Material> >::Iterator b = materials.Find(blendMode);
+    if (b != materials.End())
+        return b->second_;
 
-void Renderer2D::MarkMaterialDirty(Drawable2D* drawable)
-{
-    // Note: this may cause the drawable to appear on the dirty list multiple times
-    materialDirtyDrawables_.Push(drawable);
+    SharedPtr<Material> newMaterial = CreateMaterial(texture, blendMode);
+    materials[blendMode] = newMaterial;
+
+    return newMaterial;
 }
 
 bool Renderer2D::CheckVisibility(Drawable2D* drawable) const
@@ -262,6 +292,17 @@ void Renderer2D::OnWorldBoundingBoxUpdate()
     worldBoundingBox_ = boundingBox_;
 }
 
+SharedPtr<Material> Renderer2D::CreateMaterial(Texture2D* texture, BlendMode blendMode)
+{
+    SharedPtr<Material> newMaterial = material_->Clone();
+
+    newMaterial->SetName(texture->GetName() + "_" + blendModeNames[blendMode]);
+    newMaterial->SetTexture(TU_DIFFUSE, texture);
+    newMaterial->GetTechnique(0)->GetPass("alpha")->SetBlendMode(blendMode);
+
+    return newMaterial;
+}
+
 void CheckDrawableVisibility(const WorkItem* item, unsigned threadIndex)
 {
     Renderer2D* renderer = reinterpret_cast<Renderer2D*>(item->aux_);
@@ -271,7 +312,7 @@ void CheckDrawableVisibility(const WorkItem* item, unsigned threadIndex)
     while (start != end)
     {
         Drawable2D* drawable = *start++;
-        if (renderer->CheckVisibility(drawable) && drawable->GetVertices().Size())
+        if (renderer->CheckVisibility(drawable))
             drawable->MarkInView(renderer->frame_);
     }
 }
@@ -280,35 +321,14 @@ void Renderer2D::HandleBeginViewUpdate(StringHash eventType, VariantMap& eventDa
 {
     using namespace BeginViewUpdate;
 
-    Scene* scene = GetScene();
     // Check that we are updating the correct scene
-    if (scene != eventData[P_SCENE].GetPtr())
+    if (GetScene() != eventData[P_SCENE].GetPtr())
         return;
-    unsigned lastFrameNumber = frame_.frameNumber_;
+
     frame_ = static_cast<View*>(eventData[P_VIEW].GetPtr())->GetFrameInfo();
-    // Reset geometry use when new frame started
-    if (frame_.frameNumber_ != lastFrameNumber)
-        geometryCount_ = 0;
 
     PROFILE(UpdateRenderer2D);
 
-    if (!materialDirtyDrawables_.Empty())
-    {
-        for (unsigned i = 0; i < materialDirtyDrawables_.Size(); ++i)
-        {
-            Drawable2D* drawable = materialDirtyDrawables_[i];
-            if (!drawable->GetMaterial())
-                drawable->SetMaterial(GetMaterial(drawable->GetTexture(), drawable->GetBlendMode()));
-        }
-        materialDirtyDrawables_.Clear();
-    }
-
-    if (orderDirty_)
-    {
-        Sort(drawables_.Begin(), drawables_.End(), CompareDrawable2Ds);
-        orderDirty_ = false;
-    }
-
     Camera* camera = static_cast<Camera*>(eventData[P_CAMERA].GetPtr());
     frustum_ = &camera->GetFrustum();
     if (camera->IsOrthographic() && camera->GetNode()->GetWorldDirection() == Vector3::FORWARD)
@@ -348,59 +368,24 @@ void Renderer2D::HandleBeginViewUpdate(StringHash eventType, VariantMap& eventDa
         queue->Complete(M_MAX_UNSIGNED);
     }
 
+    ViewBatchInfo2D& viewBatchInfo = viewBatchInfos_[camera];
+    
+    // Create vertex buffer
+    if (!viewBatchInfo.vertexBuffer_)
+        viewBatchInfo.vertexBuffer_ = new VertexBuffer(context_);
+
+    UpdateViewBatchInfo(viewBatchInfo, camera);
+
     // Go through the drawables to form geometries & batches and calculate the total vertex / index count,
     // but upload the actual vertex data later. The idea is that the View class copies our batch vector to
     // its internal data structures, so we can reuse the batches for each view, provided that unique Geometry
     // objects are used for each view to specify the draw ranges
-    batches_.Clear();
-    Material* material = 0;
-    unsigned iStart = 0;
-    unsigned iCount = 0;
-    unsigned vStart = 0;
-    unsigned vCount = 0;
-    unsigned& vTotal = vertexCount_[frame_.camera_];
-    unsigned& iTotal = indexCount_[frame_.camera_];
-    vTotal = 0;
-    iTotal = 0;
-
-    for (unsigned d = 0; d < drawables_.Size(); ++d)
+    batches_.Resize(viewBatchInfo.batchCount_);
+    for (unsigned i = 0; i < viewBatchInfo.batchCount_; ++i)
     {
-        if (!drawables_[d]->IsInView(frame_))
-            continue;
-
-        Material* usedMaterial = drawables_[d]->GetMaterial();
-        const Vector<Vertex2D>& vertices = drawables_[d]->GetVertices();
-
-        // When new material encountered, finish the current batch and start new
-        if (material != usedMaterial)
-        {
-            if (material)
-            {
-                AddBatch(material, iStart, iCount, vStart, vCount);
-                iStart += iCount;
-                iCount = 0;
-                vStart += vCount;
-                vCount = 0;
-            }
-
-            material = usedMaterial;
-        }
-
-        unsigned indices;
-        if (useTris_)
-            indices = vertices.Size();
-        else
-            indices = vertices.Size() / 4 * 6;
-
-        iCount += indices;
-        iTotal += indices;
-        vCount += vertices.Size();
-        vTotal += vertices.Size();
+        batches_[i].material_ = viewBatchInfo.materials_[i];
+        batches_[i].geometry_ = viewBatchInfo.geometries_[i];
     }
-
-    // Add the final batch if necessary
-    if (material && vCount)
-        AddBatch(material, iStart, iCount, vStart, vCount);
 }
 
 void Renderer2D::GetDrawables(PODVector<Drawable2D*>& dest, Node* node)
@@ -421,79 +406,109 @@ void Renderer2D::GetDrawables(PODVector<Drawable2D*>& dest, Node* node)
         GetDrawables(dest, i->Get());
 }
 
-Material* Renderer2D::GetMaterial(Texture2D* texture, BlendMode blendMode)
+static inline bool CompareSourceBatch2Ds(const SourceBatch2D* lhs, const SourceBatch2D* rhs)
 {
-    HashMap<Texture2D*, HashMap<int, SharedPtr<Material> > >::Iterator t = cachedMaterials_.Find(texture);
-    if (t == cachedMaterials_.End())
-    {
-        SharedPtr<Material> material(CreateMaterial(texture, blendMode));
-        cachedMaterials_[texture][blendMode] = material;
-        return material;
-    }
-
-    HashMap<int, SharedPtr<Material> >& materials = t->second_;
-    HashMap<int, SharedPtr<Material> >::Iterator b = materials.Find(blendMode);
-    if (b != materials.End())
-        return b->second_;
+    if (lhs->drawOrder_ != rhs->drawOrder_)
+        return lhs->drawOrder_ < rhs->drawOrder_;
 
-    SharedPtr<Material> material(CreateMaterial(texture, blendMode));
-    materials[blendMode] = material;
+    if (lhs->material_ != rhs->material_)
+        return lhs->material_->GetNameHash() < rhs->material_->GetNameHash();
 
-    return material;
+    return lhs < rhs;
 }
 
-Material* Renderer2D::CreateMaterial(Texture2D* texture, BlendMode blendMode)
+void Renderer2D::UpdateViewBatchInfo(ViewBatchInfo2D& viewBatchInfo, Camera* camera)
 {
-    Material* material = new Material(context_);
-    if (texture)
-        material->SetName(texture->GetName() + "_" + blendModeNames[blendMode]);
-    else
-        material->SetName(blendModeNames[blendMode]);
+    // Already update in same frame
+    if (viewBatchInfo.batchUpdatedFrameNumber_ == frame_.frameNumber_)
+        return;
 
-    Technique* tech = new Technique(context_);
-    Pass* pass = tech->CreatePass(PASS_ALPHA);
-    pass->SetBlendMode(blendMode);
+    PODVector<const SourceBatch2D*>& soruceBatches = viewBatchInfo.sourceBatches_;
+    soruceBatches.Clear();
+    for (unsigned d = 0; d < drawables_.Size(); ++d)
+    {
+        if (!drawables_[d]->IsInView(camera))
+            continue;
 
-    pass->SetVertexShader("Atomic2D");
-    pass->SetPixelShader("Atomic2D");
+        const Vector<SourceBatch2D>& batches = drawables_[d]->GetSourceBatches();
+        for (unsigned b = 0; b < batches.Size(); ++b)
+        {
+            if (batches[b].material_ && !batches[b].vertices_.Empty())
+                soruceBatches.Push(&batches[b]);
+        }
+    }
 
-    pass->SetDepthWrite(false);
+    Sort(soruceBatches.Begin(), soruceBatches.End(), CompareSourceBatch2Ds);
+
+    viewBatchInfo.batchCount_ = 0;
+    Material* currMaterial = 0;
+    unsigned iStart = 0;
+    unsigned iCount = 0;
+    unsigned vStart = 0;
+    unsigned vCount = 0;
+
+    for (unsigned b = 0; b < soruceBatches.Size(); ++b)
+    {
+        Material* material = soruceBatches[b]->material_;
+        const Vector<Vertex2D>& vertices = soruceBatches[b]->vertices_;
+
+        // When new material encountered, finish the current batch and start new
+        if (currMaterial != material)
+        {
+            if (currMaterial)
+            {
+                AddViewBatch(viewBatchInfo, currMaterial, iStart, iCount, vStart, vCount);
+                iStart += iCount;
+                iCount = 0;
+                vStart += vCount;
+                vCount = 0;
+            }
+
+            currMaterial = material;
+        }
+
+        unsigned indices;
+        if (useTris_)
+            indices = vertices.Size();
+        else
+            indices = vertices.Size() * 6 / 4;
 
-    material->SetTechnique(0, tech);
-    material->SetCullMode(CULL_NONE);
+        iCount += indices;
+        vCount += vertices.Size();
+    }
 
-    material->SetTexture(TU_DIFFUSE, texture);
+    // Add the final batch if necessary
+    if (currMaterial && vCount)
+        AddViewBatch(viewBatchInfo, currMaterial, iStart, iCount, vStart, vCount);
 
-    return material;
+    viewBatchInfo.indexCount_ = iStart + iCount;
+    viewBatchInfo.vertexCount_ = vStart + vCount;
+    viewBatchInfo.batchUpdatedFrameNumber_ = frame_.frameNumber_;
 }
 
-void Renderer2D::AddBatch(Material* material, unsigned indexStart, unsigned indexCount, unsigned vertexStart, unsigned vertexCount)
+void Renderer2D::AddViewBatch(ViewBatchInfo2D& viewBatchInfo, Material* material, unsigned indexStart, unsigned indexCount, unsigned vertexStart, unsigned vertexCount)
 {
     if (!material || indexCount == 0 || vertexCount == 0)
         return;
 
+    if (viewBatchInfo.materials_.Size() <= viewBatchInfo.batchCount_)
+        viewBatchInfo.materials_.Resize(viewBatchInfo.batchCount_ + 1);
+    viewBatchInfo.materials_[viewBatchInfo.batchCount_] = material;
+
     // Allocate new geometry if necessary
-    if (geometries_.Size() <= geometryCount_)
+    if (viewBatchInfo.geometries_.Size() <= viewBatchInfo.batchCount_)
     {
         SharedPtr<Geometry> geometry(new Geometry(context_));
         geometry->SetIndexBuffer(indexBuffer_);
-        geometry->SetVertexBuffer(0, vertexBuffer_, MASK_VERTEX2D);
-        geometries_.Push(geometry);
-    }
+        geometry->SetVertexBuffer(0, viewBatchInfo.vertexBuffer_, MASK_VERTEX2D);
 
-    geometries_[geometryCount_]->SetDrawRange(TRIANGLE_LIST, indexStart, indexCount, vertexStart, vertexCount, false);
+        viewBatchInfo.geometries_.Push(geometry);
+    }
 
-    batches_.Resize(batches_.Size() + 1);
-    SourceBatch& batch = batches_.Back();
-    batch.geometry_ = geometries_[geometryCount_];
-    batch.material_ = material;
+    Geometry* geometry = viewBatchInfo.geometries_[viewBatchInfo.batchCount_];
+    geometry->SetDrawRange(TRIANGLE_LIST, indexStart, indexCount, vertexStart, vertexCount, false);
 
-    ++geometryCount_;
-}
-
-void Renderer2D::SetUseTris(bool tris)
-{
-    useTris_ = tris;
+    viewBatchInfo.batchCount_++;
 }
 
 }

+ 45 - 27
Source/Atomic/Atomic2D/Renderer2D.h

@@ -32,6 +32,33 @@ class IndexBuffer;
 class Material;
 class VertexBuffer;
 struct FrameInfo;
+struct SourceBatch2D;
+
+/// 2D view batch info.
+struct ViewBatchInfo2D
+{
+    /// Construct.
+    ViewBatchInfo2D();
+
+    /// Vertex buffer update frame number.
+    unsigned vertexBufferUpdateFrameNumber_;
+    /// Index count.
+    unsigned indexCount_;
+    /// Vertex count.
+    unsigned vertexCount_;
+    /// Vertex buffer.
+    SharedPtr<VertexBuffer> vertexBuffer_;
+    /// Batch updated frame number.
+    unsigned batchUpdatedFrameNumber_;
+    /// Source batches.
+    PODVector<const SourceBatch2D*> sourceBatches_;
+    /// Batch count;
+    unsigned batchCount_;
+    /// Materials.
+    Vector<SharedPtr<Material> > materials_;
+    /// Geometries.
+    Vector<SharedPtr<Geometry> > geometries_;
+};
 
 /// 2D renderer components.
 class ATOMIC_API Renderer2D : public Drawable
@@ -61,56 +88,47 @@ public:
     void AddDrawable(Drawable2D* drawable);
     /// Remove Drawable2D.
     void RemoveDrawable(Drawable2D* drawable);
-    /// Mark material dirty.
-    void MarkMaterialDirty(Drawable2D* drawable);
-    /// Mark order dirty.
-    void MarkOrderDirty(){ orderDirty_ = true; }
+    /// Return material by texture and blend mode.
+    Material* GetMaterial(Texture2D* texture, BlendMode blendMode);
+
     /// Check visibility.
     bool CheckVisibility(Drawable2D* drawable) const;
 
-    void SetUseTris(bool tris);
+    /// Whether this renderer uses triangles (instead of quads)
+    void SetUseTris(bool useTris) { useTris_ = useTris; }
+    bool GetUseTris() const { return useTris_; }
 
 private:
     /// Recalculate the world-space bounding box.
     virtual void OnWorldBoundingBoxUpdate();
+    /// Create material by texture and blend mode.
+    SharedPtr<Material> CreateMaterial(Texture2D* texture, BlendMode blendMode);
     /// Handle view update begin event. Determine Drawable2D's and their batches here.
     void HandleBeginViewUpdate(StringHash eventType, VariantMap& eventData);
     /// Get all drawables in node.
     void GetDrawables(PODVector<Drawable2D*>& drawables, Node* node);
-    /// Return material by texture and blend mode.
-    Material* GetMaterial(Texture2D* texture, BlendMode blendMode);
-    /// Create new material by texture and blend mode.
-    Material* CreateMaterial(Texture2D* Texture, BlendMode blendMode);
-    /// Add batch.
-    void AddBatch(Material* material, unsigned indexStart, unsigned indexCount, unsigned vertexStart, unsigned vertexCount);
+    /// Update view batch info.
+    void UpdateViewBatchInfo(ViewBatchInfo2D& viewBatchInfo, Camera* camera);
+    /// Add view batch.
+    void AddViewBatch(ViewBatchInfo2D& viewBatchInfo, Material* material, unsigned indexStart, unsigned indexCount, unsigned vertexStart, unsigned vertexCount);
 
     /// Index buffer.
     SharedPtr<IndexBuffer> indexBuffer_;
-    /// Vertex buffer.
-    SharedPtr<VertexBuffer> vertexBuffer_;
+    /// Material.
+    SharedPtr<Material> material_;
     /// Drawables.
     PODVector<Drawable2D*> drawables_;
-    /// Material dirty drawables.
-    PODVector<Drawable2D*> materialDirtyDrawables_;
-    /// Order dirty.
-    bool orderDirty_;
-    /// View frameinfo for current frame.
+    /// View frame info for current frame.
     FrameInfo frame_;
-    /// Used geometry count. Shared by all views and reset when a new frame begins.
-    unsigned geometryCount_;
-    /// Vertex count by view.
-    HashMap<Camera*, unsigned> vertexCount_;
-    /// Index count by view.
-    HashMap<Camera*, unsigned> indexCount_;
-    /// Geometries used in all views.
-    Vector<SharedPtr<Geometry> > geometries_;
+    /// View batch info.
+    HashMap<Camera*, ViewBatchInfo2D> viewBatchInfos_;
     /// Frustum for current frame.
     const Frustum* frustum_;
     /// Frustum bounding box for current frame.
     BoundingBox frustumBoundingBox_;
     /// Cached materials.
     HashMap<Texture2D*, HashMap<int, SharedPtr<Material> > > cachedMaterials_;
-
+    /// Whether or not the renderer containts tris (default is quads)
     bool useTris_;
 };
 

+ 56 - 1
Source/Atomic/Atomic2D/Sprite2D.cpp

@@ -1,5 +1,5 @@
 //
-// Copyright (c) 2008-2014 the Urho3D project.
+// Copyright (c) 2008-2015 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
@@ -24,6 +24,7 @@
 #include "../Core/Context.h"
 #include "../IO/Deserializer.h"
 #include "../Resource/ResourceCache.h"
+#include "../Atomic2D/Drawable2D.h"
 #include "../Atomic2D/Sprite2D.h"
 #include "../Atomic2D/SpriteSheet2D.h"
 #include "../Graphics/Texture2D.h"
@@ -126,6 +127,60 @@ void Sprite2D::SetSpriteSheet(SpriteSheet2D* spriteSheet)
     spriteSheet_ = spriteSheet;
 }
 
+bool Sprite2D::GetDrawRectangle(Rect& rect, bool flipX, bool flipY) const
+{
+    return GetDrawRectangle(rect, hotSpot_, flipX, flipY);
+}
+
+bool Sprite2D::GetDrawRectangle(Rect& rect, const Vector2& hotSpot, bool flipX, bool flipY) const
+{
+    if (rectangle_.Width() == 0 || rectangle_.Height() == 0)
+        return false;
+
+    float width = (float)rectangle_.Width() * PIXEL_SIZE;
+    float height = (float)rectangle_.Height() * PIXEL_SIZE;        
+
+    float hotSpotX = flipX ? (1.0f - hotSpot.x_) : hotSpot.x_;
+    float hotSpotY = flipY ? (1.0f - hotSpot.y_) : hotSpot.y_;
+
+#ifdef ATOMIC_OPENGL
+    rect.min_.x_ = -width * hotSpotX;
+    rect.max_.x_ = width * (1.0f - hotSpotX);
+    rect.min_.y_ = -height * hotSpotY;
+    rect.max_.y_ = height * (1.0f - hotSpotY);
+#else
+    const float halfPixelOffset = 0.5f * PIXEL_SIZE;
+    rect.min_.x_ = -width * hotSpotX + halfPixelOffset;
+    rect.max_.x_ = width * (1.0f - hotSpotX) + halfPixelOffset;
+    rect.min_.y_ = -height * hotSpotY + halfPixelOffset;
+    rect.max_.y_ = height * (1.0f - hotSpotY) + halfPixelOffset;
+#endif
+    return true;
+}
+
+bool Sprite2D::GetTextureRectangle(Rect& rect, bool flipX, bool flipY) const
+{
+    if (!texture_)
+        return false;
+
+    float invWidth = 1.0f / (float)texture_->GetWidth();
+    float invHeight = 1.0f / (float)texture_->GetHeight();
+
+    rect.min_.x_ = rectangle_.left_ * invWidth;
+    rect.max_.x_ = rectangle_.right_ * invWidth;
+
+    rect.min_.y_ = rectangle_.bottom_ * invHeight;
+    rect.max_.y_ = rectangle_.top_ * invHeight;
+
+    if (flipX)
+        Swap(rect.min_.x_, rect.max_.x_);
+    
+    if (flipY)
+        Swap(rect.min_.y_, rect.max_.y_);
+
+    return true;
+}
+
 ResourceRef Sprite2D::SaveToResourceRef(Sprite2D* sprite)
 {
     SpriteSheet2D* spriteSheet = 0;

+ 8 - 1
Source/Atomic/Atomic2D/Sprite2D.h

@@ -1,5 +1,5 @@
 //
-// Copyright (c) 2008-2014 the Urho3D project.
+// Copyright (c) 2008-2015 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
@@ -70,6 +70,13 @@ public:
     /// Return sprite sheet.
     SpriteSheet2D* GetSpriteSheet() const { return spriteSheet_; }
 
+    /// Return draw rectangle.
+    bool GetDrawRectangle(Rect& rect, bool flipX = false, bool flipY = false) const;
+    /// Return draw rectangle with custom hot spot.
+    bool GetDrawRectangle(Rect& rect, const Vector2& hotSpot, bool flipX = false, bool flipY = false) const;
+    /// Return texture rectangle.
+    bool GetTextureRectangle(Rect& rect, bool flipX = false, bool flipY = false) const;
+
     /// Save sprite to ResourceRef.
     static ResourceRef SaveToResourceRef(Sprite2D* sprite);
     /// Load sprite from ResourceRef.

+ 109 - 83
Source/Atomic/Atomic2D/StaticSprite2D.cpp

@@ -22,10 +22,13 @@
 
 #include "Precompiled.h"
 #include "../Core/Context.h"
+#include "../Graphics/Material.h"
+#include "../Graphics/Texture2D.h"
+#include "../Resource/ResourceCache.h"
 #include "../Scene/Scene.h"
+#include "../Atomic2D/Renderer2D.h"
 #include "../Atomic2D/Sprite2D.h"
 #include "../Atomic2D/StaticSprite2D.h"
-#include "../Graphics/Texture2D.h"
 
 #include "../DebugNew.h"
 
@@ -33,16 +36,18 @@ namespace Atomic
 {
 
 extern const char* ATOMIC2D_CATEGORY;
+extern const char* blendModeNames[];
 
 StaticSprite2D::StaticSprite2D(Context* context) :
     Drawable2D(context),
+    blendMode_(BLEND_ALPHA),
     flipX_(false),
     flipY_(false),
     color_(Color::WHITE),
     useHotSpot_(false),
     hotSpot_(0.5f, 0.5f)
 {
-    vertices_.Reserve(6);
+    sourceBatches_.Resize(1);
 }
 
 StaticSprite2D::~StaticSprite2D()
@@ -54,11 +59,13 @@ void StaticSprite2D::RegisterObject(Context* context)
     context->RegisterFactory<StaticSprite2D>(ATOMIC2D_CATEGORY);
 
     ACCESSOR_ATTRIBUTE("Is Enabled", IsEnabled, SetEnabled, bool, true, AM_DEFAULT);
+    COPY_BASE_ATTRIBUTES(Drawable2D);
     MIXED_ACCESSOR_ATTRIBUTE("Sprite", GetSpriteAttr, SetSpriteAttr, ResourceRef, ResourceRef(Sprite2D::GetTypeStatic()), AM_DEFAULT);
+    ENUM_ACCESSOR_ATTRIBUTE("Blend Mode", GetBlendMode, SetBlendMode, BlendMode, blendModeNames, BLEND_ALPHA, AM_DEFAULT);
     ACCESSOR_ATTRIBUTE("Flip X", GetFlipX, SetFlipX, bool, false, AM_DEFAULT);
     ACCESSOR_ATTRIBUTE("Flip Y", GetFlipY, SetFlipY, bool, false, AM_DEFAULT);
     ACCESSOR_ATTRIBUTE("Color", GetColor, SetColor, Color, Color::WHITE, AM_DEFAULT);
-    COPY_BASE_ATTRIBUTES(Drawable2D);
+    MIXED_ACCESSOR_ATTRIBUTE("Custom material", GetCustomMaterialAttr, SetCustomMaterialAttr, ResourceRef, ResourceRef(Material::GetTypeStatic()), AM_DEFAULT);
 }
 
 void StaticSprite2D::SetSprite(Sprite2D* sprite)
@@ -67,11 +74,21 @@ void StaticSprite2D::SetSprite(Sprite2D* sprite)
         return;
 
     sprite_ = sprite;
-    if (sprite)
-        verticesDirty_ = true;
+    UpdateMaterial();
 
+    sourceBatchesDirty_ = true;
+    MarkNetworkUpdate();
+}
 
-    SetTexture(sprite_ ? sprite_->GetTexture() : 0);
+void StaticSprite2D::SetBlendMode(BlendMode blendMode)
+{
+    if (blendMode == blendMode_)
+        return;
+
+    blendMode_ = blendMode;
+
+    UpdateMaterial();
+    MarkNetworkUpdate();
 }
 
 void StaticSprite2D::SetFlip(bool flipX, bool flipY)
@@ -81,7 +98,7 @@ void StaticSprite2D::SetFlip(bool flipX, bool flipY)
 
     flipX_ = flipX;
     flipY_ = flipY;
-    verticesDirty_ = true;
+    sourceBatchesDirty_ = true;
 
     OnFlipChanged();
 
@@ -104,7 +121,7 @@ void StaticSprite2D::SetColor(const Color& color)
         return;
 
     color_ = color;
-    verticesDirty_ = true;
+    sourceBatchesDirty_ = true;
     MarkNetworkUpdate();
 }
 
@@ -114,7 +131,7 @@ void StaticSprite2D::SetAlpha(float alpha)
         return;
 
     color_.a_ = alpha;
-    verticesDirty_ = true;
+    sourceBatchesDirty_ = true;
     MarkNetworkUpdate();
 }
 
@@ -124,7 +141,7 @@ void StaticSprite2D::SetUseHotSpot(bool useHotSpot)
         return;
 
     useHotSpot_ = useHotSpot;
-    verticesDirty_ = true;
+    sourceBatchesDirty_ = true;
     MarkNetworkUpdate();
 }
 
@@ -137,16 +154,34 @@ void StaticSprite2D::SetHotSpot(const Vector2& hotspot)
 
     if (useHotSpot_)
     {
-        verticesDirty_ = true;
+        sourceBatchesDirty_ = true;
         MarkNetworkUpdate();
     }
 }
 
+void StaticSprite2D::SetCustomMaterial(Material* customMaterial)
+{
+    if (customMaterial == customMaterial_)
+        return;
+
+    customMaterial_ = customMaterial;
+    sourceBatchesDirty_ = true;
+
+    UpdateMaterial();
+    MarkNetworkUpdate();
+}
+
 Sprite2D* StaticSprite2D::GetSprite() const
 {
     return sprite_;
 }
 
+
+Material* StaticSprite2D::GetCustomMaterial() const
+{
+    return customMaterial_;
+}
+
 void StaticSprite2D::SetSpriteAttr(const ResourceRef& value)
 {
     Sprite2D* sprite = Sprite2D::LoadFromResourceRef(this, value);
@@ -159,6 +194,17 @@ ResourceRef StaticSprite2D::GetSpriteAttr() const
     return Sprite2D::SaveToResourceRef(sprite_);
 }
 
+void StaticSprite2D::SetCustomMaterialAttr(const ResourceRef& value)
+{
+    ResourceCache* cache = GetSubsystem<ResourceCache>();
+    SetCustomMaterial(cache->GetResource<Material>(value.name_));
+}
+
+ResourceRef StaticSprite2D::GetCustomMaterialAttr() const
+{
+    return GetResourceRef(customMaterial_, Material::GetTypeStatic());
+}
+
 void StaticSprite2D::OnWorldBoundingBoxUpdate()
 {
     boundingBox_.Clear();
@@ -185,21 +231,38 @@ void StaticSprite2D::OnWorldBoundingBoxUpdate()
     worldBoundingBox_ = boundingBox_.Transformed(node_->GetWorldTransform());
 }
 
-void StaticSprite2D::UpdateVertices()
+void StaticSprite2D::OnDrawOrderChanged()
 {
-    if (!verticesDirty_)
+    sourceBatches_[0].drawOrder_ = GetDrawOrder();
+}
+
+void StaticSprite2D::UpdateSourceBatches()
+{
+    if (!sourceBatchesDirty_)
         return;
 
-    vertices_.Clear();
+    Vector<Vertex2D>& vertices = sourceBatches_[0].vertices_;
+    vertices.Clear();
 
-    Texture2D* texture = GetTexture();
-    if (!texture)
+    if (!sprite_)
         return;
 
-    const IntRect& rectangle_ = sprite_->GetRectangle();
-    if (rectangle_.Width() == 0 || rectangle_.Height() == 0)
-        return;
+    Rect drawRect;
+    if (useHotSpot_)
+    {
+        if (!sprite_->GetDrawRectangle(drawRect, hotSpot_, flipX_, flipY_))
+            return;
+    }
+    else
+    {
+        if (!sprite_->GetDrawRectangle(drawRect, flipX_, flipY_))
+            return;
+    }
 
+    Rect textureRect;
+    if (!sprite_->GetTextureRectangle(textureRect, flipX_, flipY_))
+        return;
+    
     /*
     V1---------V2
     |         / |
@@ -214,76 +277,26 @@ void StaticSprite2D::UpdateVertices()
     Vertex2D vertex2;
     Vertex2D vertex3;
 
-    float width = (float)rectangle_.Width() * PIXEL_SIZE;     // Compute width and height in pixels
-    float height = (float)rectangle_.Height() * PIXEL_SIZE;
-
-    float hotSpotX;
-    float hotSpotY;
-
-    if (useHotSpot_)
-    {
-        hotSpotX = flipX_ ? (1.0f - hotSpot_.x_) : hotSpot_.x_;
-        hotSpotY = flipY_ ? (1.0f - hotSpot_.y_) : hotSpot_.y_;
-    }
-    else
-    {
-        const Vector2& hotSpot = sprite_->GetHotSpot();
-        hotSpotX = flipX_ ? (1.0f - hotSpot.x_) : hotSpot.x_;
-        hotSpotY = flipY_ ? (1.0f - hotSpot.y_) : hotSpot.y_;
-    }
-
-#ifdef ATOMIC_OPENGL
-    float leftX = -width * hotSpotX;
-    float rightX = width * (1.0f - hotSpotX);
-    float bottomY = -height * hotSpotY;
-    float topY = height * (1.0f - hotSpotY);
-#else
-    const float halfPixelOffset = 0.5f * PIXEL_SIZE;
-    float leftX = -width * hotSpotX + halfPixelOffset;
-    float rightX = width * (1.0f - hotSpotX) + halfPixelOffset;
-    float bottomY = -height * hotSpotY + halfPixelOffset;
-    float topY = height * (1.0f - hotSpotY) + halfPixelOffset;
-#endif
-
+    // Convert to world space
     const Matrix3x4& worldTransform = node_->GetWorldTransform();
+    vertex0.position_ = worldTransform * Vector3(drawRect.min_.x_, drawRect.min_.y_, 0.0f);
+    vertex1.position_ = worldTransform * Vector3(drawRect.min_.x_, drawRect.max_.y_, 0.0f);
+    vertex2.position_ = worldTransform * Vector3(drawRect.max_.x_, drawRect.max_.y_, 0.0f);
+    vertex3.position_ = worldTransform * Vector3(drawRect.max_.x_, drawRect.min_.y_, 0.0f);
 
-    vertex0.position_ = worldTransform * Vector3(leftX, bottomY, 0.0f);
-    vertex1.position_ = worldTransform * Vector3(leftX, topY, 0.0f);
-    vertex2.position_ = worldTransform * Vector3(rightX, topY, 0.0f);
-    vertex3.position_ = worldTransform * Vector3(rightX, bottomY, 0.0f);
-
-    float invTexW = 1.0f / (float)texture->GetWidth();
-    float invTexH = 1.0f / (float)texture->GetHeight();
-
-    float leftU = rectangle_.left_ * invTexW;
-    float rightU = rectangle_.right_ * invTexW;
-    float topV = rectangle_.top_ * invTexH;
-    float bottomV = rectangle_.bottom_ * invTexH;
-    vertex0.uv_ = Vector2(leftU, bottomV);
-    vertex1.uv_ = Vector2(leftU, topV);
-    vertex2.uv_ = Vector2(rightU, topV);
-    vertex3.uv_ = Vector2(rightU, bottomV);
-
-    if (flipX_)
-    {
-        Swap(vertex0.uv_.x_, vertex3.uv_.x_);
-        Swap(vertex1.uv_.x_, vertex2.uv_.x_);
-    }
-    
-    if (flipY_)
-    {
-        Swap(vertex0.uv_.y_, vertex1.uv_.y_);
-        Swap(vertex2.uv_.y_, vertex3.uv_.y_);
-    }
+    vertex0.uv_ = textureRect.min_;
+    vertex1.uv_ = Vector2(textureRect.min_.x_, textureRect.max_.y_);
+    vertex2.uv_ = textureRect.max_;
+    vertex3.uv_ = Vector2(textureRect.max_.x_, textureRect.min_.y_);
 
     vertex0.color_ = vertex1.color_ = vertex2.color_  = vertex3.color_ = color_.ToUInt();
 
-    vertices_.Push(vertex0);
-    vertices_.Push(vertex1);
-    vertices_.Push(vertex2);
-    vertices_.Push(vertex3);
+    vertices.Push(vertex0);
+    vertices.Push(vertex1);
+    vertices.Push(vertex2);
+    vertices.Push(vertex3);
 
-    verticesDirty_ = false;
+    sourceBatchesDirty_ = false;
 }
 
 void StaticSprite2D::OnFlipChanged()
@@ -291,4 +304,17 @@ void StaticSprite2D::OnFlipChanged()
 
 }
 
+void StaticSprite2D::UpdateMaterial()
+{
+    if (customMaterial_)
+        sourceBatches_[0].material_ = customMaterial_;
+    else
+    {
+        if (sprite_)
+            sourceBatches_[0].material_ = renderer_->GetMaterial(sprite_->GetTexture(), blendMode_);
+        else
+            sourceBatches_[0].material_ = 0;
+    }
+}
+
 }

+ 23 - 3
Source/Atomic/Atomic2D/StaticSprite2D.h

@@ -44,6 +44,8 @@ public:
 
     /// Set sprite.
     void SetSprite(Sprite2D* sprite);
+    /// Set blend mode.
+    void SetBlendMode(BlendMode blendMode);
     /// Set flip.
     void SetFlip(bool flipX, bool flipY);
     /// Set flip X.
@@ -58,9 +60,13 @@ public:
     void SetUseHotSpot(bool useHotSpot);
     /// Set hot spot.
     void SetHotSpot(const Vector2& hotspot);
-    
+    /// Set custom material.
+    void SetCustomMaterial(Material* customMaterial);
+
     /// Return sprite.
     Sprite2D* GetSprite() const;
+    /// Return blend mode.
+    BlendMode GetBlendMode() const { return blendMode_; }
     /// Return flip X.
     bool GetFlipX() const { return flipX_; }
     /// Return flip Y.
@@ -73,22 +79,34 @@ public:
     bool GetUseHotSpot() const { return useHotSpot_; }
     /// Return hot spot.
     const Vector2& GetHotSpot() const { return hotSpot_; }
+    /// Return custom material.
+    Material* GetCustomMaterial() const;
 
     /// Set sprite attribute.
     void SetSpriteAttr(const ResourceRef& value);
     /// Return sprite attribute.
     ResourceRef GetSpriteAttr() const;
+    /// Set custom material attribute.
+    void SetCustomMaterialAttr(const ResourceRef& value);
+    /// Return custom material attribute.
+    ResourceRef GetCustomMaterialAttr() const;
 
 protected:
     /// Recalculate the world-space bounding box.
     virtual void OnWorldBoundingBoxUpdate();
-    /// Update vertices.
-    virtual void UpdateVertices();
+    /// Handle draw order changed.
+    virtual void OnDrawOrderChanged();
+    /// Update source batches.
+    virtual void UpdateSourceBatches();
     /// Handle flip changed.
     virtual void OnFlipChanged();
+    /// Update material.
+    void UpdateMaterial();
 
     /// Sprite.
     SharedPtr<Sprite2D> sprite_;
+    /// Blend mode.
+    BlendMode blendMode_;
     /// Flip X.
     bool flipX_;
     /// Flip Y.
@@ -99,6 +117,8 @@ protected:
     bool useHotSpot_;
     /// Hot spot.
     Vector2 hotSpot_;
+    /// Custom material.
+    SharedPtr<Material> customMaterial_;
 };
 
 }

+ 3 - 3
Source/Atomic/Atomic3D/AnimatedModel.cpp

@@ -230,13 +230,13 @@ void AnimatedModel::UpdateBatches(const FrameInfo& frame)
 
     // Note: per-geometry distances do not take skinning into account. Especially in case of a ragdoll they may be
     // much off base if the node's own transform is not updated
-    if (batches_.Size() > 1)
+    if (batches_.Size() == 1)
+        batches_[0].distance_ = distance_;
+    else
     {
         for (unsigned i = 0; i < batches_.Size(); ++i)
             batches_[i].distance_ = frame.camera_->GetDistance(worldTransform * geometryData_[i].center_);
     }
-    else if (batches_.Size() == 1)
-        batches_[0].distance_ = distance_;
 
     // Use a transformed version of the model's bounding box instead of world bounding box for LOD scale
     // determination so that animation does not change the scale

+ 2 - 2
Source/Atomic/Atomic3D/DecalSet.cpp

@@ -1,5 +1,5 @@
 //
-// Copyright (c) 2008-2014 the Urho3D project.
+// Copyright (c) 2008-2015 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
@@ -914,7 +914,7 @@ bool DecalSet::GetBones(Drawable* target, unsigned batchIndex, const float* blen
 
             if (!found)
             {
-                if (bones_.Size() >= MAX_SKIN_MATRICES)
+                if (bones_.Size() >= Graphics::GetMaxBones())
                 {
                     LOGWARNING("Maximum skinned decal bone count reached");
                     return false;

+ 2 - 0
Source/Atomic/Atomic3D/Model.h

@@ -165,6 +165,8 @@ public:
     const PODVector<Vector3>& GetGeometryCenters() const { return geometryCenters_; }
     /// Return geometry by index and LOD level. The LOD level is clamped if out of range.
     Geometry* GetGeometry(unsigned index, unsigned lodLevel) const;
+    /// Return geometry center by index.
+    const Vector3& GetGeometryCenter(unsigned index) const { return index < geometryCenters_.Size() ? geometryCenters_[index] : Vector3::ZERO; }
     /// Return geometery bone mappings.
     const Vector<PODVector<unsigned> >& GetGeometryBoneMappings() const { return geometryBoneMappings_; }
     /// Return vertex morphs.

+ 2 - 2
Source/Atomic/Atomic3D/ParticleEmitter.cpp

@@ -1,5 +1,5 @@
 //
-// Copyright (c) 2008-2014 the Urho3D project.
+// Copyright (c) 2008-2015 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
@@ -484,7 +484,7 @@ bool ParticleEmitter::EmitNewParticle()
     billboard.uv_ = textureFrames_.Size() ? textureFrames_[0].uv_ : Rect::POSITIVE;
     billboard.rotation_ = effect_->GetRandomRotation();
     const Vector<ColorFrame>& colorFrames_ = effect_->GetColorFrames();
-    billboard.color_ = colorFrames_[0].color_;
+    billboard.color_ = colorFrames_.Size() ? colorFrames_[0].color_ : Color();
     billboard.enabled_ = true;
 
     return true;

+ 10 - 12
Source/Atomic/Atomic3D/StaticModel.cpp

@@ -1,5 +1,5 @@
 //
-// Copyright (c) 2008-2014 the Urho3D project.
+// Copyright (c) 2008-2015 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
@@ -87,6 +87,7 @@ void StaticModel::ProcessRayQuery(const RayOctreeQuery& query, PODVector<RayQuer
         Ray localRay = query.ray_.Transformed(inverse);
         float distance = localRay.HitDistance(boundingBox_);
         Vector3 normal = -query.ray_.direction_;
+        unsigned hitBatch = M_MAX_UNSIGNED;
 
         if (level == RAY_TRIANGLE && distance < query.maxDistance_)
         {
@@ -103,6 +104,7 @@ void StaticModel::ProcessRayQuery(const RayOctreeQuery& query, PODVector<RayQuer
                     {
                         distance = geometryDistance;
                         normal = (node_->GetWorldTransform() * Vector4(geometryNormal, 0.0f)).Normalized();
+                        hitBatch = i;
                     }
                 }
             }
@@ -116,7 +118,7 @@ void StaticModel::ProcessRayQuery(const RayOctreeQuery& query, PODVector<RayQuer
             result.distance_ = distance;
             result.drawable_ = this;
             result.node_ = node_;
-            result.subObject_ = M_MAX_UNSIGNED;
+            result.subObject_ = hitBatch;
             results.Push(result);
         }
         break;
@@ -126,21 +128,15 @@ void StaticModel::ProcessRayQuery(const RayOctreeQuery& query, PODVector<RayQuer
 void StaticModel::UpdateBatches(const FrameInfo& frame)
 {
     const BoundingBox& worldBoundingBox = GetWorldBoundingBox();
-    const Matrix3x4& worldTransform = node_->GetWorldTransform();
     distance_ = frame.camera_->GetDistance(worldBoundingBox.Center());
 
-    if (batches_.Size() > 1)
+    if (batches_.Size() == 1)
+        batches_[0].distance_ = distance_;
+    else
     {
+        const Matrix3x4& worldTransform = node_->GetWorldTransform();
         for (unsigned i = 0; i < batches_.Size(); ++i)
-        {
             batches_[i].distance_ = frame.camera_->GetDistance(worldTransform * geometryData_[i].center_);
-            batches_[i].worldTransform_ = &worldTransform;
-        }
-    }
-    else if (batches_.Size() == 1)
-    {
-        batches_[0].distance_ = distance_;
-        batches_[0].worldTransform_ = &worldTransform;
     }
 
     float scale = worldBoundingBox.Size().DotProduct(DOT_SCALE);
@@ -255,8 +251,10 @@ void StaticModel::SetModel(Model* model)
         SetNumGeometries(model->GetNumGeometries());
         const Vector<Vector<SharedPtr<Geometry> > >& geometries = model->GetGeometries();
         const PODVector<Vector3>& geometryCenters = model->GetGeometryCenters();
+        const Matrix3x4* worldTransform = node_ ? &node_->GetWorldTransform() : (const Matrix3x4*)0;
         for (unsigned i = 0; i < geometries.Size(); ++i)
         {
+            batches_[i].worldTransform_ = worldTransform;
             geometries_[i] = geometries[i];
             geometryData_[i].center_ = geometryCenters[i];
         }

+ 5 - 1
Source/Atomic/CMakeLists.txt

@@ -34,7 +34,11 @@ endif()
 file (GLOB GRAPHICS_SOURCE Graphics/*.cpp Graphics/*.h)
 
 if (MSVC)
-    file (GLOB GRAPHICS_IMPL_SOURCE Graphics/Direct3D9/*.cpp Graphics/Direct3D9/*.h)
+    if (ATOMIC_D3D11)  
+      file (GLOB GRAPHICS_IMPL_SOURCE Graphics/Direct3D11/*.cpp Graphics/Direct3D11/*.h)
+    else()
+      file (GLOB GRAPHICS_IMPL_SOURCE Graphics/Direct3D9/*.cpp Graphics/Direct3D9/*.h)
+    endif()  
 else()
 
 # for kNet

+ 0 - 191
Source/Atomic/Container/HashTable.h

@@ -1,191 +0,0 @@
-//
-// Copyright (c) 2008-2014 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.
-//
-
-#pragma once
-
-#include "../Container/Allocator.h"
-#include "../Container/Vector.h"
-
-namespace Atomic
-{
-
-/// Hash table with fixed bucket count. Does not support iteration. Should only be used when performance is critical, as HashMap is much more user-friendly.
-template <class T, unsigned U> class HashTable
-{
-public:
-    /// Hash table node.
-    struct Node
-    {
-        /// Construct.
-        Node(unsigned hash, const T& value, Node* next) :
-            hash_(hash),
-            value_(value),
-            next_(next)
-        {
-        }
-        
-        /// Hash value.
-        unsigned hash_;
-        /// Node value.
-        T value_;
-        /// Next node in bucket.
-        Node* next_;
-    };
-    
-    /// Construct empty.
-    HashTable() :
-        allocator_(0)
-    {
-        for (unsigned i = 0; i < U; ++i)
-            ptrs_[i] = 0;
-    }
-    
-    /// Destruct.
-    ~HashTable()
-    {
-        Clear();
-        AllocatorUninitialize(allocator_);
-    }
-    
-    /// Insert by hash value. If value with same hash already exists, it is replaced.
-    void Insert(unsigned hash, const T& value)
-    {
-        unsigned bucket = hash & (U - 1);
-        
-        if (!allocator_)
-            allocator_ = AllocatorInitialize(sizeof(Node));
-        
-        Node* ptr = ptrs_[bucket];
-        while (ptr)
-        {
-            if (ptr->hash_ == hash)
-            {
-                ptr->value_ = value;
-                return;
-            }
-            ptr = ptr->next_;
-        }
-        
-        Node* newNode = static_cast<Node*>(AllocatorReserve(allocator_));
-        // Insert at the top of the bucket, connect to the previous top node if exists
-        new(newNode) Node(hash, value, ptrs_[bucket]);
-        ptrs_[bucket] = newNode;
-    }
-    
-    /// Remove by hash value. Return true if was found and removed.
-    bool Erase(unsigned hash)
-    {
-        unsigned bucket = hash & (U - 1);
-        
-        Node* ptr = ptrs_[bucket];
-        while (ptr)
-        {
-            if (ptr->hash_ == hash)
-            {
-                (ptr)->~Node();
-                AllocatorFree(allocator_, ptr);
-                return true;
-            }
-            else
-                ptr = ptr->next_;
-        }
-        
-        return false;
-    }
-    
-    /// Remove all values.
-    void Clear()
-    {
-        for (unsigned i = 0; i < U; ++i)
-        {
-            Node* ptr = ptrs_[i];
-            while (ptr)
-            {
-                Node* next = ptr->next_;
-                (ptr)->~Node();
-                AllocatorFree(allocator_, ptr);
-                ptr = next;
-            }
-        }
-    }
-    
-    /// Find by hash value. Return pointer if was found or null if not found.
-    T* Find(unsigned hash) const
-    {
-        unsigned bucket = hash & (U - 1);
-        
-        Node* ptr = ptrs_[bucket];
-        while (ptr)
-        {
-            if (ptr->hash_ == hash)
-                return &ptr->value_;
-            else
-                ptr = ptr->next_;
-        }
-        
-        return 0;
-    }
-    
-    /// Return all the keys.
-    PODVector<unsigned> Keys() const
-    {
-        PODVector<unsigned> ret;
-
-        for (unsigned i = 0; i < U; ++i)
-        {
-            Node* ptr = ptrs_[i];
-            while (ptr)
-            {
-                ret.Push(ptr->hash_);
-                ptr = ptr->next_;
-            }
-        }
-
-        return ret;
-    }
-
-    /// Return pointers to all values.
-    PODVector<T*> Values() const
-    {
-        PODVector<T*> ret;
-        
-        for (unsigned i = 0; i < U; ++i)
-        {
-            Node* ptr = ptrs_[i];
-            while (ptr)
-            {
-                ret.Push(&ptr->value_);
-                ptr = ptr->next_;
-            }
-        }
-        
-        return ret;
-    }
-    
-private:
-    /// Allocator.
-    AllocatorBlock* allocator_;
-    /// Bucket pointers, fixed size.
-    Node* ptrs_[U];
-};
-
-}

+ 21 - 1
Source/Atomic/Container/Str.cpp

@@ -1,5 +1,5 @@
 //
-// Copyright (c) 2008-2014 the Urho3D project.
+// Copyright (c) 2008-2015 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
@@ -183,6 +183,16 @@ String& String::operator += (short rhs)
     return *this += String(rhs);
 }
 
+String& String::operator += (long rhs)
+{
+    return *this += String(rhs);
+}
+
+String& String::operator += (long long rhs)
+{
+    return *this += String(rhs);
+}
+
 String& String::operator += (unsigned rhs)
 {
     return *this += String(rhs);
@@ -193,6 +203,16 @@ String& String::operator += (unsigned short rhs)
     return *this += String(rhs);
 }
 
+String& String::operator += (unsigned long rhs)
+{
+    return *this += String(rhs);
+}
+
+String& String::operator += (unsigned long long rhs)
+{
+    return *this += String(rhs);
+}
+
 String& String::operator += (float rhs)
 {
     return *this += String(rhs);

+ 10 - 2
Source/Atomic/Container/Str.h

@@ -1,5 +1,5 @@
 //
-// Copyright (c) 2008-2014 the Urho3D project.
+// Copyright (c) 2008-2015 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
@@ -206,10 +206,18 @@ public:
     String& operator += (int rhs);
     /// Add-assign a short integer.
     String& operator += (short rhs);
+    /// Add-assign a long integer.
+    String& operator += (long rhs);
+    /// Add-assign a long long integer.
+    String& operator += (long long rhs);
     /// Add-assign an unsigned integer.
     String& operator += (unsigned rhs);
     /// Add-assign a short unsigned integer.
     String& operator += (unsigned short rhs);
+    /// Add-assign a long unsigned integer.
+    String& operator += (unsigned long rhs);
+    /// Add-assign a long long unsigned integer.
+    String& operator += (unsigned long long rhs);
     /// Add-assign a float.
     String& operator += (float rhs);
     /// Add-assign a bool.
@@ -439,7 +447,7 @@ public:
         const char* ptr = str;
         while (*ptr)
             ++ptr;
-        return ptr - str;
+        return (unsigned)(ptr - str);
         #endif
     }
     

+ 1 - 1
Source/Atomic/Core/Object.h

@@ -176,7 +176,7 @@ public:
     }
     
     /// Create an object of the specific type.
-    virtual SharedPtr<Object>(CreateObject()) { return SharedPtr<Object>(new T(context_)); }
+    virtual SharedPtr<Object> CreateObject() { return SharedPtr<Object>(new T(context_)); }
 };
 
 /// Internal helper class for invoking event handler functions.

+ 14 - 11
Source/Atomic/Core/ProcessUtils.cpp

@@ -160,18 +160,21 @@ void OpenConsoleWindow()
 
 void PrintUnicode(const String& str, bool error)
 {
-#if !defined(ANDROID) && !defined(IOS)
-#ifdef WIN32
-    HANDLE stream = GetStdHandle(error ? STD_ERROR_HANDLE : STD_OUTPUT_HANDLE);
-    if (stream == INVALID_HANDLE_VALUE)
-        return;
-    WString strW(str);
-    DWORD charsWritten;
-    WriteConsoleW(stream, strW.CString(), strW.Length(), &charsWritten, 0);
-    
-    if (IsDebuggerPresent())
+    #if !defined(ANDROID) && !defined(IOS)
+    #ifdef WIN32
+    // If the output stream has been redirected, use fprintf instead of WriteConsoleW,
+    // though it means that proper Unicode output will not work
+    FILE* out = error ? stderr : stdout;
+    if (!_isatty(_fileno(out)))
+        fprintf(out, "%s", str.CString());
+    else
     {
-        OutputDebugString(str.CString());
+        HANDLE stream = GetStdHandle(error ? STD_ERROR_HANDLE : STD_OUTPUT_HANDLE);
+        if (stream == INVALID_HANDLE_VALUE)
+            return;
+        WString strW(str);
+        DWORD charsWritten;
+        WriteConsoleW(stream, strW.CString(), strW.Length(), &charsWritten, 0);
     }
     #else
     fprintf(error ? stderr : stdout, "%s", str.CString());

+ 77 - 77
Source/Atomic/Core/StringUtils.cpp

@@ -1,5 +1,5 @@
 //
-// Copyright (c) 2008-2014 the Urho3D project.
+// Copyright (c) 2008-2015 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
@@ -34,50 +34,50 @@ unsigned CountElements(const char* buffer, char separator)
 {
     if (!buffer)
         return 0;
-    
+
     const char* endPos = buffer + String::CStringLength(buffer);
     const char* pos = buffer;
     unsigned ret = 0;
-    
+
     while (pos < endPos)
     {
         if (*pos != separator)
             break;
         ++pos;
     }
-    
+
     while (pos < endPos)
     {
         const char* start = pos;
-        
+
         while (start < endPos)
         {
             if (*start == separator)
                 break;
-            
+
             ++start;
         }
-        
+
         if (start == endPos)
         {
             ++ret;
             break;
         }
-        
+
         const char* end = start;
-        
+
         while (end < endPos)
         {
             if (*end != separator)
                 break;
-            
+
             ++end;
         }
-        
+
         ++ret;
         pos = end;
     }
-    
+
     return ret;
 }
 
@@ -89,7 +89,7 @@ bool ToBool(const String& source)
 bool ToBool(const char* source)
 {
     unsigned length = String::CStringLength(source);
-    
+
     for (unsigned i = 0; i < length; ++i)
     {
         char c = tolower(source[i]);
@@ -98,7 +98,7 @@ bool ToBool(const char* source)
         else if (c != ' ' && c != '\t')
             break;
     }
-    
+
     return false;
 }
 
@@ -111,7 +111,7 @@ int ToInt(const char* source)
 {
     if (!source)
         return 0;
-    
+
     // Explicitly ask for base 10 to prevent source starts with '0' or '0x' from being converted to base 8 or base 16, respectively
     return strtol(source, 0, 10);
 }
@@ -125,7 +125,7 @@ unsigned ToUInt(const char* source)
 {
     if (!source)
         return 0;
-    
+
     return strtoul(source, 0, 10);
 }
 
@@ -138,7 +138,7 @@ float ToFloat(const char* source)
 {
     if (!source)
         return 0;
-    
+
     return (float)strtod(source, 0);
 }
 
@@ -150,18 +150,18 @@ Color ToColor(const String& source)
 Color ToColor(const char* source)
 {
     Color ret;
-    
+
     unsigned elements = CountElements(source, ' ');
     if (elements < 3)
         return ret;
-    
+
     char* ptr = (char*)source;
     ret.r_ = (float)strtod(ptr, &ptr);
     ret.g_ = (float)strtod(ptr, &ptr);
     ret.b_ = (float)strtod(ptr, &ptr);
     if (elements > 3)
         ret.a_ = (float)strtod(ptr, &ptr);
-    
+
     return ret;
 }
 
@@ -173,17 +173,17 @@ IntRect ToIntRect(const String& source)
 IntRect ToIntRect(const char* source)
 {
     IntRect ret(IntRect::ZERO);
-    
+
     unsigned elements = CountElements(source, ' ');
     if (elements < 4)
         return ret;
-    
+
     char* ptr = (char*)source;
-    ret.left_ = strtol(ptr, &ptr, 10);
-    ret.top_ = strtol(ptr, &ptr, 10);
-    ret.right_ = strtol(ptr, &ptr, 10);
-    ret.bottom_ = strtol(ptr, &ptr, 10);
-    
+    ret.left_ = (int)strtol(ptr, &ptr, 10);
+    ret.top_ = (int)strtol(ptr, &ptr, 10);
+    ret.right_ = (int)strtol(ptr, &ptr, 10);
+    ret.bottom_ = (int)strtol(ptr, &ptr, 10);
+
     return ret;
 }
 
@@ -195,15 +195,15 @@ IntVector2 ToIntVector2(const String& source)
 IntVector2 ToIntVector2(const char* source)
 {
     IntVector2 ret(IntVector2::ZERO);
-    
+
     unsigned elements = CountElements(source, ' ');
     if (elements < 2)
         return ret;
-    
+
     char* ptr = (char*)source;
-    ret.x_ = strtol(ptr, &ptr, 10);
-    ret.y_ = strtol(ptr, &ptr, 10);
-    
+    ret.x_ = (int)strtol(ptr, &ptr, 10);
+    ret.y_ = (int)strtol(ptr, &ptr, 10);
+
     return ret;
 }
 
@@ -215,17 +215,17 @@ Rect ToRect(const String& source)
 Rect ToRect(const char* source)
 {
     Rect ret(Rect::ZERO);
-    
+
     unsigned elements = CountElements(source, ' ');
     if (elements < 4)
         return ret;
-    
+
     char* ptr = (char*)source;
     ret.min_.x_ = (float)strtod(ptr, &ptr);
     ret.min_.y_ = (float)strtod(ptr, &ptr);
     ret.max_.x_ = (float)strtod(ptr, &ptr);
     ret.max_.y_ = (float)strtod(ptr, &ptr);
-    
+
     return ret;
 }
 
@@ -238,7 +238,7 @@ Quaternion ToQuaternion(const char* source)
 {
     unsigned elements = CountElements(source, ' ');
     char* ptr = (char*)source;
-    
+
     if (elements < 3)
         return Quaternion::IDENTITY;
     else if (elements < 4)
@@ -248,7 +248,7 @@ Quaternion ToQuaternion(const char* source)
         x = (float)strtod(ptr, &ptr);
         y = (float)strtod(ptr, &ptr);
         z = (float)strtod(ptr, &ptr);
-        
+
         return Quaternion(x, y, z);
     }
     else
@@ -259,7 +259,7 @@ Quaternion ToQuaternion(const char* source)
         ret.x_ = (float)strtod(ptr, &ptr);
         ret.y_ = (float)strtod(ptr, &ptr);
         ret.z_ = (float)strtod(ptr, &ptr);
-        
+
         return ret;
     }
 }
@@ -272,15 +272,15 @@ Vector2 ToVector2(const String& source)
 Vector2 ToVector2(const char* source)
 {
     Vector2 ret(Vector2::ZERO);
-    
+
     unsigned elements = CountElements(source, ' ');
     if (elements < 2)
         return ret;
-    
+
     char* ptr = (char*)source;
     ret.x_ = (float)strtod(ptr, &ptr);
     ret.y_ = (float)strtod(ptr, &ptr);
-    
+
     return ret;
 }
 
@@ -292,16 +292,16 @@ Vector3 ToVector3(const String& source)
 Vector3 ToVector3(const char* source)
 {
     Vector3 ret(Vector3::ZERO);
-    
+
     unsigned elements = CountElements(source, ' ');
     if (elements < 3)
         return ret;
-    
+
     char* ptr = (char*)source;
     ret.x_ = (float)strtod(ptr, &ptr);
     ret.y_ = (float)strtod(ptr, &ptr);
     ret.z_ = (float)strtod(ptr, &ptr);
-    
+
     return ret;
 }
 
@@ -313,20 +313,20 @@ Vector4 ToVector4(const String& source, bool allowMissingCoords)
 Vector4 ToVector4(const char* source, bool allowMissingCoords)
 {
     Vector4 ret(Vector4::ZERO);
-    
+
     unsigned elements = CountElements(source, ' ');
     char* ptr = (char*)source;
-    
+
     if (!allowMissingCoords)
     {
         if (elements < 4)
             return ret;
-        
+
         ret.x_ = (float)strtod(ptr, &ptr);
         ret.y_ = (float)strtod(ptr, &ptr);
         ret.z_ = (float)strtod(ptr, &ptr);
         ret.w_ = (float)strtod(ptr, &ptr);
-        
+
         return ret;
     }
     else
@@ -339,7 +339,7 @@ Vector4 ToVector4(const char* source, bool allowMissingCoords)
             ret.z_ = (float)strtod(ptr, &ptr);
         if (elements > 3)
             ret.w_ = (float)strtod(ptr, &ptr);
-        
+
         return ret;
     }
 }
@@ -353,25 +353,25 @@ Variant ToVectorVariant(const char* source)
 {
     Variant ret;
     unsigned elements = CountElements(source, ' ');
-    
+
     switch (elements)
     {
     case 1:
         ret.FromString(VAR_FLOAT, source);
         break;
-        
+
     case 2:
         ret.FromString(VAR_VECTOR2, source);
         break;
-        
+
     case 3:
         ret.FromString(VAR_VECTOR3, source);
         break;
-        
+
     case 4:
         ret.FromString(VAR_VECTOR4, source);
         break;
-        
+
     case 9:
         ret.FromString(VAR_MATRIX3, source);
         break;
@@ -384,7 +384,7 @@ Variant ToVectorVariant(const char* source)
         ret.FromString(VAR_MATRIX4, source);
         break;
     }
-    
+
     return ret;
 }
 
@@ -396,11 +396,11 @@ Matrix3 ToMatrix3(const String& source)
 Matrix3 ToMatrix3(const char* source)
 {
     Matrix3 ret(Matrix3::ZERO);
-    
+
     unsigned elements = CountElements(source, ' ');
     if (elements < 9)
         return ret;
-    
+
     char* ptr = (char*)source;
     ret.m00_ = (float)strtod(ptr, &ptr);
     ret.m01_ = (float)strtod(ptr, &ptr);
@@ -411,7 +411,7 @@ Matrix3 ToMatrix3(const char* source)
     ret.m20_ = (float)strtod(ptr, &ptr);
     ret.m21_ = (float)strtod(ptr, &ptr);
     ret.m22_ = (float)strtod(ptr, &ptr);
-    
+
     return ret;
 }
 
@@ -423,11 +423,11 @@ Matrix3x4 ToMatrix3x4(const String& source)
 Matrix3x4 ToMatrix3x4(const char* source)
 {
     Matrix3x4 ret(Matrix3x4::ZERO);
-    
+
     unsigned elements = CountElements(source, ' ');
     if (elements < 12)
         return ret;
-    
+
     char* ptr = (char*)source;
     ret.m00_ = (float)strtod(ptr, &ptr);
     ret.m01_ = (float)strtod(ptr, &ptr);
@@ -441,7 +441,7 @@ Matrix3x4 ToMatrix3x4(const char* source)
     ret.m21_ = (float)strtod(ptr, &ptr);
     ret.m22_ = (float)strtod(ptr, &ptr);
     ret.m23_ = (float)strtod(ptr, &ptr);
-    
+
     return ret;
 }
 
@@ -453,11 +453,11 @@ Matrix4 ToMatrix4(const String& source)
 Matrix4 ToMatrix4(const char* source)
 {
     Matrix4 ret(Matrix4::ZERO);
-    
+
     unsigned elements = CountElements(source, ' ');
     if (elements < 16)
         return ret;
-    
+
     char* ptr = (char*)source;
     ret.m00_ = (float)strtod(ptr, &ptr);
     ret.m01_ = (float)strtod(ptr, &ptr);
@@ -475,7 +475,7 @@ Matrix4 ToMatrix4(const char* source)
     ret.m31_ = (float)strtod(ptr, &ptr);
     ret.m32_ = (float)strtod(ptr, &ptr);
     ret.m33_ = (float)strtod(ptr, &ptr);
-    
+
     return ret;
 }
 
@@ -501,7 +501,7 @@ void BufferToString(String& dest, const void* data, unsigned size)
         // Room for separator
         if (i)
             ++length;
-        
+
         // Room for the value
         if (bytes[i] < 10)
             ++length;
@@ -510,16 +510,16 @@ void BufferToString(String& dest, const void* data, unsigned size)
         else
             length += 3;
     }
-    
+
     dest.Resize(length);
     unsigned index = 0;
-    
+
     // Convert values
     for (unsigned i = 0; i < size; ++i)
     {
         if (i)
             dest[index++] = ' ';
-        
+
         if (bytes[i] < 10)
         {
             dest[index++] = '0' + bytes[i];
@@ -550,14 +550,14 @@ void StringToBuffer(PODVector<unsigned char>& dest, const char* source)
         dest.Clear();
         return;
     }
-    
+
     unsigned size = CountElements(source, ' ');
     dest.Resize(size);
-    
+
     bool inSpace = true;
     unsigned index = 0;
     unsigned value = 0;
-    
+
     // Parse values
     const char* ptr = source;
     while (*ptr)
@@ -577,10 +577,10 @@ void StringToBuffer(PODVector<unsigned char>& dest, const char* source)
             dest[index++] = value;
             inSpace = true;
         }
-        
+
         ++ptr;
     }
-    
+
     // Write the final value
     if (!inSpace && index < size)
         dest[index] = value;
@@ -594,28 +594,28 @@ unsigned GetStringListIndex(const String& value, const String* strings, unsigned
 unsigned GetStringListIndex(const char* value, const String* strings, unsigned defaultIndex, bool caseSensitive)
 {
     unsigned i = 0;
-    
+
     while (!strings[i].Empty())
     {
         if (!strings[i].Compare(value, caseSensitive))
             return i;
         ++i;
     }
-    
+
     return defaultIndex;
 }
 
 unsigned GetStringListIndex(const char* value, const char** strings, unsigned defaultIndex, bool caseSensitive)
 {
     unsigned i = 0;
-    
+
     while (strings[i])
     {
         if (!String::Compare(value, strings[i], caseSensitive))
             return i;
         ++i;
     }
-    
+
     return defaultIndex;
 }
 

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