ue4.26 CurveLinearColorAtlas支持非正方形尺寸

默认CurveAtlas只能是正方形

 

改代码可以让它支持非正方形:

 改法如下:

CurveLinearColorAtlas.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
// Copyright Epic Games, Inc. All Rights Reserved.
 
#pragma once
#include "CoreMinimal.h"
#include "UObject/ObjectMacros.h"
#include "UObject/Object.h"
#include "Engine/EngineTypes.h"
#include "Engine/Texture.h"
#include "Engine/World.h"
#include "Engine/Texture2D.h"
#include "CurveLinearColorAtlas.generated.h"
 
 
static FName NAME_GradientTexture = FName(TEXT("GradientTexture"));
static FName NAME_GradientBias = FName(TEXT("GradientBias"));
static FName NAME_GradientScale = FName(TEXT("GradientScale"));
static FName NAME_GradientCount = FName(TEXT("GradientCount"));
 
class UCurveLinearColor;
class UCurveBase;
 
 
/**
*  Manages gradient LUT textures for registered actors and assigns them to the corresponding materials on the actor
*/
UCLASS()
class ENGINE_API UCurveLinearColorAtlas : public UTexture2D
{
    GENERATED_UCLASS_BODY()
 
#if WITH_EDITOR
    virtual void PostEditChangeProperty(struct FPropertyChangedEvent& PropertyChangedEvent) override;
 
    // How many slots are available per texture
    FORCEINLINE uint32 MaxSlotsPerTexture()
    {
        return TextureSize;
    }
 
    // Immediately render a new material to the specified slot index(SlotIndex must be within this section's range)
    void OnCurveUpdated(UCurveBase* Curve, EPropertyChangeType::Type ChangeType);
 
    // Re-render all texture groups
    void UpdateTextures();
#endif
 
    virtual void PostLoad() override;
 
    bool GetCurveIndex(UCurveLinearColor* InCurve, int32& Index);
 
    UFUNCTION(BlueprintCallable, Category = "Math|Curves")
    bool GetCurvePosition(UCurveLinearColor* InCurve, float& Position);
 
#if WITH_EDITORONLY_DATA
    UPROPERTY()
    uint32 bIsDirty : 1;
 
    uint32  bHasAnyDirtyTextures : 1;
    uint32  bShowDebugColorsForNullGradients : 1;   // Renders alternate blue/yellow lines for empty gradients. Good for debugging, but turns off optimization for selective updates to gradients.
 
    TArray<FFloat16Color> SrcData;
#endif
    UPROPERTY(EditAnywhere, Category = "Curves")
    uint32  TextureSize;                        // Size of the lookup textures
    //yang chao begin
    UPROPERTY(EditAnywhere, Category = "Curves")
        uint32  TextureSizeX;  
    //yang chao end
 
    UPROPERTY(EditAnywhere, Category = "Curves")
    TArray<UCurveLinearColor*> GradientCurves;
 
protected:
#if WITH_EDITORONLY_DATA
    FVector2D SizeXY;
#endif
};

  

CurveLinearColorAtlas.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
// Copyright Epic Games, Inc. All Rights Reserved.
 
/*=============================================================================
    UCurveLinearColorAtlas.cpp
=============================================================================*/
 
