19
19
// ReSharper disable CheckNamespace
20
20
21
21
using System ;
22
+ using System . Globalization ;
23
+ using System . Linq ;
24
+ using System . Reflection ;
22
25
using System . Text ;
26
+ using NLog ;
27
+ using UnityEditor ;
23
28
using UnityEngine ;
24
29
using VisualPinball . Engine . VPT ;
25
30
using VisualPinball . Unity ;
31
+ using Logger = NLog . Logger ;
26
32
using Material = UnityEngine . Material ;
33
+ using Object = UnityEngine . Object ;
27
34
28
35
namespace VisualPinball . Engine . Unity . Hdrp
29
36
{
@@ -43,9 +50,17 @@ public class MaterialConverter : IMaterialConverter
43
50
private static readonly int NormalMap = Shader . PropertyToID ( "_NormalMap" ) ;
44
51
private static readonly int UVChannelVertices = Shader . PropertyToID ( "_UVChannelVertices" ) ;
45
52
private static readonly int UVChannelNormals = Shader . PropertyToID ( "_UVChannelNormals" ) ;
53
+ private static readonly int DiffusionProfileAsset = Shader . PropertyToID ( "_DiffusionProfileAsset" ) ;
54
+ private static readonly int DiffusionProfileHash = Shader . PropertyToID ( "_DiffusionProfileHash" ) ;
55
+ private static readonly int MaterialID = Shader . PropertyToID ( "_MaterialID" ) ;
46
56
47
57
#endregion
48
58
59
+ private const string DiffusionProfilePlastic = "Packages/org.visualpinball.unity.assetlibrary/Assets/Settings/DiffusionProfiles/Plastic/PET_PETG.asset" ;
60
+
61
+ private static readonly Logger Logger = LogManager . GetCurrentClassLogger ( ) ;
62
+
63
+
49
64
public Shader GetShader ( )
50
65
{
51
66
return Shader . Find ( "HDRP/Lit" ) ;
@@ -114,8 +129,7 @@ public Material CreateMaterial(PbrMaterial vpxMaterial, ITextureProvider texture
114
129
115
130
unityMaterial . SetFloat ( Metallic , metallicValue ) ;
116
131
117
- // roughness / glossiness
118
- unityMaterial . SetFloat ( Smoothness , vpxMaterial . Roughness ) ;
132
+ SetSmoothness ( unityMaterial , vpxMaterial . Roughness ) ;
119
133
120
134
// map
121
135
if ( vpxMaterial . HasMap && textureProvider != null ) {
@@ -130,9 +144,21 @@ public Material CreateMaterial(PbrMaterial vpxMaterial, ITextureProvider texture
130
144
unityMaterial . SetTexture ( NormalMap , textureProvider . GetTexture ( vpxMaterial . NormalMap . Name ) ) ;
131
145
}
132
146
147
+ // diffusion profile
148
+ if ( vpxMaterial . DiffusionProfile != DiffusionProfileTemplate . None ) {
149
+ SetDiffusionProfile ( unityMaterial , vpxMaterial . DiffusionProfile ) ;
150
+ }
151
+
152
+ SetMaterialType ( unityMaterial , vpxMaterial . MaterialType ) ;
153
+
133
154
return unityMaterial ;
134
155
}
135
156
157
+ public void SetSmoothness ( Material unityMaterial , float smoothness )
158
+ {
159
+ unityMaterial . SetFloat ( Smoothness , smoothness ) ;
160
+ }
161
+
136
162
public Material MergeMaterials ( PbrMaterial vpxMaterial , Material texturedMaterial )
137
163
{
138
164
var nonTexturedMaterial = CreateMaterial ( vpxMaterial , null , null ) ;
@@ -146,5 +172,62 @@ public Material MergeMaterials(PbrMaterial vpxMaterial, Material texturedMateria
146
172
147
173
return mergedMaterial ;
148
174
}
175
+
176
+ public void SetDiffusionProfile ( Material material , DiffusionProfileTemplate template )
177
+ {
178
+ #if UNITY_EDITOR
179
+
180
+ var diffusionProfilePath = template switch {
181
+ DiffusionProfileTemplate . Plastics => DiffusionProfilePlastic ,
182
+ _ => throw new ArgumentOutOfRangeException ( nameof ( template ) , template , "Invalid diffusion profile." )
183
+ } ;
184
+
185
+ // unity, why tf would you make DiffusionProfileSettings internal!?!
186
+ var diffusionProfile = AssetDatabase . LoadAssetAtPath < Object > ( diffusionProfilePath ) ;
187
+
188
+ if ( diffusionProfile != null ) {
189
+
190
+ // need to get those through reflection..
191
+ var profile = diffusionProfile . GetType ( ) . GetRuntimeFields ( ) . First ( f => f . Name == "profile" ) . GetValue ( diffusionProfile ) ;
192
+ var profileHash = ( uint ) profile . GetType ( ) . GetRuntimeFields ( ) . First ( f => f . Name == "hash" ) . GetValue ( profile ) ;
193
+
194
+ var guid = AssetDatabase . AssetPathToGUID ( diffusionProfilePath ) ;
195
+ var newGuid = ConvertGUIDToVector4 ( guid ) ;
196
+ var hash = AsFloat ( profileHash ) ;
197
+
198
+ // encode back GUID and it's hash
199
+ material . SetVector ( DiffusionProfileAsset , newGuid ) ;
200
+ material . SetFloat ( DiffusionProfileHash , hash ) ;
201
+
202
+ } else {
203
+ Logger . Warn ( $ "Could not load diffusion profile at { diffusionProfilePath } ") ;
204
+ }
205
+
206
+ #endif
207
+ }
208
+
209
+ public void SetMaterialType ( Material material , MaterialType materialType )
210
+ {
211
+ material . SetFloat ( MaterialID , ( int ) materialType ) ;
212
+ }
213
+
214
+ private static Vector4 ConvertGUIDToVector4 ( string guid )
215
+ {
216
+ Vector4 vector ;
217
+ byte [ ] bytes = new byte [ 16 ] ;
218
+
219
+ for ( int i = 0 ; i < 16 ; i ++ )
220
+ bytes [ i ] = byte . Parse ( guid . Substring ( i * 2 , 2 ) , NumberStyles . HexNumber ) ;
221
+
222
+ unsafe
223
+ {
224
+ fixed ( byte * b = bytes )
225
+ vector = * ( Vector4 * ) b ;
226
+ }
227
+
228
+ return vector ;
229
+ }
230
+
231
+ private static float AsFloat ( uint val ) { unsafe { return * ( ( float * ) & val ) ; } }
149
232
}
150
233
}
0 commit comments