This commit is contained in:
2025-11-14 18:44:06 +08:00
parent 10156da245
commit 22e867d077
7013 changed files with 2572882 additions and 1804 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,13 @@
fileFormatVersion: 2
guid: fadcc2d9a34a1a34f93d4962ec37e6e7
timeCreated: 1517223090
licenseType: Store
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,105 @@
// Amplify Impostors
// Copyright (c) Amplify Creations, Lda <info@amplify.pt>
using System.Collections.Generic;
using UnityEngine;
namespace AmplifyImpostors
{
public enum ImpostorType
{
Spherical = 0,
Octahedron = 1,
HemiOctahedron = 2
}
[System.Flags]
public enum DeferredBuffers
{
AlbedoAlpha = 0x1,
SpecularSmoothness = 0x2,
NormalDepth = 0x4,
EmissionOcclusion = 0x8,
}
public enum RenderingMaps
{
Standard = 0,
Custom = 1,
}
[CreateAssetMenu( fileName = "New Impostor", order = 85 )]
[HelpURL( "https://wiki.amplify.pt/index.php?title=Unity_Products:Amplify_Impostors/Manual" )]
public class AmplifyImpostorAsset : ScriptableObject
{
[SerializeField]
public Material Material;
[SerializeField]
public Mesh Mesh;
[HideInInspector]
[SerializeField]
public int Version = 0;
[SerializeField]
public ImpostorType ImpostorType = ImpostorType.Octahedron;
[HideInInspector]
[SerializeField]
public bool LockedSizes = true;
[HideInInspector]
[SerializeField]
public int SelectedSize = 2048;
[SerializeField]
public Vector2 TexSize = new Vector2( 2048, 2048 );
[HideInInspector]
[SerializeField]
public bool DecoupleAxisFrames = false;
[SerializeField]
[Range( 1, 32 )]
public int HorizontalFrames = 16;
[SerializeField]
[Range( 1, 33 )] //check if 33 is needed later
public int VerticalFrames = 16;
[SerializeField]
[Range( 0, 64 )]
public int PixelPadding = 32;
[SerializeField]
[Range( 4, 16 )]
public int MaxVertices = 8;
[SerializeField]
[Range( 0f, 0.2f )]
public float Tolerance = 0.15f;
[SerializeField]
[Range( 0f, 1f )]
public float NormalScale = 0.01f;
[SerializeField]
public Vector2[] ShapePoints = new Vector2[] {
new Vector2(0.15f, 0f),
new Vector2(0.85f, 0f),
new Vector2(1f, 0.15f),
new Vector2(1f, 0.85f),
new Vector2(0.85f, 1f),
new Vector2(0.15f, 1f),
new Vector2(0f, 0.85f),
new Vector2(0f, 0.15f),
};
[SerializeField]
public AmplifyImpostorBakePreset Preset;
[SerializeField]
public List<TextureOutput> OverrideOutput = new List<TextureOutput>();
}
}

View File

