public void CopyActiveRenderTextureToHeightmap(RectInt sourceRect, Vector2Int dest, TerrainHeightmapSyncControl syncControl) { var source = RenderTexture.active; if (source == null) { throw new InvalidOperationException("Active RenderTexture is null."); } if (sourceRect.x < 0 || sourceRect.y < 0 || sourceRect.xMax > source.width || sourceRect.yMax > source.height) { throw new ArgumentOutOfRangeException("sourceRect"); } else if (dest.x < 0 || dest.x + sourceRect.width > heightmapResolution) { throw new ArgumentOutOfRangeException("dest.x"); } else if (dest.y < 0 || dest.y + sourceRect.height > heightmapResolution) { throw new ArgumentOutOfRangeException("dest.y"); } Internal_CopyActiveRenderTextureToHeightmap(sourceRect, dest.x, dest.y, syncControl); TerrainCallbacks.InvokeHeightmapChangedCallback(this, new RectInt(dest.x, dest.y, sourceRect.width, sourceRect.height), syncControl == TerrainHeightmapSyncControl.HeightAndLod); }
public void DirtyTextureRegion(string textureName, RectInt region, bool allowDelayedCPUSync) { if (String.IsNullOrEmpty(textureName)) { throw new ArgumentNullException("textureName"); } int resolution = 0; if (textureName == AlphamapTextureName) { resolution = alphamapResolution; } else if (textureName == HolesTextureName) { resolution = holesResolution; } else { // TODO: Support generic terrain textures. throw new ArgumentException($"Unrecognized terrain texture name: \"{textureName}\""); } if (region.x < 0 || region.x >= resolution) { throw new ArgumentOutOfRangeException("region.x"); } else if (region.width <= 0 || region.xMax > resolution) { throw new ArgumentOutOfRangeException("region.width"); } if (region.y < 0 || region.y >= resolution) { throw new ArgumentOutOfRangeException("region.y"); } else if (region.height <= 0 || region.yMax > resolution) { throw new ArgumentOutOfRangeException("region.height"); } if (textureName == HolesTextureName) { Internal_DirtyHolesRegion(region.x, region.y, region.width, region.height, allowDelayedCPUSync); return; } // TODO: Support generic terrain textures. Internal_MarkAlphamapDirtyRegion(-1, region.x, region.y, region.width, region.height); if (!allowDelayedCPUSync) { SyncTexture(textureName); } else { TerrainCallbacks.InvokeTextureChangedCallback(this, textureName, region, false); } }
public void DirtyHeightmapRegion(RectInt region, TerrainHeightmapSyncControl syncControl) { int resolution = heightmapResolution; if (region.x < 0 || region.x >= resolution) { throw new ArgumentOutOfRangeException("region.x"); } else if (region.width <= 0 || region.xMax > resolution) { throw new ArgumentOutOfRangeException("region.width"); } if (region.y < 0 || region.y >= resolution) { throw new ArgumentOutOfRangeException("region.y"); } else if (region.height <= 0 || region.yMax > resolution) { throw new ArgumentOutOfRangeException("region.height"); } Internal_DirtyHeightmapRegion(region.x, region.y, region.width, region.height, syncControl); TerrainCallbacks.InvokeHeightmapChangedCallback(this, region, syncControl == TerrainHeightmapSyncControl.HeightAndLod); }
public void CopyActiveRenderTextureToTexture(string textureName, int textureIndex, RectInt sourceRect, Vector2Int dest, bool allowDelayedCPUSync) { if (String.IsNullOrEmpty(textureName)) { throw new ArgumentNullException("textureName"); } var source = RenderTexture.active; if (source == null) { throw new InvalidOperationException("Active RenderTexture is null."); } int textureWidth = 0; int textureHeight = 0; if (textureName == HolesTextureName) { if (textureIndex != 0) { throw new ArgumentOutOfRangeException("textureIndex"); } else if (source == holesTexture) { throw new ArgumentException("source", "Active RenderTexture cannot be holesTexture."); } textureWidth = textureHeight = holesResolution; } else if (textureName == AlphamapTextureName) { if (textureIndex < 0 || textureIndex >= alphamapTextureCount) { throw new ArgumentOutOfRangeException("textureIndex"); } textureWidth = textureHeight = alphamapResolution; } else { // TODO: Support generic terrain textures. throw new ArgumentException($"Unrecognized terrain texture name: \"{textureName}\""); } if (sourceRect.x < 0 || sourceRect.y < 0 || sourceRect.xMax > source.width || sourceRect.yMax > source.height) { throw new ArgumentOutOfRangeException("sourceRect"); } else if (dest.x < 0 || dest.x + sourceRect.width > textureWidth) { throw new ArgumentOutOfRangeException("dest.x"); } else if (dest.y < 0 || dest.y + sourceRect.height > textureHeight) { throw new ArgumentOutOfRangeException("dest.y"); } if (textureName == HolesTextureName) { Internal_CopyActiveRenderTextureToHoles(sourceRect, dest.x, dest.y, allowDelayedCPUSync); return; } var dstTexture = GetAlphamapTexture(textureIndex); // Delay synching back (using ReadPixels) if CopyTexture can be used. // TODO: Checking the format compatibility is difficult as it varies by platforms. For instance copying between ARGB32 RT and RGBA32 Tex seems to be fine on all tested platforms... allowDelayedCPUSync = allowDelayedCPUSync && SupportsCopyTextureBetweenRTAndTexture; if (allowDelayedCPUSync) { if (dstTexture.mipmapCount > 1) { // Composes mip0 in a RT with full mipchain. var tmp = RenderTexture.GetTemporary(new RenderTextureDescriptor(dstTexture.width, dstTexture.height, source.graphicsFormat, source.depthStencilFormat) { sRGB = false, useMipMap = true, autoGenerateMips = false }); if (!tmp.IsCreated()) { tmp.Create(); } Graphics.CopyTexture(dstTexture, 0, 0, tmp, 0, 0); Graphics.CopyTexture(source, 0, 0, sourceRect.x, sourceRect.y, sourceRect.width, sourceRect.height, tmp, 0, 0, dest.x, dest.y); // Generate the mips on the GPU tmp.GenerateMips(); // Copy the full mipchain back to the alphamap texture Graphics.CopyTexture(tmp, dstTexture); RenderTexture.ReleaseTemporary(tmp); } else { Graphics.CopyTexture(source, 0, 0, sourceRect.x, sourceRect.y, sourceRect.width, sourceRect.height, dstTexture, 0, 0, dest.x, dest.y); } // TODO: Support generic terrain textures. Internal_MarkAlphamapDirtyRegion(textureIndex, dest.x, dest.y, sourceRect.width, sourceRect.height); } else { if (SystemInfo.graphicsDeviceType == GraphicsDeviceType.Metal || !SystemInfo.graphicsUVStartsAtTop) { dstTexture.ReadPixels(new Rect(sourceRect.x, sourceRect.y, sourceRect.width, sourceRect.height), dest.x, dest.y); } else { dstTexture.ReadPixels(new Rect(sourceRect.x, source.height - sourceRect.yMax, sourceRect.width, sourceRect.height), dest.x, dest.y); } dstTexture.Apply(true); // TODO: Check if the texture is previously marked dirty? // TODO: Support generic terrain textures. Internal_ClearAlphamapDirtyRegion(textureIndex); } TerrainCallbacks.InvokeTextureChangedCallback(this, textureName, new RectInt(dest.x, dest.y, sourceRect.width, sourceRect.height), !allowDelayedCPUSync); }