/// <summary> /// Init Virtual Texture /// </summary> /// <param name="perTextureSize">Virtual texture's basic size</param> /// <param name="maximumSize">Virtual texture's array size</param> /// <param name="indexSize">Index Texture's size</param> /// <param name="formats">Each VT's format</param> public VirtualTexture(int maximumSize, int2 indexSize, VirtualTextureFormat *formats, int formatLen, string indexTexName) { if (maximumSize > 2048) { throw new System.Exception("Virtual Texture Maximum Size can not larger than 2048"); } indexTexID = Shader.PropertyToID(indexTexName); this.indexSize = indexSize; setIndexBuffer = new ComputeBuffer(START_CHUNKSIZE * START_CHUNKSIZE, sizeof(uint)); allFormats = new NativeArray <VirtualTextureFormat>(formatLen, Allocator.Persistent); poolDict = new NativeDictionary <int2, int2, VTChunkHandleEqual>(maximumSize, Allocator.Persistent, new VTChunkHandleEqual()); UnsafeUtility.MemCpy(allFormats.GetUnsafePtr(), formats, sizeof(VirtualTextureFormat) * formatLen); shader = Resources.Load <ComputeShader>("VirtualTexture"); pool = new TexturePool(maximumSize); indexTex = new RenderTexture(indexSize.x, indexSize.y, 0, GraphicsFormat.R16G16B16A16_UNorm, 0); indexTex.enableRandomWrite = true; indexTex.useMipMap = false; indexTex.filterMode = FilterMode.Point; indexTex.Create(); textures = new RenderTexture[formatLen]; for (int i = 0; i < formatLen; ++i) { ref VirtualTextureFormat format = ref formats[i]; textures[i] = new RenderTexture((int)format.perElementSize, (int)format.perElementSize, 0, format.format, format.mipCount); textures[i].autoGenerateMips = false; textures[i].useMipMap = format.mipCount > 0; textures[i].enableRandomWrite = true; textures[i].volumeDepth = maximumSize; textures[i].dimension = TextureDimension.Tex2DArray; textures[i].antiAliasing = 1; textures[i].Create(); }
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)); } } }
public void CombineTexture(int2 startIndex, int targetSize, bool unloadCheck) { if (unloadCheck) { for (int y = 0; y < targetSize; ++y) { for (int x = 0; x < targetSize; ++x) { int2 curIdx = startIndex + int2(x, y); UnloadChunk(ref curIdx); } } } int targetElement; if (!GetChunk(ref startIndex, targetSize, out targetElement)) { return; } int3 *vtPtr = (int3 *)vtVariables.Ptr(); *vtPtr = int3(startIndex, targetSize); shader.SetInts(ShaderIDs._VTVariables, vtVariables); texSize[0] = indexSize.x; texSize[1] = indexSize.y; shader.SetInts(ShaderIDs._IndexTextureSize, texSize); shader.SetTexture(3, ShaderIDs._IndexTexture, indexTex); for (int i = 0; i < allFormats.Length; ++i) { VirtualTextureFormat fmt = allFormats[i]; RenderTexture blendRT = RenderTexture.GetTemporary(new RenderTextureDescriptor { width = (int)fmt.perElementSize, height = (int)fmt.perElementSize, volumeDepth = 1, colorFormat = fmt.format, dimension = TextureDimension.Tex2D, enableRandomWrite = true, msaaSamples = 1 }); blendRT.Create(); shader.SetInt(ShaderIDs._Count, (int)fmt.perElementSize); shader.SetTexture(3, ShaderIDs._TextureBuffer, textures[i]); shader.SetTexture(3, ShaderIDs._BlendTex, blendRT); int disp = Mathf.CeilToInt((int)fmt.perElementSize / 8f); shader.Dispatch(3, disp, disp, 1); Graphics.Blit(blendRT, textures[i], 0, targetElement); RenderTexture.ReleaseTemporary(blendRT); } vtVariables[0] = startIndex.x; vtVariables[1] = startIndex.y; vtVariables[2] = targetSize; vtVariables[3] = targetElement; shader.SetInts(ShaderIDs._VTVariables, vtVariables); shader.SetTexture(0, ShaderIDs._IndexTexture, indexTex); int dispatchCount = Mathf.CeilToInt(targetSize / 8f); shader.Dispatch(0, dispatchCount, dispatchCount, 1); }
/// <summary> /// Init Virtual Texture /// </summary> /// <param name="perTextureSize">Virtual texture's basic size</param> /// <param name="maximumSize">Virtual texture's array size</param> /// <param name="indexSize">Index Texture's size</param> /// <param name="formats">Each VT's format</param> public VirtualTexture(int maximumSize, int indexSize, NativeArray <VirtualTextureFormat> formats) { allFormats = new NativeArray <VirtualTextureFormat>(formats.Length, Allocator.Persistent); UnsafeUtility.MemCpy(allFormats.GetUnsafePtr(), formats.GetUnsafePtr(), sizeof(VirtualTextureFormat) * formats.Length); shader = Resources.Load <ComputeShader>("VirtualTexture"); commandListBuffer = new ComputeBuffer(64, sizeof(SetIndexCommand)); indexBuffers = new Native2DArray <float4>(indexSize, Allocator.Persistent); pool = new TexturePool(maximumSize); indexTex = new RenderTexture(new RenderTextureDescriptor { colorFormat = RenderTextureFormat.ARGBHalf, depthBufferBits = 0, dimension = TextureDimension.Tex2D, enableRandomWrite = true, width = indexSize, height = indexSize, volumeDepth = 1, msaaSamples = 1 }); indexTex.filterMode = FilterMode.Point; indexTex.Create(); textures = new RenderTexture[formats.Length]; for (int i = 0; i < formats.Length; ++i) { VirtualTextureFormat format = formats[i]; textures[i] = new RenderTexture(new RenderTextureDescriptor { colorFormat = format.format, depthBufferBits = 0, dimension = TextureDimension.Tex2DArray, enableRandomWrite = true, width = (int)format.perElementSize, height = (int)format.perElementSize, volumeDepth = maximumSize, msaaSamples = 1 }); textures[i].Create(); } loadNewTexFrameCount = -1; indexBuffers.SetAll(float4(0, 0, 0, -1)); }