Exemplo n.º 1
0
        private void MoveSliceToBuffer(Texture buffer, Texture cube, int sideLength, int sliceIndex)
        {
            var parametersContainer = new ComputeShaderParametersContainer();

            MultistepComputeShader computeShader =
                new MultistepComputeShader(ComputeShaderUtils.LoadComputeShader("util_moveCubeSlice_comp"), new IntVector3(sideLength, sideLength, 1));

            var kernel     = computeShader.AddKernel("CS_Main");
            var allKernels = new List <MyKernelHandle>()
            {
                kernel
            };

            var bufferTexId = parametersContainer.AddExistingComputeShaderTexture(buffer);
            var cubeTexId   = parametersContainer.AddExistingComputeShaderTexture(cube);

            computeShader.SetGlobalUniform("g_SliceIndex", sliceIndex);
            computeShader.SetTexture("_BufferTexture", bufferTexId, allKernels);
            computeShader.SetTexture("_CubeTexture", cubeTexId, allKernels);

            ComputeBufferRequestedOutParameters outParameters = new ComputeBufferRequestedOutParameters(new List <MyComputeShaderTextureId>()
            {
            }, new List <MyComputeBufferId> {
            });

            _shaderExecutorObject.AddOrder(new ComputeShaderOrder()
            {
                ParametersContainer = parametersContainer,
                OutParameters       = outParameters,
                WorkPacks           = new List <ComputeShaderWorkPack>()
                {
                    new ComputeShaderWorkPack()
                    {
                        Shader        = computeShader,
                        DispatchLoops = new List <ComputeShaderDispatchLoop>()
                        {
                            new ComputeShaderDispatchLoop()
                            {
                                DispatchCount = 1,
                                KernelHandles = allKernels
                            }
                        }
                    },
                }
            }).Wait();
        }
Exemplo n.º 2
0
        private async Task ExecuteDispatch(int sideSize, int dispatchOffset, int slicesPerDispatch, RenderTexture texture, string kernelName)
        {
            var parametersContainer = new ComputeShaderParametersContainer();

            MultistepComputeShader computeShader =
                new MultistepComputeShader(ComputeShaderUtils.LoadComputeShader(_shaderName), new IntVector3(sideSize, sideSize, slicesPerDispatch));

            var kernel     = computeShader.AddKernel(kernelName);
            var allKernels = new List <MyKernelHandle>()
            {
                kernel
            };

            var newTextureId = parametersContainer.AddExistingComputeShaderTexture(texture);

            computeShader.SetGlobalUniform("g_SideSize", sideSize);
            computeShader.SetGlobalUniform("g_SlicesPerDispatch", slicesPerDispatch);
            computeShader.SetGlobalUniform("g_DispatchOffset", dispatchOffset);
            computeShader.SetTexture("_OutTexture3D", newTextureId, allKernels);

            ComputeBufferRequestedOutParameters outParameters = new ComputeBufferRequestedOutParameters(new List <MyComputeShaderTextureId>()
            {
                newTextureId
            }, new List <MyComputeBufferId> {
            });
            await _shaderExecutorObject.AddOrder(new ComputeShaderOrder()
            {
                ParametersContainer = parametersContainer,
                OutParameters       = outParameters,
                WorkPacks           = new List <ComputeShaderWorkPack>()
                {
                    new ComputeShaderWorkPack()
                    {
                        Shader        = computeShader,
                        DispatchLoops = new List <ComputeShaderDispatchLoop>()
                        {
                            new ComputeShaderDispatchLoop()
                            {
                                DispatchCount = 1,
                                KernelHandles = allKernels
                            }
                        }
                    },
                }
            });
        }
        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 <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);
        }
Exemplo n.º 6
0
        private async Task <Grass2BakedBillboardClan> GenerateBakedBillboardTextures(
            List <DetailedGrass2SingleBillboard> singleBillboards)
        {
            var textureSize = new IntVector2(singleBillboards.First().Texture.width,
                                             singleBillboards.First().Texture.height);
            var inputBillboardsTextureArray = new Texture2DArray(textureSize.X, textureSize.Y, singleBillboards.Count,
                                                                 TextureFormat.ARGB32, false, false);

            for (int i = 0; i < singleBillboards.Count; i++)
            {
                var tex = singleBillboards[i].Texture;
                inputBillboardsTextureArray.SetPixels(tex.GetPixels(), i);
            }
            inputBillboardsTextureArray.Apply(false);

            var parametersContainer   = new ComputeShaderParametersContainer();
            var bladeSeedTextureArray = parametersContainer.AddComputeShaderTextureTemplate(
                new MyComputeShaderTextureTemplate()
            {
                Depth           = 0,
                EnableReadWrite = true,
                Format          = RenderTextureFormat.R8,
                Size            = textureSize,
                TexWrapMode     = TextureWrapMode.Clamp,
                Dimension       = TextureDimension.Tex2DArray,
                VolumeDepth     = singleBillboards.Count
            });

            var detailTextureArray = parametersContainer.AddComputeShaderTextureTemplate(
                new MyComputeShaderTextureTemplate()
            {
                Depth           = 0,
                EnableReadWrite = true,
                Format          = RenderTextureFormat.RG16,
                Size            = textureSize,
                TexWrapMode     = TextureWrapMode.Clamp,
                Dimension       = TextureDimension.Tex2DArray,
                VolumeDepth     = singleBillboards.Count
            });


            MultistepComputeShader singleToDuoGrassBillboardShader =
                new MultistepComputeShader(_computeShaderContainer.SingleToDuoBillboardShader, textureSize);

            singleToDuoGrassBillboardShader.SetGlobalUniform("g_ArrayLength", singleBillboards.Count);

            var transferKernel = singleToDuoGrassBillboardShader.AddKernel("CSSingleToDuoBillboard_Transfer");

            var inputSingleTextureArray =
                parametersContainer.AddExistingComputeShaderTexture(inputBillboardsTextureArray);

            singleToDuoGrassBillboardShader.SetTexture("InputSingleTextureArray", inputSingleTextureArray,
                                                       new List <MyKernelHandle>()
            {
                transferKernel
            });

            singleToDuoGrassBillboardShader.SetTexture("OutputBladeSeedTextureArray", bladeSeedTextureArray,
                                                       new List <MyKernelHandle>()
            {
                transferKernel
            });
            singleToDuoGrassBillboardShader.SetTexture("OutputDetailTextureArray", detailTextureArray,
                                                       new List <MyKernelHandle>()
            {
                transferKernel
            });

            ComputeBufferRequestedOutParameters outParameters = new ComputeBufferRequestedOutParameters(
                new List <MyComputeShaderTextureId>()
            {
                bladeSeedTextureArray,
                detailTextureArray
            });
            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 = new List <MyKernelHandle>()
                                {
                                    transferKernel
                                }
                            }
                        }
                    },
                }
            });

            var outBladeSeedTexture = outParameters.RetriveTexture(bladeSeedTextureArray);

            outBladeSeedTexture.filterMode = FilterMode.Point;
            outBladeSeedTexture.wrapMode   = TextureWrapMode.Clamp;

            var outDetailTexture = outParameters.RetriveTexture(detailTextureArray);

            outDetailTexture.filterMode = FilterMode.Trilinear;
            outDetailTexture.wrapMode   = TextureWrapMode.Clamp;

            return(new Grass2BakedBillboardClan(singleBillboards.Select(c => c.BladesCount).ToList(),
                                                outBladeSeedTexture, outDetailTexture));
        }