#include "Curves/CurveLinearColorAtlas.h"
#include "Curves/CurveLinearColor.h"
#include "Components/MeshComponent.h"
#include "Materials/MaterialInstanceDynamic.h"
 
 
UCurveLinearColorAtlas::UCurveLinearColorAtlas(const FObjectInitializer& ObjectInitializer)
    : Super(ObjectInitializer)
{
    TextureSize = 256;
    TextureSizeX = 256;//yang chao
#if WITH_EDITORONLY_DATA
    bHasAnyDirtyTextures = false;
    bShowDebugColorsForNullGradients = false;
    SizeXY = { (float)TextureSizeX,  1.0f };//yang chao modify TextueSize to TextureSizeX
    MipGenSettings = TMGS_NoMipmaps;
#endif
    Filter = TextureFilter::TF_Bilinear;
    SRGB = false;
    AddressX = TA_Clamp;
    AddressY = TA_Clamp;
    CompressionSettings = TC_HDR;
}
#if WITH_EDITOR
void UCurveLinearColorAtlas::PostEditChangeProperty(struct FPropertyChangedEvent& PropertyChangedEvent)
{
    Super::PostEditChangeProperty(PropertyChangedEvent);
    // Determine whether any property that requires recompression of the texture, or notification to Materials has changed.
    bool bRequiresNotifyMaterials = false;
 
    if (PropertyChangedEvent.Property != nullptr)
    {
        const FName PropertyName(PropertyChangedEvent.Property->GetFName());
        // if Resizing
        if (PropertyName == GET_MEMBER_NAME_CHECKED(UCurveLinearColorAtlas, TextureSize)
            || PropertyName == GET_MEMBER_NAME_CHECKED(UCurveLinearColorAtlas, TextureSizeX)//yang chao
            )
        {
            if ((uint32)GradientCurves.Num() > TextureSize)
            {
                int32 OldCurveCount = GradientCurves.Num();
                GradientCurves.RemoveAt(TextureSize, OldCurveCount - TextureSize);
            }
 
            Source.Init(TextureSizeX, TextureSize, 1, 1, TSF_RGBA16F);//yang chao modify TextueSize to TextureSizeX
 
            SizeXY = { (float)TextureSizeX, 1.0f };//yang chao modify TextueSize to TextureSizeX
            UpdateTextures();
            bRequiresNotifyMaterials = true;
        }
        if (PropertyName == GET_MEMBER_NAME_CHECKED(UCurveLinearColorAtlas, GradientCurves))
        {
            if ((uint32)GradientCurves.Num() > TextureSize)
            {
                int32 OldCurveCount = GradientCurves.Num();
                GradientCurves.RemoveAt(TextureSize, OldCurveCount - TextureSize);
            }
            else
            {
                for (int32 i = 0; i < GradientCurves.Num(); ++i)
                {
                    if (GradientCurves[i] != nullptr)
                    {
                        GradientCurves[i]->OnUpdateCurve.AddUObject(this, &UCurveLinearColorAtlas::OnCurveUpdated);
                    }
                }
                UpdateTextures();
                bRequiresNotifyMaterials = true;
            }
        }  
    }
 
    // Notify any loaded material instances if changed our compression format
    if (bRequiresNotifyMaterials)
    {
        NotifyMaterials();
    }
}
#endif
 
void UCurveLinearColorAtlas::PostLoad()
{
#if WITH_EDITOR
    if (FApp::CanEverRender())
    {
        FinishCachePlatformData();
    }
 
    for (int32 i = 0; i < GradientCurves.Num(); ++i)
    {
        if (GradientCurves[i] != nullptr)
        {
            GradientCurves[i]->OnUpdateCurve.AddUObject(this, &UCurveLinearColorAtlas::OnCurveUpdated);
        }
    }
    Source.Init(TextureSizeX, TextureSize, 1, 1, TSF_RGBA16F);//yang chao modify TextueSize to TextureSizeX
    SizeXY = { (float)TextureSizeX, 1.0f };//yang chao modify TextueSize to TextureSizeX
    UpdateTextures();
#endif
 
    Super::PostLoad();
}
 
#if WITH_EDITOR
static void RenderGradient(TArray<FFloat16Color>& InSrcData, UObject* Gradient, int32 StartXY, FVector2D SizeXY)
{
    if (Gradient == nullptr)
    {
        int32 Start = StartXY;
        for (uint32 y = 0; y < SizeXY.Y; y++)
        {
            // Create base mip for the texture we created.
            for (uint32 x = 0; x < SizeXY.X; x++)
            {
                InSrcData[Start + x + y * SizeXY.X] = FLinearColor::White;
            }
        }
    }
    else if (Gradient->IsA(UCurveLinearColor::StaticClass()))
    {
        // Render a gradient
        UCurveLinearColor* GradientCurve = CastChecked<UCurveLinearColor>(Gradient);
        GradientCurve->PushToSourceData(InSrcData, StartXY, SizeXY);
    }
}
 
