protected override void OnDisableFunc() { if (current != this) { return; } current = null; if (culledResultsBuffer != null) { culledResultsBuffer.Dispose(); } if (loadedBuffer != null) { loadedBuffer.Dispose(); } if (dispatchDrawBuffer != null) { dispatchDrawBuffer.Dispose(); } if (loadedBufferList.isCreated) { loadedBufferList.Dispose(); } tree.Dispose(); vt.Dispose(); loadDataList.Dispose(); loader.Dispose(); allLodLevles.Dispose(); textureBuffer.Dispose(); DestroyImmediate(albedoTex); DestroyImmediate(normalTex); DestroyImmediate(smTex); DestroyImmediate(mask); }
protected override void OnEnableFunc() { if (current && current != this) { enabled = false; Debug.LogError("Only One Terrain allowed!"); return; } current = this; //virtualTexture = new VirtualTexture() basicChunkSize = (float)(chunkSize / pow(2.0, max(1, lodDistances.Length))); InitializeMesh(); dispatchDrawBuffer = new ComputeBuffer(5, sizeof(int), ComputeBufferType.IndirectArguments); removeIndexBuffer = new ComputeBuffer(10, sizeof(int2)); const int INIT_LENGTH = 200; culledResultsBuffer = new ComputeBuffer(INIT_LENGTH, sizeof(int)); loadedBuffer = new ComputeBuffer(INIT_LENGTH, sizeof(TerrainChunkBuffer)); loadedBufferList = new NativeList <TerrainChunkBuffer>(INIT_LENGTH, Allocator.Persistent); shader = Resources.Load <ComputeShader>("TerrainCompute"); NativeArray <uint> dispatchDraw = new NativeArray <uint>(5, Allocator.Temp, NativeArrayOptions.ClearMemory); dispatchDraw[0] = (uint)meshBuffer.count; dispatchDrawBuffer.SetData(dispatchDraw); loadedBufferList.Add(new TerrainChunkBuffer { minMaxHeight = 0, scale = 10, worldPos = 0 }); UpdateBuffer(); }
protected override void OnDisableFunc() { if (current != this) { return; } current = null; if (meshBuffer != null) { meshBuffer.Dispose(); } if (removeIndexBuffer != null) { removeIndexBuffer.Dispose(); } if (culledResultsBuffer != null) { culledResultsBuffer.Dispose(); } if (loadedBuffer != null) { loadedBuffer.Dispose(); } if (dispatchDrawBuffer != null) { dispatchDrawBuffer.Dispose(); } if (loadedBufferList.isCreated) { loadedBufferList.Dispose(); } }
protected override void OnDisableFunc() { if (current != this) { return; } current = null; if (culledResultsBuffer != null) { culledResultsBuffer.Dispose(); } if (loadedBuffer != null) { loadedBuffer.Dispose(); } if (dispatchDrawBuffer != null) { dispatchDrawBuffer.Dispose(); } if (loadedBufferList.isCreated) { loadedBufferList.Dispose(); } int2 len = allTrees.Length; for (int x = 0; x < len.x; ++x) { for (int y = 0; y < len.y; ++y) { allTrees[int2(x, y)].Dispose(); } } allTrees.Dispose(); }
protected override void OnEnableFunc() { if (current && current != this) { enabled = false; Debug.LogError("Only One Terrain allowed!"); return; } current = this; int indexMapSize = 1; for (int i = 1; i < lodDistances.Length; ++i) { indexMapSize *= 2; } indexMapSize *= chunkCount; NativeArray <VirtualTextureFormat> allFormats = new NativeArray <VirtualTextureFormat>(4, Allocator.Temp, NativeArrayOptions.UninitializedMemory); allFormats[0] = new VirtualTextureFormat(VirtualTextureSize.x512, RenderTextureFormat.RHalf, "_VirtualHeightMap"); allFormats[1] = new VirtualTextureFormat(VirtualTextureSize.x1024, RenderTextureFormat.ARGB32, "_VirtualAlbedoMap"); allFormats[2] = new VirtualTextureFormat(VirtualTextureSize.x1024, RenderTextureFormat.ARGB32, "_VirtualNormalMap"); allFormats[3] = new VirtualTextureFormat(VirtualTextureSize.x1024, RenderTextureFormat.ARGB32, "_VirtualSMOMap"); virtualTexture = new VirtualTexture(129, indexMapSize, allFormats); allFormats.Dispose(); InitializeMesh(); dispatchDrawBuffer = new ComputeBuffer(5, sizeof(int), ComputeBufferType.IndirectArguments); const int INIT_LENGTH = 500; culledResultsBuffer = new ComputeBuffer(INIT_LENGTH, sizeof(int)); loadedBuffer = new ComputeBuffer(INIT_LENGTH, sizeof(TerrainChunkBuffer)); loadedBufferList = new NativeList <TerrainChunkBuffer>(INIT_LENGTH, Allocator.Persistent); shader = Resources.Load <ComputeShader>("TerrainCompute"); NativeArray <uint> dispatchDraw = new NativeArray <uint>(5, Allocator.Temp, NativeArrayOptions.ClearMemory); dispatchDraw[0] = (uint)meshBuffer.count; dispatchDrawBuffer.SetData(dispatchDraw); allTrees = new Native2DArray <TerrainQuadTree>(chunkCount, Allocator.Persistent, true); setting = new TerrainQuadTreeSettings { allLodLevles = new NativeList_Float(lodDistances.Length + 1, Allocator.Persistent), largestChunkSize = chunkSize, screenOffset = chunkOffset }; for (int i = 0; i < lodDistances.Length; ++i) { setting.allLodLevles.Add(min(lodDistances[max(0, i - 1)], lodDistances[i])); setting.allLodLevles[i] *= setting.allLodLevles[i]; } setting.allLodLevles[lodDistances.Length] = 0; int2 len = allTrees.Length; for (int x = 0; x < len.x; ++x) { for (int y = 0; y < len.y; ++y) { allTrees[int2(x, y)] = new TerrainQuadTree(-1, setting.Ptr(), TerrainQuadTree.LocalPos.LeftDown, 0, int2(x, y)); } } }
protected override void OnEnableFunc() { if (current && current != this) { enabled = false; Debug.LogError("Only One Terrain allowed!"); return; } current = this; //virtualTexture = new VirtualTexture() basicChunkSize = (float)(chunkSize / pow(2.0, max(1, lodDistances.Length))); InitializeMesh(); dispatchDrawBuffer = new ComputeBuffer(5, sizeof(int), ComputeBufferType.IndirectArguments); removeIndexBuffer = new ComputeBuffer(10, sizeof(int2)); const int INIT_LENGTH = 200; culledResultsBuffer = new ComputeBuffer(INIT_LENGTH, sizeof(int)); loadedBuffer = new ComputeBuffer(INIT_LENGTH, sizeof(TerrainChunkBuffer)); loadedBufferList = new NativeList <TerrainChunkBuffer>(INIT_LENGTH, Allocator.Persistent); shader = Resources.Load <ComputeShader>("TerrainCompute"); NativeArray <uint> dispatchDraw = new NativeArray <uint>(5, Allocator.Temp, NativeArrayOptions.ClearMemory); dispatchDraw[0] = (uint)meshBuffer.count; dispatchDrawBuffer.SetData(dispatchDraw); allTrees = new Native2DArray <TerrainQuadTree>(chunkCount, Allocator.Persistent, true); setting = new TerrainQuadTreeSettings { allLodLevles = new NativeList_Float(lodDistances.Length + 1, Allocator.Persistent), largestChunkSize = chunkSize, screenOffset = chunkOffset }; for (int i = 0; i < lodDistances.Length; ++i) { setting.allLodLevles.Add(min(lodDistances[max(0, i - 1)], lodDistances[i])); setting.allLodLevles[i] *= setting.allLodLevles[i]; } setting.allLodLevles[lodDistances.Length] = 0; int2 len = allTrees.Length; for (int x = 0; x < len.x; ++x) { for (int y = 0; y < len.y; ++y) { allTrees[int2(x, y)] = new TerrainQuadTree(-1, setting.Ptr(), TerrainQuadTree.LocalPos.LeftDown, 0, int2(x, y)); } } }
protected override void OnEnableFunc() { if (current && current != this) { enabled = false; Debug.LogError("Only One Terrain allowed!"); return; } if (!terrainData) { enabled = false; Debug.LogError("No Data!"); return; } msb = new MStringBuilder(32); textureShader = Resources.Load <ComputeShader>("ProceduralTexture"); shader = Resources.Load <ComputeShader>("TerrainCompute"); current = this; int indexMapSize = 1; for (int i = 1; i < terrainData.lodDistances.Length; ++i) { indexMapSize *= 2; } dispatchDrawBuffer = new ComputeBuffer(5, sizeof(int), ComputeBufferType.IndirectArguments); const int INIT_LENGTH = 500; culledResultsBuffer = new ComputeBuffer(INIT_LENGTH, sizeof(int)); loadedBuffer = new ComputeBuffer(INIT_LENGTH, sizeof(TerrainChunkBuffer)); loadedBufferList = new NativeList <TerrainChunkBuffer>(INIT_LENGTH, Allocator.Persistent); lodOffset = terrainData.lodDistances.Length - terrainData.renderingLevelCount; loader = new VirtualTextureLoader(lodOffset, terrainData.renderingLevelCount, terrainData.readWritePath, this); loadDataList = new NativeQueue <TerrainLoadData>(100, Allocator.Persistent); NativeArray <uint> dispatchDraw = new NativeArray <uint>(5, Allocator.Temp, NativeArrayOptions.ClearMemory); dispatchDraw[0] = 96; dispatchDrawBuffer.SetData(dispatchDraw); VirtualTextureFormat *formats = stackalloc VirtualTextureFormat[] { new VirtualTextureFormat((VirtualTextureSize)HEIGHT_RESOLUTION, RenderTextureFormat.R16, "_VirtualHeightmap"), new VirtualTextureFormat((VirtualTextureSize)COLOR_RESOLUTION, RenderTextureFormat.ARGB32, "_VirtualMainTex"), new VirtualTextureFormat((VirtualTextureSize)COLOR_RESOLUTION, RenderTextureFormat.RGHalf, "_VirtualBumpMap"), new VirtualTextureFormat((VirtualTextureSize)COLOR_RESOLUTION, RenderTextureFormat.RG16, "_VirtualSMMap") }; vt = new VirtualTexture(terrainData.virtualTexCapacity, min(2048, (int)(pow(2.0, terrainData.lodDistances.Length) + 0.1)), formats, 4, "_TerrainVTIndexTex"); allLodLevles = new NativeList_Float(terrainData.lodDistances.Length, Allocator.Persistent); for (int i = 0; i < terrainData.lodDistances.Length; ++i) { allLodLevles.Add(min(terrainData.lodDistances[max(0, i - 1)], terrainData.lodDistances[i])); } allLodLevles[terrainData.lodDistances.Length] = 0; albedoTex = new RenderTexture(new RenderTextureDescriptor { colorFormat = RenderTextureFormat.ARGB32, dimension = TextureDimension.Tex2DArray, width = COLOR_RESOLUTION, height = COLOR_RESOLUTION, volumeDepth = Mathf.Max(1, terrainData.textures.Length), enableRandomWrite = true, msaaSamples = 1 }); albedoTex.Create(); normalTex = new RenderTexture(new RenderTextureDescriptor { colorFormat = RenderTextureFormat.RGHalf, dimension = TextureDimension.Tex2DArray, width = COLOR_RESOLUTION, height = COLOR_RESOLUTION, volumeDepth = Mathf.Max(1, terrainData.textures.Length), enableRandomWrite = true, msaaSamples = 1 }); normalTex.Create(); smTex = new RenderTexture(new RenderTextureDescriptor { colorFormat = RenderTextureFormat.RG16, dimension = TextureDimension.Tex2DArray, width = COLOR_RESOLUTION, height = COLOR_RESOLUTION, volumeDepth = Mathf.Max(1, terrainData.textures.Length), enableRandomWrite = true, msaaSamples = 1 }); smTex.Create(); smTex.wrapMode = TextureWrapMode.Repeat; normalTex.wrapMode = TextureWrapMode.Repeat; albedoTex.wrapMode = TextureWrapMode.Repeat; mask = new RenderTexture(new RenderTextureDescriptor { colorFormat = RenderTextureFormat.R8, dimension = TextureDimension.Tex2D, width = MASK_RESOLUTION, height = MASK_RESOLUTION, volumeDepth = 1, enableRandomWrite = true, msaaSamples = 1 }); mask.Create(); textureBuffer = new ComputeBuffer(max(MASK_RESOLUTION * MASK_RESOLUTION / 4, HEIGHT_RESOLUTION * HEIGHT_RESOLUTION / 2), 4); tree = new TerrainQuadTree(-1, TerrainQuadTree.LocalPos.LeftDown, 0, terrainData.largestChunkSize); StartCoroutine(AsyncLoader()); } void UpdateBuffer() { if (!loadedBufferList.isCreated) { return; } if (loadedBufferList.Length > loadedBuffer.count) { loadedBuffer.Dispose(); culledResultsBuffer.Dispose(); loadedBuffer = new ComputeBuffer(loadedBufferList.Capacity, sizeof(TerrainChunkBuffer)); culledResultsBuffer = new ComputeBuffer(loadedBufferList.Capacity, sizeof(int)); } loadedBuffer.SetDataPtr(loadedBufferList.unsafePtr, loadedBufferList.Length); }
void OnFinishRead(AsyncGPUReadbackRequest request) { bool useConnection = false; commandQueue.TryDequeue(out useConnection); float depth = request.GetData <float>().Element(0); float4x4 invvp = (GL.GetGPUProjectionMatrix(cam.projectionMatrix, false) * cam.worldToCameraMatrix).inverse; float4 worldPos = mul(invvp, float4(uv * 2 - 1, depth, 1)); worldPos.xyz /= worldPos.w; MTerrain terrain = MTerrain.current; if (!terrain) { return; } NativeList <ulong> allMaskTree = new NativeList <ulong>(5, Allocator.Temp); value = Mathf.Clamp(value, 0, terrain.terrainData.allMaterials.Length - 1); terrain.treeRoot->GetMaterialMaskRoot(worldPos.xz, paintRange, ref allMaskTree); terrainEditShader.SetInt(ShaderIDs._Count, MTerrain.MASK_RESOLUTION); if (!useConnection) { //TODO terrainEditShader.SetVector("_Circle0", float4(worldPos.xz, paintRange, 1)); terrainEditShader.SetVector("_Circle1", float4(worldPos.xz, paintRange, 1)); terrainEditShader.SetMatrix("_QuadMatrix", float4x4(0)); } else { terrain.treeRoot->GetMaterialMaskRoot(lastFrameWorldPos.xz, paintRange, ref allMaskTree); float2 moveDir = lastFrameWorldPos.xz - worldPos.xz; float len = length(moveDir); moveDir /= len; float dotMove = dot(moveDir, moveDir); float2 verticleDir = float2(-moveDir.y / dotMove, moveDir.x / dotMove); float3x3 localToWorld = float3x3(float3(moveDir * len, 0), float3(verticleDir * paintRange * 2, 0), float3((lastFrameWorldPos.xz + worldPos.xz) * 0.5f, 1)); float3x3 worldToLocal = inverse(localToWorld); terrainEditShader.SetVector("_Circle0", float4(worldPos.xz, paintRange, 1)); terrainEditShader.SetVector("_Circle1", float4(lastFrameWorldPos.xz, paintRange, 1)); terrainEditShader.SetMatrix("_QuadMatrix", float4x4(float4(worldToLocal.c0, 0), float4(worldToLocal.c1, 0), float4(worldToLocal.c2, 0), 0)); } const int disp = MTerrain.MASK_RESOLUTION / 8; foreach (var i in allMaskTree) { var treeNodePtr = (TerrainQuadTree *)i; if (treeNodePtr == null) { continue; } int2 maskPos = treeNodePtr->rootPos + (int2)treeNodePtr->maskScaleOffset.yz; int texIndex = terrain.maskVT.GetChunkIndex(maskPos); if (texIndex < 0) { continue; } terrainEditShader.SetVector("_SrcDestCorner", (float4)treeNodePtr->BoundedWorldPos); terrainEditShader.SetInt(ShaderIDs._OffsetIndex, texIndex); PaintMask(terrain, treeNodePtr, texIndex, disp); } if (!useConnection) { terrain.treeRoot->UpdateChunks(double3(worldPos.xz, paintRange)); } else { terrain.treeRoot->UpdateChunks(double3(0.5f * (worldPos.xz + lastFrameWorldPos.xz), 0.5f * distance(worldPos.xz, lastFrameWorldPos.xz) + paintRange)); } lastFrameWorldPos = worldPos.xyz; }
void PaintMask(MTerrain terrain, TerrainQuadTree *treeNodePtr, int texIndex, int disp) { terrainEditShader.SetTexture(1, ShaderIDs._DestTex, terrain.maskVT.GetTexture(0)); terrainEditShader.SetFloat("_TargetValue", saturate((float)((value + 0.1) / (terrain.terrainData.allMaterials.Length - 1)))); terrainEditShader.Dispatch(1, disp, disp, 1); }