DeferredLightPass.bslinc 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327
  1. #include "$ENGINE$\GBuffer.bslinc"
  2. #include "$ENGINE$\PerCameraData.bslinc"
  3. Parameters =
  4. {
  5. Sampler2D gGBufferASamp : alias("gGBufferATex");
  6. Sampler2D gGBufferBSamp : alias("gGBufferBTex");
  7. Sampler2D gDepthBufferSamp : alias("gDepthBufferTex");
  8. Texture2D gGBufferATex : auto("GBufferA");
  9. Texture2D gGBufferBTex : auto("GBufferB");
  10. Texture2D gDepthBufferTex : auto("GBufferDepth");
  11. };
  12. Blocks =
  13. {
  14. Block PerCamera : auto("PerCamera");
  15. Block PerLight : auto("PerLight");
  16. };
  17. Technique
  18. : base("DeferredLightPass")
  19. : inherits("GBuffer")
  20. : inherits("PerCameraData") =
  21. {
  22. Language = "HLSL11";
  23. Pass =
  24. {
  25. Target =
  26. {
  27. Blend = true;
  28. Color = { ONE, ONE, ADD };
  29. WriteMask = RGB;
  30. };
  31. DepthWrite = false;
  32. Common =
  33. {
  34. #define PI 3.1415926
  35. #define HALF_PI 1.5707963
  36. cbuffer PerLight
  37. {
  38. // x, y, z - World position of the lightData
  39. // w - Type type - Directional = 0, Point = >0, Spot = >0.5
  40. float4 gLightPositionAndType;
  41. float4 gLightColorAndIntensity;
  42. // x - outerAngle in radians, y - cos(outerAngle), z - 1.0f/(cos(innerAngle) - cos(outerAngle)), w - inverse point light radius
  43. float4 gLightSpotAnglesAndSqrdInvRadius;
  44. float3 gLightDirection;
  45. // x - Num sides (zero for point lights)
  46. // y - Num slices (zero for point lights)
  47. // z - Sphere radius for point lights
  48. // w - Cone radius for spot lights
  49. float4 gLightGeometry;
  50. float4x4 gMatConeTransform;
  51. }
  52. struct LightData
  53. {
  54. float3 position;
  55. float3 direction;
  56. float intensity;
  57. bool isSpot;
  58. bool isPoint;
  59. float3 spotAngles;
  60. float3 color;
  61. float radiusSqrdInv;
  62. };
  63. float convertFromDeviceZ(float deviceZ)
  64. {
  65. return (1.0f / (deviceZ + gDeviceZToWorldZ.y)) * gDeviceZToWorldZ.x;
  66. }
  67. GBufferData decodeGBuffer(float4 GBufferAData, float4 GBufferBData, float deviceZ)
  68. {
  69. GBufferData output;
  70. output.albedo.xyz = GBufferAData.xyz;
  71. output.albedo.w = 1.0f;
  72. output.worldNormal = GBufferBData * float4(2, 2, 2, 1) - float4(1, 1, 1, 0);
  73. output.worldNormal.xyz = normalize(output.worldNormal.xyz);
  74. output.depth = convertFromDeviceZ(deviceZ);
  75. return output;
  76. }
  77. LightData getLightData()
  78. {
  79. LightData output;
  80. output.position = gLightPositionAndType.xyz;
  81. output.direction = gLightDirection;
  82. output.color = gLightColorAndIntensity.rgb;
  83. output.intensity = gLightColorAndIntensity.w;
  84. output.isPoint = gLightPositionAndType.w > 0.0f;
  85. output.isSpot = gLightPositionAndType.w > 0.5f;
  86. output.spotAngles = gLightSpotAnglesAndSqrdInvRadius.xyz;
  87. output.radiusSqrdInv = gLightSpotAnglesAndSqrdInvRadius.w;
  88. return output;
  89. }
  90. float getSpotAttenuation(float3 worldPosToLight, float3 direction, float3 angles)
  91. {
  92. float output = saturate((dot(-worldPosToLight, direction) - angles.y) * angles.z);
  93. return output * output;
  94. }
  95. float4 getLighting(float3 worldPosition, float2 uv, GBufferData gBuffer, LightData lightData)
  96. {
  97. float3 N = gBuffer.worldNormal.xyz;
  98. float NoL = 1.0f;
  99. float distanceAttenuation = 1.0f;
  100. float spotFalloff = 1.0f;
  101. float radiusAttenuation = 1.0f;
  102. if (lightData.isPoint)
  103. {
  104. float3 L = lightData.position - worldPosition;
  105. float distanceSqrd = dot(L, L);
  106. distanceAttenuation = 1/(distanceSqrd + 1);
  107. L = normalize(L);
  108. NoL = saturate(dot(N, L)); // TODO - Add bias here?
  109. radiusAttenuation = distanceSqrd * lightData.radiusSqrdInv;
  110. radiusAttenuation *= radiusAttenuation;
  111. radiusAttenuation = saturate(1.0f - radiusAttenuation);
  112. radiusAttenuation *= radiusAttenuation;
  113. if (lightData.isSpot)
  114. spotFalloff = getSpotAttenuation(L, lightData.direction, lightData.spotAngles);
  115. }
  116. else
  117. {
  118. float3 L = -lightData.direction;
  119. NoL = saturate(dot(N, L)); // TODO - Add bias here?
  120. }
  121. float attenuation = distanceAttenuation * spotFalloff * radiusAttenuation;
  122. float3 diffuse = gBuffer.albedo.xyz / PI; // TODO - Add better lighting model later
  123. float4 output = float4(lightData.color * lightData.intensity * ((NoL * attenuation) * diffuse), 1);
  124. return output;
  125. }
  126. };
  127. Fragment =
  128. {
  129. SamplerState gGBufferASamp : register(s0);
  130. SamplerState gGBufferBSamp : register(s1);
  131. SamplerState gDepthBufferSamp : register(s2);
  132. Texture2D gGBufferATex : register(t0);
  133. Texture2D gGBufferBTex : register(t1);
  134. Texture2D gDepthBufferTex : register(t2);
  135. GBufferData getGBufferData(float2 uv)
  136. {
  137. float4 GBufferAData = gGBufferATex.SampleLevel(gGBufferASamp, uv, 0);
  138. float4 GBufferBData = gGBufferBTex.SampleLevel(gGBufferBSamp, uv, 0);
  139. float deviceZ = gDepthBufferTex.SampleLevel(gDepthBufferSamp, uv, 0).r;
  140. return decodeGBuffer(GBufferAData, GBufferBData, deviceZ);
  141. }
  142. };
  143. };
  144. };
  145. Technique
  146. : base("DeferredLightPass")
  147. : inherits("GBuffer")
  148. : inherits("PerCameraData") =
  149. {
  150. Language = "GLSL";
  151. Pass =
  152. {
  153. Target =
  154. {
  155. Blend = true;
  156. Color = { ONE, ONE, ADD };
  157. WriteMask = RGB;
  158. };
  159. DepthWrite = false;
  160. Common =
  161. {
  162. #define PI 3.1415926
  163. #define HALF_PI 1.5707963
  164. layout(std140) uniform PerLight
  165. {
  166. // x, y, z - World position of the lightData
  167. // w - Type type - Directional = 0, Point = >0, Spot = >0.5
  168. vec4 gLightPositionAndType;
  169. vec4 gLightColorAndIntensity;
  170. // x - outerAngle in radians, y - cos(outerAngle), z - 1.0f/(cos(innerAngle) - cos(outerAngle)), w - inverse point light radius
  171. vec4 gLightSpotAnglesAndSqrdInvRadius;
  172. vec3 gLightDirection;
  173. // x - Num sides (zero for point lights)
  174. // y - Num slices (zero for point lights)
  175. // z - Sphere radius for point lights
  176. // w - Cone radius for spot lights
  177. vec4 gLightGeometry;
  178. mat4 gMatConeTransform;
  179. };
  180. struct LightData
  181. {
  182. vec3 position;
  183. vec3 direction;
  184. float intensity;
  185. bool isSpot;
  186. bool isPoint;
  187. vec3 spotAngles;
  188. vec3 color;
  189. float radiusSqrdInv;
  190. };
  191. float convertFromDeviceZ(float deviceZ)
  192. {
  193. return (1.0f / (deviceZ + gDeviceZToWorldZ.y)) * gDeviceZToWorldZ.x;
  194. }
  195. GBufferData decodeGBuffer(vec4 GBufferAData, vec4 GBufferBData, float deviceZ)
  196. {
  197. GBufferData gBufferData;
  198. gBufferData.albedo.xyz = GBufferAData.xyz;
  199. gBufferData.albedo.w = 1.0f;
  200. gBufferData.worldNormal = GBufferBData * vec4(2, 2, 2, 1) - vec4(1, 1, 1, 0);
  201. gBufferData.worldNormal.xyz = normalize(gBufferData.worldNormal.xyz);
  202. gBufferData.depth = convertFromDeviceZ(deviceZ);
  203. return gBufferData;
  204. }
  205. LightData getLightData()
  206. {
  207. LightData lightData;
  208. lightData.position = gLightPositionAndType.xyz;
  209. lightData.direction = gLightDirection;
  210. lightData.color = gLightColorAndIntensity.rgb;
  211. lightData.intensity = gLightColorAndIntensity.w;
  212. lightData.isPoint = gLightPositionAndType.w > 0.0f;
  213. lightData.isSpot = gLightPositionAndType.w > 0.5f;
  214. lightData.spotAngles = gLightSpotAnglesAndSqrdInvRadius.xyz;
  215. lightData.radiusSqrdInv = gLightSpotAnglesAndSqrdInvRadius.w;
  216. return lightData;
  217. }
  218. float getSpotAttenuation(vec3 worldPosToLight, vec3 direction, vec3 angles)
  219. {
  220. float atten = clamp((dot(-worldPosToLight, direction) - angles.y) * angles.z, 0.0, 1.0);
  221. return atten * atten;
  222. }
  223. vec4 getLighting(vec3 worldPosition, vec2 uv, GBufferData gBuffer, LightData lightData)
  224. {
  225. vec3 N = gBuffer.worldNormal.xyz;
  226. float NoL = 1.0f;
  227. float distanceAttenuation = 1.0f;
  228. float spotFalloff = 1.0f;
  229. float radiusAttenuation = 1.0f;
  230. if (lightData.isPoint)
  231. {
  232. vec3 L = lightData.position - worldPosition;
  233. float distanceSqrd = dot(L, L);
  234. distanceAttenuation = 1/(distanceSqrd + 1);
  235. L = normalize(L);
  236. NoL = clamp(dot(N, L), 0.0, 1.0); // TODO - Add bias here?
  237. radiusAttenuation = distanceSqrd * lightData.radiusSqrdInv;
  238. radiusAttenuation *= radiusAttenuation;
  239. radiusAttenuation = clamp(1.0f - radiusAttenuation, 0.0, 1.0);
  240. radiusAttenuation *= radiusAttenuation;
  241. if (lightData.isSpot)
  242. spotFalloff = getSpotAttenuation(L, lightData.direction, lightData.spotAngles);
  243. }
  244. else
  245. {
  246. vec3 L = -lightData.direction;
  247. NoL = clamp(dot(N, L), 0.0, 1.0); // TODO - Add bias here?
  248. }
  249. float attenuation = distanceAttenuation * spotFalloff * radiusAttenuation;
  250. vec3 diffuse = gBuffer.albedo.xyz / PI; // TODO - Add better lighting model later
  251. vec4 lighting = vec4(lightData.color * lightData.intensity * ((NoL * attenuation) * diffuse), 1);
  252. return lighting;
  253. }
  254. };
  255. Fragment =
  256. {
  257. uniform sampler2D gGBufferATex;
  258. uniform sampler2D gGBufferBTex;
  259. uniform sampler2D gDepthBufferTex;
  260. GBufferData getGBufferData(vec2 uv)
  261. {
  262. vec4 GBufferAData = textureLod(gGBufferATex, uv, 0);
  263. vec4 GBufferBData = textureLod(gGBufferBTex, uv, 0);
  264. float deviceZ = textureLod(gDepthBufferTex, uv, 0).r;
  265. return decodeGBuffer(GBufferAData, GBufferBData, deviceZ);
  266. }
  267. };
  268. };
  269. };