How do I get light/shadow buffer?

Hello there,

I’m trying to get light and shadow buffer for my post process material, but I couldn’t find it anywhere.
I thought that everything in UE is deferred lighting, so technically these thing should exist right?

If so, how do I get them in materiel’s blueprint?

Best,

Hey KillerPenguin -

Allow me to paraphrase from one of our Graphics and Rendering Engineers:

Rendering is done in many passes and sometimes we have intermediate buffers we can give access e.g. GBuffers. Lighting (like the viewmode) doesn’t exist as intermediate - it’s created by a modified pixel shader which fades the base color to grey. This costs some shader instructions and is editor only (when shipping a game this will not be in the shader). So you have to render the scene twice to get this buffer plus normal lighting. We also cannot apply the base color later because the lighting components cannot be combines like this (for correct fresnel and special shading models). You could go into the code and add an additional render GBuffer that pulls the lighting separately and exposes it as a Scene Texture for Post Process Material work but it would as mentioned above add a whole second rendering and would most certainly cause issues with certain shading models.

Thank You

Eric Ketchum

1 Like

Arr ok that clear everything up. Thx :slight_smile:

Thank you Eric. This limitation is really a shame because having the lighting pass would have enabled huge control over lighting, but I understand your explanation of why it’s quite difficult to achieve.

this is My Access GBuffer, maybe you can get something

FRHICommandListImmediate& RHICmdList = GRHICommandList.GetImmediateCommandList();
	//计数加一避免Render完成后直接清空了GBuffer,但会慢一帧,你猜
	FSceneRenderTargets::Get(RHICmdList).AdjustGBufferRefCount(RHICmdList, 1);
	FSceneRenderTargets& SceneContext = FSceneRenderTargets::Get(RHICmdList);
	if (SceneContext.GBufferA && pRenderData->mTextureTarget != nullptr)
	{
		FTexture2DRHIRef vTextTarget;
		switch (pRenderData->EShowBuff)
		{
		case EDZShowGbuffer::VE_GDZSHOWBUFFERA:
			vTextTarget = SceneContext.GetGBufferATexture();
			break;
		case EDZShowGbuffer::VE_GDZSHOWBUFFERB:
			vTextTarget = SceneContext.GetGBufferBTexture();
			break;
		case EDZShowGbuffer::VE_GDZSHOWBUFFERC:
			vTextTarget = SceneContext.GetGBufferCTexture();
			break;
		case EDZShowGbuffer::VE_GDZSHOWBUFFERD:
			vTextTarget = SceneContext.GetGBufferDTexture();
			break;
		case EDZShowGbuffer::VE_GDZSHOWBUFFERE:
			vTextTarget = SceneContext.GetGBufferETexture();
			break;
			break;
		default:
			vTextTarget = SceneContext.GetGBufferATexture();
			break;
		}
		pRenderData->format = vTextTarget->GetFormat();
		if (pRenderData->canvasWidth != vTextTarget->GetSizeX())
		{
			pRenderData->isGetGBufferData = false;
			return;
		}
		FTextureReferenceRHIRef vTexRHIRef = pRenderData->mTextureTarget->TextureReference.TextureReferenceRHI;
		FRHITexture* vRTTexture = vTexRHIRef->GetTextureReference()->GetReferencedTexture();
		FRHITexture2D* vtex = (FRHITexture2D*)vRTTexture;
		if (vtex == nullptr)
		{
			return;
		}
		switch (pRenderData->ECOPYBuffType)
		{
		case EDZCOPYGbufferType::VE_GDZSHOWGBUFFER_COPYMIP:
			UDynamicAccessGBufferRenderTarget::Copy_TextureRHI(RHICmdList,vtex, vTextTarget);
			break;
		case EDZCOPYGbufferType::VE_GDZSHOWBUFFERR_COPYMEMO:
			UDynamicAccessGBufferRenderTarget::Copy_MemoryRHI(RHICmdList, vtex, vTextTarget);
			break;
		case EDZCOPYGbufferType::VE_GDZSHOWBUFFERC_CPUARRAY:
			UDynamicAccessGBufferRenderTarget::Copy_CPUArrayRHI();
			break;
		default:
			break;
		}
		RHICmdList.CopySharedMips(vtex, vTextTarget);
	}
	//移除
	FSceneRenderTargets::Get(RHICmdList).AdjustGBufferRefCount(RHICmdList, -1);

this is MyCode:

