2
0

BsStandardDeferredLighting.cpp 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  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. DirectionalLightMat::DirectionalLightMat()
  11. :mGBufferParams(GPT_FRAGMENT_PROGRAM, mParams)
  12. {
  13. mParams->getTextureParam(GPT_FRAGMENT_PROGRAM, "gLightOcclusionTex", mLightOcclusionTexParam);
  14. }
  15. void DirectionalLightMat::bind(const GBufferTextures& gBufferInput, const SPtr<Texture>& lightOcclusion,
  16. const SPtr<GpuParamBlockBuffer>& perCamera, const SPtr<GpuParamBlockBuffer>& perLight)
  17. {
  18. mGBufferParams.bind(gBufferInput);
  19. mLightOcclusionTexParam.set(lightOcclusion);
  20. mParams->setParamBlockBuffer("PerCamera", perCamera);
  21. mParams->setParamBlockBuffer("PerLight", perLight);
  22. RendererMaterial::bind();
  23. }
  24. DirectionalLightMat* DirectionalLightMat::getVariation(bool msaa, bool singleSampleMSAA)
  25. {
  26. if (msaa)
  27. {
  28. if (singleSampleMSAA)
  29. return get(getVariation<true, true>());
  30. else
  31. return get(getVariation<true, false>());
  32. }
  33. return get(getVariation<false, false>());
  34. }
  35. PointLightMat::PointLightMat()
  36. :mGBufferParams(GPT_FRAGMENT_PROGRAM, mParams)
  37. {
  38. mParams->getTextureParam(GPT_FRAGMENT_PROGRAM, "gLightOcclusionTex", mLightOcclusionTexParam);
  39. }
  40. void PointLightMat::bind(const GBufferTextures& gBufferInput, const SPtr<Texture>& lightOcclusion,
  41. const SPtr<GpuParamBlockBuffer>& perCamera, const SPtr<GpuParamBlockBuffer>& perLight)
  42. {
  43. mGBufferParams.bind(gBufferInput);
  44. mLightOcclusionTexParam.set(lightOcclusion);
  45. mParams->setParamBlockBuffer("PerCamera", perCamera);
  46. mParams->setParamBlockBuffer("PerLight", perLight);
  47. RendererMaterial::bind();
  48. }
  49. PointLightMat* PointLightMat::getVariation(bool inside, bool msaa, bool singleSampleMSAA)
  50. {
  51. if(msaa)
  52. {
  53. if (inside)
  54. {
  55. if (singleSampleMSAA)
  56. return get(getVariation<true, true, true>());
  57. return get(getVariation<true, true, false>());
  58. }
  59. else
  60. {
  61. if (singleSampleMSAA)
  62. return get(getVariation<false, true, true>());
  63. return get(getVariation<false, true, false>());
  64. }
  65. }
  66. else
  67. {
  68. if (inside)
  69. return get(getVariation<true, false, false>());
  70. else
  71. return get(getVariation<false, false, false>());
  72. }
  73. }
  74. StandardDeferred::StandardDeferred()
  75. {
  76. mPerLightBuffer = gPerLightParamDef.createBuffer();
  77. }
  78. void StandardDeferred::renderLight(LightType lightType, const RendererLight& light, const RendererView& view,
  79. const GBufferTextures& gBufferInput, const SPtr<Texture>& lightOcclusion)
  80. {
  81. const auto& viewProps = view.getProperties();
  82. bool isMSAA = view.getProperties().numSamples > 1;
  83. SPtr<GpuParamBlockBuffer> perViewBuffer = view.getPerViewBuffer();
  84. light.getParameters(mPerLightBuffer);
  85. if (lightType == LightType::Directional)
  86. {
  87. DirectionalLightMat* material = DirectionalLightMat::getVariation(isMSAA, true);
  88. material->bind(gBufferInput, lightOcclusion, perViewBuffer, mPerLightBuffer);
  89. gRendererUtility().drawScreenQuad();
  90. // Draw pixels requiring per-sample evaluation
  91. if(isMSAA)
  92. {
  93. DirectionalLightMat* msaaMaterial = DirectionalLightMat::getVariation(true, false);
  94. msaaMaterial->bind(gBufferInput, lightOcclusion, perViewBuffer, mPerLightBuffer);
  95. gRendererUtility().drawScreenQuad();
  96. }
  97. }
  98. else // Radial or spot
  99. {
  100. // Check if viewer is inside the light volume
  101. float distSqrd = (light.internal->getBounds().getCenter() - viewProps.viewOrigin).squaredLength();
  102. // Extend the bounds slighty to cover the case when the viewer is outside, but the near plane is intersecting
  103. // the light bounds. We need to be conservative since the material for rendering outside will not properly
  104. // render the inside of the light volume.
  105. float boundRadius = light.internal->getBounds().getRadius() + viewProps.nearPlane * 3.0f;
  106. bool isInside = distSqrd < (boundRadius * boundRadius);
  107. SPtr<Mesh> stencilMesh;
  108. if(lightType == LightType::Radial)
  109. stencilMesh = RendererUtility::instance().getRadialLightStencil();
  110. else // Spot
  111. stencilMesh = RendererUtility::instance().getSpotLightStencil();
  112. PointLightMat* material = PointLightMat::getVariation(isInside, isMSAA, true);
  113. material->bind(gBufferInput, lightOcclusion, perViewBuffer, mPerLightBuffer);
  114. // Note: If MSAA is enabled this will be rendered multisampled (on polygon edges), see if this can be avoided
  115. gRendererUtility().draw(stencilMesh);
  116. // Draw pixels requiring per-sample evaluation
  117. if(isMSAA)
  118. {
  119. PointLightMat* msaaMaterial = PointLightMat::getVariation(isInside, true, false);
  120. msaaMaterial->bind(gBufferInput, lightOcclusion, perViewBuffer, mPerLightBuffer);
  121. gRendererUtility().draw(stencilMesh);
  122. }
  123. }
  124. }
  125. }}