summaryrefslogtreecommitdiff
path: root/Runtime/Graphics/ProceduralTexture.h
blob: 94740a7b713384cc66a3d79a27b074627206bbdf (plain)
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");
}