/// <summary> /// Gets Unity Material atlas from Daggerfall texture archive. /// </summary> /// <param name="archive">Archive index to create atlas from.</param> /// <param name="alphaIndex">Index to receive transparent alpha.</param> /// <param name="rectsOut">Array of rects, one for each record sub-texture and frame.</param> /// <param name="padding">Number of pixels each sub-texture.</param> /// <param name="maxAtlasSize">Max size of atlas.</param> /// <param name="rectsOut">Array of rects, one for each record sub-texture and frame.</param> /// <param name="indicesOut">Array of record indices into rect array, accounting for animation frames.</param> /// <param name="border">Number of pixels internal border around each texture.</param> /// <param name="dilate">Blend texture into surrounding empty pixels.</param> /// <param name="shrinkUVs">Number of pixels to shrink UV rect.</param> /// <param name="copyToOppositeBorder">Copy texture edges to opposite border. Requires border, will overwrite dilate.</param> /// <param name="shader">Shader for material. If null, DefaultShaderName will be applied.</param> /// <returns>Material or null.</returns> public Material GetMaterialAtlas( int archive, int alphaIndex, int padding, int maxAtlasSize, out Rect[] rectsOut, out RecordIndex[] indicesOut, int border = 0, bool dilate = false, int shrinkUVs = 0, bool copyToOppositeBorder = false) { // Ready check if (!IsReady) { rectsOut = null; indicesOut = null; return(null); } int key = MakeTextureKey((short)archive, (byte)0, (byte)0, AtlasKeyGroup); if (materialDict.ContainsKey(key)) { CachedMaterial cm = materialDict[key]; if (cm.filterMode == MainFilterMode) { // Properties are the same rectsOut = cm.atlasRects; indicesOut = cm.atlasIndices; return(cm.material); } else { // Properties don't match, remove material and reload materialDict.Remove(key); } } // Create material Material material = CreateStandardMaterial(); // Create settings GetTextureSettings settings = TextureReader.CreateTextureSettings(archive, 0, 0, alphaIndex, border, dilate); settings.createNormalMap = GenerateNormals; settings.autoEmission = true; settings.atlasShrinkUVs = shrinkUVs; settings.atlasPadding = padding; settings.atlasMaxSize = maxAtlasSize; settings.copyToOppositeBorder = copyToOppositeBorder; // Setup material material.name = string.Format("TEXTURE.{0:000} [Atlas]", archive); GetTextureResults results = textureReader.GetTexture2DAtlas(settings, AlphaTextureFormat, NonAlphaTextureFormat); material.mainTexture = results.albedoMap; material.mainTexture.filterMode = MainFilterMode; // Setup normal map if (GenerateNormals && results.normalMap != null) { results.normalMap.filterMode = MainFilterMode; material.SetTexture("_BumpMap", results.normalMap); material.EnableKeyword("_NORMALMAP"); } // Setup emission map if (results.isEmissive && results.emissionMap != null) { results.emissionMap.filterMode = MainFilterMode; material.SetTexture("_EmissionMap", results.emissionMap); material.SetColor("_EmissionColor", Color.white); material.EnableKeyword("_EMISSION"); } // TEMP: Bridging between legacy material out params and GetTextureResults for now Vector2[] sizesOut, scalesOut, offsetsOut; sizesOut = results.atlasSizes.ToArray(); scalesOut = results.atlasScales.ToArray(); offsetsOut = results.atlasOffsets.ToArray(); rectsOut = results.atlasRects.ToArray(); indicesOut = results.atlasIndices.ToArray(); // Setup cached material CachedMaterial newcm = new CachedMaterial(); newcm.key = key; newcm.keyGroup = AtlasKeyGroup; newcm.atlasRects = rectsOut; newcm.atlasIndices = indicesOut; newcm.material = material; newcm.filterMode = MainFilterMode; newcm.recordSizes = sizesOut; newcm.recordScales = scalesOut; newcm.recordOffsets = offsetsOut; newcm.atlasFrameCounts = results.atlasFrameCounts.ToArray(); materialDict.Add(key, newcm); return(material); }
/// <summary> /// Gets Unity Material from Daggerfall texture with more options. /// </summary> /// <param name="archive">Archive index.</param> /// <param name="record">Record index.</param> /// <param name="frame">Frame index.</param> /// <param name="rectOut">Receives UV rect for texture inside border.</param> /// <param name="borderSize">Number of pixels internal border around each texture.</param> /// <param name="dilate">Blend texture into surrounding empty pixels.</param> /// <returns>Material or null.</returns> public Material GetMaterial( int archive, int record, int frame, int alphaIndex, out Rect rectOut, int borderSize = 0, bool dilate = false) { // Ready check if (!IsReady) { rectOut = new Rect(); return(null); } // Try to retrieve from cache int key = MakeTextureKey((short)archive, (byte)record, (byte)frame); if (materialDict.ContainsKey(key)) { CachedMaterial cm = materialDict[key]; rectOut = cm.singleRect; return(cm.material); } // Create new texture settings GetTextureSettings settings = TextureReader.CreateTextureSettings(archive, record, frame, alphaIndex, borderSize, dilate); settings.autoEmissionForWindows = true; settings.sharpen = Sharpen; if (GenerateNormals) { settings.createNormalMap = true; settings.normalStrength = NormalTextureStrength; } // Set emissive for self-illuminated textures if (textureReader.IsEmissive(archive, record)) { settings.createEmissionMap = true; settings.emissionIndex = -1; } // Get texture GetTextureResults results = textureReader.GetTexture2D(settings, AlphaTextureFormat, NonAlphaTextureFormat); rectOut = results.singleRect; // Setup material Material material = CreateStandardMaterial(); material.name = FormatName(archive, record); material.mainTexture = results.albedoMap; material.mainTexture.filterMode = MainFilterMode; // Setup normal map if (GenerateNormals && results.normalMap != null) { results.normalMap.filterMode = MainFilterMode; material.SetTexture("_BumpMap", results.normalMap); material.EnableKeyword("_NORMALMAP"); } // Setup emission map if (results.isEmissive && !results.isWindow && results.emissionMap != null) { results.emissionMap.filterMode = MainFilterMode; material.SetTexture("_EmissionMap", results.emissionMap); material.SetColor("_EmissionColor", Color.white); material.EnableKeyword("_EMISSION"); } else if (results.isEmissive && results.isWindow && results.emissionMap != null) { results.emissionMap.filterMode = MainFilterMode; material.SetTexture("_EmissionMap", results.emissionMap); material.SetColor("_EmissionColor", DayWindowColor * DayWindowIntensity); material.EnableKeyword("_EMISSION"); } // Setup cached material DFSize size = results.textureFile.GetSize(record); DFSize scale = results.textureFile.GetScale(record); DFPosition offset = results.textureFile.GetOffset(record); Vector2[] recordSizes = new Vector2[1] { new Vector2(size.Width, size.Height) }; Vector2[] recordScales = new Vector2[1] { new Vector2(scale.Width, scale.Height) }; Vector2[] recordOffsets = new Vector2[1] { new Vector2(offset.X, offset.Y) }; CachedMaterial newcm = new CachedMaterial() { key = key, keyGroup = 0, albedoMap = results.albedoMap, normalMap = results.normalMap, emissionMap = results.emissionMap, singleRect = rectOut, material = material, filterMode = MainFilterMode, isWindow = results.isWindow, recordSizes = recordSizes, recordScales = recordScales, recordOffsets = recordOffsets, singleFrameCount = results.textureFile.GetFrameCount(record), }; materialDict.Add(key, newcm); return(material); }