#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 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 dirtyRects = new List(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 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 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