TraditionalDeferredShading.cpp 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. // Copyright (C) 2009-2023, Panagiotis Christopoulos Charitos and contributors.
  2. // All rights reserved.
  3. // Code licensed under the BSD License.
  4. // http://www.anki3d.org/LICENSE
  5. #include <AnKi/Renderer/Utils/TraditionalDeferredShading.h>
  6. #include <AnKi/Renderer/Renderer.h>
  7. #include <AnKi/Resource/ResourceManager.h>
  8. #include <AnKi/Resource/MeshResource.h>
  9. #include <AnKi/Resource/ImageResource.h>
  10. #include <AnKi/Shaders/Include/TraditionalDeferredShadingTypes.h>
  11. #include <AnKi/Scene/SceneGraph.h>
  12. #include <AnKi/Scene/Components/SkyboxComponent.h>
  13. #include <AnKi/Scene/Components/LightComponent.h>
  14. namespace anki {
  15. Error TraditionalDeferredLightShading::init()
  16. {
  17. // Init progs
  18. {
  19. ANKI_CHECK(ResourceManager::getSingleton().loadResource("ShaderBinaries/TraditionalDeferredShading.ankiprogbin", m_lightProg));
  20. for(U32 specular = 0; specular <= 1; ++specular)
  21. {
  22. ShaderProgramResourceVariantInitInfo variantInitInfo(m_lightProg);
  23. variantInitInfo.addMutation("SPECULAR", specular);
  24. const ShaderProgramResourceVariant* variant;
  25. m_lightProg->getOrCreateVariant(variantInitInfo, variant);
  26. m_lightGrProg[specular].reset(&variant->getProgram());
  27. }
  28. }
  29. // Shadow sampler
  30. {
  31. SamplerInitInfo inf;
  32. inf.m_compareOperation = CompareOperation::kLessEqual;
  33. inf.m_addressing = SamplingAddressing::kClamp;
  34. inf.m_mipmapFilter = SamplingFilter::kBase;
  35. inf.m_minMagFilter = SamplingFilter::kLinear;
  36. m_shadowSampler = GrManager::getSingleton().newSampler(inf);
  37. }
  38. // Skybox
  39. {
  40. ANKI_CHECK(ResourceManager::getSingleton().loadResource("ShaderBinaries/TraditionalDeferredShadingSkybox.ankiprogbin", m_skyboxProg));
  41. for(U32 i = 0; i < m_skyboxGrProgs.getSize(); ++i)
  42. {
  43. ShaderProgramResourceVariantInitInfo variantInitInfo(m_skyboxProg);
  44. variantInitInfo.addMutation("METHOD", i);
  45. const ShaderProgramResourceVariant* variant;
  46. m_skyboxProg->getOrCreateVariant(variantInitInfo, variant);
  47. m_skyboxGrProgs[i].reset(&variant->getProgram());
  48. }
  49. }
  50. return Error::kNone;
  51. }
  52. void TraditionalDeferredLightShading::drawLights(TraditionalDeferredLightShadingDrawInfo& info)
  53. {
  54. CommandBuffer& cmdb = *info.m_renderpassContext->m_commandBuffer;
  55. RenderPassWorkContext& rgraphCtx = *info.m_renderpassContext;
  56. // Set common state for all
  57. cmdb.setViewport(info.m_viewport.x(), info.m_viewport.y(), info.m_viewport.z(), info.m_viewport.w());
  58. // Skybox first
  59. const SkyboxComponent* skyc = SceneGraph::getSingleton().getSkybox();
  60. if(skyc)
  61. {
  62. const Bool isSolidColor = (skyc->getSkyboxType() == SkyboxType::kSolidColor);
  63. cmdb.bindShaderProgram(m_skyboxGrProgs[!isSolidColor].get());
  64. cmdb.bindSampler(0, 0, getRenderer().getSamplers().m_nearestNearestClamp.get());
  65. rgraphCtx.bindTexture(0, 1, info.m_gbufferDepthRenderTarget, TextureSubresourceInfo(DepthStencilAspectBit::kDepth));
  66. if(!isSolidColor)
  67. {
  68. cmdb.bindSampler(0, 2, getRenderer().getSamplers().m_trilinearRepeatAniso.get());
  69. cmdb.bindTexture(0, 3, &skyc->getImageResource().getTextureView());
  70. }
  71. TraditionalDeferredSkyboxUniforms unis;
  72. unis.m_solidColor = (isSolidColor) ? skyc->getSolidColor() : Vec3(0.0f);
  73. unis.m_inputTexUvBias = info.m_gbufferTexCoordsBias;
  74. unis.m_inputTexUvScale = info.m_gbufferTexCoordsScale;
  75. unis.m_invertedViewProjectionMat = info.m_invViewProjectionMatrix;
  76. unis.m_cameraPos = info.m_cameraPosWSpace.xyz();
  77. cmdb.setPushConstants(&unis, sizeof(unis));
  78. drawQuad(cmdb);
  79. }
  80. // Light shading
  81. {
  82. const LightComponent* dirLightc = SceneGraph::getSingleton().getDirectionalLight();
  83. TraditionalDeferredShadingUniforms* unis = allocateAndBindUniforms<TraditionalDeferredShadingUniforms>(cmdb, 0, 0);
  84. unis->m_inputTexUvScale = info.m_gbufferTexCoordsScale;
  85. unis->m_inputTexUvBias = info.m_gbufferTexCoordsBias;
  86. unis->m_fbUvScale = info.m_lightbufferTexCoordsScale;
  87. unis->m_fbUvBias = info.m_lightbufferTexCoordsBias;
  88. unis->m_invViewProjMat = info.m_invViewProjectionMatrix;
  89. unis->m_cameraPos = info.m_cameraPosWSpace.xyz();
  90. if(dirLightc)
  91. {
  92. unis->m_dirLight.m_diffuseColor = dirLightc->getDiffuseColor().xyz();
  93. unis->m_dirLight.m_active = 1;
  94. unis->m_dirLight.m_direction = dirLightc->getDirection();
  95. ANKI_ASSERT(info.m_effectiveShadowDistance > 0.0f);
  96. unis->m_dirLight.m_effectiveShadowDistance = info.m_effectiveShadowDistance;
  97. unis->m_dirLight.m_lightMatrix = info.m_dirLightMatrix;
  98. }
  99. else
  100. {
  101. unis->m_dirLight.m_active = 0;
  102. }
  103. cmdb.bindStorageBuffer(0, 1, info.m_visibleLightsBuffer.m_buffer, info.m_visibleLightsBuffer.m_offset, info.m_visibleLightsBuffer.m_range);
  104. cmdb.bindStorageBuffer(0, 2, &GpuSceneBuffer::getSingleton().getBuffer(),
  105. GpuSceneArrays::Light::getSingleton().getGpuSceneOffsetOfArrayBase(),
  106. GpuSceneArrays::Light::getSingleton().getElementCount() * GpuSceneArrays::Light::getSingleton().getElementSize());
  107. // NOTE: Use nearest sampler because we don't want the result to sample the near tiles
  108. cmdb.bindSampler(0, 3, getRenderer().getSamplers().m_nearestNearestClamp.get());
  109. rgraphCtx.bindColorTexture(0, 4, info.m_gbufferRenderTargets[0]);
  110. rgraphCtx.bindColorTexture(0, 5, info.m_gbufferRenderTargets[1]);
  111. rgraphCtx.bindColorTexture(0, 6, info.m_gbufferRenderTargets[2]);
  112. rgraphCtx.bindTexture(0, 7, info.m_gbufferDepthRenderTarget, TextureSubresourceInfo(DepthStencilAspectBit::kDepth));
  113. cmdb.bindSampler(0, 8, m_shadowSampler.get());
  114. if(dirLightc && dirLightc->getShadowEnabled())
  115. {
  116. ANKI_ASSERT(info.m_directionalLightShadowmapRenderTarget.isValid());
  117. rgraphCtx.bindTexture(0, 9, info.m_directionalLightShadowmapRenderTarget, TextureSubresourceInfo(DepthStencilAspectBit::kDepth));
  118. }
  119. else
  120. {
  121. // No shadows for the dir light, bind a random depth texture (need depth because validation complains)
  122. rgraphCtx.bindTexture(0, 9, info.m_gbufferDepthRenderTarget, TextureSubresourceInfo(DepthStencilAspectBit::kDepth));
  123. }
  124. cmdb.bindShaderProgram(m_lightGrProg[info.m_computeSpecular].get());
  125. drawQuad(cmdb);
  126. }
  127. }
  128. } // end namespace anki