Heroes_of_Hiis/Assets/Polaris - Low Poly Ecosystem/Polaris - Low Poly Terrain .../Runtime/Scripts/ErosionTool/GErosionApplier.cs

327 lines
14 KiB
C#

#if GRIFFIN
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
namespace Pinwheel.Griffin.ErosionTool
{
public class GErosionApplier
{
public GErosionSimulator Simulator { get; private set; }
private static Material applyGeometryMaterial;
private static Material ApplyGeometryMaterial
{
get
{
if (applyGeometryMaterial == null)
{
applyGeometryMaterial = new Material(GRuntimeSettings.Instance.internalShaders.applyErosionShader);
}
return applyGeometryMaterial;
}
}
private static Material applyTextureMaterial;
private static Material ApplyTextureMaterial
{
get
{
if (applyTextureMaterial == null)
{
applyTextureMaterial = new Material(GRuntimeSettings.Instance.internalShaders.erosionTexturerShader);
}
return applyTextureMaterial;
}
}
private static readonly int HEIGHT_MAP = Shader.PropertyToID("_HeightMap");
private static readonly int SIMULATION_DATA = Shader.PropertyToID("_SimulationData");
private static readonly int FALLOFF_TEXTURE = Shader.PropertyToID("_FalloffTexture");
private static readonly int BOUNDS = Shader.PropertyToID("_Bounds");
private static readonly int MAIN_TEX = Shader.PropertyToID("_MainTex");
private static readonly int EROSION_MAP = Shader.PropertyToID("_ErosionMap");
private static readonly int EROSION_ALBEDO = Shader.PropertyToID("_ErosionAlbedo");
private static readonly int EROSION_METALLIC = Shader.PropertyToID("_ErosionMetallic");
private static readonly int EROSION_SMOOTHNESS = Shader.PropertyToID("_ErosionSmoothness");
private static readonly int EROSION_CHANNEL_INDEX = Shader.PropertyToID("_ErosionChannelIndex");
private static readonly int EROSION_INTENSITY = Shader.PropertyToID("_ErosionIntensity");
private static readonly int EROSION_EXPONENT = Shader.PropertyToID("_ErosionExponent");
private static readonly int DEPOSITION_ALBEDO = Shader.PropertyToID("_DepositionAlbedo");
private static readonly int DEPOSITION_METALLIC = Shader.PropertyToID("_DepositionMetallic");
private static readonly int DEPOSITION_SMOOTHNESS = Shader.PropertyToID("_DepositionSmoothness");
private static readonly int DEPOSITION_CHANNEL_INDEX = Shader.PropertyToID("_DepositionChannelIndex");
private static readonly int DEPOSITION_INTENSITY = Shader.PropertyToID("_DepositionIntensity");
private static readonly int DEPOSITION_EXPONENT = Shader.PropertyToID("_DepositionExponent");
private static readonly int PASS_APPLY_SPLAT = 0;
private static readonly int PASS_APPLY_ALBEDO = 1;
private static readonly int PASS_APPLY_METALLIC = 2;
public GErosionApplier(GErosionSimulator s)
{
Simulator = s;
}
public void ApplyGeometry()
{
List<GStylizedTerrain> terrains = Simulator.GetIntersectedTerrains();
if (terrains.Count == 0)
return;
for (int i = 0; i < terrains.Count; ++i)
{
ApplyGeometry(terrains[i]);
}
for (int i = 0; i < terrains.Count; ++i)
{
UpdateGeometry(terrains[i]);
}
}
private void ApplyGeometry(GStylizedTerrain t)
{
Vector3[] worldCorner = Simulator.GetQuad();
Vector2[] uvCorners = new Vector2[worldCorner.Length];
for (int i = 0; i < uvCorners.Length; ++i)
{
uvCorners[i] = t.WorldPointToUV(worldCorner[i]);
}
Rect dirtyRect = GUtilities.GetRectContainsPoints(uvCorners);
if (!dirtyRect.Overlaps(new Rect(0, 0, 1, 1)))
return;
int resolution = t.TerrainData.Geometry.HeightMapResolution;
RenderTexture rt = new RenderTexture(resolution, resolution, 0, GGeometry.HeightMapRTFormat, RenderTextureReadWrite.Linear);
GCommon.CopyToRT(t.TerrainData.Geometry.HeightMap, rt);
ApplyGeometryMaterial.SetTexture(HEIGHT_MAP, t.TerrainData.Geometry.HeightMap);
ApplyGeometryMaterial.SetTexture(SIMULATION_DATA, Simulator.SimulationData);
ApplyGeometryMaterial.SetTexture(FALLOFF_TEXTURE, Simulator.FalloffTexture);
ApplyGeometryMaterial.SetVector(BOUNDS, Simulator.Bounds);
GCommon.DrawQuad(rt, uvCorners, ApplyGeometryMaterial, 0);
Color[] oldHeightMapColors = t.TerrainData.Geometry.HeightMap.GetPixels();
RenderTexture.active = rt;
t.TerrainData.Geometry.HeightMap.ReadPixels(new Rect(0, 0, resolution, resolution), 0, 0);
t.TerrainData.Geometry.HeightMap.Apply();
RenderTexture.active = null;
Color[] newHeightMapColors = t.TerrainData.Geometry.HeightMap.GetPixels();
rt.Release();
GUtilities.DestroyObject(rt);
List<Rect> dirtyRects = new List<Rect>(GCommon.CompareTerrainTexture(t.TerrainData.Geometry.ChunkGridSize, oldHeightMapColors, newHeightMapColors));
for (int i = 0; i < dirtyRects.Count; ++i)
{
t.TerrainData.Geometry.SetRegionDirty(dirtyRects[i]);
t.TerrainData.Foliage.SetTreeRegionDirty(dirtyRects[i]);
t.TerrainData.Foliage.SetGrassRegionDirty(dirtyRects[i]);
}
}
private void UpdateGeometry(GStylizedTerrain t)
{
t.TerrainData.SetDirty(GTerrainData.DirtyFlags.Geometry);
t.UpdateTreesPosition();
t.UpdateGrassPatches();
t.TerrainData.Foliage.ClearTreeDirtyRegions();
t.TerrainData.Foliage.ClearGrassDirtyRegions();
t.TerrainData.SetDirty(GTerrainData.DirtyFlags.Foliage);
}
public void ApplySplat()
{
List<GStylizedTerrain> terrains = Simulator.GetIntersectedTerrains();
if (terrains.Count == 0)
return;
for (int i = 0; i < terrains.Count; ++i)
{
ApplySplat(terrains[i]);
}
}
private void ApplySplat(GStylizedTerrain t)
{
int controlMapCount = t.TerrainData.Shading.SplatControlMapCount;
int controlMapResolution = t.TerrainData.Shading.SplatControlResolution;
RenderTexture[] rtControls = new RenderTexture[controlMapCount];
for (int i = 0; i < controlMapCount; ++i)
{
rtControls[i] = new RenderTexture(controlMapResolution, controlMapResolution, 0, RenderTextureFormat.ARGB32, RenderTextureReadWrite.Linear);
}
if (!Internal_ApplySplat(t, rtControls))
{
for (int i = 0; i < controlMapCount; ++i)
{
rtControls[i].Release();
Object.DestroyImmediate(rtControls[i]);
}
return;
}
for (int i = 0; i < controlMapCount; ++i)
{
Texture2D splatControl = t.TerrainData.Shading.GetSplatControl(i);
RenderTexture.active = rtControls[i];
splatControl.ReadPixels(new Rect(0, 0, controlMapResolution, controlMapResolution), 0, 0);
splatControl.Apply();
RenderTexture.active = null;
rtControls[i].Release();
Object.DestroyImmediate(rtControls[i]);
}
}
public bool Internal_ApplySplat(GStylizedTerrain t, RenderTexture[] rtControls)
{
Vector3[] worldCorner = Simulator.GetQuad();
Vector2[] uvCorners = new Vector2[worldCorner.Length];
for (int i = 0; i < uvCorners.Length; ++i)
{
uvCorners[i] = t.WorldPointToUV(worldCorner[i]);
}
Rect dirtyRect = GUtilities.GetRectContainsPoints(uvCorners);
if (!dirtyRect.Overlaps(new Rect(0, 0, 1, 1)))
return false;
GErosionTexturingConfigs config = Simulator.TexturingConfigs;
Material mat = ApplyTextureMaterial;
mat.SetTexture(EROSION_MAP, Simulator.ErosionMap);
mat.SetTexture(FALLOFF_TEXTURE, Simulator.FalloffTexture);
mat.SetFloat(EROSION_INTENSITY, config.ErosionIntensity);
mat.SetFloat(EROSION_EXPONENT, config.ErosionExponent);
mat.SetFloat(DEPOSITION_INTENSITY, config.DepositionIntensity);
mat.SetFloat(DEPOSITION_EXPONENT, config.DepositionExponent);
int controlMapCount = t.TerrainData.Shading.SplatControlMapCount;
for (int i = 0; i < controlMapCount; ++i)
{
Texture2D control = t.TerrainData.Shading.GetSplatControl(i);
GCommon.CopyToRT(control, rtControls[i]);
mat.SetTexture(MAIN_TEX, control);
if (config.ErosionSplatIndex / 4 == i)
{
mat.SetInt(EROSION_CHANNEL_INDEX, config.ErosionSplatIndex % 4);
}
else
{
mat.SetInt(EROSION_CHANNEL_INDEX, -1);
}
if (config.DepositionSplatIndex / 4 == i)
{
mat.SetInt(DEPOSITION_CHANNEL_INDEX, config.DepositionSplatIndex % 4);
}
else
{
mat.SetInt(DEPOSITION_CHANNEL_INDEX, -1);
}
GCommon.DrawQuad(rtControls[i], uvCorners, mat, PASS_APPLY_SPLAT);
}
return true;
}
public void ApplyAMS()
{
List<GStylizedTerrain> terrains = Simulator.GetIntersectedTerrains();
if (terrains.Count == 0)
return;
for (int i = 0; i < terrains.Count; ++i)
{
ApplyAMS(terrains[i]);
}
}
private void ApplyAMS(GStylizedTerrain t)
{
int albedoResolution = t.TerrainData.Shading.AlbedoMapResolution;
RenderTexture rtAlbedo = new RenderTexture(albedoResolution, albedoResolution, 0, RenderTextureFormat.ARGB32, RenderTextureReadWrite.Linear);
int metallicResolution = t.TerrainData.Shading.MetallicMapResolution;
RenderTexture rtMetallic = new RenderTexture(metallicResolution, metallicResolution, 0, RenderTextureFormat.ARGB32, RenderTextureReadWrite.Linear);
if (!Internal_ApplyAMS(t, rtAlbedo, rtMetallic))
{
rtAlbedo.Release();
Object.DestroyImmediate(rtAlbedo);
rtMetallic.Release();
Object.DestroyImmediate(rtMetallic);
return;
}
Texture2D albedoMap = t.TerrainData.Shading.AlbedoMap;
RenderTexture.active = rtAlbedo;
albedoMap.ReadPixels(new Rect(0, 0, albedoResolution, albedoResolution), 0, 0);
albedoMap.Apply();
RenderTexture.active = null;
rtAlbedo.Release();
Object.DestroyImmediate(rtAlbedo);
Texture2D metallicMap = t.TerrainData.Shading.MetallicMap;
RenderTexture.active = rtMetallic;
metallicMap.ReadPixels(new Rect(0, 0, metallicResolution, metallicResolution), 0, 0);
metallicMap.Apply();
RenderTexture.active = null;
rtMetallic.Release();
Object.DestroyImmediate(rtMetallic);
}
public bool Internal_ApplyAMS(GStylizedTerrain t, RenderTexture rtAlbedo, RenderTexture rtMetallic)
{
Vector3[] worldCorner = Simulator.GetQuad();
Vector2[] uvCorners = new Vector2[worldCorner.Length];
for (int i = 0; i < uvCorners.Length; ++i)
{
uvCorners[i] = t.WorldPointToUV(worldCorner[i]);
}
Rect dirtyRect = GUtilities.GetRectContainsPoints(uvCorners);
if (!dirtyRect.Overlaps(new Rect(0, 0, 1, 1)))
return false;
GCommon.CopyToRT(t.TerrainData.Shading.AlbedoMap, rtAlbedo);
GCommon.CopyToRT(t.TerrainData.Shading.MetallicMap, rtMetallic);
GErosionTexturingConfigs config = Simulator.TexturingConfigs;
Material mat = ApplyTextureMaterial;
mat.SetTexture(EROSION_MAP, Simulator.ErosionMap);
mat.SetTexture(FALLOFF_TEXTURE, Simulator.FalloffTexture);
mat.SetFloat(EROSION_INTENSITY, config.ErosionIntensity);
mat.SetFloat(EROSION_EXPONENT, config.ErosionExponent);
mat.SetColor(EROSION_ALBEDO, config.ErosionAlbedo);
mat.SetFloat(EROSION_METALLIC, config.ErosionMetallic);
mat.SetFloat(EROSION_SMOOTHNESS, config.ErosionSmoothness);
mat.SetFloat(DEPOSITION_INTENSITY, config.DepositionIntensity);
mat.SetFloat(DEPOSITION_EXPONENT, config.DepositionExponent);
mat.SetColor(DEPOSITION_ALBEDO, config.DepositionAlbedo);
mat.SetFloat(DEPOSITION_METALLIC, config.DepositionMetallic);
mat.SetFloat(DEPOSITION_SMOOTHNESS, config.DepositionSmoothness);
mat.SetTexture(MAIN_TEX, t.TerrainData.Shading.AlbedoMap);
GCommon.DrawQuad(rtAlbedo, uvCorners, mat, PASS_APPLY_ALBEDO);
mat.SetTexture(MAIN_TEX, t.TerrainData.Shading.MetallicMap);
GCommon.DrawQuad(rtMetallic, uvCorners, mat, PASS_APPLY_METALLIC);
return true;
}
}
}
#endif