BsLightRendering.cpp 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250
  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.radius = mInternal->getBounds().getRadius();
  27. output.direction = mInternal->getRotation().zAxis();
  28. output.intensity = mInternal->getIntensity();
  29. output.spotAngles.x = spotAngle.valueRadians();
  30. output.spotAngles.y = Math::cos(output.spotAngles.x);
  31. output.spotAngles.z = 1.0f / (Math::cos(spotFalloffAngle) - output.spotAngles.y);
  32. output.radiusSqrdInv = 1.0f / (output.radius * output.radius);
  33. output.color = Vector3(color.r, color.g, color.b);
  34. }
  35. GPULightData::GPULightData()
  36. :mNumLights {}
  37. { }
  38. void GPULightData::setLights(const Vector<LightData>& lightData, UINT32 numDirLights, UINT32 numRadialLights,
  39. UINT32 numSpotLights)
  40. {
  41. mNumLights[0] = numDirLights;
  42. mNumLights[1] = numRadialLights;
  43. mNumLights[2] = numSpotLights;
  44. Vector3I lightOffsets;
  45. lightOffsets[0] = numDirLights;
  46. lightOffsets[1] = lightOffsets[0] + numRadialLights;
  47. lightOffsets[2] = lightOffsets[1] + numSpotLights;
  48. UINT32 totalNumLights = (UINT32)lightOffsets[2];
  49. UINT32 size = totalNumLights * sizeof(LightData);
  50. UINT32 curBufferSize;
  51. if (mLightBuffer != nullptr)
  52. curBufferSize = mLightBuffer->getSize();
  53. else
  54. curBufferSize = 0;
  55. if (size > curBufferSize || curBufferSize == 0)
  56. {
  57. // Allocate at least one block even if no lights, to avoid issues with null buffers
  58. UINT32 bufferSize = std::max(1, Math::ceilToInt(size / (float)BUFFER_INCREMENT)) * BUFFER_INCREMENT;
  59. GPU_BUFFER_DESC bufferDesc;
  60. bufferDesc.type = GBT_STRUCTURED;
  61. bufferDesc.elementCount = bufferSize / sizeof(LightData);
  62. bufferDesc.elementSize = sizeof(LightData);
  63. bufferDesc.format = BF_UNKNOWN;
  64. mLightBuffer = GpuBuffer::create(bufferDesc);
  65. }
  66. if (size > 0)
  67. mLightBuffer->writeData(0, size, lightData.data(), BWT_DISCARD);
  68. }
  69. const UINT32 TiledDeferredLighting::TILE_SIZE = 16;
  70. TiledDeferredLighting::TiledDeferredLighting(const SPtr<Material>& material, const SPtr<GpuParamsSet>& paramsSet,
  71. UINT32 sampleCount)
  72. :mSampleCount(sampleCount), mMaterial(material), mParamsSet(paramsSet), mLightOffsets()
  73. {
  74. SPtr<GpuParams> params = mParamsSet->getGpuParams();
  75. auto& texParams = mMaterial->getShader()->getTextureParams();
  76. for (auto& entry : texParams)
  77. {
  78. if (entry.second.rendererSemantic == RPS_GBufferA)
  79. params->getTextureParam(GPT_COMPUTE_PROGRAM, entry.second.name, mGBufferA);
  80. else if (entry.second.rendererSemantic == RPS_GBufferB)
  81. params->getTextureParam(GPT_COMPUTE_PROGRAM, entry.second.name, mGBufferB);
  82. else if (entry.second.rendererSemantic == RPS_GBufferC)
  83. params->getTextureParam(GPT_COMPUTE_PROGRAM, entry.second.name, mGBufferC);
  84. else if (entry.second.rendererSemantic == RPS_GBufferDepth)
  85. params->getTextureParam(GPT_COMPUTE_PROGRAM, entry.second.name, mGBufferDepth);
  86. }
  87. params->getBufferParam(GPT_COMPUTE_PROGRAM, "gLights", mLightBufferParam);
  88. if(params->hasLoadStoreTexture(GPT_COMPUTE_PROGRAM, "gOutput"))
  89. params->getLoadStoreTextureParam(GPT_COMPUTE_PROGRAM, "gOutput", mOutputTextureParam);
  90. if (params->hasBuffer(GPT_COMPUTE_PROGRAM, "gOutput"))
  91. params->getBufferParam(GPT_COMPUTE_PROGRAM, "gOutput", mOutputBufferParam);
  92. mParamBuffer = gTiledLightingParamDef.createBuffer();
  93. mParamsSet->setParamBlockBuffer("Params", mParamBuffer, true);
  94. }
  95. void TiledDeferredLighting::execute(const SPtr<RenderTargets>& gbuffer,
  96. const SPtr<GpuParamBlockBuffer>& perCamera, bool noLighting)
  97. {
  98. Vector2I framebufferSize;
  99. framebufferSize[0] = gbuffer->getWidth();
  100. framebufferSize[1] = gbuffer->getHeight();
  101. gTiledLightingParamDef.gFramebufferSize.set(mParamBuffer, framebufferSize);
  102. if (noLighting)
  103. {
  104. Vector3I lightOffsets;
  105. lightOffsets[0] = 0;
  106. lightOffsets[1] = 0;
  107. lightOffsets[2] = 0;
  108. gTiledLightingParamDef.gLightOffsets.set(mParamBuffer, lightOffsets);
  109. }
  110. else
  111. {
  112. gTiledLightingParamDef.gLightOffsets.set(mParamBuffer, mLightOffsets);
  113. }
  114. mParamBuffer->flushToGPU();
  115. mGBufferA.set(gbuffer->getTextureA());
  116. mGBufferB.set(gbuffer->getTextureB());
  117. mGBufferC.set(gbuffer->getTextureC());
  118. mGBufferDepth.set(gbuffer->getTextureDepth());
  119. mParamsSet->setParamBlockBuffer("PerCamera", perCamera, true);
  120. const RenderAPIInfo& rapiInfo = RenderAPI::instance().getAPIInfo();
  121. if (mSampleCount > 1 && !rapiInfo.isFlagSet(RenderAPIFeatureFlag::MSAAImageStores))
  122. {
  123. SPtr<GpuBuffer> sceneColorBuffer = gbuffer->getFlattenedSceneColorBuffer();
  124. mOutputBufferParam.set(sceneColorBuffer);
  125. }
  126. else
  127. {
  128. SPtr<Texture> sceneColorTex = gbuffer->getSceneColor();
  129. mOutputTextureParam.set(sceneColorTex);
  130. }
  131. UINT32 width = gbuffer->getWidth();
  132. UINT32 height = gbuffer->getHeight();
  133. UINT32 numTilesX = (UINT32)Math::ceilToInt(width / (float)TILE_SIZE);
  134. UINT32 numTilesY = (UINT32)Math::ceilToInt(height / (float)TILE_SIZE);
  135. gRendererUtility().setComputePass(mMaterial, 0);
  136. gRendererUtility().setPassParams(mParamsSet);
  137. RenderAPI::instance().dispatchCompute(numTilesX, numTilesY);
  138. }
  139. void TiledDeferredLighting::setLights(const GPULightData& lightData)
  140. {
  141. mLightBufferParam.set(lightData.getLightBuffer());
  142. mLightOffsets[0] = lightData.getNumDirLights();
  143. mLightOffsets[1] = mLightOffsets[0] + lightData.getNumRadialLights();
  144. mLightOffsets[2] = mLightOffsets[1] + lightData.getNumSpotLights();
  145. }
  146. template<int MSAA_COUNT>
  147. TTiledDeferredLightingMat<MSAA_COUNT>::TTiledDeferredLightingMat()
  148. :mInternal(mMaterial, mParamsSet, MSAA_COUNT)
  149. {
  150. }
  151. template<int MSAA_COUNT>
  152. void TTiledDeferredLightingMat<MSAA_COUNT>::_initDefines(ShaderDefines& defines)
  153. {
  154. defines.set("TILE_SIZE", TiledDeferredLighting::TILE_SIZE);
  155. defines.set("MSAA_COUNT", MSAA_COUNT);
  156. }
  157. template<int MSAA_COUNT>
  158. void TTiledDeferredLightingMat<MSAA_COUNT>::execute(const SPtr<RenderTargets>& gbuffer,
  159. const SPtr<GpuParamBlockBuffer>& perCamera, bool noLighting)
  160. {
  161. mInternal.execute(gbuffer, perCamera, noLighting);
  162. }
  163. template<int MSAA_COUNT>
  164. void TTiledDeferredLightingMat<MSAA_COUNT>::setLights(const GPULightData& lightData)
  165. {
  166. mInternal.setLights(lightData);
  167. }
  168. template class TTiledDeferredLightingMat<1>;
  169. template class TTiledDeferredLightingMat<2>;
  170. template class TTiledDeferredLightingMat<4>;
  171. template class TTiledDeferredLightingMat<8>;
  172. FlatFramebufferToTextureParamDef gFlatFramebufferToTextureParamDef;
  173. FlatFramebufferToTextureMat::FlatFramebufferToTextureMat()
  174. {
  175. SPtr<GpuParams> params = mParamsSet->getGpuParams();
  176. params->getBufferParam(GPT_FRAGMENT_PROGRAM, "gInput", mInputParam);
  177. mParamBuffer = gTiledLightingParamDef.createBuffer();
  178. mParamsSet->setParamBlockBuffer("Params", mParamBuffer, true);
  179. }
  180. void FlatFramebufferToTextureMat::_initDefines(ShaderDefines& defines)
  181. {
  182. // Do nothing
  183. }
  184. void FlatFramebufferToTextureMat::execute(const SPtr<GpuBuffer>& flatFramebuffer, const SPtr<Texture>& target)
  185. {
  186. const TextureProperties& props = target->getProperties();
  187. Vector2I framebufferSize;
  188. framebufferSize[0] = props.getWidth();
  189. framebufferSize[1] = props.getHeight();
  190. gFlatFramebufferToTextureParamDef.gFramebufferSize.set(mParamBuffer, framebufferSize);
  191. gFlatFramebufferToTextureParamDef.gSampleCount.set(mParamBuffer, props.getNumSamples());
  192. mParamBuffer->flushToGPU();
  193. mInputParam.set(flatFramebuffer);
  194. gRendererUtility().setPass(mMaterial, 0);
  195. gRendererUtility().setPassParams(mParamsSet);
  196. Rect2 area(0.0f, 0.0f, (float)props.getWidth(), (float)props.getHeight());
  197. gRendererUtility().drawScreenQuad(area);
  198. }
  199. }}