because Alpha channel Save in GBufferD’s R channel
so we Add ScreenPixelAlphaShder.usf to write alpha channel
#include "Common.usf"
Texture2D InTexture;
SamplerState InTextureSampler;
Texture2D InAlphaTexture;
SamplerState InAlphaTextureSampler;
void Main(FScreenVertexOutput Input,
out float4 OutColor : SV_Target0)
{
OutColor = Texture2DSample(InTexture, InTextureSampler, Input.UV);
OutColor.a = Texture2DSample(InAlphaTexture, InAlphaTextureSampler, Input.UV).r;
}
Add FScreenAlphaPS class in ScreenRendering.h
class FScreenAlphaPS : public FGlobalShader
{
DECLARE_EXPORTED_SHADER_TYPE(FScreenPS, Global, ENGINE_API);
public:
static bool ShouldCache(EShaderPlatform Platform) { return true; }
FScreenAlphaPS(const ShaderMetaType::CompiledShaderInitializerType& Initializer) :
FGlobalShader(Initializer)
{
InTexture.Bind(Initializer.ParameterMap, TEXT("InTexture"), SPF_Mandatory);
InTextureSampler.Bind(Initializer.ParameterMap, TEXT("InTextureSampler"));
InAlphaTexture.Bind(Initializer.ParameterMap, TEXT("InAlphaTexture"), SPF_Mandatory);
InAlphaTextureSampler.Bind(Initializer.ParameterMap, TEXT("InAlphaTextureSampler"));
}
FScreenAlphaPS() {}
void SetParameters(FRHICommandList& RHICmdList, const FTexture* Texture)
{
SetTextureParameter(RHICmdList, GetPixelShader(), InTexture, InTextureSampler, Texture);
}
void SetParameters(FRHICommandList& RHICmdList, FSamplerStateRHIParamRef SamplerStateRHI, FTextureRHIParamRef TextureRHI)
{
SetTextureParameter(RHICmdList, GetPixelShader(), InTexture, InTextureSampler, SamplerStateRHI, TextureRHI);
}
void SetAlphaParameters(FRHICommandList& RHICmdList, const FTexture* Texture)
{
SetTextureParameter(RHICmdList, GetPixelShader(), InAlphaTexture, InAlphaTextureSampler, Texture);
}
void SetAlphaParameters(FRHICommandList& RHICmdList, FSamplerStateRHIParamRef SamplerStateRHI, FTextureRHIParamRef TextureRHI)
{
SetTextureParameter(RHICmdList, GetPixelShader(), InAlphaTexture, InAlphaTextureSampler, SamplerStateRHI, TextureRHI);
}
virtual bool Serialize(FArchive& Ar) override
{
bool bShaderHasOutdatedParameters = FGlobalShader::Serialize(Ar);
Ar << InTexture;
Ar << InTextureSampler;
Ar << InAlphaTexture;
Ar << InAlphaTextureSampler;
return bShaderHasOutdatedParameters;
}
private:
FShaderResourceParameter InTexture;
FShaderResourceParameter InTextureSampler;
FShaderResourceParameter InAlphaTexture;
FShaderResourceParameter InAlphaTextureSampler;
};
Add FScreenAlphaPS Implement in ScreenRendering.cpp
IMPLEMENT_SHADER_TYPE(, FScreenAlphaPS, TEXT("ScreenPixelAlphaShader"), TEXT("Main"), SF_Pixel);
We Add SceneCaputureModify.h
#pragma once
class USceneCaptureComponent2D;
class FSceneRenderer;
class USceneCaptureComponent;
class UTextureRenderTarget;
class FRHICommandListImmediate;
class RENDERER_API FSceneCaptureModify
{
public:
static void UpdateSceneCaptureContents(
USceneCaptureComponent2D* CaptureComponent,
FMatrix const& ProjectionMatrix,
bool bDrawHiddenOnly);
private:
static void FSceneRenderer* CreateSceneRenderer(
USceneCaptureComponent* SceneCaptureComponent,
UTextureRenderTarget* TextureTarget,
const FMatrix& ViewRotationMatrix,
const FVector& ViewLocation,
const FMatrix& ProjectionMatrix,
float MaxViewDistance,
bool bCaptureSceneColour,
FPostProcessSettings* PostProcessSettings,
float PostProcessBlendWeight
bool bDrawHiddenOnly);
static void UpdateSceneCaptureContent_RenderThread(
FRHICommandListImmediate& RHICmdList, FSceneRenderer* SceneRenderer,
FTextureRenderTargetResource* TextureRenderTarget,
const FName OwnerName,
const FResolveParams& ResolveParams,
bool bUseSceneColorTexture)
};
then modify SceneCaptureRendering Add CopyCaptureToTargetWithAlpha
static void CopyCaptureToTargetWithAlpha(
FRHICommandListImmediate& RHICmdList,
const FRenderTarget* Target, const FIntPoint& TargetSize, FViewInfo& View, const FIntRect& ViewRect,
FTextureRHIParamRef SourceTextureRHI,
FTextureRHIParamRef AlphaTextureRHI,
bool bNeedsFlippedRenderTarget)
{
SetRenderTarget(RHICmdList, Target->GetRenderTargetTexture(), NULL);
RHICmdList.SetRasterizerState(TStaticRasterizerState<FM_Solid, CM_None>::GetRHI());
RHICmdList.SetDepthStencilState(TStaticDepthStencilState<false, CF_Always>::GetRHI());
RHICmdList.SetBlendState(TStaticBlendState<>::GetRHI());
TShaderMapRef<FScreenVS> VertexShader(View.ShaderMap);
TShaderMapRef<FScreenAlphaPS> PixelShader(View.ShaderMap);
static FGlobalBoundShaderState BoundShaderState;
SetGlobalBoundShaderState(RHICmdList, View.GetFeatureLevel(), BoundShaderState, GFilterVertexDeclaration.VertexDeclarationRHI, *VertexShader, *PixelShader);
FRenderingCompositePassContext Context(RHICmdList, View);
VertexShader->SetParameters(RHICmdList, View);
PixelShader->SetParameters(RHICmdList, TStaticSamplerState<SF_Point>::GetRHI(), SourceTextureRHI);
PixelShader->SetAlphaParameters(RHICmdList, TStaticSamplerState<SF_Point>::GetRHI(), AlphaTextureRHI);
if (bNeedsFlippedRenderTarget)
{
DrawRectangle(
RHICmdList,
ViewRect.Min.X, ViewRect.Min.Y,
ViewRect.Width(), ViewRect.Height(),
ViewRect.Min.X, ViewRect.Height() - ViewRect.Min.Y,
ViewRect.Width(), -ViewRect.Height(),
TargetSize,
TargetSize,
*VertexShader,
EDRF_UseTriangleOptimization);
}
else
{
DrawRectangle(
RHICmdList,
ViewRect.Min.X, ViewRect.Min.Y,
ViewRect.Width(), ViewRect.Height(),
ViewRect.Min.X, ViewRect.Min.Y,
ViewRect.Width(), ViewRect.Height(),
TargetSize,
FSceneRenderTargets::Get(RHICmdList).GetBufferSizeXY(),
*VertexShader,
EDRF_UseTriangleOptimization);
}
}
void FSceneCaptureModify::UpdateSceneCaptureContent_RenderThread(
FRHICommandListImmediate& RHICmdList,
FSceneRenderer* SceneRenderer,
FTextureRenderTargetResource* TextureRenderTarget,
const FName OwnerName,
const FResolveParams& ResolveParams,
bool bUseSceneColorTexture)
{
FMemMark MemStackMark(FMemStack::Get());
// update any resources that needed a deferred update
FDeferredUpdateResource::UpdateResources(RHICmdList);
{
#if WANTS_DRAW_MESH_EVENTS
FString EventName;
OwnerName.ToString(EventName);
SCOPED_DRAW_EVENTF(RHICmdList, SceneCapture, TEXT("SceneCapture %s"), *EventName);
#else
SCOPED_DRAW_EVENT(RHICmdList, UpdateSceneCaptureContent_RenderThread);
#endif
const bool bIsMobileHDR = IsMobileHDR();
const bool bRHINeedsFlip = RHINeedsToSwitchVerticalAxis(GMaxRHIShaderPlatform);
const bool bNeedsFlippedRenderTarget = !bIsMobileHDR && bRHINeedsFlip;
// Intermediate render target that will need to be flipped (needed on !IsMobileHDR())
TRefCountPtr<IPooledRenderTarget> FlippedPooledRenderTarget;
const FRenderTarget* Target = SceneRenderer->ViewFamily.RenderTarget;
if (bNeedsFlippedRenderTarget)
{
// We need to use an intermediate render target since the result will be flipped
auto& RenderTarget = Target->GetRenderTargetTexture();
FPooledRenderTargetDesc Desc(FPooledRenderTargetDesc::Create2DDesc(Target->GetSizeXY(),
RenderTarget.GetReference()->GetFormat(),
FClearValueBinding::None,
TexCreate_None,
TexCreate_RenderTargetable,
false));
GRenderTargetPool.FindFreeElement(Desc, FlippedPooledRenderTarget, TEXT("SceneCaptureFlipped"));
}
// Helper class to allow setting render target
struct FRenderTargetOverride : public FRenderTarget
{
FRenderTargetOverride(FRHITexture2D* In)
{
RenderTargetTextureRHI = In;
}
virtual FIntPoint GetSizeXY() const { return FIntPoint(RenderTargetTextureRHI->GetSizeX(), RenderTargetTextureRHI->GetSizeY()); }
FTexture2DRHIRef GetTextureParamRef() { return RenderTargetTextureRHI; }
} FlippedRenderTarget(
FlippedPooledRenderTarget.GetReference()
? FlippedPooledRenderTarget.GetReference()->GetRenderTargetItem().TargetableTexture->GetTexture2D()
: nullptr);
FViewInfo& View = SceneRenderer->Views[0];
FIntRect ViewRect = View.ViewRect;
FIntRect UnconstrainedViewRect = View.UnconstrainedViewRect;
SetRenderTarget(RHICmdList, Target->GetRenderTargetTexture(), NULL);
RHICmdList.Clear(true, FLinearColor::Black, false, (float)ERHIZBuffer::FarPlane, false, 0, ViewRect);
// Render the scene normally
{
SCOPED_DRAW_EVENT(RHICmdList, RenderScene);
if (bNeedsFlippedRenderTarget)
{
// Hijack the render target
SceneRenderer->ViewFamily.RenderTarget = &FlippedRenderTarget; //-V506
}
SceneRenderer->Render(RHICmdList);
if (bNeedsFlippedRenderTarget)
{
// And restore it
SceneRenderer->ViewFamily.RenderTarget = Target;
}
}
const FIntPoint TargetSize(UnconstrainedViewRect.Width(), UnconstrainedViewRect.Height());
if (bNeedsFlippedRenderTarget)
{
// We need to flip this texture upside down (since we depended on tonemapping to fix this on the hdr path)
SCOPED_DRAW_EVENT(RHICmdList, FlipCapture);
CopyCaptureToTarget(RHICmdList, Target, TargetSize, View, ViewRect, FlippedRenderTarget.GetTextureParamRef(), true);
}
else if (bUseSceneColorTexture && (bIsMobileHDR || SceneRenderer->FeatureLevel >= ERHIFeatureLevel::SM4))
{
// Copy the captured scene into the destination texture (only required on HDR or deferred as that implies post-processing)
SCOPED_DRAW_EVENT(RHICmdList, CaptureSceneColor);
FSceneRenderTargets::Get_Todo_PassContent().AdjustGBufferRefCount(1);
CopyCaptureToTargetWithAlpha(RHICmdList, Target, TargetSize, View, ViewRect,
FSceneRenderTargets::Get(RHICmdList).GetSceneColorTexture(),
FSceneRenderTargets::Get(RHICmdList).GBufferD->GetRenderTargetItem().TargetableTexture, false);
FSceneRenderTargets::Get_Todo_PassContent().AdjustGBufferRefCount(-1);
}
RHICmdList.CopyToResolveTarget(TextureRenderTarget->GetRenderTargetTexture(), TextureRenderTarget->TextureRHI, false, ResolveParams);
}
FSceneRenderer::WaitForTasksClearSnapshotsAndDeleteSceneRenderer(RHICmdList, SceneRenderer);
}
void FSceneCaptureModify::UpdateSceneCaptureContents(
USceneCaptureComponent2D* CaptureComponent,
FMatrix const& ProjectionMatrix,
bool bDrawHiddenOnly)
{
check(CaptureComponent);
if (CaptureComponent->TextureTarget)
{
FTransform Transform = CaptureComponent->GetComponentToWorld();
FVector ViewLocation = Transform.GetTranslation();
// Remove the translation from Transform because we only need rotation.
Transform.SetTranslation(FVector::ZeroVector);
FMatrix ViewRotationMatrix = Transform.ToInverseMatrixWithScale();
// swap axis st. x=z,y=x,z=y (unreal coord space) so that z is up
ViewRotationMatrix = ViewRotationMatrix * FMatrix(
FPlane(0, 0, 1, 0),
FPlane(1, 0, 0, 0),
FPlane(0, 1, 0, 0),
FPlane(0, 0, 0, 1));
const bool bUseSceneColorTexture = CaptureComponent->CaptureSource == SCS_SceneColorHDR;
FSceneRenderer* SceneRenderer = CreateSceneRenderer(
CaptureComponent, CaptureComponent->TextureTarget, ViewRotationMatrix, ViewLocation,
ProjectionMatrix, CaptureComponent->MaxViewDistanceOverride,
bUseSceneColorTexture,
&CaptureComponent->PostProcessSettings, CaptureComponent->PostProcessBlendWeight, bDrawHiddenOnly);
FTextureRenderTargetResource* TextureRenderTarget = CaptureComponent->TextureTarget->GameThread_GetRenderTargetResource();
const FName OwnerName = CaptureComponent->GetOwner() ? CaptureComponent->GetOwner()->GetFName() : NAME_None;
ENQUEUE_UNIQUE_RENDER_COMMAND_FOURPARAMETER(
CaptureCommand,
FSceneRenderer*, SceneRenderer, SceneRenderer,
FTextureRenderTargetResource*, TextureRenderTarget, TextureRenderTarget,
FName, OwnerName, OwnerName,
bool, bUseSceneColorTexture, bUseSceneColorTexture,
{
UpdateSceneCaptureContent_RenderThread(RHICmdList, SceneRenderer, TextureRenderTarget, OwnerName, FResolveParams(), bUseSceneColorTexture);
});
}
}
FSceneRenderer* FSceneCaptureModify::CreateSceneRenderer(
USceneCaptureComponent* SceneCaptureComponent,
UTextureRenderTarget* TextureTarget,
const FMatrix& ViewRotationMatrix,
const FVector& ViewLocation,
const FMatrix& ProjectionMatrix,
float MaxViewDistance,
bool bCaptureSceneColour,
FPostProcessSettings* PostProcessSettings,
float PostProcessBlendWeight,
bool bDrawHiddenOnly)
{
FSceneInterface* Scene = SceneCaptureComponent->GetWorld()->Scene;
FIntPoint CaptureSize(TextureTarget->GetSurfaceWidth(), TextureTarget->GetSurfaceHeight());
FTextureRenderTargetResource* Resource = TextureTarget->GameThread_GetRenderTargetResource();
FSceneViewFamily::ConstructionValues ConstructionValues(
Resource,
Scene,
SceneCaptureComponent->ShowFlags);
ConstructionValues.SetResolveScene(!bCaptureSceneColour);
FSceneViewFamilyContext ViewFamily(ConstructionValues);
FSceneViewInitOptions ViewInitOptions;
ViewInitOptions.SetViewRectangle(FIntRect(0, 0, CaptureSize.X, CaptureSize.Y));
ViewInitOptions.ViewFamily = &ViewFamily;
ViewInitOptions.ViewOrigin = ViewLocation;
ViewInitOptions.ViewRotationMatrix = ViewRotationMatrix;
ViewInitOptions.BackgroundColor = FLinearColor::Black;
ViewInitOptions.OverrideFarClippingPlaneDistance = MaxViewDistance;
ViewInitOptions.SceneViewStateInterface = SceneCaptureComponent->GetViewState();
if (bCaptureSceneColour)
{
ViewFamily.EngineShowFlags.PostProcessing = 0;
ViewInitOptions.OverlayColor = FLinearColor::Black;
}
ViewInitOptions.ProjectionMatrix = ProjectionMatrix;
FSceneView* View = new FSceneView(ViewInitOptions);
View->bIsSceneCapture = true;
check(SceneCaptureComponent);
if (bDrawHiddenOnly)
{
for (auto It = SceneCaptureComponent->HiddenComponents.CreateConstIterator(); It; ++It)
{
// If the primitive component was destroyed, the weak pointer will return NULL.
UPrimitiveComponent* PrimitiveComponent = It->Get();
if (PrimitiveComponent)
{
View->ShowPrimitives.Add(PrimitiveComponent->ComponentId);
}
}
}
else
{
for (auto It = SceneCaptureComponent->HiddenComponents.CreateConstIterator(); It; ++It)
{
// If the primitive component was destroyed, the weak pointer will return NULL.
UPrimitiveComponent* PrimitiveComponent = It->Get();
if (PrimitiveComponent)
{
View->HiddenPrimitives.Add(PrimitiveComponent->ComponentId);
}
}
}
ViewFamily.Views.Add(View);
View->StartFinalPostprocessSettings(ViewLocation);
View->OverridePostProcessSettings(*PostProcessSettings, PostProcessBlendWeight);
View->EndFinalPostprocessSettings(ViewInitOptions);
return FSceneRenderer::CreateSceneRenderer(&ViewFamily, NULL);
}
We Add ShowPrimitives in SceneView.h
/** The primitives which are show for this view **/
TSet<FPrimitiveComponentId> ShowPrimitives;
And Modify SceneVisbility.cpp
void FSceneRenderer::ComputeViewVisibility(FRHICommandListImmediate& RHICmdList)
// If any primitives are explicitly show, hide others.
if (View.ShowPrimitive.Num())
{
for (FSceneSetBitIterator BitIt(View.PrimitiveVisibilityMap); BitIt; ++BitIt)
{
if (View.ShowPrimitives.Contains(Scene->PrimitiveComponentIds[BitIt.GetIndex()]))
{
View.PrimitiveVisibilityMap.AccessCorrespondingBit(BitIt) = true;
}
else
{
View.PrimitiveVisibilityMap.AccessCorrespondingBit(BitIt) = false;
}
}
}
// If any primitives are explicitly hidden, remove them now.
if (View.HiddenPrimitives.Num())
{
for (FSceneSetBitIterator BitIt(View.PrimitiveVisibilityMap); BitIt; ++BitIt)
{
if (View.HiddenPrimitives.Contains(Scene->PrimitiveComponentIds[BitIt.GetIndex()]))
{
View.PrimitiveVisibilityMap.AccessCorrespondingBit(BitIt) = false;
}
}
}
now we can let SceneCaptureComponent2D has Alpha Channel