Example #1
0
    private IEnumerator Start()
    {
        //Wait for all cells to add themselves to the list
        yield return(null);

        maskTexture = new RenderTexture(textureSize, textureSize, 0, RenderTextureFormat.ARGB32)
        {
            enableRandomWrite = true
        };

        maskTexture.Create();

        computeShader.SetInt(textureSizeID, textureSize);
        computeShader.SetTexture(0, maskTextureID, maskTexture);
        computeShader.SetFloat(mapSizeID, mapSize);

        for (int i = 0; i < materials.Length; i++)
        {
            materials[i].SetTexture(maskTextureID, maskTexture);
            materials[i].SetFloat(mapSizeID, mapSize);
        }

        foreach (var cell in cells)
        {
            CellBufferEntry entry = new CellBufferEntry();
            bufferElements.Add(entry);
        }

        /*Here we're creating the compute buffer. The first argument is the number of elemenets in total(in this case, the number of cells * the number of variables for each cell),
         * and the second argument is the size in bytes of each element. To discover the sive of a type, we can use the command "sizeof" and pass the corresponding type as an argument.*/
        shaderBuffer = new ComputeBuffer(bufferElements.Count * 3, sizeof(float));

        isReady = true;
    }
Example #2
0
    private void Update()
    {
        if (!isReady)
        {
            return;
        }

        //Here we update the list of the elements we're gonna put into the sahder buffer with the actual cells data
        for (int i = 0; i < cells.Count; i++)
        {
            CellBufferEntry entry = bufferElements[i];
            entry.posX        = cells[i].transform.localPosition.x;
            entry.posY        = cells[i].transform.localPosition.z;
            entry.visibility  = cells[i].visibility;
            bufferElements[i] = entry;
        }

        //Updates the materials
        for (int i = 0; i < materials.Length; i++)
        {
            materials[i].SetVector(offsetID, transform.position);             //Add the position of this parent object, so we can move the map around freely
        }

        //Here we set the data of the compute buffer and then set the buffer into the compute shader.
        shaderBuffer.SetData(bufferElements);                   //Here, the data will be set as an array containing each field of the struct in order, like: [cell0.posX, cell0.posY, cell0.visibility, cell1.posX, cellY.posY, ..., cellN.visbility]
        computeShader.SetBuffer(0, cellBufferID, shaderBuffer); //The first parameter is the kernel ID. A kernel is a function in the compute shader that'll execute our functionality. Kinda like a thread, but not exactly (a kernel will be executed in multiple threads)

        //Here we update other variables in the compute shader, just like any other shader
        computeShader.SetInt(cellCountID, bufferElements.Count);
        computeShader.SetFloat(radiusID, radius / mapSize);         //Here and in the line below we are dividing by the map size so we can have a range from 0-1, just like our UV coordinates. This way, we can modify the texture  at the same location as our cell
        computeShader.SetFloat(blendID, blendDistance / mapSize);

        /*"Dispatch" executes the compute kernel in the shader.
         * The other 3 parameters is how many worker groups we want in each dimension of our texture.
         * Since we're working with a 2D texture, we can set the Z value to 1.
         * For the X and Y axis, we can calculate the amount of workers by getting the texture size and dividing it by 8 (why? idk).
         * This basically means we'll render 8x8 square of texels at once, until we cover the entire texture*/
        computeShader.Dispatch(0, Mathf.CeilToInt(textureSize / 8.0f), Mathf.CeilToInt(textureSize / 8.0f), 1);
    }