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
|
#pragma once
#include "Configuration/UnityConfigure.h"
#include "Runtime/Utilities/dynamic_array.h"
#include "Texture.h"
#include "External/Allegorithmic/builds/Engines/include/substance/handle.h"
class ColorRGBAf;
class ColorRGBA32;
class ProceduralMaterial;
enum ProceduralOutputType
{
Substance_OType_Unknown = 0,
Substance_OType_Diffuse,
Substance_OType_Normal,
Substance_OType_Height,
Substance_OType_Emissive,
Substance_OType_Specular,
Substance_OType_Opacity,
ProceduralOutputType_Count
};
enum SubstanceOutputFormat
{
Substance_OFormat_Compressed = 0,
Substance_OFormat_Raw
};
/* A ProceduralTexture is a dynamic texture generated by the Substance engine.
* It's part of a Substance graph hierarchy, compound of ProceduralMaterial, SubstanceArchive.
*/
class ProceduralTexture : public Texture
{
public:
// Uploaded texture parameters
struct TextureParameters
{
DECLARE_SERIALIZE(TextureParameters)
int width;
int height;
int mipLevels;
TextureFormat textureFormat;
bool IsValid () const { return width != 0; }
friend bool operator == (const TextureParameters& lhs, const TextureParameters& rhs)
{
return lhs.width == rhs.width && lhs.height == rhs.height && lhs.mipLevels == rhs.mipLevels && lhs.textureFormat == rhs.textureFormat;
}
TextureParameters ();
TextureParameters (int inWidth, int inHeight, int inMipLevels, TextureFormat inFormat);
void Invalidate() { *this = TextureParameters(); }
};
// Flags
enum Flag
{
Flag_Binded = 1<<0, // the output is altered by an input
Flag_Uploaded = 1<<1, // the data has been uploaded
Flag_AwakeClone = 1<<2, // the texture need awake from clone
Flag_Cached = 1<<3 // the texture has been cached, editor flag only
};
// Upload State
enum UploadState
{
UploadState_None, // no data has been uploaded
UploadState_Waiting, // blue waiting texture
UploadState_Valid, // lower states indicate the current uploaded data isn't valid
UploadState_Baked, // baked texture
UploadState_Generated // generated texture
};
protected: // FIELDS
PPtr<ProceduralMaterial> m_SubstanceMaterial; // The parent procedural material from which we get generated
ProceduralMaterial* m_PingedMaterial; // The pinged procedural material
UInt64 m_SubstanceTextureUID; // The index of this texture (i.e. Substance output) WORD[shuffledID,baseID]
unsigned int m_SubstancePreShuffleUID; // This ID is required to use substanceLinkerHandleSelectOutputs
ProceduralOutputType m_Type;
ProceduralOutputType m_AlphaSource;
unsigned int m_Flags;
UploadState m_UploadState;
SubstanceOutputFormat m_Format;
TextureFormat m_SubstanceFormat; // Platform dependant format required for substance generation
TextureParameters m_TextureParameters;
std::vector<UInt8> m_BakedData; // Baked texture if substance isn't supported
TextureParameters m_BakedParameters;
TextureID m_ClonedID; // Link to the source ID when cloned and not generated
public: // METHODS
REGISTER_DERIVED_CLASS( ProceduralTexture, Texture )
DECLARE_OBJECT_SERIALIZE( ProceduralTexture )
ProceduralTexture( MemLabelId label, ObjectCreationMode mode );
#if ENABLE_SUBSTANCE
ProceduralTexture* Clone(ProceduralMaterial* owner);
void AwakeClone();
#endif
virtual int GetDataWidth() const { return m_TextureParameters.width; }
virtual int GetDataHeight() const { return m_TextureParameters.height; }
TextureFormat GetDataFormat() const { return m_TextureParameters.textureFormat; }
int GetDataMipLevels() const { return m_TextureParameters.mipLevels; }
virtual TextureDimension GetDimension () const { return kTexDim2D; }
virtual bool HasMipMap () const { return m_TextureParameters.mipLevels != 1; }
virtual int CountMipmaps() const { return m_TextureParameters.mipLevels; }
const ProceduralOutputType& GetType() const { return m_Type; }
const ProceduralOutputType& GetAlphaSource() const { return m_AlphaSource; }
bool IsFlagEnabled(const Flag& flag) const { return m_Flags & (unsigned int)flag; }
void EnableFlag(const Flag& flag, bool enabled=true) { if (enabled) m_Flags |= (unsigned int)flag; else m_Flags &= ~(unsigned int)flag; }
#if ENABLE_PROFILER
virtual int GetStorageMemorySize() const { return m_TextureParameters.width * m_TextureParameters.height; }
#endif
virtual bool ExtractImage (ImageReference* image, int imageIndex = 0) const { return false; }
virtual void UnloadFromGfxDevice(bool forceUnloadAll);
virtual void UploadToGfxDevice();
void RemoveTexture ();
void UploadWaitingTexture ();
void UploadBakedTexture ();
// Gets the output texture UID (i.e. output UID for the Substance engine)
unsigned int GetSubstanceTextureUID() const { return m_SubstanceTextureUID & 0xffffffff; }
unsigned int GetSubstanceBaseTextureUID() const { return (m_SubstanceTextureUID >> 32); }
void SetSubstancePreShuffleUID(unsigned int id) { m_SubstancePreShuffleUID = id; }
unsigned int GetSubstancePreShuffleUID() const { return m_SubstancePreShuffleUID; }
// Set the UIDs
// (Don't call externally though !)
void SetSubstanceShuffledUID(unsigned int textureUID);
void SetSubstanceFormat(TextureFormat format) { m_SubstanceFormat = format; }
TextureFormat GetSubstanceFormat() const { return m_SubstanceFormat; }
virtual void AwakeFromLoadThreaded();
virtual void AwakeFromLoad( AwakeFromLoadMode awakeMode );
virtual bool ShouldIgnoreInGarbageDependencyTracking () { return false; }
// (Don't call externally though !)
void UploadSubstanceTexture(SubstanceTexture& outputTexture);
bool HasBeenGenerated() const { return m_UploadState==UploadState_Generated; }
bool HasBeenUploaded() const { return (m_UploadState==UploadState_Generated) || (m_UploadState==UploadState_Baked); }
#if UNITY_EDITOR
// Creates the texture (one time call only by importer)
void Init( ProceduralMaterial& _Parent, int _TextureIndex, ProceduralOutputType type, SubstanceOutputFormat format, ProceduralOutputType alphaSource, bool requireCompressed );
const TextureParameters& GetTextureParameters() const { return m_TextureParameters; }
TextureParameters& GetTextureParameters() { return m_TextureParameters; }
virtual TextureFormat GetEditorUITextureFormat () const { return m_TextureParameters.textureFormat; }
#endif
bool IsBaked() const;
std::vector<UInt8>& GetBakedData() { return m_BakedData; }
const TextureParameters& GetBakedParameters() const { return m_BakedParameters; }
TextureParameters& GetBakedParameters() { return m_BakedParameters; }
bool GetPixels32(int x, int y, int width, int height, ColorRGBA32* data);
bool IsValid() { return m_TextureParameters.IsValid(); }
void Invalidate();
void SetOwner(ProceduralMaterial* material);
ProceduralMaterial* GetSubstanceMaterial() { return m_PingedMaterial; }
#if UNITY_EDITOR
PPtr<ProceduralMaterial>& GetSubstanceMaterialPtr() { return m_SubstanceMaterial; }
#endif
};
template<class T>
void ProceduralTexture::TextureParameters::Transfer(T& transfer)
{
TRANSFER(width);
TRANSFER(height);
TRANSFER(mipLevels);
transfer.Transfer(reinterpret_cast<int&> (textureFormat), "textureFormat");
}
|