BsImageBasedLighting.cpp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459
  1. //********************************** Banshee Engine (www.banshee3d.com) **************************************************//
  2. //**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
  3. #include "BsImageBasedLighting.h"
  4. #include "BsMaterial.h"
  5. #include "BsShader.h"
  6. #include "BsGpuBuffer.h"
  7. #include "BsGpuParamsSet.h"
  8. #include "BsReflectionProbe.h"
  9. #include "BsLightProbeCache.h"
  10. #include "BsGpuParamsSet.h"
  11. #include "BsRenderTargets.h"
  12. #include "BsRenderBeast.h"
  13. #include "BsRendererUtility.h"
  14. namespace bs { namespace ct
  15. {
  16. static const UINT32 BUFFER_INCREMENT = 16 * sizeof(ReflProbeData);
  17. ReflProbeParamsParamDef gReflProbeParamsParamDef;
  18. TiledImageBasedLightingParamDef gTiledImageBasedLightingParamDef;
  19. GPUReflProbeData::GPUReflProbeData()
  20. :mNumProbes(0)
  21. { }
  22. void GPUReflProbeData::setProbes(const Vector<ReflProbeData>& probeData, UINT32 numProbes)
  23. {
  24. mNumProbes = numProbes;
  25. UINT32 size = numProbes * sizeof(ReflProbeData);
  26. UINT32 curBufferSize;
  27. if (mProbeBuffer != nullptr)
  28. curBufferSize = mProbeBuffer->getSize();
  29. else
  30. curBufferSize = 0;
  31. if (size > curBufferSize || curBufferSize == 0)
  32. {
  33. // Allocate at least one block even if no probes, to avoid issues with null buffers
  34. UINT32 bufferSize = std::max(1, Math::ceilToInt(size / (float)BUFFER_INCREMENT)) * BUFFER_INCREMENT;
  35. GPU_BUFFER_DESC bufferDesc;
  36. bufferDesc.type = GBT_STRUCTURED;
  37. bufferDesc.elementCount = bufferSize / sizeof(ReflProbeData);
  38. bufferDesc.elementSize = sizeof(ReflProbeData);
  39. bufferDesc.format = BF_UNKNOWN;
  40. mProbeBuffer = GpuBuffer::create(bufferDesc);
  41. }
  42. if (size > 0)
  43. mProbeBuffer->writeData(0, size, probeData.data(), BWT_DISCARD);
  44. }
  45. RendererReflectionProbe::RendererReflectionProbe(ReflectionProbe* probe)
  46. :probe(probe)
  47. {
  48. arrayIdx = -1;
  49. texture = nullptr;
  50. customTexture = probe->getCustomTexture() != nullptr;
  51. textureDirty = LightProbeCache::instance().isRadianceDirty(probe->getUUID());
  52. arrayDirty = true;
  53. errorFlagged = false;
  54. }
  55. void RendererReflectionProbe::getParameters(ReflProbeData& output) const
  56. {
  57. output.type = probe->getType() == ReflectionProbeType::Sphere ? 0
  58. : probe->getType() == ReflectionProbeType::Box ? 1 : 2;
  59. output.position = probe->getPosition();
  60. output.boxExtents = probe->getExtents();
  61. if (probe->getType() == ReflectionProbeType::Sphere)
  62. output.radius = probe->getRadius();
  63. else
  64. output.radius = output.boxExtents.length();
  65. output.transitionDistance = probe->getTransitionDistance();
  66. output.cubemapIdx = arrayIdx;
  67. output.invBoxTransform.setInverseTRS(output.position, probe->getRotation(), output.boxExtents);
  68. }
  69. void ImageBasedLightingParams::populate(const SPtr<GpuParamsSet>& paramsSet, GpuProgramType programType, bool optional,
  70. bool gridIndices)
  71. {
  72. SPtr<GpuParams> params = paramsSet->getGpuParams();
  73. // Sky
  74. if (!optional || params->hasTexture(programType, "gSkyReflectionTex"))
  75. {
  76. params->getTextureParam(programType, "gSkyReflectionTex", skyReflectionsTexParam);
  77. params->getSamplerStateParam(programType, "gSkyReflectionSamp", skyReflectionsSampParam);
  78. params->getTextureParam(programType, "gSkyIrradianceTex", skyIrradianceTexParam);
  79. }
  80. // Reflections
  81. if (!optional || params->hasTexture(programType, "gReflProbeCubemaps"))
  82. {
  83. params->getTextureParam(programType, "gReflProbeCubemaps", reflectionProbeCubemapsTexParam);
  84. params->getSamplerStateParam(programType, "gReflProbeSamp", reflectionProbeCubemapsSampParam);
  85. params->getBufferParam(programType, "gReflectionProbes", reflectionProbesParam);
  86. params->getTextureParam(programType, "gPreintegratedEnvBRDF", preintegratedEnvBRDFParam);
  87. }
  88. if(gridIndices)
  89. {
  90. if (!optional || params->hasBuffer(programType, "gReflectionProbeIndices"))
  91. params->getBufferParam(programType, "gReflectionProbeIndices", reflectionProbeIndicesParam);
  92. }
  93. reflProbeParamsBindingIdx = paramsSet->getParamBlockBufferIndex("ReflProbeParams");
  94. }
  95. // Note: Using larger tiles than in tiled deferred lighting since we use AABB for intersections, which is more
  96. // expensive to compute than frustums. This way we amortize the cost even though other parts of the shader might suffer
  97. // due to increased thread group load.
  98. const UINT32 TiledDeferredImageBasedLighting::TILE_SIZE = 32;
  99. TiledDeferredImageBasedLighting::TiledDeferredImageBasedLighting(const SPtr<Material>& material,
  100. const SPtr<GpuParamsSet>& paramsSet, UINT32 sampleCount)
  101. :mSampleCount(sampleCount), mMaterial(material), mParamsSet(paramsSet)
  102. {
  103. SPtr<GpuParams> params = mParamsSet->getGpuParams();
  104. auto& texParams = mMaterial->getShader()->getTextureParams();
  105. for (auto& entry : texParams)
  106. {
  107. if (entry.second.rendererSemantic == RPS_GBufferA)
  108. params->getTextureParam(GPT_COMPUTE_PROGRAM, entry.second.name, mGBufferA);
  109. else if (entry.second.rendererSemantic == RPS_GBufferB)
  110. params->getTextureParam(GPT_COMPUTE_PROGRAM, entry.second.name, mGBufferB);
  111. else if (entry.second.rendererSemantic == RPS_GBufferC)
  112. params->getTextureParam(GPT_COMPUTE_PROGRAM, entry.second.name, mGBufferC);
  113. else if (entry.second.rendererSemantic == RPS_GBufferDepth)
  114. params->getTextureParam(GPT_COMPUTE_PROGRAM, entry.second.name, mGBufferDepth);
  115. }
  116. if (mSampleCount > 1)
  117. {
  118. params->getBufferParam(GPT_COMPUTE_PROGRAM, "gInColor", mInColorBufferParam);
  119. params->getBufferParam(GPT_COMPUTE_PROGRAM, "gOutput", mOutputBufferParam);
  120. }
  121. else
  122. {
  123. params->getTextureParam(GPT_COMPUTE_PROGRAM, "gInColor", mInColorTextureParam);
  124. params->getLoadStoreTextureParam(GPT_COMPUTE_PROGRAM, "gOutput", mOutputTextureParam);
  125. }
  126. mParamBuffer = gTiledImageBasedLightingParamDef.createBuffer();
  127. mParamsSet->setParamBlockBuffer("Params", mParamBuffer, true);
  128. mImageBasedParams.populate(mParamsSet, GPT_COMPUTE_PROGRAM, false, false);
  129. mReflectionsParamBuffer = gReflProbeParamsParamDef.createBuffer();
  130. mParamsSet->setParamBlockBuffer("ReflProbeParams", mReflectionsParamBuffer);
  131. SAMPLER_STATE_DESC reflSamplerDesc;
  132. reflSamplerDesc.magFilter = FO_LINEAR;
  133. reflSamplerDesc.minFilter = FO_LINEAR;
  134. reflSamplerDesc.mipFilter = FO_LINEAR;
  135. mReflectionSamplerState = SamplerState::create(reflSamplerDesc);
  136. mImageBasedParams.skyReflectionsSampParam.set(mReflectionSamplerState);
  137. mImageBasedParams.reflectionProbeCubemapsSampParam.set(mReflectionSamplerState);
  138. }
  139. void TiledDeferredImageBasedLighting::execute(const SPtr<RenderTargets>& renderTargets,
  140. const SPtr<GpuParamBlockBuffer>& perCamera, const SPtr<Texture>& preintegratedGF)
  141. {
  142. Vector2I framebufferSize;
  143. framebufferSize[0] = renderTargets->getWidth();
  144. framebufferSize[1] = renderTargets->getHeight();
  145. gTiledImageBasedLightingParamDef.gFramebufferSize.set(mParamBuffer, framebufferSize);
  146. mParamBuffer->flushToGPU();
  147. mReflectionsParamBuffer->flushToGPU();
  148. mGBufferA.set(renderTargets->getGBufferA());
  149. mGBufferB.set(renderTargets->getGBufferB());
  150. mGBufferC.set(renderTargets->getGBufferC());
  151. mGBufferDepth.set(renderTargets->getSceneDepth());
  152. mImageBasedParams.preintegratedEnvBRDFParam.set(preintegratedGF);
  153. mParamsSet->setParamBlockBuffer("PerCamera", perCamera, true);
  154. if (mSampleCount > 1)
  155. {
  156. mInColorBufferParam.set(renderTargets->getLightAccumulationBuffer());
  157. mOutputBufferParam.set(renderTargets->getSceneColorBuffer());
  158. }
  159. else
  160. {
  161. mInColorTextureParam.set(renderTargets->getLightAccumulation());
  162. mOutputTextureParam.set(renderTargets->getSceneColor());
  163. }
  164. UINT32 width = renderTargets->getWidth();
  165. UINT32 height = renderTargets->getHeight();
  166. UINT32 numTilesX = (UINT32)Math::ceilToInt(width / (float)TILE_SIZE);
  167. UINT32 numTilesY = (UINT32)Math::ceilToInt(height / (float)TILE_SIZE);
  168. gRendererUtility().setComputePass(mMaterial, 0);
  169. gRendererUtility().setPassParams(mParamsSet);
  170. RenderAPI::instance().dispatchCompute(numTilesX, numTilesY);
  171. }
  172. void TiledDeferredImageBasedLighting::setReflectionProbes(const GPUReflProbeData& probeData,
  173. const SPtr<Texture>& reflectionCubemaps, bool capturingReflections)
  174. {
  175. mImageBasedParams.reflectionProbesParam.set(probeData.getProbeBuffer());
  176. mImageBasedParams.reflectionProbeCubemapsTexParam.set(reflectionCubemaps);
  177. gReflProbeParamsParamDef.gNumProbes.set(mReflectionsParamBuffer, probeData.getNumProbes());
  178. UINT32 numMips = 0;
  179. if (reflectionCubemaps != nullptr)
  180. numMips = reflectionCubemaps->getProperties().getNumMipmaps() + 1;
  181. gReflProbeParamsParamDef.gReflCubemapNumMips.set(mReflectionsParamBuffer, numMips);
  182. gReflProbeParamsParamDef.gUseReflectionMaps.set(mReflectionsParamBuffer, capturingReflections ? 0 : 1);
  183. }
  184. void TiledDeferredImageBasedLighting::setSky(const SPtr<Texture>& skyReflections, const SPtr<Texture>& skyIrradiance,
  185. float brightness)
  186. {
  187. mImageBasedParams.skyReflectionsTexParam.set(skyReflections);
  188. mImageBasedParams.skyIrradianceTexParam.set(skyIrradiance);
  189. UINT32 skyReflectionsAvailable = 0;
  190. UINT32 numMips = 0;
  191. if (skyReflections != nullptr)
  192. {
  193. numMips = skyReflections->getProperties().getNumMipmaps() + 1;
  194. skyReflectionsAvailable = 1;
  195. }
  196. gReflProbeParamsParamDef.gSkyCubemapNumMips.set(mReflectionsParamBuffer, numMips);
  197. gReflProbeParamsParamDef.gSkyCubemapAvailable.set(mReflectionsParamBuffer, skyReflectionsAvailable);
  198. gReflProbeParamsParamDef.gSkyBrightness.set(mReflectionsParamBuffer, brightness);
  199. }
  200. // Reverse bits functions used for Hammersley sequence
  201. float reverseBits(UINT32 bits)
  202. {
  203. bits = (bits << 16u) | (bits >> 16u);
  204. bits = ((bits & 0x55555555u) << 1u) | ((bits & 0xAAAAAAAAu) >> 1u);
  205. bits = ((bits & 0x33333333u) << 2u) | ((bits & 0xCCCCCCCCu) >> 2u);
  206. bits = ((bits & 0x0F0F0F0Fu) << 4u) | ((bits & 0xF0F0F0F0u) >> 4u);
  207. bits = ((bits & 0x00FF00FFu) << 8u) | ((bits & 0xFF00FF00u) >> 8u);
  208. return (float)(double(bits) / (double)0x100000000LL);
  209. }
  210. void hammersleySequence(UINT32 i, UINT32 count, float& e0, float& e1)
  211. {
  212. e0 = i / (float)count;
  213. e1 = reverseBits(i);
  214. }
  215. Vector3 sphericalToCartesian(float cosTheta, float sinTheta, float phi)
  216. {
  217. Vector3 output;
  218. output.x = sinTheta * cos(phi);
  219. output.y = sinTheta * sin(phi);
  220. output.z = cosTheta;
  221. return output;
  222. }
  223. // Generates an angle in spherical coordinates, importance sampled for the specified roughness based on some uniformly
  224. // distributed random variables in range [0, 1].
  225. void importanceSampleGGX(float e0, float e1, float roughness4, float& cosTheta, float& phi)
  226. {
  227. // See GGXImportanceSample.nb for derivation (essentially, take base GGX, normalize it, generate PDF, split PDF into
  228. // marginal probability for theta and conditional probability for phi. Plug those into the CDF, invert it.)
  229. cosTheta = sqrt((1.0f - e0) / (1.0f + (roughness4 - 1.0f) * e0));
  230. phi = 2.0f * Math::PI * e1;
  231. }
  232. float calcMicrofacetShadowingSmithGGX(float roughness4, float NoV, float NoL)
  233. {
  234. // Note: See lighting shader for derivation. Includes microfacet BRDF divisor.
  235. float g1V = NoV + sqrt(NoV * (NoV - NoV * roughness4) + roughness4);
  236. float g1L = NoL + sqrt(NoL * (NoL - NoL * roughness4) + roughness4);
  237. return 1.0f / (g1V * g1L);
  238. }
  239. SPtr<Texture> TiledDeferredImageBasedLighting::generatePreintegratedEnvBRDF()
  240. {
  241. TEXTURE_DESC desc;
  242. desc.type = TEX_TYPE_2D;
  243. desc.format = PF_FLOAT16_RG;
  244. desc.width = 128;
  245. desc.height = 32;
  246. SPtr<Texture> texture = Texture::create(desc);
  247. PixelData pixelData = texture->lock(GBL_WRITE_ONLY_DISCARD);
  248. for (UINT32 y = 0; y < desc.height; y++)
  249. {
  250. float roughness = (float)(y + 0.5f) / desc.height;
  251. float m = roughness * roughness;
  252. float m2 = m*m;
  253. for (UINT32 x = 0; x < desc.width; x++)
  254. {
  255. float NoV = (float)(x + 0.5f) / desc.width;
  256. Vector3 V;
  257. V.x = sqrt(1.0f - NoV * NoV); // sine
  258. V.y = 0.0f;
  259. V.z = NoV;
  260. // These are the two integrals resulting from the second part of the split-sum approximation. Described in
  261. // Epic's 2013 paper:
  262. // http://blog.selfshadow.com/publications/s2013-shading-course/karis/s2013_pbs_epic_notes_v2.pdf
  263. float scale = 0.0f;
  264. float offset = 0.0f;
  265. // We use the same importance sampling function we use for reflection cube importance sampling, only we
  266. // sample G and F, instead of D factors of the microfactet BRDF. See GGXImportanceSample.nb for derivation.
  267. constexpr UINT32 NumSamples = 128;
  268. for (UINT32 i = 0; i < NumSamples; i++)
  269. {
  270. float e0, e1;
  271. hammersleySequence(i, NumSamples, e0, e1);
  272. float cosTheta, phi;
  273. importanceSampleGGX(e0, e1, m2, cosTheta, phi);
  274. float sinTheta = sqrt(1.0f - cosTheta * cosTheta);
  275. Vector3 H = sphericalToCartesian(cosTheta, sinTheta, phi);
  276. Vector3 L = 2.0f * Vector3::dot(V, H) * H - V;
  277. float VoH = std::max(Vector3::dot(V, H), 0.0f);
  278. float NoL = std::max(L.z, 0.0f); // N assumed (0, 0, 1)
  279. float NoH = std::max(H.z, 0.0f); // N assumed (0, 0, 1)
  280. // Set second part of the split sum integral is split into two parts:
  281. // F0*I[G * (1 - (1 - v.h)^5) * cos(theta)] + I[G * (1 - v.h)^5 * cos(theta)] (F0 * scale + bias)
  282. // We calculate the fresnel scale (1 - (1 - v.h)^5) and bias ((1 - v.h)^5) parts
  283. float fc = pow(1.0f - VoH, 5.0f);
  284. float fresnelScale = 1.0f - fc;
  285. float fresnelOffset = fc;
  286. // We calculate the G part
  287. float G = calcMicrofacetShadowingSmithGGX(m2, NoV, NoL);
  288. // When we factor out G and F, then divide D by PDF, this is what's left
  289. // Note: This is based on PDF: D * NoH / (4 * VoH). (4 * VoH) factor comes from the Jacobian of the
  290. // transformation from half vector to light vector
  291. float pdfFactor = 4.0f * VoH / NoH;
  292. if (NoL > 0.0f)
  293. {
  294. scale += NoL * pdfFactor * G * fresnelScale;
  295. offset += NoL * pdfFactor * G * fresnelOffset;
  296. }
  297. }
  298. scale /= NumSamples;
  299. offset /= NumSamples;
  300. Color color;
  301. color.r = Math::clamp01(scale);
  302. color.g = Math::clamp01(offset);
  303. pixelData.setColorAt(color, x, y);
  304. }
  305. }
  306. texture->unlock();
  307. return texture;
  308. }
  309. template<int MSAA_COUNT>
  310. TTiledDeferredImageBasedLightingMat<MSAA_COUNT>::TTiledDeferredImageBasedLightingMat()
  311. :mInternal(mMaterial, mParamsSet, MSAA_COUNT)
  312. {
  313. }
  314. template<int MSAA_COUNT>
  315. void TTiledDeferredImageBasedLightingMat<MSAA_COUNT>::_initDefines(ShaderDefines& defines)
  316. {
  317. defines.set("TILE_SIZE", TiledDeferredImageBasedLighting::TILE_SIZE);
  318. defines.set("MSAA_COUNT", MSAA_COUNT);
  319. }
  320. template<int MSAA_COUNT>
  321. void TTiledDeferredImageBasedLightingMat<MSAA_COUNT>::execute(const SPtr<RenderTargets>& gbuffer,
  322. const SPtr<GpuParamBlockBuffer>& perCamera, const SPtr<Texture>& preintegratedGF)
  323. {
  324. mInternal.execute(gbuffer, perCamera, preintegratedGF);
  325. }
  326. template<int MSAA_COUNT>
  327. void TTiledDeferredImageBasedLightingMat<MSAA_COUNT>::setReflectionProbes(const GPUReflProbeData& probeData,
  328. const SPtr<Texture>& reflectionCubemaps, bool capturingReflections)
  329. {
  330. mInternal.setReflectionProbes(probeData, reflectionCubemaps, capturingReflections);
  331. }
  332. template<int MSAA_COUNT>
  333. void TTiledDeferredImageBasedLightingMat<MSAA_COUNT>::setSky(const SPtr<Texture>& skyReflections,
  334. const SPtr<Texture>& skyIrradiance, float brightness)
  335. {
  336. mInternal.setSky(skyReflections, skyIrradiance, brightness);
  337. }
  338. template<int MSAA_COUNT>
  339. SPtr<GpuParamBlockBuffer> TTiledDeferredImageBasedLightingMat<MSAA_COUNT>::getReflectionsParamBuffer() const
  340. {
  341. return mInternal.getReflectionsParamBuffer();
  342. }
  343. template<int MSAA_COUNT>
  344. SPtr<SamplerState> TTiledDeferredImageBasedLightingMat<MSAA_COUNT>::getReflectionsSamplerState() const
  345. {
  346. return mInternal.getReflectionsSamplerState();
  347. }
  348. TiledDeferredImageBasedLightingMaterials::TiledDeferredImageBasedLightingMaterials()
  349. {
  350. mInstances[0] = bs_new<TTiledDeferredImageBasedLightingMat<1>>();
  351. mInstances[1] = bs_new<TTiledDeferredImageBasedLightingMat<2>>();
  352. mInstances[2] = bs_new<TTiledDeferredImageBasedLightingMat<4>>();
  353. mInstances[3] = bs_new<TTiledDeferredImageBasedLightingMat<8>>();
  354. }
  355. TiledDeferredImageBasedLightingMaterials::~TiledDeferredImageBasedLightingMaterials()
  356. {
  357. for (UINT32 i = 0; i < 4; i++)
  358. bs_delete(mInstances[i]);
  359. }
  360. ITiledDeferredImageBasedLightingMat* TiledDeferredImageBasedLightingMaterials::get(UINT32 msaa)
  361. {
  362. if (msaa == 1)
  363. return mInstances[0];
  364. else if (msaa == 2)
  365. return mInstances[1];
  366. else if (msaa == 4)
  367. return mInstances[2];
  368. else
  369. return mInstances[3];
  370. }
  371. }}