static void UpdateTexture(UCurveLinearColorAtlas& Atlas)
{
    const int32 TextureDataSize = Atlas.Source.CalcMipSize(0);
 
    FGuid MD5Guid;
    FMD5 MD5;
    MD5.Update(reinterpret_cast<const uint8*>(Atlas.SrcData.GetData()), TextureDataSize);
    MD5.Final(reinterpret_cast<uint8*>(&MD5Guid));
 
    uint32* TextureData = reinterpret_cast<uint32*>(Atlas.Source.LockMip(0));
    FMemory::Memcpy(TextureData, Atlas.SrcData.GetData(), TextureDataSize);
    Atlas.Source.UnlockMip(0);
 
    Atlas.Source.SetId(MD5Guid, /*bInGuidIsHash*/ true);
    Atlas.UpdateResource();
}
 
// Immediately render a new material to the specified slot index (SlotIndex must be within this section's range)
void UCurveLinearColorAtlas::OnCurveUpdated(UCurveBase* Curve, EPropertyChangeType::Type ChangeType)
{
    if (ChangeType != EPropertyChangeType::Interactive)
    {
        UCurveLinearColor* Gradient = CastChecked<UCurveLinearColor>(Curve);
 
        int32 SlotIndex = GradientCurves.Find(Gradient);
 
        if (SlotIndex != INDEX_NONE && (uint32)SlotIndex < MaxSlotsPerTexture())
        {
            // Determine the position of the gradient
            int32 StartXY = SlotIndex * TextureSize;
 
            // Render the single gradient to the render target
            RenderGradient(SrcData, Gradient, StartXY, SizeXY);
 
            UpdateTexture(*this);
        }
    }  
}
 
// Render any textures
void UCurveLinearColorAtlas::UpdateTextures()
{
    // Save off the data needed to render each gradient.
    // Callback into the section owner to get the Gradients array
    const int32 TextureDataSize = Source.CalcMipSize(0);
    SrcData.Empty();
    SrcData.AddUninitialized(TextureDataSize);
 
    int32 NumSlotsToRender = FMath::Min(GradientCurves.Num(), (int32)MaxSlotsPerTexture());
    for (int32 i = 0; i < NumSlotsToRender; ++i)
    {
        if (GradientCurves[i] != nullptr)
        {
            int32 StartXY = i * TextureSizeX;//yang chao modify TextueSize to TextureSizeX
            RenderGradient(SrcData, GradientCurves[i], StartXY, SizeXY);
        }
 
    }
 
    for (uint32 y = 0; y < TextureSizeX; y++)//yang chao modify TextueSize to TextureSizeX
    {
        // Create base mip for the texture we created.
        for (uint32 x = GradientCurves.Num(); x < TextureSize; x++)
        {
            SrcData[x*TextureSizeX + y] = FLinearColor::White;//yang chao modify TextueSize to TextureSizeX
        }
    }
 
    UpdateTexture(*this);
 
    bIsDirty = false;
}
 
#endif
 
bool UCurveLinearColorAtlas::GetCurveIndex(UCurveLinearColor* InCurve, int32& Index)
{
    Index = GradientCurves.Find(InCurve);
    if (Index != INDEX_NONE)
    {
        return true;
    }
    return false;
}
 
bool UCurveLinearColorAtlas::GetCurvePosition(UCurveLinearColor* InCurve, float& Position)
{
    int32 Index = GradientCurves.Find(InCurve);
    Position = 0.0f;
    if (Index != INDEX_NONE)
    {
        Position = (float)Index;
        return true;
    }
    return false;
}

  

--补充:

看了下ue5.0的文档,已经支持非正方形了:(面板上有squre resolution勾选,下面有texture height)

Curve Atlases in Unreal Engine Materials | Unreal Engine 5.0 Documentation

 

posted on   wantnon  阅读(62)  评论(0编辑  收藏  举报

相关博文:
阅读排行:
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 提示词工程——AI应用必不可少的技术
· Open-Sora 2.0 重磅开源!
· 字符编码:从基础到乱码解决
历史上的今天:
2015-01-28 cocos2dx 3.x 避免空sprite

导航

< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5
点击右上角即可分享
微信分享提示