BsStandardDeferredLighting.cpp 5.4 KB

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