1208 lines
32 KiB
C#
1208 lines
32 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using UnityEngine;
|
|
|
|
namespace CTS
|
|
{
|
|
[Serializable]
|
|
public class CTSProfile : ScriptableObject
|
|
{
|
|
[SerializeField]
|
|
private int m_ctsMajorVersion = CTSConstants.MajorVersion;
|
|
|
|
[SerializeField]
|
|
private int m_ctsMinorVersion = CTSConstants.MinorVersion;
|
|
|
|
[SerializeField]
|
|
private int m_ctsPatchVersion = CTSConstants.PatchVersion;
|
|
|
|
public bool m_useMaterialControlBlock;
|
|
|
|
public bool m_showGlobalSettings = true;
|
|
|
|
public bool m_showSnowSettings;
|
|
|
|
public bool m_showTextureSettings;
|
|
|
|
public bool m_showGeoSettings;
|
|
|
|
public bool m_showDetailSettings;
|
|
|
|
public bool m_showColorMapSettings;
|
|
|
|
public bool m_showOptimisationSettings;
|
|
|
|
public string m_ctsDirectory = "Assets/CTS/";
|
|
|
|
[SerializeField]
|
|
private CTSConstants.ShaderType m_shaderType = CTSConstants.ShaderType.Basic;
|
|
|
|
[HideInInspector]
|
|
[SerializeField]
|
|
public CTSConstants.EnvironmentRenderer m_currentRenderPipelineType;
|
|
|
|
public float m_globalUvMixPower = 3f;
|
|
|
|
public float m_globalUvMixStartDistance = 400f;
|
|
|
|
public float m_globalNormalPower = 0.1f;
|
|
|
|
public float m_globalDetailNormalClosePower;
|
|
|
|
public float m_globalDetailNormalCloseTiling = 60f;
|
|
|
|
public float m_globalDetailNormalFarPower;
|
|
|
|
public float m_globalDetailNormalFarTiling = 300f;
|
|
|
|
public float m_globalTerrainSmoothness = 1f;
|
|
|
|
public float m_globalTerrainSpecular = 1f;
|
|
|
|
public float m_globalTesselationPower = 7f;
|
|
|
|
public float m_globalTesselationMinDistance;
|
|
|
|
public float m_globalTesselationMaxDistance = 50f;
|
|
|
|
public float m_globalTesselationPhongStrength = 1f;
|
|
|
|
public CTSConstants.AOType m_globalAOType = CTSConstants.AOType.NormalMapBased;
|
|
|
|
public float m_globalAOPower = 1f;
|
|
|
|
public float m_globalBasemapDistance = 1000f;
|
|
|
|
public bool m_globalStripTexturesAtRuntime = true;
|
|
|
|
public string m_terrainLayerPath = "";
|
|
|
|
public float m_colorMapClosePower;
|
|
|
|
public float m_colorMapFarPower;
|
|
|
|
public float m_colorMapOpacity = 1f;
|
|
|
|
public float m_geoMapCloseOffset;
|
|
|
|
public float m_geoMapClosePower;
|
|
|
|
public float m_geoMapTilingClose = 100f;
|
|
|
|
public float m_geoMapFarOffset;
|
|
|
|
public float m_geoMapFarPower;
|
|
|
|
public float m_geoMapTilingFar = 100f;
|
|
|
|
public float m_snowAmount;
|
|
|
|
public float m_snowMaxAngle = 40f;
|
|
|
|
public float m_snowMaxAngleHardness = 1f;
|
|
|
|
public float m_snowMinHeight = -1000f;
|
|
|
|
public float m_snowMinHeightBlending = 57f;
|
|
|
|
public float m_snowNoisePower = 0.8f;
|
|
|
|
public float m_snowNoiseTiling = 0.02f;
|
|
|
|
public float m_snowNormalScale = 1f;
|
|
|
|
public float m_snowDetailPower = 1f;
|
|
|
|
public float m_snowTilingClose = 6.9f;
|
|
|
|
public float m_snowTilingFar = 3f;
|
|
|
|
public float m_snowBrightness = 1f;
|
|
|
|
public float m_snowBlendNormal = 0.9f;
|
|
|
|
public float m_snowSmoothness = 1f;
|
|
|
|
public Color m_snowTint = new Color(1f, 1f, 1f);
|
|
|
|
public float m_snowSpecular = 1f;
|
|
|
|
public float m_snowHeightmapBlendClose = 1f;
|
|
|
|
public float m_snowHeightmapBlendFar = 1f;
|
|
|
|
public float m_snowHeightmapDepth = 8f;
|
|
|
|
public float m_snowHeightmapContrast = 1f;
|
|
|
|
public float m_snowHeightmapMinValue;
|
|
|
|
public float m_snowHeightmapMaxValue = 1f;
|
|
|
|
public float m_snowTesselationDepth;
|
|
|
|
public float m_snowAOStrength = 1f;
|
|
|
|
public Vector4 m_snowAverage;
|
|
|
|
private static TextureFormat m_workTextureFormat = TextureFormat.RGBA32;
|
|
|
|
public bool terrainLayerAssetRebuild;
|
|
|
|
public TextureFormat m_albedoFormat = TextureFormat.DXT5;
|
|
|
|
public int m_albedoAniso = 8;
|
|
|
|
public FilterMode m_albedoFilterMode = FilterMode.Bilinear;
|
|
|
|
[SerializeField]
|
|
private CTSConstants.TextureSize m_albedoTextureSize = CTSConstants.TextureSize.Texture_1024;
|
|
|
|
public int m_albedoTextureSizePx = 1024;
|
|
|
|
[SerializeField]
|
|
private bool m_albedoCompress = true;
|
|
|
|
public TextureFormat m_normalFormat = TextureFormat.DXT5;
|
|
|
|
public int m_normalAniso = 8;
|
|
|
|
public FilterMode m_normalFilterMode = FilterMode.Bilinear;
|
|
|
|
[SerializeField]
|
|
private CTSConstants.TextureSize m_normalTextureSize = CTSConstants.TextureSize.Texture_1024;
|
|
|
|
public int m_normalTextureSizePx = 1024;
|
|
|
|
[SerializeField]
|
|
private bool m_normalCompress = true;
|
|
|
|
public int m_globalDetailNormalMapIdx = -1;
|
|
|
|
[SerializeField]
|
|
private Texture2D m_globalDetailNormalMap;
|
|
|
|
public int m_snowAlbedoTextureIdx = -1;
|
|
|
|
[SerializeField]
|
|
private Texture2D m_snowAlbedoTexture;
|
|
|
|
public int m_snowNormalTextureIdx = -1;
|
|
|
|
[SerializeField]
|
|
private Texture2D m_snowNormalTexture;
|
|
|
|
public int m_snowHeightTextureIdx = -1;
|
|
|
|
[SerializeField]
|
|
private Texture2D m_snowHeightTexture;
|
|
|
|
public int m_snowAOTextureIdx = -1;
|
|
|
|
[SerializeField]
|
|
private Texture2D m_snowAOTexture;
|
|
|
|
public int m_snowEmissionTextureIdx = -1;
|
|
|
|
[SerializeField]
|
|
private Texture2D m_snowEmissionTexture;
|
|
|
|
[SerializeField]
|
|
private Texture2D m_snowGlitterTexture;
|
|
|
|
public float m_snowGlitterColorPower = 0.2f;
|
|
|
|
public float m_snowGlitterNoiseThreshold = 0.991f;
|
|
|
|
public float m_snowGlitterSpecularPower = 0.2f;
|
|
|
|
public float m_snowGlitterSmoothness = 0.9f;
|
|
|
|
public float m_snowGlitterRefreshSpeed = 4f;
|
|
|
|
public float m_snowGlitterTiling = 2.5f;
|
|
|
|
[SerializeField]
|
|
private Texture2D m_geoAlbedoTexture;
|
|
|
|
[SerializeField]
|
|
private List<CTSTerrainTextureDetails> m_terrainTextures = new List<CTSTerrainTextureDetails>();
|
|
|
|
[SerializeField]
|
|
private List<Texture2D> m_replacementTerrainAlbedos = new List<Texture2D>();
|
|
|
|
[SerializeField]
|
|
private List<Texture2D> m_replacementTerrainNormals = new List<Texture2D>();
|
|
|
|
[SerializeField]
|
|
private Texture2DArray m_albedosTextureArray;
|
|
|
|
public bool m_needsAlbedosArrayUpdate;
|
|
|
|
[SerializeField]
|
|
private Texture2DArray m_normalsTextureArray;
|
|
|
|
public bool m_needsNormalsArrayUpdate;
|
|
|
|
[SerializeField]
|
|
public TerrainLayer[] cachedTerrainLayers;
|
|
|
|
public int MajorVersion
|
|
{
|
|
get
|
|
{
|
|
return m_ctsMajorVersion;
|
|
}
|
|
set
|
|
{
|
|
if (!m_ctsMajorVersion.Equals(value))
|
|
{
|
|
m_ctsMajorVersion = value;
|
|
m_needsAlbedosArrayUpdate = true;
|
|
m_needsNormalsArrayUpdate = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
public int MinorVersion
|
|
{
|
|
get
|
|
{
|
|
return m_ctsMinorVersion;
|
|
}
|
|
set
|
|
{
|
|
if (!m_ctsMinorVersion.Equals(value))
|
|
{
|
|
m_ctsMinorVersion = value;
|
|
m_needsAlbedosArrayUpdate = true;
|
|
m_needsNormalsArrayUpdate = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
public int PatchVersion
|
|
{
|
|
get
|
|
{
|
|
return m_ctsPatchVersion;
|
|
}
|
|
set
|
|
{
|
|
if (!m_ctsPatchVersion.Equals(value))
|
|
{
|
|
m_ctsPatchVersion = value;
|
|
m_needsAlbedosArrayUpdate = true;
|
|
m_needsNormalsArrayUpdate = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
public CTSConstants.ShaderType ShaderType
|
|
{
|
|
get
|
|
{
|
|
return m_shaderType;
|
|
}
|
|
set
|
|
{
|
|
if (m_shaderType != value)
|
|
{
|
|
m_shaderType = value;
|
|
}
|
|
}
|
|
}
|
|
|
|
public CTSConstants.TextureSize AlbedoTextureSize
|
|
{
|
|
get
|
|
{
|
|
return m_albedoTextureSize;
|
|
}
|
|
set
|
|
{
|
|
if (m_albedoTextureSize != value)
|
|
{
|
|
CompleteTerrainShader.SetDirty(this, recordUndo: false, isPlayingAllowed: true);
|
|
m_albedoTextureSize = value;
|
|
m_albedoTextureSizePx = CTSConstants.GetTextureSize(m_albedoTextureSize);
|
|
m_needsAlbedosArrayUpdate = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
public bool AlbedoCompressionEnabled
|
|
{
|
|
get
|
|
{
|
|
return m_albedoCompress;
|
|
}
|
|
set
|
|
{
|
|
if (m_albedoCompress != value)
|
|
{
|
|
CompleteTerrainShader.SetDirty(this, recordUndo: false, isPlayingAllowed: true);
|
|
m_albedoCompress = value;
|
|
m_needsAlbedosArrayUpdate = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
public CTSConstants.TextureSize NormalTextureSize
|
|
{
|
|
get
|
|
{
|
|
return m_normalTextureSize;
|
|
}
|
|
set
|
|
{
|
|
if (m_normalTextureSize != value)
|
|
{
|
|
CompleteTerrainShader.SetDirty(this, recordUndo: false, isPlayingAllowed: true);
|
|
m_normalTextureSize = value;
|
|
m_normalTextureSizePx = CTSConstants.GetTextureSize(m_normalTextureSize);
|
|
m_needsNormalsArrayUpdate = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
public bool NormalCompressionEnabled
|
|
{
|
|
get
|
|
{
|
|
return m_normalCompress;
|
|
}
|
|
set
|
|
{
|
|
if (m_normalCompress != value)
|
|
{
|
|
CompleteTerrainShader.SetDirty(this, recordUndo: false, isPlayingAllowed: true);
|
|
m_normalCompress = value;
|
|
m_needsNormalsArrayUpdate = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
public Texture2D GlobalDetailNormalMap
|
|
{
|
|
get
|
|
{
|
|
return m_globalDetailNormalMap;
|
|
}
|
|
set
|
|
{
|
|
if (IsDifferentTexture(m_globalDetailNormalMap, value))
|
|
{
|
|
CompleteTerrainShader.SetDirty(this, recordUndo: false, isPlayingAllowed: true);
|
|
m_globalDetailNormalMap = value;
|
|
m_needsNormalsArrayUpdate = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
public Texture2D SnowAlbedo
|
|
{
|
|
get
|
|
{
|
|
return m_snowAlbedoTexture;
|
|
}
|
|
set
|
|
{
|
|
if (IsDifferentTexture(m_snowAlbedoTexture, value))
|
|
{
|
|
CompleteTerrainShader.SetDirty(this, recordUndo: false, isPlayingAllowed: true);
|
|
m_snowAlbedoTexture = value;
|
|
m_needsAlbedosArrayUpdate = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
public Texture2D SnowNormal
|
|
{
|
|
get
|
|
{
|
|
return m_snowNormalTexture;
|
|
}
|
|
set
|
|
{
|
|
if (IsDifferentTexture(m_snowNormalTexture, value))
|
|
{
|
|
CompleteTerrainShader.SetDirty(this, recordUndo: false, isPlayingAllowed: true);
|
|
m_snowNormalTexture = value;
|
|
m_needsNormalsArrayUpdate = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
public Texture2D SnowHeight
|
|
{
|
|
get
|
|
{
|
|
return m_snowHeightTexture;
|
|
}
|
|
set
|
|
{
|
|
if (IsDifferentTexture(m_snowHeightTexture, value))
|
|
{
|
|
CompleteTerrainShader.SetDirty(this, recordUndo: false, isPlayingAllowed: true);
|
|
m_snowHeightTexture = value;
|
|
m_needsAlbedosArrayUpdate = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
public Texture2D SnowAmbientOcclusion
|
|
{
|
|
get
|
|
{
|
|
return m_snowAOTexture;
|
|
}
|
|
set
|
|
{
|
|
if (IsDifferentTexture(m_snowAOTexture, value))
|
|
{
|
|
CompleteTerrainShader.SetDirty(this, recordUndo: false, isPlayingAllowed: true);
|
|
m_snowAOTexture = value;
|
|
m_needsAlbedosArrayUpdate = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
public Texture2D SnowEmission
|
|
{
|
|
get
|
|
{
|
|
return m_snowEmissionTexture;
|
|
}
|
|
set
|
|
{
|
|
if (IsDifferentTexture(m_snowEmissionTexture, value))
|
|
{
|
|
CompleteTerrainShader.SetDirty(this, recordUndo: false, isPlayingAllowed: true);
|
|
m_snowEmissionTexture = value;
|
|
m_needsAlbedosArrayUpdate = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
public Texture2D SnowGlitter
|
|
{
|
|
get
|
|
{
|
|
return m_snowGlitterTexture;
|
|
}
|
|
set
|
|
{
|
|
if (IsDifferentTexture(m_snowGlitterTexture, value))
|
|
{
|
|
CompleteTerrainShader.SetDirty(this, recordUndo: false, isPlayingAllowed: true);
|
|
m_snowGlitterTexture = value;
|
|
}
|
|
}
|
|
}
|
|
|
|
public Texture2D GeoAlbedo
|
|
{
|
|
get
|
|
{
|
|
return m_geoAlbedoTexture;
|
|
}
|
|
set
|
|
{
|
|
if (IsDifferentTexture(m_geoAlbedoTexture, value))
|
|
{
|
|
CompleteTerrainShader.SetDirty(this, recordUndo: false, isPlayingAllowed: true);
|
|
m_geoAlbedoTexture = value;
|
|
}
|
|
}
|
|
}
|
|
|
|
public List<CTSTerrainTextureDetails> TerrainTextures
|
|
{
|
|
get
|
|
{
|
|
return m_terrainTextures;
|
|
}
|
|
set
|
|
{
|
|
m_terrainTextures = value;
|
|
}
|
|
}
|
|
|
|
public List<Texture2D> ReplacementTerrainAlbedos => m_replacementTerrainAlbedos;
|
|
|
|
public List<Texture2D> ReplacementTerrainNormals => m_replacementTerrainNormals;
|
|
|
|
public Texture2DArray AlbedosTextureArray
|
|
{
|
|
get
|
|
{
|
|
return m_albedosTextureArray;
|
|
}
|
|
set
|
|
{
|
|
CompleteTerrainShader.SetDirty(this, recordUndo: false, isPlayingAllowed: false);
|
|
m_albedosTextureArray = value;
|
|
m_needsAlbedosArrayUpdate = false;
|
|
}
|
|
}
|
|
|
|
public Texture2DArray NormalsTextureArray
|
|
{
|
|
get
|
|
{
|
|
return m_normalsTextureArray;
|
|
}
|
|
set
|
|
{
|
|
CompleteTerrainShader.SetDirty(this, recordUndo: false, isPlayingAllowed: false);
|
|
m_normalsTextureArray = value;
|
|
m_needsNormalsArrayUpdate = false;
|
|
}
|
|
}
|
|
|
|
public bool NeedsArrayUpdate()
|
|
{
|
|
if (m_needsAlbedosArrayUpdate)
|
|
{
|
|
return true;
|
|
}
|
|
if (m_needsNormalsArrayUpdate)
|
|
{
|
|
return true;
|
|
}
|
|
for (int i = 0; i < m_terrainTextures.Count; i++)
|
|
{
|
|
if (m_terrainTextures[i].TextureHasChanged())
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
public void RegenerateArraysIfNecessary()
|
|
{
|
|
for (int i = 0; i < m_terrainTextures.Count; i++)
|
|
{
|
|
}
|
|
if (m_needsAlbedosArrayUpdate)
|
|
{
|
|
ConstructAlbedosTextureArray();
|
|
}
|
|
if (m_needsNormalsArrayUpdate)
|
|
{
|
|
ConstructNormalsTextureArray();
|
|
}
|
|
for (int j = 0; j < m_terrainTextures.Count; j++)
|
|
{
|
|
m_terrainTextures[j].ResetChangedFlags();
|
|
}
|
|
}
|
|
|
|
private void ConstructAlbedosTextureArray()
|
|
{
|
|
m_needsAlbedosArrayUpdate = false;
|
|
List<Texture2D> list = new List<Texture2D>();
|
|
int num = 0;
|
|
CTSTerrainTextureDetails cTSTerrainTextureDetails = null;
|
|
byte minHeight;
|
|
byte maxHeight;
|
|
for (int i = 0; i < m_terrainTextures.Count; i++)
|
|
{
|
|
cTSTerrainTextureDetails = m_terrainTextures[i];
|
|
if (cTSTerrainTextureDetails.Albedo != null)
|
|
{
|
|
Texture2D texture2D = ((!(cTSTerrainTextureDetails.Smoothness == null) || !(cTSTerrainTextureDetails.Roughness == null)) ? BakeAlbedo(cTSTerrainTextureDetails.Albedo, cTSTerrainTextureDetails.Smoothness, cTSTerrainTextureDetails.Roughness) : ((!m_albedoCompress) ? ResizeTexture(cTSTerrainTextureDetails.Albedo, m_albedoFormat, m_albedoAniso, m_albedoTextureSizePx, m_albedoTextureSizePx, mipmap: true, linear: false, compress: false) : ResizeTexture(cTSTerrainTextureDetails.Albedo, m_albedoFormat, m_albedoAniso, m_albedoTextureSizePx, m_albedoTextureSizePx, mipmap: true, linear: false, compress: true)));
|
|
list.Add(texture2D);
|
|
Color linear = texture2D.GetPixels(texture2D.mipmapCount - 1)[0].linear;
|
|
cTSTerrainTextureDetails.m_albedoAverage = new Vector4(linear.r, linear.g, linear.b, linear.a);
|
|
cTSTerrainTextureDetails.m_albedoIdx = num++;
|
|
if ((m_shaderType == CTSConstants.ShaderType.Advanced || m_shaderType == CTSConstants.ShaderType.Tesselation) && (cTSTerrainTextureDetails.Height != null || cTSTerrainTextureDetails.AmbientOcclusion != null))
|
|
{
|
|
list.Add(BakeHAOTexture(cTSTerrainTextureDetails.m_name, cTSTerrainTextureDetails.Height, cTSTerrainTextureDetails.AmbientOcclusion, out minHeight, out maxHeight));
|
|
if (cTSTerrainTextureDetails.Height != null)
|
|
{
|
|
cTSTerrainTextureDetails.m_heightIdx = num;
|
|
cTSTerrainTextureDetails.m_heightMin = (float)(int)minHeight / 255f;
|
|
cTSTerrainTextureDetails.m_heightMax = (float)(int)maxHeight / 255f;
|
|
}
|
|
else
|
|
{
|
|
cTSTerrainTextureDetails.m_heightIdx = -1;
|
|
}
|
|
if (cTSTerrainTextureDetails.AmbientOcclusion != null)
|
|
{
|
|
cTSTerrainTextureDetails.m_aoIdx = num;
|
|
}
|
|
else
|
|
{
|
|
cTSTerrainTextureDetails.m_aoIdx = -1;
|
|
}
|
|
num++;
|
|
}
|
|
else
|
|
{
|
|
cTSTerrainTextureDetails.m_aoIdx = -1;
|
|
cTSTerrainTextureDetails.m_heightIdx = -1;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
cTSTerrainTextureDetails.m_albedoIdx = -1;
|
|
}
|
|
cTSTerrainTextureDetails.m_albedoWasChanged = false;
|
|
}
|
|
if (m_snowAlbedoTexture != null)
|
|
{
|
|
Texture2D texture2D2 = ((!m_albedoCompress) ? ResizeTexture(m_snowAlbedoTexture, m_albedoFormat, m_normalAniso, m_albedoTextureSizePx, m_albedoTextureSizePx, mipmap: true, linear: false, compress: false) : ResizeTexture(m_snowAlbedoTexture, m_albedoFormat, m_normalAniso, m_albedoTextureSizePx, m_albedoTextureSizePx, mipmap: true, linear: false, compress: true));
|
|
Color linear2 = texture2D2.GetPixels(texture2D2.mipmapCount - 1)[0].linear;
|
|
m_snowAverage = new Vector4(linear2.r, linear2.g, linear2.b, linear2.a);
|
|
list.Add(texture2D2);
|
|
m_snowAlbedoTextureIdx = num++;
|
|
}
|
|
else
|
|
{
|
|
m_snowAlbedoTextureIdx = -1;
|
|
}
|
|
if (m_snowHeightTexture != null || m_snowAOTexture != null)
|
|
{
|
|
list.Add(BakeHAOTexture("CTS_SnowHAO", m_snowHeightTexture, m_snowAOTexture, out minHeight, out maxHeight));
|
|
if (m_snowHeightTexture != null)
|
|
{
|
|
m_snowHeightTextureIdx = num;
|
|
m_snowHeightmapMinValue = (float)(int)minHeight / 255f;
|
|
m_snowHeightmapMaxValue = (float)(int)maxHeight / 255f;
|
|
}
|
|
else
|
|
{
|
|
m_snowHeightTextureIdx = -1;
|
|
m_snowHeightmapMinValue = 0f;
|
|
m_snowHeightmapMaxValue = 1f;
|
|
}
|
|
if (m_snowAOTexture != null)
|
|
{
|
|
m_snowAOTextureIdx = num;
|
|
}
|
|
else
|
|
{
|
|
m_snowAOTextureIdx = -1;
|
|
}
|
|
num++;
|
|
}
|
|
else
|
|
{
|
|
m_snowAOTextureIdx = -1;
|
|
m_snowHeightTextureIdx = -1;
|
|
}
|
|
Texture2DArray textureArray = GetTextureArray(list, CTSConstants.TextureType.Albedo, m_albedoAniso);
|
|
AlbedosTextureArray = textureArray;
|
|
}
|
|
|
|
private void ConstructNormalsTextureArray()
|
|
{
|
|
m_needsNormalsArrayUpdate = false;
|
|
List<Texture2D> list = new List<Texture2D>();
|
|
int num = 0;
|
|
CTSTerrainTextureDetails cTSTerrainTextureDetails = null;
|
|
for (int i = 0; i < m_terrainTextures.Count; i++)
|
|
{
|
|
cTSTerrainTextureDetails = m_terrainTextures[i];
|
|
if (cTSTerrainTextureDetails.Normal != null)
|
|
{
|
|
list.Add(BakeNormal(cTSTerrainTextureDetails.Normal));
|
|
cTSTerrainTextureDetails.m_normalIdx = num++;
|
|
}
|
|
else
|
|
{
|
|
cTSTerrainTextureDetails.m_normalIdx = -1;
|
|
}
|
|
cTSTerrainTextureDetails.m_normalWasChanged = false;
|
|
}
|
|
if (m_snowNormalTexture != null)
|
|
{
|
|
list.Add(BakeNormal(m_snowNormalTexture));
|
|
m_snowNormalTextureIdx = num++;
|
|
}
|
|
else
|
|
{
|
|
m_snowNormalTextureIdx = -1;
|
|
}
|
|
if ((bool)m_globalDetailNormalMap)
|
|
{
|
|
list.Add(BakeNormal(m_globalDetailNormalMap));
|
|
m_globalDetailNormalMapIdx = num++;
|
|
}
|
|
else
|
|
{
|
|
m_globalDetailNormalMapIdx = -1;
|
|
}
|
|
Texture2DArray textureArray = GetTextureArray(list, CTSConstants.TextureType.Normal, m_normalAniso);
|
|
NormalsTextureArray = textureArray;
|
|
}
|
|
|
|
public void UpdateSettingsFromTerrain(Terrain terrain, bool forceUpdate)
|
|
{
|
|
if (terrain == null || terrain.terrainData == null)
|
|
{
|
|
return;
|
|
}
|
|
if (forceUpdate)
|
|
{
|
|
m_needsAlbedosArrayUpdate = true;
|
|
m_needsNormalsArrayUpdate = true;
|
|
}
|
|
CTSSplatPrototype[] cTSSplatPrototypes = CTSSplatPrototype.GetCTSSplatPrototypes(terrain);
|
|
while (m_terrainTextures.Count > cTSSplatPrototypes.Length)
|
|
{
|
|
m_terrainTextures.RemoveAt(m_terrainTextures.Count - 1);
|
|
m_needsAlbedosArrayUpdate = true;
|
|
m_needsNormalsArrayUpdate = true;
|
|
}
|
|
CTSTerrainTextureDetails cTSTerrainTextureDetails = null;
|
|
for (int i = 0; i < cTSSplatPrototypes.Length; i++)
|
|
{
|
|
CTSSplatPrototype cTSSplatPrototype = cTSSplatPrototypes[i];
|
|
if (i < m_terrainTextures.Count)
|
|
{
|
|
cTSTerrainTextureDetails = m_terrainTextures[i];
|
|
cTSTerrainTextureDetails.Albedo = cTSSplatPrototype.texture;
|
|
cTSTerrainTextureDetails.m_albedoTilingClose = cTSSplatPrototypes[i].tileSize.x;
|
|
cTSTerrainTextureDetails.Normal = cTSSplatPrototype.normalMap;
|
|
}
|
|
else
|
|
{
|
|
cTSTerrainTextureDetails = new CTSTerrainTextureDetails();
|
|
cTSTerrainTextureDetails.m_textureIdx = i;
|
|
cTSTerrainTextureDetails.Albedo = cTSSplatPrototypes[i].texture;
|
|
cTSTerrainTextureDetails.m_albedoTilingClose = cTSSplatPrototypes[i].tileSize.x;
|
|
cTSTerrainTextureDetails.Normal = cTSSplatPrototypes[i].normalMap;
|
|
m_terrainTextures.Add(cTSTerrainTextureDetails);
|
|
}
|
|
}
|
|
RegenerateArraysIfNecessary();
|
|
}
|
|
|
|
private void ImportTexture(Texture2D texture, int textureSize, bool asNormal = false)
|
|
{
|
|
if (!(texture == null))
|
|
{
|
|
Debug.Log("Importing " + texture.name + " " + textureSize);
|
|
}
|
|
}
|
|
|
|
private Color32[] GetTextureColors(Texture2D source, TextureFormat format, int dimensions)
|
|
{
|
|
Texture2D texture2D = ResizeTexture(source, format, m_albedoAniso, dimensions, dimensions, mipmap: false, linear: false, compress: false);
|
|
Color32[] pixels = texture2D.GetPixels32();
|
|
if (!Application.isPlaying)
|
|
{
|
|
UnityEngine.Object.DestroyImmediate(texture2D);
|
|
return pixels;
|
|
}
|
|
UnityEngine.Object.Destroy(texture2D);
|
|
return pixels;
|
|
}
|
|
|
|
public Texture2D BakeHAOTexture(string name, Texture2D hTexture, Texture2D aoTexture, out byte minHeight, out byte maxHeight)
|
|
{
|
|
minHeight = 0;
|
|
maxHeight = byte.MaxValue;
|
|
int num = m_albedoTextureSizePx * m_albedoTextureSizePx;
|
|
if (num == 0)
|
|
{
|
|
return null;
|
|
}
|
|
Texture2D texture2D = new Texture2D(m_albedoTextureSizePx, m_albedoTextureSizePx, m_workTextureFormat, mipChain: true, linear: false);
|
|
texture2D.name = "CTS_" + name + "_HAO";
|
|
texture2D.anisoLevel = m_albedoAniso;
|
|
texture2D.filterMode = m_albedoFilterMode;
|
|
Color32[] pixels = texture2D.GetPixels32();
|
|
if (hTexture != null)
|
|
{
|
|
minHeight = byte.MaxValue;
|
|
maxHeight = 0;
|
|
Texture2D texture2D2 = ResizeTexture(hTexture, m_workTextureFormat, m_albedoAniso, m_albedoTextureSizePx, m_albedoTextureSizePx, mipmap: false, linear: false, compress: false);
|
|
Color32[] pixels2 = texture2D2.GetPixels32();
|
|
for (int i = 0; i < num; i++)
|
|
{
|
|
byte g = pixels2[i].g;
|
|
if (g < minHeight)
|
|
{
|
|
minHeight = g;
|
|
}
|
|
if (g > maxHeight)
|
|
{
|
|
maxHeight = g;
|
|
}
|
|
pixels[i].r = (pixels[i].g = (pixels[i].b = g));
|
|
}
|
|
if (Application.isPlaying)
|
|
{
|
|
UnityEngine.Object.Destroy(texture2D2);
|
|
}
|
|
else
|
|
{
|
|
UnityEngine.Object.DestroyImmediate(texture2D2);
|
|
}
|
|
}
|
|
if (aoTexture != null)
|
|
{
|
|
Texture2D texture2D3 = ResizeTexture(aoTexture, m_workTextureFormat, m_albedoAniso, m_albedoTextureSizePx, m_albedoTextureSizePx, mipmap: false, linear: false, compress: false);
|
|
Color32[] pixels3 = texture2D3.GetPixels32();
|
|
for (int j = 0; j < num; j++)
|
|
{
|
|
pixels[j].a = pixels3[j].g;
|
|
}
|
|
if (Application.isPlaying)
|
|
{
|
|
UnityEngine.Object.Destroy(texture2D3);
|
|
}
|
|
else
|
|
{
|
|
UnityEngine.Object.DestroyImmediate(texture2D3);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for (int k = 0; k < num; k++)
|
|
{
|
|
pixels[k].a = byte.MaxValue;
|
|
}
|
|
}
|
|
texture2D.SetPixels32(pixels);
|
|
texture2D.Apply(updateMipmaps: true);
|
|
if (m_albedoCompress)
|
|
{
|
|
texture2D = CompressTexture(texture2D, m_albedoFormat);
|
|
}
|
|
return texture2D;
|
|
}
|
|
|
|
private Texture2D BakeNormal(Texture2D normalTexture)
|
|
{
|
|
int num = m_normalTextureSizePx * m_normalTextureSizePx;
|
|
if (num == 0 || normalTexture == null)
|
|
{
|
|
return null;
|
|
}
|
|
Texture2D texture2D = new Texture2D(m_normalTextureSizePx, m_normalTextureSizePx, m_workTextureFormat, mipChain: true, linear: true);
|
|
texture2D.name = "CTS_" + base.name + "_Normal";
|
|
texture2D.anisoLevel = m_normalAniso;
|
|
texture2D.filterMode = m_normalFilterMode;
|
|
Color32[] pixels = texture2D.GetPixels32();
|
|
Texture2D texture2D2 = ResizeTexture(normalTexture, m_workTextureFormat, m_normalAniso, m_normalTextureSizePx, m_normalTextureSizePx, mipmap: false, linear: true, compress: false);
|
|
Color32[] pixels2 = texture2D2.GetPixels32();
|
|
for (int i = 0; i < num; i++)
|
|
{
|
|
pixels[i].r = 128;
|
|
pixels[i].g = pixels2[i].g;
|
|
pixels[i].b = 128;
|
|
pixels[i].a = pixels2[i].a;
|
|
}
|
|
if (Application.isPlaying)
|
|
{
|
|
UnityEngine.Object.Destroy(texture2D2);
|
|
}
|
|
else
|
|
{
|
|
UnityEngine.Object.DestroyImmediate(texture2D2);
|
|
}
|
|
texture2D.SetPixels32(pixels);
|
|
texture2D.Apply(updateMipmaps: true);
|
|
if (m_normalCompress)
|
|
{
|
|
texture2D = CompressTexture(texture2D, m_normalFormat);
|
|
}
|
|
return texture2D;
|
|
}
|
|
|
|
private Texture2D BakeAlbedo(Texture2D albedoTexture, Texture2D smoothnessTexture, Texture2D roughnessTexture)
|
|
{
|
|
int num = m_normalTextureSizePx * m_normalTextureSizePx;
|
|
if (num == 0)
|
|
{
|
|
return null;
|
|
}
|
|
Texture2D texture2D = new Texture2D(m_albedoTextureSizePx, m_albedoTextureSizePx, m_workTextureFormat, mipChain: true, linear: false);
|
|
texture2D.name = "CTS_" + base.name + "_ASm";
|
|
texture2D.anisoLevel = m_albedoAniso;
|
|
texture2D.filterMode = m_albedoFilterMode;
|
|
Color32[] pixels = texture2D.GetPixels32();
|
|
if (albedoTexture != null)
|
|
{
|
|
Texture2D texture2D2 = ResizeTexture(albedoTexture, m_workTextureFormat, m_albedoAniso, m_albedoTextureSizePx, m_albedoTextureSizePx, mipmap: false, linear: false, compress: false);
|
|
Color32[] pixels2 = texture2D2.GetPixels32();
|
|
for (int i = 0; i < num; i++)
|
|
{
|
|
pixels[i].r = pixels2[i].r;
|
|
pixels[i].g = pixels2[i].g;
|
|
pixels[i].b = pixels2[i].b;
|
|
}
|
|
if (Application.isPlaying)
|
|
{
|
|
UnityEngine.Object.Destroy(texture2D2);
|
|
}
|
|
else
|
|
{
|
|
UnityEngine.Object.DestroyImmediate(texture2D2);
|
|
}
|
|
}
|
|
if (roughnessTexture != null && smoothnessTexture == null)
|
|
{
|
|
Texture2D texture2D3 = ResizeTexture(roughnessTexture, m_workTextureFormat, m_albedoAniso, m_albedoTextureSizePx, m_albedoTextureSizePx, mipmap: false, linear: false, compress: false);
|
|
Color32[] pixels3 = texture2D3.GetPixels32();
|
|
for (int j = 0; j < num; j++)
|
|
{
|
|
pixels[j].a = (byte)(255 - pixels3[j].g);
|
|
}
|
|
if (Application.isPlaying)
|
|
{
|
|
UnityEngine.Object.Destroy(texture2D3);
|
|
}
|
|
else
|
|
{
|
|
UnityEngine.Object.DestroyImmediate(texture2D3);
|
|
}
|
|
}
|
|
if (smoothnessTexture != null)
|
|
{
|
|
Texture2D texture2D4 = ResizeTexture(smoothnessTexture, m_workTextureFormat, m_albedoAniso, m_albedoTextureSizePx, m_albedoTextureSizePx, mipmap: false, linear: false, compress: false);
|
|
Color32[] pixels4 = texture2D4.GetPixels32();
|
|
for (int k = 0; k < num; k++)
|
|
{
|
|
pixels[k].a = pixels4[k].g;
|
|
}
|
|
if (Application.isPlaying)
|
|
{
|
|
UnityEngine.Object.Destroy(texture2D4);
|
|
}
|
|
else
|
|
{
|
|
UnityEngine.Object.DestroyImmediate(texture2D4);
|
|
}
|
|
}
|
|
texture2D.SetPixels32(pixels);
|
|
texture2D.Apply(updateMipmaps: true);
|
|
if (m_albedoCompress)
|
|
{
|
|
texture2D = CompressTexture(texture2D, m_albedoFormat);
|
|
}
|
|
return texture2D;
|
|
}
|
|
|
|
private static Texture2D CompressTexture(Texture2D texture, TextureFormat textureFormat)
|
|
{
|
|
texture.Compress(highQuality: true);
|
|
texture.Apply(updateMipmaps: true);
|
|
return texture;
|
|
}
|
|
|
|
private void DebugTextureColorData(string name, Color32 color)
|
|
{
|
|
Debug.Log($"{name} - r{color.r} g{color.g} b{color.b} a{color.a}");
|
|
}
|
|
|
|
private static void SaveTexture(string path, Texture2D texture)
|
|
{
|
|
byte[] bytes = texture.EncodeToPNG();
|
|
File.WriteAllBytes(path + ".png", bytes);
|
|
}
|
|
|
|
public static Texture2D ResizeTexture(Texture2D texture, TextureFormat format, int aniso, int width, int height, bool mipmap, bool linear, bool compress)
|
|
{
|
|
RenderTexture renderTexture = ((!linear) ? RenderTexture.GetTemporary(width, height, 0, RenderTextureFormat.Default, RenderTextureReadWrite.sRGB) : RenderTexture.GetTemporary(width, height, 0, RenderTextureFormat.Default, RenderTextureReadWrite.Linear));
|
|
bool sRGBWrite = GL.sRGBWrite;
|
|
if (linear)
|
|
{
|
|
GL.sRGBWrite = false;
|
|
}
|
|
else
|
|
{
|
|
GL.sRGBWrite = true;
|
|
}
|
|
Graphics.Blit(texture, renderTexture);
|
|
RenderTexture active = RenderTexture.active;
|
|
RenderTexture.active = renderTexture;
|
|
Texture2D texture2D = new Texture2D(width, height, m_workTextureFormat, mipmap, linear);
|
|
texture2D.name = texture.name + " X";
|
|
texture2D.anisoLevel = aniso;
|
|
texture2D.filterMode = texture.filterMode;
|
|
texture2D.wrapMode = texture.wrapMode;
|
|
texture2D.mipMapBias = texture.mipMapBias;
|
|
texture2D.ReadPixels(new Rect(0f, 0f, renderTexture.width, renderTexture.height), 0, 0);
|
|
texture2D.Apply(updateMipmaps: true);
|
|
Texture2D result = CompressTexture(texture2D, format);
|
|
RenderTexture.active = active;
|
|
RenderTexture.ReleaseTemporary(renderTexture);
|
|
GL.sRGBWrite = sRGBWrite;
|
|
return result;
|
|
}
|
|
|
|
private Texture2DArray GetTextureArray(List<Texture2D> sourceTextures, CTSConstants.TextureType textureType, int aniso)
|
|
{
|
|
if (sourceTextures == null)
|
|
{
|
|
return null;
|
|
}
|
|
if (sourceTextures.Count == 0)
|
|
{
|
|
return null;
|
|
}
|
|
Texture2D texture2D = sourceTextures[0];
|
|
TextureFormat format = texture2D.format;
|
|
int width = texture2D.width;
|
|
int height = texture2D.height;
|
|
for (int i = 1; i < sourceTextures.Count; i++)
|
|
{
|
|
if (sourceTextures[i].width != width || sourceTextures[i].height != height)
|
|
{
|
|
Debug.Log($"GetTextureArray : {sourceTextures[i].name} width {sourceTextures[i].width} <> {width}, height {sourceTextures[i].height} <> {height}");
|
|
return null;
|
|
}
|
|
}
|
|
Texture2DArray texture2DArray;
|
|
switch (textureType)
|
|
{
|
|
case CTSConstants.TextureType.Albedo:
|
|
case CTSConstants.TextureType.AmbientOcclusion:
|
|
case CTSConstants.TextureType.Height:
|
|
texture2DArray = new Texture2DArray(width, height, sourceTextures.Count, format, mipChain: true, linear: false);
|
|
break;
|
|
case CTSConstants.TextureType.Normal:
|
|
texture2DArray = new Texture2DArray(width, height, sourceTextures.Count, format, mipChain: true, linear: true);
|
|
break;
|
|
default:
|
|
throw new ArgumentOutOfRangeException("textureType", textureType, null);
|
|
}
|
|
texture2DArray.filterMode = texture2D.filterMode;
|
|
texture2DArray.wrapMode = texture2D.wrapMode;
|
|
texture2DArray.anisoLevel = aniso;
|
|
texture2DArray.mipMapBias = texture2D.mipMapBias;
|
|
for (int j = 0; j < sourceTextures.Count; j++)
|
|
{
|
|
if (sourceTextures[j] != null)
|
|
{
|
|
texture2D = sourceTextures[j];
|
|
for (int k = 0; k < texture2D.mipmapCount; k++)
|
|
{
|
|
Graphics.CopyTexture(texture2D, 0, k, texture2DArray, j, k);
|
|
}
|
|
}
|
|
}
|
|
texture2DArray.Apply(updateMipmaps: false);
|
|
return texture2DArray;
|
|
}
|
|
|
|
public static bool IsDifferentTexture(Texture2D src, Texture2D target)
|
|
{
|
|
if (src == null)
|
|
{
|
|
if (target != null)
|
|
{
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
if (target == null)
|
|
{
|
|
return true;
|
|
}
|
|
if (src.GetInstanceID() != target.GetInstanceID())
|
|
{
|
|
return true;
|
|
}
|
|
if (src.width != target.width)
|
|
{
|
|
return true;
|
|
}
|
|
if (src.height != target.height)
|
|
{
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
public void ConstructTerrainReplacementAlbedos()
|
|
{
|
|
if (Application.isPlaying)
|
|
{
|
|
return;
|
|
}
|
|
while (m_replacementTerrainAlbedos.Count > m_terrainTextures.Count)
|
|
{
|
|
m_replacementTerrainAlbedos.RemoveAt(m_replacementTerrainAlbedos.Count - 1);
|
|
}
|
|
while (m_replacementTerrainAlbedos.Count < m_terrainTextures.Count)
|
|
{
|
|
m_replacementTerrainAlbedos.Add(null);
|
|
}
|
|
string text = m_ctsDirectory + "Terrains/ReplacementTextures/";
|
|
Directory.CreateDirectory(text);
|
|
CTSTerrainTextureDetails cTSTerrainTextureDetails = null;
|
|
for (int i = 0; i < m_terrainTextures.Count; i++)
|
|
{
|
|
cTSTerrainTextureDetails = m_terrainTextures[i];
|
|
if (cTSTerrainTextureDetails.Albedo != null)
|
|
{
|
|
string path = text + cTSTerrainTextureDetails.Albedo.name + "_cts.png";
|
|
if (!File.Exists(path))
|
|
{
|
|
Texture2D texture2D = ResizeTexture(cTSTerrainTextureDetails.Albedo, m_albedoFormat, m_albedoAniso, 64, 64, mipmap: false, linear: true, compress: false);
|
|
texture2D.name = cTSTerrainTextureDetails.Albedo.name + "_cts";
|
|
m_replacementTerrainAlbedos[i] = texture2D;
|
|
byte[] bytes = m_replacementTerrainAlbedos[i].EncodeToPNG();
|
|
File.WriteAllBytes(path, bytes);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
m_replacementTerrainAlbedos[i] = null;
|
|
}
|
|
}
|
|
CompleteTerrainShader.SetDirty(this, recordUndo: false, isPlayingAllowed: true);
|
|
}
|
|
|
|
public void ConstructTerrainReplacementNormals()
|
|
{
|
|
if (Application.isPlaying)
|
|
{
|
|
return;
|
|
}
|
|
while (m_replacementTerrainNormals.Count > m_terrainTextures.Count)
|
|
{
|
|
m_replacementTerrainNormals.RemoveAt(m_replacementTerrainNormals.Count - 1);
|
|
}
|
|
while (m_replacementTerrainNormals.Count < m_terrainTextures.Count)
|
|
{
|
|
m_replacementTerrainNormals.Add(null);
|
|
}
|
|
string text = m_ctsDirectory + "Terrains/ReplacementTextures/";
|
|
Directory.CreateDirectory(text);
|
|
CTSTerrainTextureDetails cTSTerrainTextureDetails = null;
|
|
for (int i = 0; i < m_terrainTextures.Count; i++)
|
|
{
|
|
cTSTerrainTextureDetails = m_terrainTextures[i];
|
|
if (cTSTerrainTextureDetails.Normal != null)
|
|
{
|
|
string path = text + cTSTerrainTextureDetails.Normal.name + "_nrm_cts.png";
|
|
if (!File.Exists(path))
|
|
{
|
|
Texture2D texture2D = ResizeTexture(cTSTerrainTextureDetails.Normal, m_normalFormat, m_normalAniso, 64, 64, mipmap: false, linear: true, compress: false);
|
|
texture2D.name = cTSTerrainTextureDetails.Normal.name + "_nrm_cts";
|
|
m_replacementTerrainNormals[i] = texture2D;
|
|
byte[] bytes = m_replacementTerrainNormals[i].EncodeToPNG();
|
|
File.WriteAllBytes(path, bytes);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
m_replacementTerrainNormals[i] = null;
|
|
}
|
|
}
|
|
CompleteTerrainShader.SetDirty(this, recordUndo: false, isPlayingAllowed: true);
|
|
}
|
|
}
|
|
}
|