Hello everyone, I’m trying to create own “viewport” with image of mesh. For this, I created child class of SCompoundWidget with SImage within. I using SceneCaptureComponent for transffer texture from TextureRenderTarget to SImage(using FSlateBrush).
This is code setup capture component:
SceneCaptureComponent = NewObject<USceneCaptureComponent2D>(ViewportCharacter, USceneCaptureComponent2D::StaticClass(), TEXT("ViewportSceneCapture"));
SceneCaptureComponent->TextureTarget = TextureRenderTarget;
SceneCaptureComponent->bCaptureEveryFrame = true;
SceneCaptureComponent->SetTickableWhenPaused(true);
SceneCaptureComponent->ProjectionType = ECameraProjectionMode::Orthographic;
SceneCaptureComponent->OrthoWidth = bMinOrthoWidth;
SceneCaptureComponent->RegisterComponent();
SceneCaptureComponent->SnapTo(RootComponent); // root - it is mesh
SceneCaptureComponent->UpdateContent();
This is code setup TextureRenderTarget:
TextureRenderTarget = NewObject<UTextureRenderTarget2D>(UTextureRenderTarget2D::StaticClass());
TextureRenderTarget->bHDR = false;
TextureRenderTarget->TargetGamma = GEditor->GetDisplayGamma();
TextureRenderTarget->ClearColor = FLinearColor::Black;
TextureRenderTarget->InitAutoFormat(bSize.X, bSize.Y); //auto init from value bHDR
After init, I waiting first call method Tick:
void FSSkeletonEditorViewport::Tick(const FGeometry& AllottedGeometry, const double InCurrentTime, const float InDeltaTime)
{
UpdateSizeViewport(AllottedGeometry); // checks whether viewport size change, if true bUpdateRenderTarget = true, and updating bSize
if (bUpdateRenderTarget)
{
UpdateTexture(Texture, TextureRenderTarget);
CreateWidget(); // create SImage and paste in "Viewport"
}
}
Where call my own method UpdateTexture which contains code:
void FSSkeletonEditorViewport::UpdateTexture(UTexture2D* InTexture, UTextureRenderTarget2D* TextureRenderTarget)
{
bUpdateRenderTarget = false;
float PrevSizeX = TextureRenderTarget->SizeX;
float PrevSizeY = TextureRenderTarget->SizeY;
float Epsilon = 0.9;
if ((PrevSizeX - bSize.X) > Epsilon)
{
bUpdateRenderTarget = true;
SceneCaptureComponent->UpdateContent();
TextureRenderTarget->UpdateResourceImmediate(false);
}
else if ((PrevSizeY - bSize.Y) > Epsilon)
{
bUpdateRenderTarget = true;
SceneCaptureComponent->UpdateContent();
TextureRenderTarget->UpdateResourceImmediate(false);
}
TextureRenderTarget->SizeX = bSize.X; // bSize - size of "viewport"
TextureRenderTarget->SizeY = bSize.Y;
FTextureRenderTargetResource* RTResource = TextureRenderTarget->GameThread_GetRenderTargetResource();
FReadSurfaceDataFlags ReadPixelFlags(RCM_MinMaxNorm);
ReadPixelFlags.SetLinearToGamma(true);
TArray<FColor> SurfData;
RTResource->ReadPixels(SurfData, ReadPixelFlags);
for (FColor& color : SurfData)
{
color.A = 255;
}
// Lock and copies the data between the textures
void* TextureData = InTexture->PlatformData->Mips[0].BulkData.Lock(LOCK_READ_WRITE);
const int32 TextureDataSize = SurfData.Num() * 4;
FMemory::Memcpy(TextureData, SurfData.GetData(), TextureDataSize);
InTexture->PlatformData->Mips[0].BulkData.Unlock();
// Apply Texture changes to GPU memory
InTexture->UpdateResource();
}
Every tick checks need update TextureRenderTarget or not, UpdateTexture method call when viewport has been stretched or compressed, when I changing size of TextureRenderTarget in method UpdateTexture:
TextureRenderTarget->SizeX = bSize.X; // bSize - size of "viewport"
TextureRenderTarget->SizeY = bSize.Y;
However, resulting image is not updated, it is stretched or compressed.
It is normal state(1):
It is stratched state, when LBM is not released(2):
It is stratched state, when LBM is released(3):
It is comprassed state(4):
**Based on all this, I have two problems:
- Image is updated incorrectly.
- Image is not updating, when I changing size of viewport(stretching or compressing)**
How can solve them? I trying solve them about two weeks, cannot find any documentation for setup TextureRenderTarget2D and SceneCaptureComponent2D in C++.
Thank you in advance.