@@ -0,0 +1,13 @@
fileFormatVersion: 2
guid: e7ba7a43222473d4292f91ae936fe2cc
timeCreated: 1530191356
licenseType: Store
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,115 @@
// Amplify Impostors
// Copyright (c) Amplify Creations, Lda <info@amplify.pt>
using System.Collections.Generic;
using UnityEngine;
namespace AmplifyImpostors
{
public enum ImageFormat
{
PNG = 0,
TGA = 1,
EXR = 2
}
public enum TextureChannels
{
RGBA = 0,
RGB = 1
}
public enum TextureCompression
{
None = 0,
Normal = 1,
High = 2,
Low = 3,
}
public enum TextureScale
{
Full = 1,
Half = 2,
Quarter = 4,
Eighth = 8,
}
[System.Flags]
public enum OverrideMask
{
OutputToggle = 1 << 0,
NameSuffix = 1 << 1,
RelativeScale = 1 << 2,
ColorSpace = 1 << 3,
QualityCompression = 1 << 4,
FileFormat = 1 << 5,
}
public enum PresetPipeline
{
Legacy = 0,
Lightweight = 1,
HighDefinition = 2
}
[System.Serializable]
public class TextureOutput
{
[SerializeField]
public int Index = -1;
[SerializeField]
public OverrideMask OverrideMask = 0;
public bool Active = true;
public string Name = string.Empty;
public TextureScale Scale = TextureScale.Full;
public bool SRGB = false;
public TextureChannels Channels = TextureChannels.RGBA;
public TextureCompression Compression = TextureCompression.Normal;
public ImageFormat ImageFormat = ImageFormat.TGA;
public TextureOutput() { }
public TextureOutput( bool a, string n, TextureScale s, bool sr, TextureChannels c, TextureCompression nc, ImageFormat i )
{
Active = a;
Name = n;
Scale = s;
SRGB = sr;
Channels = c;
Compression = nc;
ImageFormat = i;
}
public TextureOutput Clone()
{
return (TextureOutput)this.MemberwiseClone();
}
}
[CreateAssetMenu( fileName = "New Bake Preset", order = 86 )]
public class AmplifyImpostorBakePreset : ScriptableObject
{
// 0 => _Albedo(Alpha)
// 1 => _Normals(Depth)
// 2 => _Specular(Smoothness)
// 3 => _Occlusion
// 4 => _Emission
// 5 => _Position
public const int DefaultOutputCount = 6;
[SerializeField]
public Shader BakeShader = null;
[SerializeField]
public Shader RuntimeShader = null;
[SerializeField]
public int AlphaIndex = 0;
[SerializeField]
public List<TextureOutput> Output = new List<TextureOutput>();
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 32f7caa019b8743459b7b0ab1fdc3bae
timeCreated: 1533123553
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,4 @@
{
"name": "AmplifyImpostors.Runtime",
"allowUnsafeCode": true
}

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: a1a7cacb6cec073439a2b2c1849d773b
AssemblyDefinitionImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 77734ff038237eb409985a81c51661db
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,27 @@
// Amplify Impostors
// Copyright (c) Amplify Creations, Lda <info@amplify.pt>
//#define HDRP10
using UnityEngine;
using UnityEngine.Rendering;
namespace AmplifyImpostors
{
public class BakeHDRPTool
{
#if HDRP10
static UnityEngine.Rendering.HighDefinition.ShaderVariablesGlobal g_globalShaderVariables = new UnityEngine.Rendering.HighDefinition.ShaderVariablesGlobal();
public static void SetupShaderVariableGlobals( Matrix4x4 viewMat, Matrix4x4 projMatrix , CommandBuffer commandBuffer )
{
g_globalShaderVariables._ViewMatrix = viewMat;
g_globalShaderVariables._InvViewMatrix = viewMat.inverse;
g_globalShaderVariables._ProjMatrix = projMatrix;
g_globalShaderVariables._ViewProjMatrix = projMatrix * viewMat;
g_globalShaderVariables._WorldSpaceCameraPos_Internal = Vector4.zero;
ConstantBuffer.PushGlobal( commandBuffer, g_globalShaderVariables, UnityEngine.Rendering.HighDefinition.HDShaderIDs._ShaderVariablesGlobal );
}
#else
public static void SetupShaderVariableGlobals( Matrix4x4 viewMat, Matrix4x4 projMatrix , CommandBuffer commandBuffer ){/*This does nothing on HDRP lower that 10*/}
#endif
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: e367a26cc52b15240b9dfc03c3537c16
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,462 @@
// Amplify Impostors
// Copyright (c) Amplify Creations, Lda <info@amplify.pt>
using UnityEngine;
using UnityEngine.Rendering;
#if UNITY_EDITOR
using UnityEditor;
#endif
using System.Reflection;
using System;
using System.IO;
namespace AmplifyImpostors
{
public static class BoundsEx
{
public static Bounds Transform( this Bounds bounds, Matrix4x4 matrix )
{
var center = matrix.MultiplyPoint3x4( bounds.center );
var extents = bounds.extents;
var axisX = matrix.MultiplyVector( new Vector3( extents.x, 0, 0 ) );
var axisY = matrix.MultiplyVector( new Vector3( 0, extents.y, 0 ) );
var axisZ = matrix.MultiplyVector( new Vector3( 0, 0, extents.z ) );
extents.x = Mathf.Abs( axisX.x ) + Mathf.Abs( axisY.x ) + Mathf.Abs( axisZ.x );
extents.y = Mathf.Abs( axisX.y ) + Mathf.Abs( axisY.y ) + Mathf.Abs( axisZ.y );
extents.z = Mathf.Abs( axisX.z ) + Mathf.Abs( axisY.z ) + Mathf.Abs( axisZ.z );
return new Bounds { center = center, extents = extents };
}
}
public static class MaterialEx
{
#if UNITY_EDITOR
public static void CopyPropertiesFrom( this Material to, Material from )
{
int count = from.shader.GetPropertyCount();
for( int i = 0; i < count; i++ )
{
var ty = from.shader.GetPropertyType( i );
var name = from.shader.GetPropertyName( i );
switch( ty )
{
case ShaderPropertyType.Color:
to.SetColor( name, from.GetColor( name ) );
break;
case ShaderPropertyType.Vector:
to.SetVector( name, from.GetVector( name ) );
break;
case ShaderPropertyType.Float:
to.SetFloat( name, from.GetFloat( name ) );
break;
case ShaderPropertyType.Range:
to.SetFloat( name, from.GetFloat( name ) );
break;
case ShaderPropertyType.Texture:
to.SetTexture( name, from.GetTexture( name ) );
to.SetTextureOffset( name, from.GetTextureOffset( name ) );
to.SetTextureScale( name, from.GetTextureScale( name ) );
break;
default:
break;
}
}
to.renderQueue = from.renderQueue;
to.globalIlluminationFlags = from.globalIlluminationFlags;
to.shaderKeywords = from.shaderKeywords;
foreach( var keyword in to.shaderKeywords )
{
to.EnableKeyword( keyword );
}
to.enableInstancing = from.enableInstancing;
EditorUtility.SetDirty( to );
}
#endif
public static void EnsureTextureKeywordState( this Material material, string property, string keyword )
{
var tex = material.HasProperty( property ) ? material.GetTexture( property ) : null;
EnsureKeywordState( material, keyword, tex != null );
}
public static void EnsureKeywordState( this Material material, string keyword, bool state )
{
if ( state && !material.IsKeywordEnabled( keyword ) )
{
material.EnableKeyword( keyword );
}
else if ( !state && material.IsKeywordEnabled( keyword ) )
{
material.DisableKeyword( keyword );
}
}
}
public static class Texture2DEx
{
static readonly byte[] Footer = { 0x54, 0x52, 0x55, 0x45, 0x56, 0x49, 0x53, 0x49, 0x4F, 0x4E, 0x2D, 0x58, 0x46, 0x49, 0x4C, 0x45, 0x2E, 0x00 }; // TRUEVISION-XFILE.\0 signature (new TGA format)
public enum Compression
{
None,
RLE
}
public static byte[] EncodeToTGA( this Texture2D tex, Compression compression = Compression.RLE )
{
const int headerSize = 18;
const int bytesRGB24 = 3;
const int bytesRGBA32 = 4;
int bytesPerPixel = tex.format == TextureFormat.ARGB32 || tex.format == TextureFormat.RGBA32 ? bytesRGBA32 : bytesRGB24;
using( MemoryStream stream = new MemoryStream( headerSize + tex.width * tex.height * bytesPerPixel ) )
{
using( BinaryWriter writer = new BinaryWriter( stream ) )
{
writer.Write( (byte)0 ); // IDLength (not in use)
writer.Write( (byte)0 ); // ColorMapType (not in use)
writer.Write( (byte)( compression == Compression.None ? 2 : 10 ) ); // DataTypeCode (10 == Runlength encoded RGB images)
writer.Write( (short)0 ); // ColorMapOrigin (not in use)
writer.Write( (short)0 ); // ColorMapLength (not in use)
writer.Write( (byte)0 ); // ColorMapDepth (not in use)
writer.Write( (short)0 ); // Origin X
writer.Write( (short)0 ); // Origin Y
writer.Write( (short)tex.width ); // Width
writer.Write( (short)tex.height ); // Height
writer.Write( (byte)( bytesPerPixel * 8 ) ); // Bits Per Pixel
writer.Write( (byte)8 ); // ImageDescriptor (photoshop uses 8?)
Color32[] pixels = tex.GetPixels32();
if( compression == Compression.None )
{
for( int i = 0; i < pixels.Length; i++ )
{
Color32 pixel = pixels[ i ];
writer.Write( pixel.r );
writer.Write( pixel.g );
writer.Write( pixel.b );
if( bytesPerPixel == bytesRGBA32 )
writer.Write( pixel.a );
}
}
else
{
const int maxPacket = 128;
int packetStart = 0;
int packetEnd = 0;
while( packetStart < pixels.Length )
{
Color32 currentPixel = pixels[ packetStart ];
bool isRLE = ( packetStart != pixels.Length - 1 ) && Equals( pixels[ packetStart ], pixels[ packetStart + 1 ] );
int endOfWidth = ( ( packetStart / tex.width ) + 1 ) * tex.width;
int readEnd = Mathf.Min( packetStart + maxPacket, pixels.Length, endOfWidth );
for( packetEnd = packetStart + 1; packetEnd < readEnd; ++packetEnd )
{
bool bPreviousEqualsCurrent = Equals( pixels[ packetEnd - 1 ], pixels[ packetEnd ] );
if( !isRLE && bPreviousEqualsCurrent || isRLE && !bPreviousEqualsCurrent )
break;
}
int packetLength = packetEnd - packetStart;
if( isRLE )
{
writer.Write( (byte)( ( packetLength - 1 ) | ( 1 << 7 ) ) );
writer.Write( currentPixel.r );
writer.Write( currentPixel.g );
writer.Write( currentPixel.b );
if( bytesPerPixel == bytesRGBA32 )
writer.Write( currentPixel.a );
}
else
{
writer.Write( (byte)( packetLength - 1 ) );
for( int i = packetStart; i < packetEnd; ++i )
{
Color32 pixel = pixels[ i ];
writer.Write( pixel.r );
writer.Write( pixel.g );
writer.Write( pixel.b );
if( bytesPerPixel == bytesRGBA32 )
writer.Write( pixel.a );
}
}
packetStart = packetEnd;
}
}
writer.Write( 0 ); // Offset of meta-information (not in use)
writer.Write( 0 ); // Offset of Developer-Area (not in use)
writer.Write( Footer ); // Signature
}
return stream.ToArray();
}
}
private static bool Equals( Color32 first, Color32 second )
{
return first.r == second.r && first.g == second.g && first.b == second.b && first.a == second.a;
}
}
public static class SpriteUtilityEx
{
private static System.Type type = null;
public static System.Type Type { get { return ( type == null ) ? type = System.Type.GetType( "UnityEditor.Sprites.SpriteUtility, UnityEditor" ) : type; } }
public static void GenerateOutline( Texture2D texture, Rect rect, float detail, byte alphaTolerance, bool holeDetection, out Vector2[][] paths )
{
Vector2[][] opaths = new Vector2[ 0 ][];
object[] parameters = new object[] { texture, rect, detail, alphaTolerance, holeDetection, opaths };
MethodInfo method = Type.GetMethod( "GenerateOutline", BindingFlags.Static | BindingFlags.NonPublic );
method.Invoke( null, parameters );
paths = (Vector2[][])parameters[ 5 ];
}
}
public static class RenderTextureEx
{
public static RenderTexture GetTemporary( RenderTexture renderTexture )
{
return RenderTexture.GetTemporary( renderTexture.width, renderTexture.height, renderTexture.depth, renderTexture.format );
}
}
public static class Vector2Ex
{
public static float Cross( this Vector2 O, Vector2 A, Vector2 B )
{
return ( A.x - O.x ) * ( B.y - O.y ) - ( A.y - O.y ) * ( B.x - O.x );
}
public static float TriangleArea( this Vector2 O, Vector2 A, Vector2 B )
{
return Mathf.Abs( ( A.x - B.x ) * ( O.y - A.y ) - ( A.x - O.x ) * ( B.y - A.y ) ) * 0.5f;
}
public static float TriangleArea( this Vector3 O, Vector3 A, Vector3 B )
{
return Mathf.Abs( ( A.x - B.x ) * ( O.y - A.y ) - ( A.x - O.x ) * ( B.y - A.y ) ) * 0.5f;
}
public static Vector2[] ConvexHull( Vector2[] P )
{
if( P.Length > 1 )
{
int n = P.Length, k = 0;
Vector2[] H = new Vector2[ 2 * n ];
Comparison<Vector2> comparison = new Comparison<Vector2>( ( a, b ) =>
{
if( a.x == b.x )
return a.y.CompareTo( b.y );
else
return a.x.CompareTo( b.x );
} );
Array.Sort<Vector2>( P, comparison );
// Build lower hull
for( int i = 0; i < n; ++i )
{
while( k >= 2 && P[ i ].Cross( H[ k - 2 ], H[ k - 1 ] ) <= 0 )
k--;
H[ k++ ] = P[ i ];
}
// Build upper hull
for( int i = n - 2, t = k + 1; i >= 0; i-- )
{
while( k >= t && P[ i ].Cross( H[ k - 2 ], H[ k - 1 ] ) <= 0 )
k--;
H[ k++ ] = P[ i ];
}
if( k > 1 )
Array.Resize<Vector2>( ref H, k - 1 );
return H;
}
else if( P.Length <= 1 )
{
return P;
}
else
{
return null;
}
}
public static Vector2[] ScaleAlongNormals( Vector2[] P, float scaleAmount )
{
Vector2[] normals = new Vector2[ P.Length ];
for( int i = 0; i < normals.Length; i++ )
{
int prev = i - 1;
int next = i + 1;
if( i == 0 )
prev = P.Length - 1;
if( i == P.Length - 1 )
next = 0;
Vector2 ba = P[ i ] - P[ prev ];
Vector2 bc = P[ i ] - P[ next ];
Vector2 normal = ( ba.normalized + bc.normalized ).normalized;
normals[ i ] = normal;
}
for( int i = 0; i < normals.Length; i++ )
{
P[ i ] = P[ i ] + normals[ i ] * scaleAmount;
}
return P;
}
static Vector2[] ReduceLeastSignificantVertice( Vector2[] P )
{
float currentArea = 0;
int smallestIndex = 0;
int replacementIndex = 0;
Vector2 newPos = Vector2.zero;
for( int i = 0; i < P.Length; i++ )
{
int next = i + 1;
int upNext = i + 2;
int finalNext = i + 3;
if( next >= P.Length )
next -= P.Length;
if( upNext >= P.Length )
upNext -= P.Length;
if( finalNext >= P.Length )
finalNext -= P.Length;
Vector2 intersect = GetIntersectionPointCoordinates( P[ i ], P[ next ], P[ upNext ], P[ finalNext ] );
if( i == 0 )
{
currentArea = intersect.TriangleArea( P[ next ], P[ upNext ] );
if( OutsideBounds( intersect ) > 0 )
currentArea = currentArea + OutsideBounds( intersect ) * 1;
smallestIndex = next;
replacementIndex = upNext;
newPos = intersect;
}
else
{
float newArea = intersect.TriangleArea( P[ next ], P[ upNext ] );
if( OutsideBounds( intersect ) > 0 )
newArea = newArea + OutsideBounds( intersect ) * 1;
if( newArea < currentArea && OutsideBounds( intersect ) <= 0 )
{
currentArea = newArea;
smallestIndex = next;
replacementIndex = upNext;
newPos = intersect;
}
}
}
P[ replacementIndex ] = newPos;
return Array.FindAll<Vector2>( P, x => Array.IndexOf( P, x ) != smallestIndex );
}
public static Vector2[] ReduceVertices( Vector2[] P, int maxVertices )
{
if( maxVertices == 4 )
{
// turn into a box
Rect newBox = new Rect( P[ 0 ].x, P[ 0 ].y, 0f, 0f );
for( int i = 0; i < P.Length; i++ )
{
newBox.xMin = Mathf.Min( newBox.xMin, P[ i ].x );
newBox.xMax = Mathf.Max( newBox.xMax, P[ i ].x );
newBox.yMin = Mathf.Min( newBox.yMin, P[ i ].y );
newBox.yMax = Mathf.Max( newBox.yMax, P[ i ].y );
}
P = new Vector2[]
{
new Vector2(newBox.xMin, newBox.yMin),
new Vector2(newBox.xMax, newBox.yMin),
new Vector2(newBox.xMax, newBox.yMax),
new Vector2(newBox.xMin, newBox.yMax),
};
}
else
{
// remove vertices to target count (naive implementation)
int reduction = Math.Max( 0, P.Length - maxVertices );
for( int k = 0; k < reduction; k++ )
{
P = ReduceLeastSignificantVertice( P );
// OLD METHOD
//float prevArea = 0;
//int indexForRemoval = 0;
//for( int i = 0; i < P.Length; i++ )
//{
// int prev = i - 1;
// int next = i + 1;
// if( i == 0 )
// prev = P.Length - 1;
// if( i == P.Length - 1 )
// next = 0;
// float area = P[ i ].TriangleArea( P[ prev ], P[ next ] );
// if( i == 0 )
// prevArea = area;
// if( area < prevArea )
// {
// indexForRemoval = i;
// prevArea = area;
// }
//}
//ArrayUtility.RemoveAt<Vector2>( ref P, indexForRemoval );
}
}
return P;
}
static Vector2 GetIntersectionPointCoordinates( Vector2 A1, Vector2 A2, Vector2 B1, Vector2 B2 )
{
float tmp = ( B2.x - B1.x ) * ( A2.y - A1.y ) - ( B2.y - B1.y ) * ( A2.x - A1.x );
if( tmp == 0 )
{
return ( ( Vector2.Lerp( A2, B1, 0.5f ) - ( Vector2.one * 0.5f ) ) * 1000 ) + ( Vector2.one * 500f );//Vector2.positiveInfinity;// Vector2.zero;
}
float mu = ( ( A1.x - B1.x ) * ( A2.y - A1.y ) - ( A1.y - B1.y ) * ( A2.x - A1.x ) ) / tmp;
return new Vector2(
B1.x + ( B2.x - B1.x ) * mu,
B1.y + ( B2.y - B1.y ) * mu
);
}
static float OutsideBounds( Vector2 P )
{
P = P - ( Vector2.one * 0.5f );
float vert = Mathf.Clamp01( Mathf.Abs( P.y ) - 0.5f );
float hori = Mathf.Clamp01( Mathf.Abs( P.x ) - 0.5f );
return hori + vert;
}
}
}

View File

@@ -0,0 +1,13 @@
fileFormatVersion: 2
guid: 821be38acbe37c847922cabdcd593fe5
timeCreated: 1517333254
licenseType: Store
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,80 @@
// Amplify Impostors
// Copyright (c) Amplify Creations, Lda <info@amplify.pt>
using System.Collections;
using System.Collections.Generic;
using System.IO;
using UnityEngine;
#if UNITY_EDITOR
using UnityEditor;
#endif
namespace AmplifyImpostors
{
public static class ImpostorBakingTools
{
#if UNITY_EDITOR
public static string OpenFolderForImpostor( this AmplifyImpostor instance )
{
string oneLevelUp = Application.dataPath + "/../";
string directory = Path.GetFullPath( oneLevelUp ).Replace( "\\", "/" );
string objectPath = AssetDatabase.GetAssetPath( instance.RootTransform );
// Find Path next to prefab
if( string.IsNullOrEmpty( objectPath ) )
{
objectPath = AssetDatabase.GetAssetPath( PrefabUtility.GetCorrespondingObjectFromSource( instance.RootTransform ) );
}
Preferences.GlobalRelativeFolder = EditorPrefs.GetString( Preferences.PrefGlobalRelativeFolder, "" );
string fullpath = string.Empty;
string suggestedRelativePath = directory + objectPath;
if( string.IsNullOrEmpty( objectPath ) )
suggestedRelativePath = Application.dataPath;
else
suggestedRelativePath = Path.GetDirectoryName( suggestedRelativePath ).Replace( "\\", "/" );
Preferences.GlobalFolder = EditorPrefs.GetString( Preferences.PrefGlobalFolder, "" );
// Find best match
if( Preferences.GlobalDefaultMode && AssetDatabase.IsValidFolder( Preferences.GlobalFolder.TrimStart( '/' ) ) )
fullpath = directory + Preferences.GlobalFolder;
else if( AssetDatabase.IsValidFolder( FileUtil.GetProjectRelativePath( suggestedRelativePath + Preferences.GlobalRelativeFolder ).TrimEnd( '/' ) ) )
fullpath = suggestedRelativePath + Preferences.GlobalRelativeFolder;
else if( AssetDatabase.IsValidFolder( FileUtil.GetProjectRelativePath( suggestedRelativePath ).TrimEnd( '/' ) ) )
fullpath = suggestedRelativePath;
else
fullpath = Application.dataPath;
string fileName = instance.name + "_Impostor";
if( !string.IsNullOrEmpty( instance.m_impostorName ) )
fileName = instance.m_impostorName;
//Debug.Log( fullpath );
//Debug.Log( fileName );
string folderpath = EditorUtility.SaveFilePanelInProject( "Save Impostor to folder", fileName, "asset", "", FileUtil.GetProjectRelativePath( fullpath ) );
fileName = Path.GetFileNameWithoutExtension( folderpath );
if( !string.IsNullOrEmpty( fileName ) )
{
folderpath = Path.GetDirectoryName( folderpath ).Replace( "\\", "/" );
if( !string.IsNullOrEmpty( folderpath ) )
{
folderpath += "/";
if( !Preferences.GlobalDefaultMode )
{
instance.m_folderPath = folderpath;
}
else
{
Preferences.GlobalFolder = folderpath;
EditorPrefs.SetString( Preferences.PrefGlobalFolder, Preferences.GlobalFolder );
}
instance.m_impostorName = fileName;
}
}
return folderpath;
}
#endif
}
}

View File

@@ -0,0 +1,13 @@
fileFormatVersion: 2
guid: 8f54ccaf72377ff41a49e3882c8b6e7f
timeCreated: 1527167385
licenseType: Store
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,203 @@
// Amplify Impostors
// Copyright (c) Amplify Creations, Lda <info@amplify.pt>
using System.IO;
using UnityEditor;
using UnityEngine;
namespace AmplifyImpostors
{
public class Preferences
{
#if UNITY_EDITOR
public enum ShowOption
{
Always = 0,
OnNewVersion = 1,
Never = 2
}
private static readonly GUIContent StartUp = new GUIContent( "Show start screen on Unity launch", "You can set if you want to see the start screen everytime Unity launches, only just when there's a new version available or never." );
private static readonly GUIContent AutoSRP = new GUIContent( "Auto import SRP shaders", "By default Amplify Impostors checks for your SRP version and automatically imports compatible shaders.\nTurn this OFF if you prefer to import them manually." );
public static readonly string PrefGlobalFolder = "IMPOSTORS_GLOBALFOLDER";
public static readonly string PrefGlobalRelativeFolder = "IMPOSTORS_GLOBALRELATIVEFOLDER";
public static readonly string PrefGlobalDefault = "IMPOSTORS_GLOBALDEFAULT";
public static readonly string PrefGlobalTexImport = "IMPOSTORS_GLOBALTEXIMPORT";
public static readonly string PrefGlobalCreateLodGroup = "IMPOSTORS_GLOBALCREATELODGROUP ";
public static readonly string PrefGlobalGBuffer0Name = "IMPOSTORS_GLOBALGBUFFER0SUFFIX";
public static readonly string PrefGlobalGBuffer1Name = "IMPOSTORS_GLOBALGBUFFER1SUFFIX";
public static readonly string PrefGlobalGBuffer2Name = "IMPOSTORS_GLOBALGBUFFER2SUFFIX";
public static readonly string PrefGlobalGBuffer3Name = "IMPOSTORS_GLOBALGBUFFER3SUFFIX";
public static readonly string PrefGlobalGBuffer4Name = "IMPOSTORS_GLOBALGBUFFER4SUFFIX";
public static readonly string PrefGlobalGBuffer5Name = "IMPOSTORS_GLOBALGBUFFER5SUFFIX";
public static readonly string PrefGlobalBakingOptions = "IMPOSTORS_GLOBALBakingOptions";
public static readonly string PrefGlobalStartUp = "IMPOSTORS_GLOBALSTARTUP";
public static readonly string PrefGlobalAutoSRP = "IMPOSTORS_GLOBALAUTOSRP";
public static readonly string PrefDataImpType = "IMPOSTORS_DATAIMPTYPE";
public static readonly string PrefDataTexSizeLocked = "IMPOSTORS_DATATEXSIZEXLOCKED";
public static readonly string PrefDataTexSizeSelected = "IMPOSTORS_DATATEXSIZEXSELECTED";
public static readonly string PrefDataTexSizeX = "IMPOSTORS_DATATEXSIZEX";
public static readonly string PrefDataTexSizeY = "IMPOSTORS_DATATEXSIZEY";
public static readonly string PrefDataDecoupledFrames = "IMPOSTORS_DATADECOUPLEDFRAMES";
public static readonly string PrefDataXFrames = "IMPOSTORS_DATAXFRAMES";
public static readonly string PrefDataYFrames = "IMPOSTORS_DATAYFRAMES";
public static readonly string PrefDataPixelBleeding = "IMPOSTORS_DATAPIXELBLEEDING";
public static readonly string PrefDataTolerance = "IMPOSTORS_DATATOLERANCE ";
public static readonly string PrefDataNormalScale = "IMPOSTORS_DATANORMALSCALE";
public static readonly string PrefDataMaxVertices = "IMPOSTORS_DATAMAXVERTICES";
public static readonly string DefaultAlbedoName = "_AlbedoAlpha";
public static readonly string DefaultSpecularName = "_SpecularSmoothness";
public static readonly string DefaultNormalName = "_NormalDepth";
public static readonly string DefaultEmissionName = "_EmissionOcclusion";
public static readonly string DefaultOcclusionName = "_Occlusion";
public static readonly string DefaultPositionName = "_Position";
public static bool GlobalDefaultMode = EditorPrefs.GetBool( PrefGlobalDefault, false );
public static string GlobalFolder = EditorPrefs.GetString( PrefGlobalFolder, "" );
public static string GlobalRelativeFolder = EditorPrefs.GetString( PrefGlobalRelativeFolder, "" );
public static int GlobalTexImport = EditorPrefs.GetInt( PrefGlobalTexImport, 0 );
public static bool GlobalCreateLodGroup = EditorPrefs.GetBool( PrefGlobalCreateLodGroup, false );
public static string GlobalAlbedo = EditorPrefs.GetString( PrefGlobalGBuffer0Name, DefaultAlbedoName );
public static string GlobalNormals = EditorPrefs.GetString( PrefGlobalGBuffer1Name, DefaultNormalName );
public static string GlobalSpecular = EditorPrefs.GetString( PrefGlobalGBuffer2Name, DefaultSpecularName );
public static string GlobalOcclusion = EditorPrefs.GetString( PrefGlobalGBuffer3Name, DefaultOcclusionName );
public static string GlobalEmission = EditorPrefs.GetString( PrefGlobalGBuffer4Name, DefaultEmissionName );
public static string GlobalPosition = EditorPrefs.GetString( PrefGlobalGBuffer5Name, DefaultPositionName );
public static bool GlobalBakingOptions = EditorPrefs.GetBool( PrefGlobalBakingOptions, true );
public static ShowOption GlobalStartUp = ( ShowOption )EditorPrefs.GetInt( PrefGlobalStartUp, 0 );
public static bool GlobalAutoSRP = EditorPrefs.GetBool( PrefGlobalAutoSRP, true );
private static readonly GUIContent DefaultSuffixesLabel = new GUIContent( "Default Suffixes", "Default Suffixes for new Bake Presets" );
private static bool PrefsLoaded = false;
private static GUIContent PathButtonContent = new GUIContent();
[SettingsProvider]
public static SettingsProvider ImpostorsSettings()
{
var provider = new SettingsProvider( "Preferences/Amplify Impostors", SettingsScope.User )
{
guiHandler = ( string searchContext ) => {
PreferencesGUI();
}
};
return provider;
}
public static void PreferencesGUI()
{
if ( !PrefsLoaded )
{
LoadDefaults();
PrefsLoaded = true;
}
PathButtonContent.text = string.IsNullOrEmpty( GlobalFolder ) ? "Click to select folder" : GlobalFolder;
EditorGUIUtility.labelWidth = 250;
GlobalStartUp = ( ShowOption )EditorGUILayout.EnumPopup( StartUp, GlobalStartUp );
GlobalAutoSRP = EditorGUILayout.Toggle( AutoSRP, GlobalAutoSRP );
GlobalDefaultMode = ( FolderMode )EditorGUILayout.EnumPopup( "New Impostor Default Path", GlobalDefaultMode ? FolderMode.Global : FolderMode.RelativeToPrefab ) == FolderMode.Global;
EditorGUILayout.BeginHorizontal();
if ( GlobalDefaultMode )
{
EditorGUI.BeginChangeCheck();
GlobalFolder = EditorGUILayout.TextField( "Global Folder", GlobalFolder );
if ( EditorGUI.EndChangeCheck() )
{
GlobalFolder = GlobalFolder.TrimStart( new char[] { '/', '*', '.', ' ' } );
GlobalFolder = "/" + GlobalFolder;
GlobalFolder = GlobalFolder.TrimEnd( new char[] { '/', '*', '.', ' ' } );
EditorPrefs.SetString( PrefGlobalFolder, GlobalFolder );
}
if ( GUILayout.Button( "...", "minibutton", GUILayout.Width( 20 )/*GUILayout.MaxWidth( Screen.width * 0.5f )*/ ) )
{
string oneLevelUp = Application.dataPath + "/../";
string directory = Path.GetFullPath( oneLevelUp ).Replace( "\\", "/" );
string fullpath = directory + GlobalFolder;
string folderpath = EditorUtility.SaveFolderPanel( "Save Impostor to folder", FileUtil.GetProjectRelativePath( fullpath ), null );
folderpath = FileUtil.GetProjectRelativePath( folderpath );
if ( !string.IsNullOrEmpty( folderpath ) )
{
GlobalFolder = folderpath;
GlobalFolder = GlobalFolder.TrimStart( new char[] { '/', '*', '.', ' ' } );
GlobalFolder = "/" + GlobalFolder;
GlobalFolder = GlobalFolder.TrimEnd( new char[] { '/', '*', '.', ' ' } );
EditorPrefs.SetString( PrefGlobalFolder, GlobalFolder );
}
}
}
else
{
EditorGUI.BeginChangeCheck();
GlobalRelativeFolder = EditorGUILayout.TextField( "Relative to Prefab Folder", GlobalRelativeFolder );
if ( EditorGUI.EndChangeCheck() )
{
GlobalRelativeFolder = GlobalRelativeFolder.TrimStart( new char[] { '/', '*', '.', ' ' } );
GlobalRelativeFolder = "/" + GlobalRelativeFolder;
GlobalRelativeFolder = GlobalRelativeFolder.TrimEnd( new char[] { '/', '*', '.', ' ' } );
EditorPrefs.SetString( PrefGlobalRelativeFolder, GlobalRelativeFolder );
}
EditorGUI.BeginDisabledGroup( true );
GUILayout.Button( "...", "minibutton", GUILayout.Width( 20 ) );
EditorGUI.EndDisabledGroup();
}
EditorGUILayout.EndHorizontal();
GlobalTexImport = EditorGUILayout.Popup( "Texture Importer Settings", GlobalTexImport, new string[] { "Ask if resolution is different", "Don't ask, always change", "Don't ask, never change" } );
GlobalCreateLodGroup = EditorGUILayout.Toggle( "Create LODGroup if not present", GlobalCreateLodGroup );
GUILayout.Space( 5 );
GUILayout.Label( DefaultSuffixesLabel, "boldlabel" );
GlobalAlbedo = EditorGUILayout.TextField( "Albedo (RGB) Alpha (A)", GlobalAlbedo );
GlobalNormals = EditorGUILayout.TextField( "Normal (RGB) Depth (A)", GlobalNormals );
GlobalSpecular = EditorGUILayout.TextField( "Specular (RGB) Smoothness (A)", GlobalSpecular );
GlobalOcclusion = EditorGUILayout.TextField( "Occlusion (RGB)", GlobalOcclusion );
GlobalEmission = EditorGUILayout.TextField( "Emission (RGB)", GlobalEmission );
GlobalPosition = EditorGUILayout.TextField( "Position (RGB)", GlobalPosition );
if ( GUI.changed )
{
EditorPrefs.SetInt( PrefGlobalStartUp, ( int )GlobalStartUp );
EditorPrefs.SetBool( PrefGlobalAutoSRP, GlobalAutoSRP );
EditorPrefs.SetBool( PrefGlobalDefault, GlobalDefaultMode );
EditorPrefs.SetInt( PrefGlobalTexImport, GlobalTexImport );
EditorPrefs.SetBool( PrefGlobalCreateLodGroup, GlobalCreateLodGroup );
EditorPrefs.SetString( PrefGlobalGBuffer0Name, GlobalAlbedo );
EditorPrefs.SetString( PrefGlobalGBuffer1Name, GlobalSpecular );
EditorPrefs.SetString( PrefGlobalGBuffer2Name, GlobalNormals );
EditorPrefs.SetString( PrefGlobalGBuffer3Name, GlobalEmission );
EditorPrefs.SetString( PrefGlobalGBuffer4Name, GlobalOcclusion );
EditorPrefs.SetString( PrefGlobalGBuffer5Name, GlobalPosition );
}
}
public static void LoadDefaults()
{
GlobalStartUp = ( ShowOption )EditorPrefs.GetInt( PrefGlobalStartUp, 0 );
GlobalAutoSRP = EditorPrefs.GetBool( PrefGlobalAutoSRP, true );
GlobalFolder = EditorPrefs.GetString( PrefGlobalFolder, "" );
GlobalRelativeFolder = EditorPrefs.GetString( PrefGlobalRelativeFolder, "" );
GlobalDefaultMode = EditorPrefs.GetBool( PrefGlobalDefault, false );
GlobalTexImport = EditorPrefs.GetInt( PrefGlobalTexImport, 0 );
GlobalCreateLodGroup = EditorPrefs.GetBool( PrefGlobalCreateLodGroup, false );
GlobalBakingOptions = EditorPrefs.GetBool( PrefGlobalBakingOptions, true );
GlobalAlbedo = EditorPrefs.GetString( PrefGlobalGBuffer0Name, DefaultAlbedoName );
GlobalSpecular = EditorPrefs.GetString( PrefGlobalGBuffer1Name, DefaultSpecularName );
GlobalNormals = EditorPrefs.GetString( PrefGlobalGBuffer2Name, DefaultNormalName );
GlobalEmission = EditorPrefs.GetString( PrefGlobalGBuffer3Name, DefaultEmissionName );
GlobalOcclusion = EditorPrefs.GetString( PrefGlobalGBuffer4Name, DefaultOcclusionName );
GlobalPosition = EditorPrefs.GetString( PrefGlobalGBuffer5Name, DefaultPositionName );
}
#endif
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: a5333d9fdffa80b4f82078d0b3a3670f
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,134 @@
// Modified code from: http://wiki.unity3d.com/index.php?title=Triangulator
using UnityEngine;
using System.Collections.Generic;
namespace AmplifyImpostors
{
public class Triangulator
{
private List<Vector2> m_points = new List<Vector2>();
public List<Vector2> Points { get { return m_points; } }
public Triangulator( Vector2[] points )
{
m_points = new List<Vector2>( points );
}
public Triangulator( Vector2[] points, bool invertY = true )
{
if( invertY )
{
m_points = new List<Vector2>();
for( int i = 0; i < points.Length; i++ )
{
m_points.Add( new Vector2( points[ i ].x, 1 - points[ i ].y ) );
}
}
else
{
m_points = new List<Vector2>( points );
}
}
public int[] Triangulate()
{
List<int> indices = new List<int>();
int n = m_points.Count;
if( n < 3 )
return indices.ToArray();
int[] V = new int[ n ];
if( Area() > 0 )
{
for( int v = 0; v < n; v++ )
V[ v ] = v;
}
else
{
for( int v = 0; v < n; v++ )
V[ v ] = ( n - 1 ) - v;
}
int nv = n;
int count = 2 * nv;
for( int m = 0, v = nv - 1; nv > 2; )
{
if( ( count-- ) <= 0 )
return indices.ToArray();
int u = v;
if( nv <= u )
u = 0;
v = u + 1;
if( nv <= v )
v = 0;
int w = v + 1;
if( nv <= w )
w = 0;
if( Snip( u, v, w, nv, V ) )
{
int a, b, c, s, t;
a = V[ u ];
b = V[ v ];
c = V[ w ];
indices.Add( a );
indices.Add( b );
indices.Add( c );
m++;
for( s = v, t = v + 1; t < nv; s++, t++ )
V[ s ] = V[ t ];
nv--;
count = 2 * nv;
}
}
indices.Reverse();
return indices.ToArray();
}
private float Area()
{
int n = m_points.Count;
float A = 0.0f;
for( int p = n - 1, q = 0; q < n; p = q++ )
{
Vector2 pval = m_points[ p ];
Vector2 qval = m_points[ q ];
A += pval.x * qval.y - qval.x * pval.y;
}
return ( A * 0.5f );
}
private bool Snip( int u, int v, int w, int n, int[] V )
{
int p;
Vector2 A = m_points[ V[ u ] ];
Vector2 B = m_points[ V[ v ] ];
Vector2 C = m_points[ V[ w ] ];
if( Mathf.Epsilon > ( ( ( B.x - A.x ) * ( C.y - A.y ) ) - ( ( B.y - A.y ) * ( C.x - A.x ) ) ) )
return false;
for( p = 0; p < n; p++ )
{
if( ( p == u ) || ( p == v ) || ( p == w ) )
continue;
Vector2 P = m_points[ V[ p ] ];
if( InsideTriangle( P, A, B, C ) )
return false;
}
return true;
}
private bool InsideTriangle( Vector2 pt, Vector2 v1, Vector2 v2, Vector2 v3 )
{
bool b1, b2, b3;
b1 = pt.Cross( v1, v2 ) < 0.0f;
b2 = pt.Cross( v2, v3 ) < 0.0f;
b3 = pt.Cross( v3, v1 ) < 0.0f;
return ( ( b1 == b2 ) && ( b2 == b3 ) );
}
}
}

View File

@@ -0,0 +1,13 @@
fileFormatVersion: 2
guid: 42b1e7d3f2b55c04094ade095b7998dd
timeCreated: 1526468584
licenseType: Store
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,25 @@
// Amplify Impostors
// Copyright (c) Amplify Creations, Lda <info@amplify.pt>
using System;
using UnityEngine;
namespace AmplifyImpostors
{
[Serializable]
public class VersionInfo
{
public const byte Major = 1;
public const byte Minor = 0;
public const byte Release = 1;
public static byte Revision = 0;
public static string StaticToString()
{
return string.Format( "{0}.{1}.{2}", Major, Minor, Release ) + ( Revision > 0 ? "." + Revision.ToString() : "" );
}
public static int FullNumber { get { return Major * 10000 + Minor * 1000 + Release * 100 + Revision; } }
public static string FullLabel { get { return "Version=" + FullNumber; } }
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 80c1dd1ce4de2e8488e2aea2a98dcc6b
timeCreated: 1481126955
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: