private static void ComputeCompressionScalers(ProceduralTexture2D target) { target.compressionScalers = Vector4.one; if (target.compressionQuality != ProceduralTexture2D.CompressionLevel.None && target.type != ProceduralTexture2D.TextureType.Other) { target.compressionScalers.x = 1.0f / target.colorSpaceVector1.magnitude; target.compressionScalers.y = 1.0f / target.colorSpaceVector2.magnitude; target.compressionScalers.z = 1.0f / target.colorSpaceVector3.magnitude; } }
private static void PreprocessData(ProceduralTexture2D target) { if (target.input == null) { return; } // Init progress bar stepCounter = 0; totalSteps = (target.type != ProceduralTexture2D.TextureType.Other ? 4 : 0) + (target.type != ProceduralTexture2D.TextureType.Other ? 9 : 12) + 1; EditorUtility.DisplayProgressBar("Pre-processing Procedural Texture Data", target.name, (float)stepCounter / (totalSteps - 1)); // Section 1.4 Improvement: using a decorrelated color space for Color RGB and Normal XYZ textures TextureFormat inputFormat = TextureFormat.RGB24; TextureData albedoData = TextureToTextureData(target.input, ref inputFormat); TextureData decorrelated = new TextureData(albedoData); if (target.type != ProceduralTexture2D.TextureType.Other) { DecorrelateColorSpace(ref albedoData, ref decorrelated, ref target.colorSpaceVector1, ref target.colorSpaceVector2, ref target.colorSpaceVector3, ref target.colorSpaceOrigin, target.name); } ComputeCompressionScalers(target); // Perform precomputations TextureData Tinput = new TextureData(decorrelated.width, decorrelated.height); TextureData invT = new TextureData(LUT_WIDTH, (int)(Mathf.Log((float)Tinput.width) / Mathf.Log(2.0f))); // Height = Number of prefiltered LUT levels List <int> channelsToProcess = new List <int> { 0, 1, 2 }; if ((target.type == ProceduralTexture2D.TextureType.Color && target.includeAlpha == true) || target.type == ProceduralTexture2D.TextureType.Other) { channelsToProcess.Add(3); } Precomputations(ref decorrelated, channelsToProcess, ref Tinput, ref invT, target.name); RescaleForCompression(target, ref Tinput); EditorUtility.DisplayProgressBar("Pre-processing Procedural Texture Data", target.name, (float)stepCounter++ / (totalSteps - 1)); // Serialize precomputed data and setup material FinalizePrecomputedTextures(ref inputFormat, target, ref Tinput, ref invT); target.memoryUsageBytes = target.Tinput.GetRawTextureData().Length + target.invT.GetRawTextureData().Length; EditorUtility.ClearProgressBar(); // Update current applied settings target.currentInput = target.input; target.currentIncludeAlpha = target.includeAlpha; target.currentGenerateMipMaps = target.generateMipMaps; target.currentFilterMode = target.filterMode; target.currentAnisoLevel = target.anisoLevel; target.currentCompressionQuality = target.compressionQuality; }
static void FinalizePrecomputedTextures(ref TextureFormat inputFormat, ProceduralTexture2D target, ref TextureData Tinput, ref TextureData invT) { // Serialize precomputed data as new subasset texture. Reuse existing texture if possible to avoid breaking texture references in shadergraph. if (target.Tinput == null) { target.Tinput = new Texture2D(Tinput.width, Tinput.height, inputFormat, target.generateMipMaps, true); AssetDatabase.AddObjectToAsset(target.Tinput, target); } target.Tinput.Resize(Tinput.width, Tinput.height, inputFormat, target.generateMipMaps); target.Tinput.name = target.input.name + "_T"; target.Tinput.SetPixels(Tinput.data); target.Tinput.wrapMode = TextureWrapMode.Repeat; target.Tinput.filterMode = target.filterMode; target.Tinput.anisoLevel = target.anisoLevel; target.Tinput.Apply(); if (target.compressionQuality != ProceduralTexture2D.CompressionLevel.None) { if (target.compressionQuality == ProceduralTexture2D.CompressionLevel.HighQuality) { EditorUtility.CompressTexture(target.Tinput, TextureFormat.BC7, (int)target.compressionQuality); } else if (inputFormat == TextureFormat.RGBA32) { EditorUtility.CompressTexture(target.Tinput, TextureFormat.DXT5, (int)target.compressionQuality); } else { EditorUtility.CompressTexture(target.Tinput, TextureFormat.DXT1, (int)target.compressionQuality); } } target.Tinput.Apply(); if (target.invT == null) { target.invT = new Texture2D(invT.width, invT.height, inputFormat, false, true); AssetDatabase.AddObjectToAsset(target.invT, target); } target.invT.Resize(invT.width, invT.height, inputFormat, false); target.invT.name = target.input.name + "_invT"; target.invT.wrapMode = TextureWrapMode.Clamp; target.invT.filterMode = FilterMode.Bilinear; target.invT.SetPixels(invT.data); target.invT.Apply(); // Update asset database AssetDatabase.SaveAssets(); AssetDatabase.Refresh(); }
private bool UnappliedSettingChanges(ProceduralTexture2D target) { if (target.currentInput != target.input || target.currentIncludeAlpha != target.includeAlpha || target.currentGenerateMipMaps != target.generateMipMaps || target.currentFilterMode != target.filterMode || target.currentAnisoLevel != target.anisoLevel || target.currentCompressionQuality != target.compressionQuality) { return(true); } else { return(false); } }
private void CopyInputTextureImportType(ProceduralTexture2D target) { string path = AssetDatabase.GetAssetPath(target.input); TextureImporter inputImporter = (TextureImporter)TextureImporter.GetAtPath(path); switch (inputImporter.textureType) { case TextureImporterType.NormalMap: target.type = ProceduralTexture2D.TextureType.Normal; break; default: target.type = ProceduralTexture2D.TextureType.Color; break; } }
private static void RescaleForCompression(ProceduralTexture2D target, ref TextureData Tinput) { int channelCount = (target.type == ProceduralTexture2D.TextureType.Color && target.includeAlpha == true) || target.type == ProceduralTexture2D.TextureType.Other ? 4 : 3; // If we use DXT compression // we need to rescale the Gaussian channels (see Section 1.6) if (target.compressionQuality != ProceduralTexture2D.CompressionLevel.None && target.type != ProceduralTexture2D.TextureType.Other) { for (int y = 0; y < Tinput.height; y++) { for (int x = 0; x < Tinput.width; x++) { for (int i = 0; i < channelCount; i++) { float v = Tinput.GetColor(x, y)[i]; v = (v - 0.5f) / target.compressionScalers[i] + 0.5f; Tinput.GetColorRef(x, y)[i] = v; } } } } }