BsLightRendering.cpp 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  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. const UINT32 TiledDeferredLightingMat::TILE_SIZE = 16;
  36. TiledDeferredLightingMat::TiledDeferredLightingMat()
  37. {
  38. SPtr<GpuParams> params = mParamsSet->getGpuParams();
  39. auto& texParams = mMaterial->getShader()->getTextureParams();
  40. for (auto& entry : texParams)
  41. {
  42. if (entry.second.rendererSemantic == RPS_GBufferA)
  43. params->getTextureParam(GPT_COMPUTE_PROGRAM, entry.second.name, mGBufferA);
  44. else if (entry.second.rendererSemantic == RPS_GBufferB)
  45. params->getTextureParam(GPT_COMPUTE_PROGRAM, entry.second.name, mGBufferB);
  46. else if (entry.second.rendererSemantic == RPS_GBufferDepth)
  47. params->getTextureParam(GPT_COMPUTE_PROGRAM, entry.second.name, mGBufferDepth);
  48. }
  49. params->getBufferParam(GPT_COMPUTE_PROGRAM, "gDirLights", mDirLightBufferParam);
  50. params->getBufferParam(GPT_COMPUTE_PROGRAM, "gPointLights", mPointLightBufferParam);
  51. params->getBufferParam(GPT_COMPUTE_PROGRAM, "gSpotLights", mSpotLightBufferParam);
  52. params->getLoadStoreTextureParam(GPT_COMPUTE_PROGRAM, "gOutput", mOutputParam);
  53. mParamBuffer = gTiledLightingParamDef.createBuffer();
  54. mParamsSet->setParamBlockBuffer("Params", mParamBuffer, true);
  55. }
  56. void TiledDeferredLightingMat::_initDefines(ShaderDefines& defines)
  57. {
  58. defines.set("TILE_SIZE", TILE_SIZE);
  59. }
  60. void TiledDeferredLightingMat::execute(const SPtr<RenderTargets>& gbuffer, const SPtr<GpuParamBlockBuffer>& perCamera)
  61. {
  62. mGBufferA.set(gbuffer->getTextureA());
  63. mGBufferB.set(gbuffer->getTextureB());
  64. mGBufferDepth.set(gbuffer->getTextureDepth());
  65. mParamsSet->setParamBlockBuffer("PerCamera", perCamera, true);
  66. SPtr<Texture> sceneColorTex = gbuffer->getSceneColor();
  67. mOutputParam.set(sceneColorTex);
  68. UINT32 width = sceneColorTex->getProperties().getWidth();
  69. UINT32 height = sceneColorTex->getProperties().getHeight();
  70. UINT32 numTilesX = (UINT32)Math::ceilToInt(width / (float)TILE_SIZE);
  71. UINT32 numTilesY = (UINT32)Math::ceilToInt(height / (float)TILE_SIZE);
  72. gRendererUtility().setComputePass(mMaterial, 0);
  73. gRendererUtility().setPassParams(mParamsSet);
  74. RenderAPI::instance().dispatchCompute(numTilesX, numTilesY);
  75. }
  76. void TiledDeferredLightingMat::setLights(const Vector<LightData>(&lightData)[3])
  77. {
  78. Vector3I numLightsPerType;
  79. for (UINT32 i = 0; i < 3; i++)
  80. {
  81. UINT32 numLights = (UINT32)lightData[i].size();
  82. numLightsPerType[i] = numLights;
  83. UINT32 size = numLights * sizeof(LightData);
  84. UINT32 curBufferSize;
  85. if (mLightBuffers[i] != nullptr)
  86. curBufferSize = mLightBuffers[i]->getSize();
  87. else
  88. curBufferSize = 0;
  89. if(size > curBufferSize || curBufferSize == 0)
  90. {
  91. // Allocate at least one block even if no lights, to avoid issues with null buffers
  92. UINT32 bufferSize = std::max(1, Math::ceilToInt(size / (float)BUFFER_INCREMENT)) * BUFFER_INCREMENT;
  93. GPU_BUFFER_DESC bufferDesc;
  94. bufferDesc.type = GBT_STRUCTURED;
  95. bufferDesc.elementCount = bufferSize / sizeof(LightData);
  96. bufferDesc.elementSize = sizeof(LightData);
  97. bufferDesc.format = BF_UNKNOWN;
  98. mLightBuffers[i] = GpuBuffer::create(bufferDesc);
  99. }
  100. mLightBuffers[i]->writeData(0, size, lightData[i].data(), BWT_DISCARD);
  101. }
  102. mDirLightBufferParam.set(mLightBuffers[0]);
  103. mPointLightBufferParam.set(mLightBuffers[1]);
  104. mSpotLightBufferParam.set(mLightBuffers[2]);
  105. gTiledLightingParamDef.gNumLightsPerType.set(mParamBuffer, numLightsPerType);
  106. mParamBuffer->flushToGPU();
  107. }
  108. }}