public async Task <TextureWithCoords> ApplyFeatureAsync(TextureWithCoords texture, TerrainCardinalResolution resolution, bool canMultistep) { ComputeShaderParametersContainer parametersContainer = new ComputeShaderParametersContainer(); IntVector2 textureSize = texture.TextureSize; var heightComputeBuffer = parametersContainer.AddComputeBufferTemplate(new MyComputeBufferTemplate() { Count = textureSize.X * textureSize.Y, Stride = 4, Type = ComputeBufferType.Default }); var outRenderTexture = parametersContainer.AddComputeShaderTextureTemplate( new MyComputeShaderTextureTemplate() { Size = textureSize, Depth = 24, EnableReadWrite = true, Format = RenderTextureFormat.RFloat, TexWrapMode = TextureWrapMode.Clamp, }); MultistepComputeShader transferComputeShader = new MultistepComputeShader(_computeShaderContainer.HeightTransferShaderPlain, textureSize); var textureToBufferKernel = transferComputeShader.AddKernel("CSHeightTransform_InputTextureToBuffer"); var bufferToTextureKernel = transferComputeShader.AddKernel("CSHeightTransform_BufferToOutputTexture"); transferComputeShader.SetGlobalUniform("g_sideLength", textureSize.X); var inputHeightTexture = parametersContainer.AddExistingComputeShaderTexture(texture.Texture); transferComputeShader.SetTexture("InputHeightTexture", inputHeightTexture, new List <MyKernelHandle>() { textureToBufferKernel }); transferComputeShader.SetTexture("OutputHeightTexture", outRenderTexture, new List <MyKernelHandle>() { bufferToTextureKernel }); transferComputeShader.SetBuffer("HeightBuffer", heightComputeBuffer, new List <MyKernelHandle>() { textureToBufferKernel, bufferToTextureKernel }); ////////////////////////////// MultistepComputeShader thermalErosionComputeShader = new MultistepComputeShader(_computeShaderContainer.TweakedThermalErosionShader, textureSize); var kernel1 = thermalErosionComputeShader.AddKernel("CSTweakedThermal_Precalculation"); var kernel2 = thermalErosionComputeShader.AddKernel("CSTweakedThermal_Erosion"); var configuration = _configurations[resolution]; thermalErosionComputeShader.SetGlobalUniform("g_tParam", configuration.TParam); thermalErosionComputeShader.SetGlobalUniform("g_cParam", configuration.CParam); thermalErosionComputeShader.SetGlobalUniform("g_sideLength", textureSize.X); thermalErosionComputeShader.SetTexture("InputHeightTexture", inputHeightTexture, new List <MyKernelHandle>() { kernel1 }); thermalErosionComputeShader.SetBuffer("HeightBuffer0", heightComputeBuffer, new List <MyKernelHandle>() { kernel1, kernel2 }); var MyHeightBuffer1 = parametersContainer.AddComputeBufferTemplate(new MyComputeBufferTemplate() { Count = textureSize.X * textureSize.Y, Stride = 4, Type = ComputeBufferType.Default }); thermalErosionComputeShader.SetBuffer("HeightBuffer1", MyHeightBuffer1, new List <MyKernelHandle>() { kernel1, kernel2 }); var MyMidTextureBuffer = parametersContainer.AddComputeBufferTemplate(new MyComputeBufferTemplate() { Count = textureSize.X * textureSize.Y, Stride = 4 * 2, Type = ComputeBufferType.Default }); thermalErosionComputeShader.SetBuffer("MidTextureBuffer", MyMidTextureBuffer, new List <MyKernelHandle>() { kernel1, kernel2 }); var outParameters = new ComputeBufferRequestedOutParameters(new List <MyComputeShaderTextureId>() { outRenderTexture }); await _shaderExecutorObject.AddOrder(new ComputeShaderOrder() { OutParameters = outParameters, ParametersContainer = parametersContainer, WorkPacks = new List <ComputeShaderWorkPack>() { new ComputeShaderWorkPack() { Shader = transferComputeShader, DispatchLoops = new List <ComputeShaderDispatchLoop>() { new ComputeShaderDispatchLoop() { DispatchCount = 1, KernelHandles = new List <MyKernelHandle>() { textureToBufferKernel } } } }, new ComputeShaderWorkPack() { DispatchLoops = new List <ComputeShaderDispatchLoop>() { new ComputeShaderDispatchLoop() { DispatchCount = 30, KernelHandles = new List <MyKernelHandle>() { kernel1, kernel2 } }, }, Shader = thermalErosionComputeShader }, new ComputeShaderWorkPack() { Shader = transferComputeShader, DispatchLoops = new List <ComputeShaderDispatchLoop>() { new ComputeShaderDispatchLoop() { DispatchCount = 1, KernelHandles = new List <MyKernelHandle>() { bufferToTextureKernel } } } }, } }); return(new TextureWithCoords(sizedTexture: new TextureWithSize() { Texture = outParameters.RetriveTexture(outRenderTexture), Size = texture.TextureSize }, coords: texture.Coords)); }
public async Task <TextureWithCoords> ApplyFeatureAsync(TextureWithCoords texture, TerrainCardinalResolution resolution, bool canMultistep) { ComputeShaderParametersContainer parametersContainer = new ComputeShaderParametersContainer(); IntVector2 textureSize = texture.TextureSize; var heightComputeBuffer = parametersContainer.AddComputeBufferTemplate(new MyComputeBufferTemplate() { Count = textureSize.X * textureSize.Y, Stride = 4, Type = ComputeBufferType.Default }); var outRenderTexture = parametersContainer.AddComputeShaderTextureTemplate( new MyComputeShaderTextureTemplate() { Depth = 24, EnableReadWrite = true, Format = RenderTextureFormat.RFloat, Size = textureSize, TexWrapMode = TextureWrapMode.Clamp }); MultistepComputeShader transferComputeShader = new MultistepComputeShader(_computeShaderContainer.HeightTransferShaderPlain, textureSize); var textureToBufferKernel = transferComputeShader.AddKernel("CSHeightTransform_InputTextureToBuffer"); var bufferToTextureKernel = transferComputeShader.AddKernel("CSHeightTransform_BufferToOutputTexture"); transferComputeShader.SetGlobalUniform("g_sideLength", textureSize.X); var transferInputHeightTexture = parametersContainer.AddExistingComputeShaderTexture(texture.Texture); transferComputeShader.SetTexture("InputHeightTexture", transferInputHeightTexture, new List <MyKernelHandle>() { textureToBufferKernel }); transferComputeShader.SetTexture("OutputHeightTexture", outRenderTexture, new List <MyKernelHandle>() { bufferToTextureKernel }); transferComputeShader.SetBuffer("HeightBuffer", heightComputeBuffer, new List <MyKernelHandle>() { textureToBufferKernel, bufferToTextureKernel }); ////////////////////////////// //var configuration = // new HydraulicEroderConfiguration() // { // StepCount = 20, // kr_ConstantWaterAddition = 0.000002f, // 0.0001f, // ks_GroundToSedimentFactor = 1f, // ke_WaterEvaporationFactor = 0.05f, // kc_MaxSedimentationFactor = 0.8f, // }; var configuration = _configurations[resolution]; MultistepComputeShader computeShader = new MultistepComputeShader(_computeShaderContainer.HydraulicErosionShader, textureSize); var kernel_water = computeShader.AddKernel("CSHydraulicErosion_Water"); var kernel_erostion = computeShader.AddKernel("CSHydraulicErosion_Erosion"); var kernel_deltaSum = computeShader.AddKernel("CSHydraulicErosion_DeltaSum"); var kernel_clearDelta = computeShader.AddKernel("CSHydraulicErosion_ClearDelta"); var kernel_evaporation = computeShader.AddKernel("CSHydraulicErosion_Evaporation"); var kernel_sedimentationToGround = computeShader.AddKernel("CSHydraulicErosion_SedimentationToGround"); computeShader.SetGlobalUniform("g_sideLength", textureSize.X); computeShader.SetGlobalUniform("g_krParam", configuration.kr_ConstantWaterAddition); computeShader.SetGlobalUniform("g_ksParam", configuration.ks_GroundToSedimentFactor); computeShader.SetGlobalUniform("g_keParam", configuration.ke_WaterEvaporationFactor); computeShader.SetGlobalUniform("g_kcParam", configuration.kc_MaxSedimentationFactor); var allKernels = new List <MyKernelHandle>() { kernel_water, kernel_erostion, kernel_deltaSum, kernel_clearDelta, kernel_evaporation, kernel_sedimentationToGround }; computeShader.SetBuffer("HeightMap", heightComputeBuffer, new List <MyKernelHandle>() { kernel_water, kernel_erostion, kernel_evaporation, kernel_sedimentationToGround }); var waterMap = parametersContainer.AddComputeBufferTemplate(new MyComputeBufferTemplate() { Count = textureSize.X * textureSize.Y, Stride = 4, Type = ComputeBufferType.Default }); computeShader.SetBuffer("WaterMap", waterMap, new List <MyKernelHandle>() { kernel_water, kernel_erostion, kernel_deltaSum, kernel_evaporation, }); var deltaBuffer = parametersContainer.AddComputeBufferTemplate(new MyComputeBufferTemplate() { Count = textureSize.X * textureSize.Y, Stride = 4 * 2 * 9, Type = ComputeBufferType.Default }); computeShader.SetBuffer("DeltaBuffer", deltaBuffer, new List <MyKernelHandle>() { kernel_erostion, kernel_deltaSum, kernel_clearDelta }); var sedimentMap = parametersContainer.AddComputeBufferTemplate(new MyComputeBufferTemplate() { Count = textureSize.X * textureSize.Y, Stride = 4, Type = ComputeBufferType.Default }); computeShader.SetBuffer("SedimentMap", sedimentMap, new List <MyKernelHandle>() { kernel_water, kernel_erostion, kernel_deltaSum, kernel_evaporation, kernel_sedimentationToGround }); var debugTexture = parametersContainer.AddComputeShaderTextureTemplate(new MyComputeShaderTextureTemplate() { Depth = 24, EnableReadWrite = true, Format = RenderTextureFormat.ARGB32, Size = textureSize, TexWrapMode = TextureWrapMode.Clamp }); computeShader.SetTexture("DebugTexture", debugTexture, new List <MyKernelHandle>() { kernel_water, kernel_erostion, kernel_deltaSum, kernel_clearDelta, kernel_evaporation, kernel_sedimentationToGround }); var loopedKernels = new List <MyKernelHandle>() { kernel_water, kernel_erostion, kernel_deltaSum, kernel_clearDelta, kernel_evaporation, }; ComputeBufferRequestedOutParameters outParameters = new ComputeBufferRequestedOutParameters( new List <MyComputeShaderTextureId>() { outRenderTexture }); await _shaderExecutorObject.AddOrder(new ComputeShaderOrder() { ParametersContainer = parametersContainer, OutParameters = outParameters, WorkPacks = new List <ComputeShaderWorkPack>() { new ComputeShaderWorkPack() { Shader = transferComputeShader, DispatchLoops = new List <ComputeShaderDispatchLoop>() { new ComputeShaderDispatchLoop() { DispatchCount = 1, KernelHandles = new List <MyKernelHandle>() { textureToBufferKernel } } } }, new ComputeShaderWorkPack() { DispatchLoops = new List <ComputeShaderDispatchLoop>() { new ComputeShaderDispatchLoop() { DispatchCount = configuration.StepCount, KernelHandles = loopedKernels, }, new ComputeShaderDispatchLoop() { DispatchCount = 1, KernelHandles = new List <MyKernelHandle>() { kernel_sedimentationToGround } } }, Shader = computeShader }, new ComputeShaderWorkPack() { Shader = transferComputeShader, DispatchLoops = new List <ComputeShaderDispatchLoop>() { new ComputeShaderDispatchLoop() { DispatchCount = 1, KernelHandles = new List <MyKernelHandle>() { bufferToTextureKernel } } } }, } }); return(new TextureWithCoords(sizedTexture: new TextureWithSize() { Texture = outParameters.RetriveTexture(outRenderTexture), Size = texture.TextureSize }, coords: texture.Coords)); }
public async Task RenderWeld(WeldTextureDrawingOrder order) { var changedPixelsCount = order.WeldOnTextureInfo.WeldRange.Y - order.WeldOnTextureInfo.WeldRange.X; var parametersContainer = new ComputeShaderParametersContainer(); MultistepComputeShader singleToDuoGrassBillboardShader = new MultistepComputeShader(_computeShaderContainer.WeldRenderingShader, new IntVector2(changedPixelsCount, 1)); var kernel = singleToDuoGrassBillboardShader.AddKernel("CSTerrainWelding_Main"); var allKernels = new List <MyKernelHandle>() { kernel }; var weldTextureInShader = parametersContainer.AddExistingComputeShaderTexture(_weldTexture); singleToDuoGrassBillboardShader.SetTexture("WeldTexture", weldTextureInShader, allKernels); var weldTextureChangesInfo = CalculateWeldTextureChangedPixelsShaderRange(order.WeldOnTextureInfo); var weldTextureChangesInfoInShader = parametersContainer.AddComputeBufferTemplate( new MyComputeBufferTemplate() { BufferData = new WeldTexturePixelChangesInfo[] { weldTextureChangesInfo }, Count = 1, Stride = System.Runtime.InteropServices.Marshal.SizeOf(typeof(WeldTexturePixelChangesInfo)), Type = ComputeBufferType.Default }); singleToDuoGrassBillboardShader.SetBuffer("WeldTextureChangesInfo", weldTextureChangesInfoInShader, allKernels); var samplingDistance = Mathf.RoundToInt(Mathf.Pow(2, Mathf.Max(order.FirstSideInfo.LodLevel, order.SecondSideInfo.LodLevel))); var firstSideChangedPixelsShaderRange = CalculateSideChangedPixelsShaderRange(order.FirstSideInfo, order.FirstSideInfo.SamplingDistance == 0 ? samplingDistance : order.FirstSideInfo.SamplingDistance); var secondSideChangedPixelsShaderRange = CalculateSideChangedPixelsShaderRange(order.SecondSideInfo, order.SecondSideInfo.SamplingDistance == 0 ? samplingDistance : order.SecondSideInfo.SamplingDistance); var terrainSideChangesInfoInShader = parametersContainer.AddComputeBufferTemplate( new MyComputeBufferTemplate() { BufferData = new TerrainSidePixelChangesInfo[] { firstSideChangedPixelsShaderRange, secondSideChangedPixelsShaderRange }, Count = 2, Stride = System.Runtime.InteropServices.Marshal.SizeOf(typeof(TerrainSidePixelChangesInfo)), Type = ComputeBufferType.Default }); singleToDuoGrassBillboardShader.SetBuffer("TerrainSideChangesInfos", terrainSideChangesInfoInShader, allKernels); singleToDuoGrassBillboardShader.SetTexture("FirstHeightTexture", parametersContainer.AddExistingComputeShaderTexture(order.FirstSideInfo.HeightTexture.Texture), allKernels); singleToDuoGrassBillboardShader.SetTexture("SecondHeightTexture", parametersContainer.AddExistingComputeShaderTexture(order.SecondSideInfo.HeightTexture.Texture), allKernels); ComputeBufferRequestedOutParameters outParameters = new ComputeBufferRequestedOutParameters(); await _shaderExecutorObject.AddOrder(new ComputeShaderOrder() { ParametersContainer = parametersContainer, OutParameters = outParameters, WorkPacks = new List <ComputeShaderWorkPack>() { new ComputeShaderWorkPack() { Shader = singleToDuoGrassBillboardShader, DispatchLoops = new List <ComputeShaderDispatchLoop>() { new ComputeShaderDispatchLoop() { DispatchCount = 1, KernelHandles = allKernels } } }, } }); }
public async Task <float[]> Generate(Mesh mesh, string outBufferName, int outBufferStrideInFloat, int outBufferCount, Dictionary <string, ComputeBuffer> additionalComputeBuffers = null, bool meshMustbeUniquefied = true) { // UWAGA. Program shadera uruchamiany po raz dla każdego trójkąta if (meshMustbeUniquefied) { Preconditions.Assert(mesh.vertices.Length == mesh.triangles.Length, $"Vertices count (${mesh.vertices.Length}) is not equal to triangles array count (${mesh.triangles.Length}). Vertices are most propably shared. Uniquefy them!"); } if (additionalComputeBuffers == null) { additionalComputeBuffers = new Dictionary <string, ComputeBuffer>(); } var parametersContainer = new ComputeShaderParametersContainer(); MultistepComputeShader barycentricGeneratorShader = new MultistepComputeShader(ComputeShaderUtils.LoadComputeShader(_shaderName), new IntVector2(mesh.triangles.Length / 3, 1)); var kernel = barycentricGeneratorShader.AddKernel("CS_Main"); var allKernels = new List <MyKernelHandle>() { kernel }; var triangleBufferTemplate = parametersContainer.AddComputeBufferTemplate(new MyComputeBufferTemplate() { BufferData = mesh.triangles, Count = mesh.triangles.Length, Stride = sizeof(int), Type = ComputeBufferType.Default }); barycentricGeneratorShader.SetBuffer("Triangles", triangleBufferTemplate, allKernels); var vertexBufferTemplate = parametersContainer.AddComputeBufferTemplate(new MyComputeBufferTemplate() { BufferData = mesh.vertices, Count = mesh.vertices.Length, Stride = sizeof(float) * 3, Type = ComputeBufferType.Default }); barycentricGeneratorShader.SetBuffer("Vertices", vertexBufferTemplate, allKernels); var normalsBufferTemplate = parametersContainer.AddComputeBufferTemplate(new MyComputeBufferTemplate() { BufferData = mesh.normals, Count = mesh.normals.Length, Stride = sizeof(float) * 3, Type = ComputeBufferType.Default }); barycentricGeneratorShader.SetBuffer("Normals", normalsBufferTemplate, allKernels); var outBarycentricBufferTemplate = parametersContainer.AddComputeBufferTemplate(new MyComputeBufferTemplate() { Count = outBufferCount, Stride = sizeof(float) * outBufferStrideInFloat, Type = ComputeBufferType.Default }); barycentricGeneratorShader.SetBuffer(outBufferName, outBarycentricBufferTemplate, allKernels); foreach (var pair in additionalComputeBuffers) { var id = parametersContainer.AddExistingComputeBuffer(pair.Value); barycentricGeneratorShader.SetBuffer(pair.Key, id, allKernels); } ComputeBufferRequestedOutParameters outParameters = new ComputeBufferRequestedOutParameters(new List <MyComputeBufferId> { outBarycentricBufferTemplate }); await _shaderExecutorObject.AddOrder(new ComputeShaderOrder() { ParametersContainer = parametersContainer, OutParameters = outParameters, WorkPacks = new List <ComputeShaderWorkPack>() { new ComputeShaderWorkPack() { Shader = barycentricGeneratorShader, DispatchLoops = new List <ComputeShaderDispatchLoop>() { new ComputeShaderDispatchLoop() { DispatchCount = 1, KernelHandles = allKernels } } }, } }); DebugCheckVariables.Check(outParameters); float[] outArray = new float[outBufferStrideInFloat * outBufferCount]; outParameters.CreatedBuffers[outBarycentricBufferTemplate].GetData(outArray); return(outArray); }
public async Task <List <Grass2TypeWithIntensity> > GenerateGrassIntenstiyAsync( MyRectangle generationArea, Dictionary <HabitatType, Texture2D> habitatTexturesDict, IntVector2 habitatTexturesSize, UvdSizedTexture pathProximityTexture) { var generatedGrassTypes = _configuration.GrassTypeToSourceHabitats .Where(c => c.Value.Any(k => habitatTexturesDict.ContainsKey(k))).Select(c => c.Key).ToList(); if (!generatedGrassTypes.Any()) { Debug.Log("W34 Returning empty grass intensity, Because of OutGrassTypes from habitats: " + StringUtils.ToString(habitatTexturesDict.Keys)); return(new List <Grass2TypeWithIntensity>()); } //////// var usedGrassTypesPositions = CreateUsedGrassTypesPositions(generatedGrassTypes); var usedHabitatTypesPositions = CreateUsedHabitatTypesPositions(habitatTexturesDict); if (!usedHabitatTypesPositions.Any()) { Debug.Log("W34 Returning empty grass intensity, Because of In habitatTypes, from habitats: " + StringUtils.ToString(habitatTexturesDict.Keys)); return(new List <Grass2TypeWithIntensity>()); } ////// var habitatTextureArray = await CreateHabitatTexture2DArrayAsync(habitatTexturesDict, habitatTexturesSize); ////// var outFigureSize = new IntVector2( Mathf.CeilToInt(generationArea.Width * _configuration.OutputPixelsPerUnit), Mathf.CeilToInt(generationArea.Height * _configuration.OutputPixelsPerUnit) ); ComputeShaderParametersContainer parametersContainer = new ComputeShaderParametersContainer(); MultistepComputeShader habitatToGrassShader = new MultistepComputeShader(_computeShaderContainer.HabitatToGrassTypeShader, outFigureSize); var usedKernelNames = generatedGrassTypes.Select(c => HabitatToGrassUtils.GrassTypeToKernelName[c]) .ToList(); var usedKernels = usedKernelNames.Select(c => habitatToGrassShader.AddKernel(c)).ToList(); var usedGrassTypesPositionsBuffer = parametersContainer.AddComputeBufferTemplate(new MyComputeBufferTemplate() { Count = usedGrassTypesPositions.Length, BufferData = usedGrassTypesPositions, Stride = 4, Type = ComputeBufferType.Default }); habitatToGrassShader.SetBuffer("OutputGrassTypePositions", usedGrassTypesPositionsBuffer, usedKernels); var usedHabitatTypesPositionsBuffer = parametersContainer.AddComputeBufferTemplate(new MyComputeBufferTemplate() { Count = usedHabitatTypesPositions.Length, BufferData = usedHabitatTypesPositions, Stride = 4, Type = ComputeBufferType.Default }); habitatToGrassShader.SetBuffer("InputHabitatTypePositions", usedHabitatTypesPositionsBuffer, usedKernels); var outIntensitiesBuffer = parametersContainer.AddComputeBufferTemplate(new MyComputeBufferTemplate() { Count = outFigureSize.X * outFigureSize.Y * generatedGrassTypes.Count, Type = ComputeBufferType.Default, Stride = 4 }); habitatToGrassShader.SetBuffer("OutIntensityBuffer", outIntensitiesBuffer, usedKernels); var habitatTextureArrayInShader = parametersContainer.AddExistingComputeShaderTexture(habitatTextureArray); habitatToGrassShader.SetTexture("HabitatTexturesArray", habitatTextureArrayInShader, usedKernels); var pathProximityTextureInShader = parametersContainer.AddExistingComputeShaderTexture(pathProximityTexture.TextureWithSize.Texture); habitatToGrassShader.SetTexture("PathProximityTexture", pathProximityTextureInShader, usedKernels); habitatToGrassShader.SetGlobalUniform("g_Coords", generationArea.ToVector4()); habitatToGrassShader.SetGlobalUniform("g_PathProximityUv", pathProximityTexture.Uv.ToVector4()); habitatToGrassShader.SetGlobalUniform("g_OutTextureSize", outFigureSize.ToFloatVec()); habitatToGrassShader.SetGlobalUniform("g_MaxProximity", _configuration.MaxProximity); ComputeBufferRequestedOutParameters outParameters = new ComputeBufferRequestedOutParameters( requestedBufferIds: new List <MyComputeBufferId>() { outIntensitiesBuffer }); await _shaderExecutorObject.AddOrder(new ComputeShaderOrder() { OutParameters = outParameters, ParametersContainer = parametersContainer, WorkPacks = new List <ComputeShaderWorkPack>() { new ComputeShaderWorkPack() { DispatchLoops = new List <ComputeShaderDispatchLoop>() { new ComputeShaderDispatchLoop() { DispatchCount = 1, KernelHandles = usedKernels } }, Shader = habitatToGrassShader } } }); var outIntensitiesNativeArray = await _commonExecutor.AddAction(() => { var array = new float[outFigureSize.X *outFigureSize.Y *generatedGrassTypes.Count]; outParameters.RetriveBuffer(outIntensitiesBuffer).GetData(array); //DebugCreateTexture(array, generationArea, outFigureSize, generatedGrassTypes.Count); return(array); }); return(RetriveIntensityFiguresFromTextureArray(outIntensitiesNativeArray, generatedGrassTypes, outFigureSize)); }