DeferredPointLightPass.bslinc 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252
  1. #include "$ENGINE$\DeferredLightPass.bslinc"
  2. Technique
  3. : inherits("DeferredLightPass") =
  4. {
  5. Language = "HLSL11";
  6. Pass =
  7. {
  8. DepthWrite = false;
  9. #ifdef INSIDE_GEOMETRY
  10. DepthRead = false;
  11. Cull = CW;
  12. #else
  13. DepthRead = true;
  14. Cull = CCW;
  15. #endif
  16. Common =
  17. {
  18. struct VStoFS
  19. {
  20. float4 position : SV_POSITION;
  21. float4 screenPos : TEXCOORD0;
  22. };
  23. };
  24. Vertex =
  25. {
  26. struct VertexInput
  27. {
  28. float3 position : POSITION;
  29. uint vertexIdx : SV_VERTEXID;
  30. };
  31. VStoFS main(VertexInput input)
  32. {
  33. VStoFS output;
  34. float3 worldPosition;
  35. uint numSides = gLightGeometry.x;
  36. if(numSides > 0) // Generate spot light geometry
  37. {
  38. uint numSlices = gLightGeometry.y;
  39. float radius = gLightGeometry.w;
  40. float angle = gLightSpotAnglesAndSqrdInvRadius.x;
  41. // Extra scale to ensure edges lie on the circle, not inside it
  42. // TODO - These can be precomputed
  43. float extraRadiusScale = 1.0f / cos(PI / (float)numSides);
  44. float angleTan = tan(angle);
  45. float height = radius / angleTan;
  46. uint sphereStartIdx = numSides * numSlices;
  47. // Cone vertices
  48. if (input.vertexIdx < sphereStartIdx)
  49. {
  50. uint sliceIdx = input.vertexIdx / numSides;
  51. uint sideIdx = input.vertexIdx % numSides;
  52. float curAngle = sideIdx * 2 * PI / (float)numSides;
  53. float sliceOffset = height * sliceIdx / (float)(numSlices - 1);
  54. float sliceRadius = sliceOffset * angleTan * extraRadiusScale;
  55. float4 localPos = float4(sliceRadius * cos(curAngle),
  56. sliceRadius * sin(curAngle), -sliceOffset, 1.0f);
  57. worldPosition = (mul(gMatConeTransform, localPos)).xyz;
  58. }
  59. else // Sphere cap vertices
  60. {
  61. uint sphereVertexIdx = input.vertexIdx - sphereStartIdx;
  62. uint sliceIdx = sphereVertexIdx / numSides;
  63. uint sideIdx = sphereVertexIdx % numSides;
  64. float curAngle = sideIdx * 2 * PI / (float)numSides;
  65. float sliceOffset = radius * sliceIdx / (float)(numSlices - 1);
  66. float sliceRadius = sqrt(max(0.0f, radius * radius - sliceOffset * sliceOffset)) * extraRadiusScale;
  67. float4 localPos = float4(sliceRadius * cos(curAngle),
  68. sliceRadius * sin(curAngle), -height - sliceOffset, 1.0f);
  69. worldPosition = (mul(gMatConeTransform, localPos)).xyz;
  70. }
  71. }
  72. else // Scale and position pre-generated sphere geometry
  73. {
  74. worldPosition = input.position * gLightGeometry.z + gLightPositionAndType.xyz;
  75. }
  76. output.screenPos = mul(gMatViewProj, float4(worldPosition, 1));
  77. output.position = output.screenPos;
  78. return output;
  79. }
  80. };
  81. Fragment =
  82. {
  83. float4 main(VStoFS input) : SV_Target0
  84. {
  85. float2 correctedPos = input.screenPos.xy / input.screenPos.w;
  86. float2 screenUV = correctedPos * gClipToUVScaleOffset.xy + gClipToUVScaleOffset.zw;
  87. GBufferData gBufferData = getGBufferData(screenUV);
  88. if(gBufferData.worldNormal.w > 0.0f)
  89. {
  90. // x, y are now in clip space, z, w are in view space
  91. // We multiply them by a special inverse view-projection matrix, that had the projection entries that effect
  92. // z, w eliminated (since they are already in view space)
  93. float4 mixedSpacePos = float4(correctedPos.xy * -gBufferData.depth, gBufferData.depth, 1);
  94. float4 worldPosition4D = mul(gMatScreenToWorld, mixedSpacePos);
  95. float3 worldPosition = worldPosition4D.xyz / worldPosition4D.w;
  96. LightData lightData = getLightData();
  97. return getLighting(worldPosition, screenUV, gBufferData, lightData);
  98. }
  99. else
  100. return float4(0.0f, 0.0f, 0.0f, 0.0f);
  101. }
  102. };
  103. };
  104. };
  105. Technique
  106. : inherits("DeferredLightPass") =
  107. {
  108. Language = "GLSL";
  109. Pass =
  110. {
  111. DepthWrite = false;
  112. #ifdef INSIDE_GEOMETRY
  113. DepthRead = false;
  114. Cull = CW;
  115. #else
  116. DepthRead = true;
  117. Cull = CCW;
  118. #endif
  119. Vertex =
  120. {
  121. varying vec4 position;
  122. varying vec4 screenPos;
  123. in vec3 bs_position;
  124. in int gl_VertexID;
  125. out gl_PerVertex
  126. {
  127. vec4 gl_Position;
  128. };
  129. void main()
  130. {
  131. vec3 worldPosition;
  132. uint numSides = uint(gLightGeometry.x);
  133. if(numSides > 0) // Generate spot light geometry
  134. {
  135. uint numSlices = uint(gLightGeometry.y);
  136. float radius = gLightGeometry.w;
  137. float angle = gLightSpotAnglesAndSqrdInvRadius.x;
  138. // Extra scale to ensure edges lie on the circle, not inside it
  139. // TODO - These can be precomputed
  140. float extraRadiusScale = 1.0f / cos(PI / float(numSides));
  141. float angleTan = tan(angle);
  142. float height = radius / angleTan;
  143. uint sphereStartIdx = numSides * numSlices;
  144. // Cone vertices
  145. if (gl_VertexID < sphereStartIdx)
  146. {
  147. uint sliceIdx = gl_VertexID / numSides;
  148. uint sideIdx = gl_VertexID % numSides;
  149. float curAngle = float(sideIdx) * 2 * PI / float(numSides);
  150. float sliceOffset = height * sliceIdx / float(numSlices - 1);
  151. float sliceRadius = sliceOffset * angleTan * extraRadiusScale;
  152. vec4 localPos = vec4(sliceRadius * cos(curAngle),
  153. sliceRadius * sin(curAngle), -sliceOffset, 1.0f);
  154. worldPosition = (gMatConeTransform * localPos).xyz;
  155. }
  156. else // Sphere cap vertices
  157. {
  158. uint sphereVertexIdx = gl_VertexID - sphereStartIdx;
  159. uint sliceIdx = sphereVertexIdx / numSides;
  160. uint sideIdx = sphereVertexIdx % numSides;
  161. float curAngle = float(sideIdx) * 2 * PI / float(numSides);
  162. float sliceOffset = radius * sliceIdx / float(numSlices - 1);
  163. float sliceRadius = sqrt(max(0.0f, radius * radius - sliceOffset * sliceOffset)) * extraRadiusScale;
  164. vec4 localPos = vec4(sliceRadius * cos(curAngle),
  165. sliceRadius * sin(curAngle), -height - sliceOffset, 1.0f);
  166. worldPosition = (gMatConeTransform * localPos).xyz;
  167. }
  168. }
  169. else // Scale and position pre-generated sphere geometry
  170. {
  171. worldPosition = bs_position * gLightGeometry.z + gLightPositionAndType.xyz;
  172. }
  173. screenPos = gMatViewProj * vec4(worldPosition, 1);
  174. position = screenPos;
  175. gl_Position = position;
  176. }
  177. };
  178. Fragment =
  179. {
  180. in vec4 position;
  181. in vec4 screenPos;
  182. out vec4 fragColor;
  183. void main()
  184. {
  185. vec2 correctedPos = screenPos.xy / screenPos.w;
  186. vec2 screenUV = correctedPos * gClipToUVScaleOffset.xy + gClipToUVScaleOffset.zw;
  187. GBufferData gBufferData = getGBufferData(screenUV);
  188. if(gBufferData.worldNormal.w > 0.0f)
  189. {
  190. // x, y are now in clip space, z, w are in view space
  191. // We multiply them by a special inverse view-projection matrix, that had the projection entries that effect
  192. // z, w eliminated (since they are already in view space)
  193. vec4 mixedSpacePos = vec4(correctedPos.xy * -gBufferData.depth, gBufferData.depth, 1);
  194. vec4 worldPosition4D = gMatScreenToWorld * mixedSpacePos;
  195. vec3 worldPosition = worldPosition4D.xyz / worldPosition4D.w;
  196. LightData lightData = getLightData();
  197. fragColor = getLighting(worldPosition, screenUV, gBufferData, lightData);
  198. }
  199. else
  200. fragColor = vec4(0.0f, 0.0f, 0.0f, 0.0f);
  201. }
  202. };
  203. };
  204. };