DeferredPointLightPass.bslinc 6.9 KB

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