Decal.bsl 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342
  1. #define CLIP_POS 1
  2. #define NO_ANIMATION 1
  3. #include "$ENGINE$\PerCameraData.bslinc"
  4. #include "$ENGINE$\PerObjectData.bslinc"
  5. #include "$ENGINE$\VertexInput.bslinc"
  6. #if MSAA_MODE != 0
  7. #define MSAA_COUNT 2
  8. #endif
  9. #include "$ENGINE$\DepthInput.bslinc"
  10. #include "$ENGINE$\MaskInput.bslinc"
  11. #include "$ENGINE$\GBufferOutput.bslinc"
  12. shader Surface
  13. {
  14. mixin PerCameraData;
  15. mixin PerObjectData;
  16. mixin VertexInput;
  17. mixin GBufferOutput;
  18. mixin DepthInput;
  19. mixin MaskInput;
  20. variations
  21. {
  22. [name("Blend mode"),show]
  23. BLEND_MODE =
  24. {
  25. [name("Transparent")] 0,
  26. [name("Stain")] 1,
  27. [name("Normals")] 2,
  28. [name("Emissive")] 3
  29. };
  30. INSIDE_GEOMETRY = { true, false };
  31. // 0 - None
  32. // 1 - Resolve single sample only
  33. // 2 - Resolve all samples
  34. MSAA_MODE = { 0, 1, 2 };
  35. };
  36. blend
  37. {
  38. independant = true;
  39. // Scene color
  40. target
  41. {
  42. enabled = true;
  43. color = { srcA, srcIA, add };
  44. alpha = { zero, one, add };
  45. #if BLEND_MODE != 3
  46. writemask = empty;
  47. #endif
  48. };
  49. // Albedo
  50. target
  51. {
  52. enabled = true;
  53. #if BLEND_MODE == 1
  54. color = { dstRGB, zero, add };
  55. #else
  56. color = { srcA, srcIA, add };
  57. #endif
  58. alpha = { zero, one, add };
  59. #if BLEND_MODE != 0
  60. #if BLEND_MODE != 1
  61. writemask = empty;
  62. #endif
  63. #endif
  64. };
  65. // Normal
  66. target
  67. {
  68. enabled = true;
  69. color = { srcA, srcIA, add };
  70. alpha = { zero, one, add };
  71. #if BLEND_MODE == 3
  72. writemask = empty;
  73. #endif
  74. };
  75. // Metallic & roughness
  76. target
  77. {
  78. enabled = true;
  79. color = { srcA, srcIA, add };
  80. alpha = { zero, one, add };
  81. #if BLEND_MODE != 0
  82. #if BLEND_MODE != 1
  83. writemask = empty;
  84. #endif
  85. #endif
  86. };
  87. // Velocity
  88. target
  89. {
  90. enabled = true;
  91. writemask = empty;
  92. };
  93. };
  94. depth
  95. {
  96. write = false;
  97. #if INSIDE_GEOMETRY
  98. read = false;
  99. #else
  100. read = true;
  101. #endif
  102. };
  103. raster
  104. {
  105. #if INSIDE_GEOMETRY
  106. cull = cw;
  107. #else
  108. cull = ccw;
  109. #endif
  110. };
  111. #if MSAA_MODE > 0
  112. stencil
  113. {
  114. enabled = true;
  115. readmask = 0x80;
  116. #if INSIDE_GEOMETRY
  117. back = { keep, keep, keep, eq };
  118. #else
  119. front = { keep, keep, keep, eq };
  120. #endif
  121. #if MSAA_MODE == 1
  122. reference = 0;
  123. #else
  124. reference = 0x80;
  125. #endif
  126. };
  127. #endif
  128. code
  129. {
  130. [alias(gOpacityTex)]
  131. SamplerState gOpacitySamp;
  132. Texture2D gOpacityTex = white;
  133. #if BLEND_MODE == 3
  134. [alias(gEmissiveMaskTex)]
  135. SamplerState gEmissiveMaskSamp;
  136. Texture2D gEmissiveMaskTex = black;
  137. #endif
  138. #if BLEND_MODE != 3
  139. [alias(gNormalTex)]
  140. SamplerState gNormalSamp;
  141. Texture2D gNormalTex = normal;
  142. #endif
  143. #if BLEND_MODE == 0 || BLEND_MODE == 1
  144. [alias(gAlbedoTex)]
  145. SamplerState gAlbedoSamp;
  146. [alias(gRoughnessTex)]
  147. SamplerState gRoughnessSamp;
  148. [alias(gMetalnessTex)]
  149. SamplerState gMetalnessSamp;
  150. Texture2D gAlbedoTex = white;
  151. Texture2D gRoughnessTex = white;
  152. Texture2D gMetalnessTex = black;
  153. #endif
  154. cbuffer MaterialParams
  155. {
  156. float2 gUVOffset = { 0.0f, 0.0f };
  157. float2 gUVTile = { 1.0f, 1.0f };
  158. #if BLEND_MODE == 3
  159. [color][hdr]
  160. float3 gEmissiveColor = { 1.0f, 1.0f, 1.0f };
  161. #endif
  162. #if BLEND_MODE == 0 || BLEND_MODE == 1
  163. [spriteuv(gAlbedoTex)]
  164. float4 gSpriteUV;
  165. #endif
  166. };
  167. [internal]
  168. cbuffer DecalParams
  169. {
  170. float4x4 gWorldToDecal;
  171. float3 gDecalNormal;
  172. float gNormalTolerance;
  173. float gFlipDerivatives;
  174. uint gLayerMask;
  175. }
  176. float3x3 getWorldToTangent(float3 N, float3 p, float2 uv)
  177. {
  178. float3 dp1 = ddx(p);
  179. float3 dp2 = ddy(p);
  180. float2 duv1 = ddx(uv);
  181. float2 duv2 = ddy(uv);
  182. float3 dp2perp = cross(dp2, N);
  183. float3 dp1perp = cross(N, dp1);
  184. float3 T = dp2perp * duv1.x + dp1perp * duv2.x;
  185. float3 B = dp2perp * duv1.y + dp1perp * duv2.y;
  186. float invmax = rsqrt(max(dot(T,T), dot(B,B)));
  187. return float3x3(T * invmax, B * invmax, N);
  188. }
  189. struct DecalVStoFS
  190. {
  191. float4 position : SV_Position;
  192. float4 clipPos : TEXCOORD0;
  193. };
  194. DecalVStoFS vsmain(VertexInput_PO input)
  195. {
  196. DecalVStoFS output;
  197. float4 worldPosition = getVertexWorldPosition(input);
  198. output.position = mul(gMatViewProj, worldPosition);
  199. output.clipPos = output.position;
  200. return output;
  201. }
  202. void fsmain(
  203. in DecalVStoFS input,
  204. in float4 screenPos : SV_Position,
  205. #if MSAA_MODE == 2
  206. uint sampleIdx : SV_SampleIndex,
  207. #endif
  208. out float4 OutSceneColor : SV_Target0,
  209. out float4 OutGBufferA : SV_Target1,
  210. out float4 OutGBufferB : SV_Target2,
  211. out float4 OutGBufferC : SV_Target3)
  212. {
  213. #if MSAA_MODE == 0
  214. float deviceZ = gDepthBufferTex.Load(int3(screenPos.xy, 0)).r;
  215. uint layer = (uint)(gMaskTex.Load(int3(screenPos.xy, 0)).r * 256.0f);
  216. #elif MSAA_MODE == 1
  217. float deviceZ = gDepthBufferTex.Load(screenPos.xy, 0).r;
  218. uint layer = (uint)(gMaskTex.Load(screenPos.xy, 0).r * 256.0f);
  219. #else
  220. float deviceZ = gDepthBufferTex.Load(screenPos.xy, sampleIdx).r;
  221. uint layer = (uint)(gMaskTex.Load(screenPos.xy, sampleIdx).r * 256.0f);
  222. #endif
  223. if(layer < 32 && (gLayerMask & (1 << layer)) == 0)
  224. discard;
  225. float depth = convertFromDeviceZ(deviceZ);
  226. float2 ndcPos = input.clipPos.xy / input.clipPos.w;
  227. // x, y are now in clip space, z, w are in view space
  228. // We multiply them by a special inverse view-projection matrix, that had the projection entries that effect
  229. // z, w eliminated (since they are already in view space)
  230. // Note: Multiply by depth should be avoided if using ortographic projection
  231. float4 mixedSpacePos = float4(ndcPos.xy * -depth, depth, 1);
  232. float4 worldPosition4D = mul(gMatScreenToWorld, mixedSpacePos);
  233. float3 worldPosition = worldPosition4D.xyz / worldPosition4D.w;
  234. float4 decalPos = mul(gWorldToDecal, float4(worldPosition, 1.0f));
  235. float3 decalUV = (decalPos.xyz + 1.0f) * 0.5f;
  236. float alpha = 0.0f;
  237. if(any(decalUV < 0.0f) || any(decalUV > 1.0f))
  238. {
  239. #ifdef METAL
  240. // 'discard' is causing artifacts on Metal
  241. OutSceneColor = 0;
  242. OutGBufferA = 0;
  243. OutGBufferB = 0;
  244. OutGBufferC = 0;
  245. return;
  246. #else
  247. discard;
  248. #endif
  249. }
  250. float3 worldNormal = normalize(cross(ddy(worldPosition), ddx(worldPosition))) * gFlipDerivatives;
  251. if(dot(worldNormal, gDecalNormal) > gNormalTolerance)
  252. discard;
  253. float3x3 worldToTangent = getWorldToTangent(worldNormal, worldPosition, decalUV.xy);
  254. float2 uv = (decalUV.xy * gUVTile + gUVOffset);
  255. #if BLEND_MODE == 0 || BLEND_MODE == 1
  256. uv = uv * gSpriteUV.zw + gSpriteUV.xy;
  257. #endif
  258. float opacity = gOpacityTex.Sample(gOpacitySamp, uv);
  259. #if BLEND_MODE == 3
  260. OutSceneColor = float4(gEmissiveColor * gEmissiveMaskTex.Sample(gEmissiveMaskSamp, uv).x, opacity);
  261. #elif BLEND_MODE == 2
  262. float3 normal = normalize(gNormalTex.Sample(gNormalSamp, uv) * 2.0f - float3(1, 1, 1));
  263. // Flip multiplication order since we need to transform with tangentToWorld, which is the transpose
  264. worldNormal = mul(normal, worldToTangent);
  265. OutGBufferB = float4(worldNormal * 0.5f + 0.5f, opacity);
  266. #else
  267. float4 albedo = gAlbedoTex.Sample(gAlbedoSamp, uv);
  268. opacity *= albedo.a;
  269. OutGBufferA = float4(albedo.xyz, opacity);
  270. float3 normal = normalize(gNormalTex.Sample(gNormalSamp, uv) * 2.0f - float3(1, 1, 1));
  271. // Flip multiplication order since we need to transform with tangentToWorld, which is the transpose
  272. worldNormal = mul(normal, worldToTangent);
  273. OutGBufferB = float4(worldNormal * 0.5f + 0.5f, opacity);
  274. float roughness = gRoughnessTex.Sample(gRoughnessSamp, uv).x;
  275. float metalness = gMetalnessTex.Sample(gMetalnessSamp, uv).x;
  276. OutGBufferC = float4(roughness, metalness, 0.0f, opacity);
  277. #endif
  278. }
  279. };
  280. };