void UDynamicAccessGBufferRenderTarget::CaputerGBuffer_RenderThread(FCommitRenderData* pRenderData)
{
	FRHICommandListImmediate& RHICmdList = GRHICommandList.GetImmediateCommandList();
	//计数加一避免Render完成后直接清空了GBuffer,但会慢一帧,你猜
	FSceneRenderTargets::Get(RHICmdList).AdjustGBufferRefCount(RHICmdList, 1);
	FSceneRenderTargets& SceneContext = FSceneRenderTargets::Get(RHICmdList);
	if (SceneContext.GBufferA && pRenderData->mTextureTarget != nullptr)
	{
		FTexture2DRHIRef vTextTarget;
		switch (pRenderData->EShowBuff)
		{
		case EDZShowGbuffer::VE_GDZSHOWBUFFERA:
			vTextTarget = SceneContext.GetGBufferATexture();
			break;
		case EDZShowGbuffer::VE_GDZSHOWBUFFERB:
			vTextTarget = SceneContext.GetGBufferBTexture();
			break;
		case EDZShowGbuffer::VE_GDZSHOWBUFFERC:
			vTextTarget = SceneContext.GetGBufferCTexture();
			break;
		case EDZShowGbuffer::VE_GDZSHOWBUFFERD:
			vTextTarget = SceneContext.GetGBufferDTexture();
			break;
		case EDZShowGbuffer::VE_GDZSHOWBUFFERE:
			vTextTarget = SceneContext.GetGBufferETexture();
			break;
			break;
		default:
			vTextTarget = SceneContext.GetGBufferATexture();
			break;
		}
		pRenderData->format = vTextTarget->GetFormat();
		if (pRenderData->canvasWidth != vTextTarget->GetSizeX())
		{
			pRenderData->isGetGBufferData = false;
			return;
		}
		FTextureReferenceRHIRef vTexRHIRef = pRenderData->mTextureTarget->TextureReference.TextureReferenceRHI;
		FRHITexture* vRTTexture = vTexRHIRef->GetTextureReference()->GetReferencedTexture();
		FRHITexture2D* vtex = (FRHITexture2D*)vRTTexture;
		if (vtex == nullptr)
		{
			return;
		}
		switch (pRenderData->ECOPYBuffType)
		{
		case EDZCOPYGbufferType::VE_GDZSHOWGBUFFER_COPYMIP:
			UDynamicAccessGBufferRenderTarget::Copy_TextureRHI(RHICmdList,vtex, vTextTarget);
			break;
		case EDZCOPYGbufferType::VE_GDZSHOWBUFFERR_COPYMEMO:
			UDynamicAccessGBufferRenderTarget::Copy_MemoryRHI(RHICmdList, vtex, vTextTarget);
			break;
		case EDZCOPYGbufferType::VE_GDZSHOWBUFFERC_CPUARRAY:
			UDynamicAccessGBufferRenderTarget::Copy_CPUArrayRHI();
			break;
		default:
			break;
		}
		RHICmdList.CopySharedMips(vtex, vTextTarget);
	}
	//移除
	FSceneRenderTargets::Get(RHICmdList).AdjustGBufferRefCount(RHICmdList, -1);
}

Two ways with Access the data to view:

    //利用SharedMip的共享方式在这里会快一些
    //扩展方式
    void UDynamicAccessGBufferRenderTarget::Copy_TextureRHI(FRHICommandListImmediate& RHICmdList,FRHITexture2D* pDesc,FRHITexture2D* pSrc)
    {
    	RHICmdList.CopySharedMips(pDesc, pSrc);
    }
    
    //内存CPY,但需要锁住,这样就会让另外的渲染不能访问,会造成掉帧率。
    void UDynamicAccessGBufferRenderTarget::Copy_MemoryRHI(FRHICommandListImmediate& RHICmdList, FRHITexture2D* pDesc, FRHITexture2D* pSrc)
    {
    	uint32 Lolstrid = 0;
    	void * UAVRenderTargetData = RHILockTexture2D(pDesc, 0, RLM_WriteOnly, Lolstrid, true);
    	void * UAVCSData = RHILockTexture2D(pSrc, 0, RLM_ReadOnly, Lolstrid, true);
    	FMemory::Memcpy(UAVRenderTargetData, UAVCSData, GPixelFormats[pSrc->GetFormat()].BlockBytes * pSrc->GetSizeX() * pSrc->GetSizeY());
    	RHICmdList.UnlockTexture2D(pDesc, 0, false);
    	RHICmdList.UnlockTexture2D(pSrc, 0, false);
    }