Просмотр исходного кода

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 лет назад
Родитель
Сommit
43f8416e97
100 измененных файлов с 1956 добавлено и 1267 удалено
  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;
 }
 

Некоторые файлы не были показаны из-за большого количества измененных файлов