public static void BlendArray(ref Serializable2DFloatArray baseData, Serializable2DFloatArray blendingData, Serializable2DFloatArray stencil, MMTerrainLayer.EMMTerrainLayerBlendMode blendMode, Common.Coord offset, Common.Coord max, Common.Coord originalSize) { if (blendingData == null) { return; } if (baseData == null) { baseData = blendingData; return; } var width = baseData.Width; var height = baseData.Height; if (TerrainWrapper.ComputeShaders && ShouldCompute(baseData)) { var blendShader = ComputeShaderPool.GetShader("MadMaps/WorldStamp/ComputeShaders/BlendFloatArray"); int kernelHandle = blendShader.FindKernel("BlendFloats"); //var baseBuffer = new ComputeBuffer(baseData.Width * baseData.Height, sizeof(float)); var baseBuffer = ComputeShaderPool.GetBuffer(baseData.Width * baseData.Height, sizeof(float)); baseBuffer.SetData(baseData.Data); blendShader.SetBuffer(kernelHandle, "_Base", baseBuffer); blendShader.SetVector("_BaseSize", new Vector4(baseData.Width, baseData.Height)); //var blendBuffer = new ComputeBuffer(blendingData.Width * blendingData.Height, sizeof(float)); var blendBuffer = ComputeShaderPool.GetBuffer(blendingData.Width * blendingData.Height, sizeof(float)); blendBuffer.SetData(blendingData.Data); blendShader.SetBuffer(kernelHandle, "_Blend", blendBuffer); blendShader.SetVector("_BlendSize", new Vector4(blendingData.Width, blendingData.Height)); ComputeBuffer stencilBuffer = null; if (stencil != null && stencil.Width > 0 && stencil.Height > 0) { //stencilBuffer = new ComputeBuffer(stencil.Width * stencil.Height, sizeof(float)); stencilBuffer = ComputeShaderPool.GetBuffer(stencil.Width * stencil.Height, sizeof(float)); stencilBuffer.SetData(stencil.Data); blendShader.SetBuffer(kernelHandle, "_Stencil", stencilBuffer); blendShader.SetVector("_StencilSize", new Vector4(stencil.Width, stencil.Height)); } else { stencilBuffer = ComputeShaderPool.GetBuffer(1, sizeof(float)); blendShader.SetBuffer(kernelHandle, "_Stencil", stencilBuffer); blendShader.SetVector("_StencilSize", new Vector4(0, 0)); } blendShader.SetInt("_BlendMode", (int)blendMode); blendShader.SetVector("_MinMax", new Vector4(offset.x, offset.z, max.x, max.z)); blendShader.SetVector("_TotalSize", new Vector4(originalSize.x, originalSize.z, 0, 0)); blendShader.Dispatch(kernelHandle, baseData.Width, baseData.Height, 1); baseBuffer.GetData(baseData.Data); /*baseBuffer.Release(); * baseBuffer.Dispose(); * blendBuffer.Release(); * blendBuffer.Dispose();*/ ComputeShaderPool.ReturnBuffer(baseBuffer); ComputeShaderPool.ReturnBuffer(blendBuffer); if (stencilBuffer != null) { /*stencilBuffer.Release(); * stencilBuffer.Dispose();*/ ComputeShaderPool.ReturnBuffer(stencilBuffer); } //Resources.UnloadAsset(blendShader); UseCount++; } else { for (int dx = 0; dx < width; dx++) { for (int dz = 0; dz < height; dz++) { var blendingVal = blendingData[dx, dz]; var baseValue = baseData[dx, dz]; switch (blendMode) { case MMTerrainLayer.EMMTerrainLayerBlendMode.Set: baseData[dx, dz] = blendingVal; break; case MMTerrainLayer.EMMTerrainLayerBlendMode.Additive: baseData[dx, dz] += blendingVal; break; case MMTerrainLayer.EMMTerrainLayerBlendMode.Stencil: var xF = (dx + offset.x) / (float)originalSize.x; var zF = (dz + offset.z) / (float)originalSize.z; float strength; stencil.StencilBilinearSample(new Vector2(xF, zF), out strength); //strength = 1; if (strength > 0) { baseData[dx, dz] = Mathf.Lerp(baseValue, blendingVal, strength); } break; } } } } GC.Collect(3, GCCollectionMode.Forced); }
public static void StencilEraseArray( ref Serializable2DByteArray baseData, Serializable2DFloatArray stencil, Common.Coord min, Common.Coord max, Common.Coord size, bool invert, bool absolute) { if (baseData == null || stencil == null) { return; } var width = baseData.Width; var height = baseData.Height; if (TerrainWrapper.ComputeShaders && ShouldCompute(baseData)) { var blendShader = ComputeShaderPool.GetShader("MadMaps/WorldStamp/ComputeShaders/StencilIntArray"); int kernelHandle = blendShader.FindKernel("StencilInts"); var dataAsInt = baseData.Data.ConvertToIntArray(); //var baseBuffer = new ComputeBuffer(baseData.Width * baseData.Height, sizeof(float)); var baseBuffer = ComputeShaderPool.GetBuffer(baseData.Width * baseData.Height, sizeof(float)); baseBuffer.SetData(dataAsInt); blendShader.SetBuffer(kernelHandle, "_Base", baseBuffer); blendShader.SetVector("_BaseSize", new Vector4(baseData.Width, baseData.Height)); blendShader.SetVector("_MinMax", new Vector4(min.x, min.z, max.x, max.z)); blendShader.SetVector("_TotalSize", new Vector4(size.x, size.z)); //ComputeBuffer stencilBuffer= new ComputeBuffer(stencil.Width * stencil.Height, sizeof(float)); var stencilBuffer = ComputeShaderPool.GetBuffer(stencil.Width * stencil.Height, sizeof(float)); stencilBuffer.SetData(stencil.Data); blendShader.SetBuffer(kernelHandle, "_Stencil", stencilBuffer); blendShader.SetVector("_StencilSize", new Vector4(stencil.Width, stencil.Height)); blendShader.SetBool("_Invert", invert); blendShader.SetBool("_Absolute", absolute); blendShader.Dispatch(kernelHandle, baseData.Width, baseData.Height, 1); baseBuffer.GetData(dataAsInt); for (int i = 0; i < dataAsInt.Length; i++) { var val = dataAsInt[i]; baseData.Data[i] = (byte)Mathf.Clamp(val, 0, 255); } /*baseBuffer.Release(); * baseBuffer.Dispose(); * stencilBuffer.Release(); * stencilBuffer.Dispose(); * Resources.UnloadAsset(blendShader);*/ ComputeShaderPool.ReturnBuffer(baseBuffer); ComputeShaderPool.ReturnBuffer(stencilBuffer); UseCount++; } else { for (var u = 0; u < width; ++u) { var uF = (u + min.x) / (float)size.x; for (var v = 0; v < height; ++v) { var vF = (v + min.z) / (float)size.z; float value; stencil.StencilBilinearSample(new Vector2(uF, vF), out value); var existingValue = baseData[u, v]; var newValue = existingValue; if (absolute) { newValue = (byte)(value > 0 ? existingValue : 0); } else { newValue = (byte)Mathf.Clamp(existingValue * (1 - value), 0, 255); if (invert) { newValue = (byte)Mathf.Clamp(existingValue * value, 0, 255); } } baseData[u, v] = newValue; } } } GC.Collect(3, GCCollectionMode.Forced); }