0
\$\begingroup\$

I have a TArray of type FColor (I got it from the viewport) and I want to change that to a Texture2D object I can't find anything in the API's and I'm new to Unreal.

Thanks

\$\endgroup\$
  • 1
    \$\begingroup\$ Change it to a Texture2D - do you mean dynamically make a texture from the array of colors? If so, this is not a trivial task. What are you trying to achieve by doing this? \$\endgroup\$ – JonS Apr 8 '18 at 12:51
  • \$\begingroup\$ I was trying to generate a texture from the viewport to be used on an object. I think render target is the way to do it but I still want to know how I can change a bitmap (TArray<FColor>) to a Texture2D \$\endgroup\$ – user3927312 Apr 10 '18 at 23:05
  • \$\begingroup\$ Yes a rendertarget is a good way to do that. Bear in mind that while editor and runtime can create a rendertarget image, only the editor can save the image. Beyond that, actually writing a new Texture2D is likely to need C++ code - unless there's a sneaky way via materials and HLSL code. \$\endgroup\$ – JonS Apr 11 '18 at 5:54
  • \$\begingroup\$ I don't mind C++ I just don't know where to look in the docs \$\endgroup\$ – user3927312 Apr 12 '18 at 2:11
  • \$\begingroup\$ The process is kinda hidden. Try reading this, then adapting it for your needs: answers.unrealengine.com/questions/475962/… \$\endgroup\$ – JonS Apr 12 '18 at 23:14
1
\$\begingroup\$

It is possible with C++

Then you should lock its data Memcpy the data And update resources.

Here is a code snippet I am using currently:

    static UTexture2D* CreateTextureFromBGRA(FColor* data, int width, int height)
    {
        UTexture2D* Texture;

        Texture = UTexture2D::CreateTransient(width, height, PF_B8G8R8A8);
        if(!Texture)
        {
            return nullptr;
        }

#if WITH_EDITORONLY_DATA
        Texture->MipGenSettings = TMGS_NoMipmaps;
#endif
        Texture->NeverStream = true;

        Texture->SRGB = 0;

        FTexture2DMipMap& Mip = Texture->PlatformData->Mips[0];
        void* Data = Mip.BulkData.Lock(LOCK_READ_WRITE);

        FMemory::Memcpy(Data, data, width * height * 4);
        Mip.BulkData.Unlock();
        Texture->UpdateResource();

        return Texture;
    }


    static UTexture2D* CreateTextureFromDXT5(uint8* data, int width, int height)
    {
        UTexture2D* Texture;
        Texture = UTexture2D::CreateTransient(width, height, PF_DXT5);

        if (!Texture)
        {
            return nullptr;
        }

#if WITH_EDITORONLY_DATA
        Texture->MipGenSettings = TMGS_NoMipmaps;
#endif
        Texture->NeverStream = true;
        Texture->SRGB = 0;

        FTexture2DMipMap& Mip = Texture->PlatformData->Mips[0];
        void* Data = Mip.BulkData.Lock(LOCK_READ_WRITE);

        int32 NumBlocksX = width / GPixelFormats[PF_DXT5].BlockSizeX;
        int32 NumBlocksY = height / GPixelFormats[PF_DXT5].BlockSizeY;


        FMemory::Memcpy(Data, data, NumBlocksX * NumBlocksY * GPixelFormats[PF_DXT5].BlockBytes);

        Mip.BulkData.Unlock();
        Texture->UpdateResource();

        return Texture;
    }
```
\$\endgroup\$
  • \$\begingroup\$ I think I got around this using a render target after all. Still good to have a fast solution! \$\endgroup\$ – user3927312 Apr 22 at 20:52
  • 1
    \$\begingroup\$ Idk about render target, but this solution shines only if done async to game-thread, the code is thread safe, the only thing is that you will have to remove Async flag from the texture when transferred to game-thread, otherwise it will not get garbage collected. \$\endgroup\$ – ColdSteel Apr 22 at 22:34

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.