DeferredLightPass.bslinc 8.8 KB

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