BsLightRendering.cpp 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281
  1. //********************************** Banshee Engine (www.banshee3d.com) **************************************************//
  2. //**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
  3. #include "BsLightRendering.h"
  4. #include "BsMaterial.h"
  5. #include "BsShader.h"
  6. #include "BsRenderBeast.h"
  7. #include "BsRenderTargets.h"
  8. #include "BsGpuParams.h"
  9. #include "BsGpuParamsSet.h"
  10. #include "BsGpuBuffer.h"
  11. #include "BsLight.h"
  12. #include "BsRendererUtility.h"
  13. namespace bs { namespace ct
  14. {
  15. static const UINT32 BUFFER_INCREMENT = 16 * sizeof(LightData);
  16. TiledLightingParamDef gTiledLightingParamDef;
  17. RendererLight::RendererLight(Light* light)
  18. :mInternal(light)
  19. { }
  20. void RendererLight::getParameters(LightData& output) const
  21. {
  22. Radian spotAngle = Math::clamp(mInternal->getSpotAngle() * 0.5f, Degree(0), Degree(89));
  23. Radian spotFalloffAngle = Math::clamp(mInternal->getSpotFalloffAngle() * 0.5f, Degree(0), (Degree)spotAngle);
  24. Color color = mInternal->getColor();
  25. output.position = mInternal->getPosition();
  26. output.attRadius = mInternal->getBounds().getRadius();
  27. output.srcRadius = mInternal->getSourceRadius();
  28. output.direction = mInternal->getRotation().zAxis();
  29. output.luminance = mInternal->getLuminance();
  30. output.spotAngles.x = spotAngle.valueRadians();
  31. output.spotAngles.y = Math::cos(output.spotAngles.x);
  32. output.spotAngles.z = 1.0f / std::max(Math::cos(spotFalloffAngle) - output.spotAngles.y, 0.001f);
  33. output.attRadiusSqrdInv = 1.0f / (output.attRadius * output.attRadius);
  34. output.color = Vector3(color.r, color.g, color.b);
  35. // If directional lights, convert angular radius in degrees to radians
  36. if (mInternal->getType() == LightType::Directional)
  37. output.srcRadius *= Math::DEG2RAD;
  38. // Create position for fake attenuation for area spot lights (with disc center)
  39. if (mInternal->getType() == LightType::Spot)
  40. output.shiftedLightPosition = output.position - output.direction * (output.srcRadius / Math::tan(spotAngle * 0.5f));
  41. else
  42. output.shiftedLightPosition = output.position;
  43. }
  44. GPULightData::GPULightData()
  45. :mNumLights{}
  46. { }
  47. void GPULightData::setLights(const Vector<LightData>& lightData, UINT32 numDirLights, UINT32 numRadialLights,
  48. UINT32 numSpotLights)
  49. {
  50. mNumLights[0] = numDirLights;
  51. mNumLights[1] = numRadialLights;
  52. mNumLights[2] = numSpotLights;
  53. Vector3I lightOffsets;
  54. lightOffsets[0] = numDirLights;
  55. lightOffsets[1] = lightOffsets[0] + numRadialLights;
  56. lightOffsets[2] = lightOffsets[1] + numSpotLights;
  57. UINT32 totalNumLights = (UINT32)lightOffsets[2];
  58. UINT32 size = totalNumLights * sizeof(LightData);
  59. UINT32 curBufferSize;
  60. if (mLightBuffer != nullptr)
  61. curBufferSize = mLightBuffer->getSize();
  62. else
  63. curBufferSize = 0;
  64. if (size > curBufferSize || curBufferSize == 0)
  65. {
  66. // Allocate at least one block even if no lights, to avoid issues with null buffers
  67. UINT32 bufferSize = std::max(1, Math::ceilToInt(size / (float)BUFFER_INCREMENT)) * BUFFER_INCREMENT;
  68. GPU_BUFFER_DESC bufferDesc;
  69. bufferDesc.type = GBT_STRUCTURED;
  70. bufferDesc.elementCount = bufferSize / sizeof(LightData);
  71. bufferDesc.elementSize = sizeof(LightData);
  72. bufferDesc.format = BF_UNKNOWN;
  73. mLightBuffer = GpuBuffer::create(bufferDesc);
  74. }
  75. if (size > 0)
  76. mLightBuffer->writeData(0, size, lightData.data(), BWT_DISCARD);
  77. }
  78. const UINT32 TiledDeferredLighting::TILE_SIZE = 16;
  79. TiledDeferredLighting::TiledDeferredLighting(const SPtr<Material>& material, const SPtr<GpuParamsSet>& paramsSet,
  80. UINT32 sampleCount)
  81. :mSampleCount(sampleCount), mMaterial(material), mParamsSet(paramsSet), mLightOffsets()
  82. {
  83. SPtr<GpuParams> params = mParamsSet->getGpuParams();
  84. auto& texParams = mMaterial->getShader()->getTextureParams();
  85. for (auto& entry : texParams)
  86. {
  87. if (entry.second.rendererSemantic == RPS_GBufferA)
  88. params->getTextureParam(GPT_COMPUTE_PROGRAM, entry.second.name, mGBufferA);
  89. else if (entry.second.rendererSemantic == RPS_GBufferB)
  90. params->getTextureParam(GPT_COMPUTE_PROGRAM, entry.second.name, mGBufferB);
  91. else if (entry.second.rendererSemantic == RPS_GBufferC)
  92. params->getTextureParam(GPT_COMPUTE_PROGRAM, entry.second.name, mGBufferC);
  93. else if (entry.second.rendererSemantic == RPS_GBufferDepth)
  94. params->getTextureParam(GPT_COMPUTE_PROGRAM, entry.second.name, mGBufferDepth);
  95. }
  96. params->getBufferParam(GPT_COMPUTE_PROGRAM, "gLights", mLightBufferParam);
  97. if (params->hasLoadStoreTexture(GPT_COMPUTE_PROGRAM, "gOutput"))
  98. params->getLoadStoreTextureParam(GPT_COMPUTE_PROGRAM, "gOutput", mOutputTextureParam);
  99. if (params->hasBuffer(GPT_COMPUTE_PROGRAM, "gOutput"))
  100. params->getBufferParam(GPT_COMPUTE_PROGRAM, "gOutput", mOutputBufferParam);
  101. mParamBuffer = gTiledLightingParamDef.createBuffer();
  102. mParamsSet->setParamBlockBuffer("Params", mParamBuffer, true);
  103. }
  104. void TiledDeferredLighting::execute(const SPtr<RenderTargets>& renderTargets, const SPtr<GpuParamBlockBuffer>& perCamera,
  105. bool noLighting)
  106. {
  107. Vector2I framebufferSize;
  108. framebufferSize[0] = renderTargets->getWidth();
  109. framebufferSize[1] = renderTargets->getHeight();
  110. gTiledLightingParamDef.gFramebufferSize.set(mParamBuffer, framebufferSize);
  111. if (noLighting)
  112. {
  113. Vector3I lightOffsets;
  114. lightOffsets[0] = 0;
  115. lightOffsets[1] = 0;
  116. lightOffsets[2] = 0;
  117. gTiledLightingParamDef.gLightOffsets.set(mParamBuffer, lightOffsets);
  118. }
  119. else
  120. {
  121. gTiledLightingParamDef.gLightOffsets.set(mParamBuffer, mLightOffsets);
  122. }
  123. mParamBuffer->flushToGPU();
  124. mGBufferA.set(renderTargets->getGBufferA());
  125. mGBufferB.set(renderTargets->getGBufferB());
  126. mGBufferC.set(renderTargets->getGBufferC());
  127. mGBufferDepth.set(renderTargets->getSceneDepth());
  128. mParamsSet->setParamBlockBuffer("PerCamera", perCamera, true);
  129. if (mSampleCount > 1)
  130. {
  131. SPtr<GpuBuffer> lightAccumulation = renderTargets->getLightAccumulationBuffer();
  132. mOutputBufferParam.set(lightAccumulation);
  133. }
  134. else
  135. {
  136. SPtr<Texture> lightAccumulation = renderTargets->getLightAccumulation();
  137. mOutputTextureParam.set(lightAccumulation);
  138. }
  139. UINT32 width = renderTargets->getWidth();
  140. UINT32 height = renderTargets->getHeight();
  141. UINT32 numTilesX = (UINT32)Math::ceilToInt(width / (float)TILE_SIZE);
  142. UINT32 numTilesY = (UINT32)Math::ceilToInt(height / (float)TILE_SIZE);
  143. gRendererUtility().setComputePass(mMaterial, 0);
  144. gRendererUtility().setPassParams(mParamsSet);
  145. RenderAPI::instance().dispatchCompute(numTilesX, numTilesY);
  146. }
  147. void TiledDeferredLighting::setLights(const GPULightData& lightData)
  148. {
  149. mLightBufferParam.set(lightData.getLightBuffer());
  150. mLightOffsets[0] = lightData.getNumDirLights();
  151. mLightOffsets[1] = mLightOffsets[0] + lightData.getNumRadialLights();
  152. mLightOffsets[2] = mLightOffsets[1] + lightData.getNumSpotLights();
  153. }
  154. template<int MSAA_COUNT>
  155. TTiledDeferredLightingMat<MSAA_COUNT>::TTiledDeferredLightingMat()
  156. :mInternal(mMaterial, mParamsSet, MSAA_COUNT)
  157. {
  158. }
  159. template<int MSAA_COUNT>
  160. void TTiledDeferredLightingMat<MSAA_COUNT>::_initDefines(ShaderDefines& defines)
  161. {
  162. defines.set("TILE_SIZE", TiledDeferredLighting::TILE_SIZE);
  163. defines.set("MSAA_COUNT", MSAA_COUNT);
  164. }
  165. template<int MSAA_COUNT>
  166. void TTiledDeferredLightingMat<MSAA_COUNT>::execute(const SPtr<RenderTargets>& gbuffer,
  167. const SPtr<GpuParamBlockBuffer>& perCamera, bool noLighting)
  168. {
  169. mInternal.execute(gbuffer, perCamera, noLighting);
  170. }
  171. template<int MSAA_COUNT>
  172. void TTiledDeferredLightingMat<MSAA_COUNT>::setLights(const GPULightData& lightData)
  173. {
  174. mInternal.setLights(lightData);
  175. }
  176. TiledDeferredLightingMaterials::TiledDeferredLightingMaterials()
  177. {
  178. mInstances[0] = bs_new<TTiledDeferredLightingMat<1>>();
  179. mInstances[1] = bs_new<TTiledDeferredLightingMat<2>>();
  180. mInstances[2] = bs_new<TTiledDeferredLightingMat<4>>();
  181. mInstances[3] = bs_new<TTiledDeferredLightingMat<8>>();
  182. }
  183. TiledDeferredLightingMaterials::~TiledDeferredLightingMaterials()
  184. {
  185. for (UINT32 i = 0; i < 4; i++)
  186. bs_delete(mInstances[i]);
  187. }
  188. ITiledDeferredLightingMat* TiledDeferredLightingMaterials::get(UINT32 msaa)
  189. {
  190. if (msaa == 1)
  191. return mInstances[0];
  192. else if (msaa == 2)
  193. return mInstances[1];
  194. else if (msaa == 4)
  195. return mInstances[2];
  196. else
  197. return mInstances[3];
  198. }
  199. FlatFramebufferToTextureParamDef gFlatFramebufferToTextureParamDef;
  200. FlatFramebufferToTextureMat::FlatFramebufferToTextureMat()
  201. {
  202. SPtr<GpuParams> params = mParamsSet->getGpuParams();
  203. params->getBufferParam(GPT_FRAGMENT_PROGRAM, "gInput", mInputParam);
  204. mParamBuffer = gTiledLightingParamDef.createBuffer();
  205. mParamsSet->setParamBlockBuffer("Params", mParamBuffer, true);
  206. }
  207. void FlatFramebufferToTextureMat::_initDefines(ShaderDefines& defines)
  208. {
  209. // Do nothing
  210. }
  211. void FlatFramebufferToTextureMat::execute(const SPtr<GpuBuffer>& flatFramebuffer, const SPtr<Texture>& target)
  212. {
  213. const TextureProperties& props = target->getProperties();
  214. Vector2I framebufferSize;
  215. framebufferSize[0] = props.getWidth();
  216. framebufferSize[1] = props.getHeight();
  217. gFlatFramebufferToTextureParamDef.gFramebufferSize.set(mParamBuffer, framebufferSize);
  218. gFlatFramebufferToTextureParamDef.gSampleCount.set(mParamBuffer, props.getNumSamples());
  219. mParamBuffer->flushToGPU();
  220. mInputParam.set(flatFramebuffer);
  221. gRendererUtility().setPass(mMaterial, 0);
  222. gRendererUtility().setPassParams(mParamsSet);
  223. Rect2 area(0.0f, 0.0f, (float)props.getWidth(), (float)props.getHeight());
  224. gRendererUtility().drawScreenQuad(area);
  225. }
  226. }}