Your code works. Not sure where the problem is. Maybe something is happening during the saving of the asset?
Example code I made based on it
ImageFunctionLibrary.cpp
// Fill out your copyright notice in the Description page of Project Settings.
#include "ImageFunctionLibrary.h"
UTexture2D* UImageFunctionLibrary::GeneratePerlin(int32 textureWidth, int32 textureHeight)
{
UTexture2D* NewTexture = UTexture2D::CreateTransient(textureWidth, textureHeight);
FTexturePlatformData* PlatformData = NewTexture->GetPlatformData();
FTexture2DMipMap* MipMap = &PlatformData->Mips[0];
MipMap->BulkData.Lock(LOCK_READ_WRITE);
uint8* RawImageData = (uint8*)MipMap->BulkData.Realloc(textureWidth * textureHeight * 4);
int32 numPixels = textureWidth * textureHeight;
for (int32 x = 0; x < numPixels; x++)
{
FColor RandomColor = FColor::MakeRandomColor();
RawImageData[4 * x] = RandomColor.B;
RawImageData[4 * x + 1] = RandomColor.G;
RawImageData[4 * x + 2] = RandomColor.R;
RawImageData[4 * x + 3] = 255;
}
MipMap->BulkData.Unlock();
NewTexture->UpdateResource();
return NewTexture;
}
.h
#pragma once
#include "CoreMinimal.h"
#include "Kismet/BlueprintFunctionLibrary.h"
#include "Engine/Texture2D.h"
#include "ImageFunctionLibrary.generated.h"
/**
*
*/
UCLASS()
class YOUR_API UImageFunctionLibrary : public UBlueprintFunctionLibrary
{
GENERATED_BODY()
UFUNCTION(BlueprintCallable)
static UTexture2D* GeneratePerlin(int32 textureWidth = 512, int32 textureHeight = 512);
};
Editor widget
Generation in engine
Double check if your UV map of the target mesh is not throwing off your results.


