void Renderer::cullAndSort (const shared_ptr<GBuffer>& gbuffer, const Array<shared_ptr<Surface>>& allSurfaces, Array<shared_ptr<Surface>>& allVisibleSurfaces, Array<shared_ptr<Surface>>& forwardOpaqueSurfaces, Array<shared_ptr<Surface>>& forwardBlendedSurfaces) { BEGIN_PROFILER_EVENT("Renderer::cullAndSort"); const shared_ptr<Camera>& camera = gbuffer->camera(); Surface::cull(camera->frame(), camera->projection(), gbuffer->rect2DBounds(), allSurfaces, allVisibleSurfaces); Surface::sortBackToFront(allVisibleSurfaces, camera->frame().lookVector()); // Extract everything that uses a forward rendering pass (including the skybox, which is emissive // and benefits from a forward pass because it may have high dynamic range). Leave the skybox in the // deferred pass to produce correct motion vectors as well. for (int i = 0; i < allVisibleSurfaces.size(); ++i) { const shared_ptr<Surface>& surface = allVisibleSurfaces[i]; if (! surface->canBeFullyRepresentedInGBuffer(gbuffer->specification())) { if (surface->requiresBlending()) { forwardBlendedSurfaces.append(surface); } else { forwardOpaqueSurfaces.append(surface); } } } END_PROFILER_EVENT(); }
void Renderer::computeShadowing (RenderDevice* rd, const Array<shared_ptr<Surface>>& allSurfaces, const shared_ptr<GBuffer>& gbuffer, const shared_ptr<Framebuffer>& depthPeelFramebuffer, LightingEnvironment& lightingEnvironment) { BEGIN_PROFILER_EVENT("Renderer::computeShadowing"); // Compute shadows Surface::renderShadowMaps(rd, lightingEnvironment.lightArray, allSurfaces); if (! gbuffer->colorGuardBandThickness().isZero()) { rd->setGuardBandClip2D(gbuffer->colorGuardBandThickness()); } // Compute AO if (notNull(lightingEnvironment.ambientOcclusion)) { lightingEnvironment.ambientOcclusion->update (rd, lightingEnvironment.ambientOcclusionSettings, gbuffer->camera(), gbuffer->texture(GBuffer::Field::DEPTH_AND_STENCIL), notNull(depthPeelFramebuffer) ? depthPeelFramebuffer->texture(Framebuffer::DEPTH) : shared_ptr<Texture>(), gbuffer->texture(GBuffer::Field::CS_NORMAL), gbuffer->texture(GBuffer::Field::SS_POSITION_CHANGE), gbuffer->depthGuardBandThickness() - gbuffer->colorGuardBandThickness()); } END_PROFILER_EVENT(); }
void AmbientOcclusion::computeCSZ (RenderDevice* rd, const Array<shared_ptr<Framebuffer> >& cszFramebuffers, const shared_ptr<Texture>& csZBuffer, const AmbientOcclusionSettings& settings, const shared_ptr<Texture>& depthBuffer, const Vector3& clipInfo, const shared_ptr<Texture>& peeledDepthBuffer) { BEGIN_PROFILER_EVENT("computeCSZ"); // Generate level 0 cszFramebuffers[0]->set(Framebuffer::DEPTH, depthBuffer); rd->push2D(cszFramebuffers[0]); { rd->clear(true, false, false); rd->setDepthWrite(false); rd->setDepthTest(RenderDevice::DEPTH_GREATER); Args args; args.setUniform(SYMBOL_clipInfo, clipInfo); args.setUniform(SYMBOL_DEPTH_AND_STENCIL_buffer, depthBuffer, Sampler::buffer()); alwaysAssertM(!settings.useDepthPeelBuffer || notNull(peeledDepthBuffer), "Tried to run AO with peeled depth buffer, but buffer was null"); args.setMacro(SYMBOL_USE_PEELED_DEPTH_BUFFER, settings.useDepthPeelBuffer); if (settings.useDepthPeelBuffer) { args.setUniform(SYMBOL_peeledDepthBuffer, peeledDepthBuffer, Sampler::buffer()); } args.setRect(rd->viewport()); LAUNCH_SHADER("AmbientOcclusion_reconstructCSZ.*", args); } rd->pop2D(); // Generate the other levels (we don't have a depth texture to cull against for these) for (int i = 1; i <= MAX_MIP_LEVEL; ++i) { Args args; args.setUniform("CSZ_buffer", csZBuffer, cszSamplerSettings()); args.setMacro(SYMBOL_USE_PEELED_DEPTH_BUFFER, settings.useDepthPeelBuffer); rd->push2D(cszFramebuffers[i]); { rd->clear(); args.setUniform(SYMBOL_previousMIPNumber, i - 1); args.setRect(rd->viewport()); LAUNCH_SHADER("AmbientOcclusion_minify.*", args); } rd->pop2D(); } END_PROFILER_EVENT(); }
void Renderer::computeGBuffer (RenderDevice* rd, const Array<shared_ptr<Surface>>& sortedVisibleSurfaces, const shared_ptr<GBuffer>& gbuffer, const shared_ptr<Framebuffer>& depthPeelFramebuffer, float depthPeelSeparationHint) { BEGIN_PROFILER_EVENT("Renderer::computeGBuffer"); const shared_ptr<Camera>& camera = gbuffer->camera(); Surface::renderIntoGBuffer(rd, sortedVisibleSurfaces, gbuffer, camera->previousFrame(), camera->expressivePreviousFrame()); if (notNull(depthPeelFramebuffer)) { rd->pushState(depthPeelFramebuffer); { rd->clear(); rd->setProjectionAndCameraMatrix(camera->projection(), camera->frame()); Surface::renderDepthOnly(rd, sortedVisibleSurfaces, CullFace::BACK, gbuffer->texture(GBuffer::Field::DEPTH_AND_STENCIL), depthPeelSeparationHint, true, Color3::white() / 3.0f); } rd->popState(); } END_PROFILER_EVENT(); }
void AmbientOcclusion::compute (RenderDevice* rd, const AmbientOcclusionSettings& settings, const shared_ptr<Texture>& depthBuffer, const Vector3& clipConstant, const Vector4& projConstant, float projScale, const CFrame& currentCameraFrame, const CFrame& prevCameraFrame, const shared_ptr<Texture>& peeledDepthBuffer, const shared_ptr<Texture>& normalBuffer, const shared_ptr<Texture>& ssVelocityBuffer) { BEGIN_PROFILER_EVENT("AmbientOcclusion"); alwaysAssertM(depthBuffer, "Depth buffer is required."); int depthBufferCount = 1; if (notNull(peeledDepthBuffer)) { ++depthBufferCount; } initializePerViewBuffers(depthBufferCount); resizeBuffers(depthBuffer); # if COMBINE_CSZ_INTO_ONE_TEXTURE == 1 m_perViewBuffers[0]->resizeBuffers(depthBuffer, peeledDepthBuffer); computeCSZ(rd, m_perViewBuffers[0]->cszFramebuffers, m_perViewBuffers[0]->cszBuffer, settings, depthBuffer, clipConstant, peeledDepthBuffer); # else shared_ptr<Texture> depthTexture = depthBuffer; for (int i = 0; i < m_perViewBuffers.size(); ++i) { m_perViewBuffers[i]->resizeBuffers(depthTexture, shared_ptr<Texture>()); computeCSZ(rd, m_perViewBuffers[i]->cszFramebuffers, m_perViewBuffers[i]->cszBuffer, settings, depthTexture, clipConstant, shared_ptr<Texture>()); depthTexture = peeledDepthBuffer; } # endif # if COMBINE_CSZ_INTO_ONE_TEXTURE == 1 shared_ptr<Texture> depthPeelCSZ = m_perViewBuffers[0]->cszBuffer; # else shared_ptr<Texture> depthPeelCSZ = notNull(peeledDepthBuffer) ? m_perViewBuffers[1]->cszBuffer : shared_ptr<Texture>(); # endif computeRawAO(rd, settings, depthBuffer, clipConstant, projConstant, projScale, m_perViewBuffers[0]->cszBuffer, depthPeelCSZ, normalBuffer); if (notNull(ssVelocityBuffer)) { m_temporallyFilteredBuffer = m_temporalFilter.apply(rd, clipConstant, projConstant, currentCameraFrame, prevCameraFrame, m_rawAOBuffer, depthBuffer, ssVelocityBuffer, Vector2((float)m_guardBandSize, (float)m_guardBandSize), 1, settings.temporalFilterSettings); } else { m_temporallyFilteredBuffer = m_rawAOBuffer; } if (settings.blurRadius != 0) { BEGIN_PROFILER_EVENT("Blur"); alwaysAssertM(settings.blurRadius >= 0 && settings.blurRadius <= 6, "The AO blur radius must be a nonnegative number, 6 or less"); alwaysAssertM(settings.blurStepSize > 0, "Must use a positive blur step size"); blurHorizontal(rd, settings, depthBuffer, projConstant, normalBuffer); blurVertical(rd, settings, depthBuffer, projConstant, normalBuffer); END_PROFILER_EVENT(); } // else the result is still in the m_temporallyFilteredBuffer END_PROFILER_EVENT(); }