BsStandardDeferredLighting.cpp 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. //********************************** Banshee Engine (www.banshee3d.com) **************************************************//
  2. //**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
  3. #include "BsStandardDeferredLighting.h"
  4. #include "BsRendererUtility.h"
  5. #include "BsRendererView.h"
  6. #include "BsGpuParamsSet.h"
  7. #include "BsRenderTargets.h"
  8. #include "BsMesh.h"
  9. namespace bs { namespace ct {
  10. PerLightParamDef gPerLightParamDef;
  11. template<bool MSAA>
  12. DirectionalLightMat<MSAA>::DirectionalLightMat()
  13. :mGBufferParams(mMaterial, mParamsSet)
  14. {
  15. const GpuParams& gpuParams = *mParamsSet->getGpuParams();
  16. gpuParams.getTextureParam(GPT_FRAGMENT_PROGRAM, "gLightOcclusionTex", mLightOcclusionTexParam);
  17. }
  18. template<bool MSAA>
  19. void DirectionalLightMat<MSAA>::_initDefines(ShaderDefines& defines)
  20. {
  21. if (MSAA)
  22. defines.set("MSAA_COUNT", 2); // Actual count doesn't matter, as long as it's greater than one
  23. else
  24. defines.set("MSAA_COUNT", 1);
  25. }
  26. template<bool MSAA>
  27. void DirectionalLightMat<MSAA>::bind(const RenderTargets& renderTargets, const SPtr<GpuParamBlockBuffer>& perCamera)
  28. {
  29. RendererUtility::instance().setPass(mMaterial, 0);
  30. mGBufferParams.bind(renderTargets);
  31. mLightOcclusionTexParam.set(renderTargets.get(RTT_LightOcclusion));
  32. mParamsSet->setParamBlockBuffer("PerCamera", perCamera, true);
  33. }
  34. template<bool MSAA>
  35. void DirectionalLightMat<MSAA>::setPerLightParams(const SPtr<GpuParamBlockBuffer>& perLight)
  36. {
  37. mParamsSet->setParamBlockBuffer("PerLight", perLight, true);
  38. gRendererUtility().setPassParams(mParamsSet);
  39. }
  40. template class DirectionalLightMat<true>;
  41. template class DirectionalLightMat<false>;
  42. template<bool MSAA, bool InsideGeometry>
  43. PointLightMat<MSAA, InsideGeometry>::PointLightMat()
  44. :mGBufferParams(mMaterial, mParamsSet)
  45. {
  46. const GpuParams& gpuParams = *mParamsSet->getGpuParams();
  47. gpuParams.getTextureParam(GPT_FRAGMENT_PROGRAM, "gLightOcclusionTex", mLightOcclusionTexParam);
  48. }
  49. template<bool MSAA, bool InsideGeometry>
  50. void PointLightMat<MSAA, InsideGeometry>::_initDefines(ShaderDefines& defines)
  51. {
  52. if (MSAA)
  53. defines.set("MSAA_COUNT", 2); // Actual count doesn't matter, as long as it's greater than one
  54. else
  55. defines.set("MSAA_COUNT", 1);
  56. if (InsideGeometry)
  57. defines.set("INSIDE_GEOMETRY", 1);
  58. }
  59. template<bool MSAA, bool InsideGeometry>
  60. void PointLightMat<MSAA, InsideGeometry>::bind(const RenderTargets& renderTargets,
  61. const SPtr<GpuParamBlockBuffer>& perCamera)
  62. {
  63. RendererUtility::instance().setPass(mMaterial, 0);
  64. mGBufferParams.bind(renderTargets);
  65. mLightOcclusionTexParam.set(renderTargets.get(RTT_LightOcclusion));
  66. mParamsSet->setParamBlockBuffer("PerCamera", perCamera, true);
  67. }
  68. template<bool MSAA, bool InsideGeometry>
  69. void PointLightMat<MSAA, InsideGeometry>::setPerLightParams(const SPtr<GpuParamBlockBuffer>& perLight)
  70. {
  71. mParamsSet->setParamBlockBuffer("PerLight", perLight, true);
  72. gRendererUtility().setPassParams(mParamsSet);
  73. }
  74. template class PointLightMat<false, false>;
  75. template class PointLightMat<false, true>;
  76. template class PointLightMat<true, false>;
  77. template class PointLightMat<true, true>;
  78. StandardDeferred::StandardDeferred()
  79. {
  80. mPerLightBuffer = gPerLightParamDef.createBuffer();
  81. }
  82. void StandardDeferred::renderLight(LightType lightType, const RendererLight& light, const RendererView& view,
  83. const RenderTargets& renderTargets)
  84. {
  85. const auto& viewProps = view.getProperties();
  86. bool isMSAA = view.getProperties().numSamples > 1;
  87. SPtr<GpuParamBlockBuffer> perViewBuffer = view.getPerViewBuffer();
  88. light.getParameters(mPerLightBuffer);
  89. if (lightType == LightType::Directional)
  90. {
  91. if(isMSAA)
  92. {
  93. mDirLightMat_T.bind(renderTargets, perViewBuffer);
  94. mDirLightMat_T.setPerLightParams(mPerLightBuffer);
  95. }
  96. else
  97. {
  98. mDirLightMat_F.bind(renderTargets, perViewBuffer);
  99. mDirLightMat_F.setPerLightParams(mPerLightBuffer);
  100. }
  101. gRendererUtility().drawScreenQuad();
  102. }
  103. else // Radial or spot
  104. {
  105. // Check if viewer is inside the light volume
  106. float distSqrd = (light.internal->getBounds().getCenter() - viewProps.viewOrigin).squaredLength();
  107. // Extend the bounds slighty to cover the case when the viewer is outside, but the near plane is intersecting
  108. // the light bounds. We need to be conservative since the material for rendering outside will not properly
  109. // render the inside of the light volume.
  110. float boundRadius = light.internal->getBounds().getRadius() + viewProps.nearPlane * 3.0f;
  111. bool isInside = distSqrd < (boundRadius * boundRadius);
  112. if(isMSAA)
  113. {
  114. if(isInside)
  115. {
  116. mPointLightMat_TT.bind(renderTargets, perViewBuffer);
  117. mPointLightMat_TT.setPerLightParams(mPerLightBuffer);
  118. }
  119. else
  120. {
  121. mPointLightMat_TF.bind(renderTargets, perViewBuffer);
  122. mPointLightMat_TF.setPerLightParams(mPerLightBuffer);
  123. }
  124. }
  125. else
  126. {
  127. if(isInside)
  128. {
  129. mPointLightMat_FT.bind(renderTargets, perViewBuffer);
  130. mPointLightMat_FT.setPerLightParams(mPerLightBuffer);
  131. }
  132. else
  133. {
  134. mPointLightMat_FF.bind(renderTargets, perViewBuffer);
  135. mPointLightMat_TF.setPerLightParams(mPerLightBuffer);
  136. }
  137. }
  138. SPtr<Mesh> stencilMesh;
  139. if(lightType == LightType::Radial)
  140. stencilMesh = RendererUtility::instance().getRadialLightStencil();
  141. else // Spot
  142. stencilMesh = RendererUtility::instance().getSpotLightStencil();
  143. gRendererUtility().draw(stencilMesh);
  144. }
  145. }
  146. }}