예제 #1
0
        SubsurfaceScatteringParameters PrepareSubsurfaceScatteringParameters(HDCamera hdCamera)
        {
            var parameters = new SubsurfaceScatteringParameters();

            parameters.subsurfaceScatteringCS = m_SubsurfaceScatteringCS;
            parameters.subsurfaceScatteringCS.shaderKeywords = null;

            if (asset.currentPlatformRenderPipelineSettings.increaseSssSampleCount)
            {
                m_SubsurfaceScatteringCS.EnableKeyword("SSS_ENABLE_NEAR_FIELD");
            }
            if (hdCamera.frameSettings.IsEnabled(FrameSettingsField.MSAA))
            {
                m_SubsurfaceScatteringCS.EnableKeyword("ENABLE_MSAA");
            }

            parameters.subsurfaceScatteringCSKernel = m_SubsurfaceScatteringKernel;
            parameters.needTemporaryBuffer          = NeedTemporarySubsurfaceBuffer() || hdCamera.frameSettings.IsEnabled(FrameSettingsField.MSAA);
            parameters.copyStencilForSplitLighting  = m_SSSCopyStencilForSplitLighting;
            parameters.combineLighting    = m_CombineLightingPass;
            parameters.texturingModeFlags = m_SSSTexturingModeFlags;
            parameters.numTilesX          = ((int)hdCamera.screenSize.x + 15) / 16;
            parameters.numTilesY          = ((int)hdCamera.screenSize.y + 15) / 16;
            parameters.numTilesZ          = hdCamera.viewCount;

            parameters.worldScales            = m_SSSWorldScales;
            parameters.filterKernels          = m_SSSFilterKernels;
            parameters.shapeParams            = m_SSSShapeParams;
            parameters.diffusionProfileHashes = m_SSSDiffusionProfileHashes;

            parameters.coarseStencilBuffer = m_SharedRTManager.GetCoarseStencilBuffer();

            return(parameters);
        }
예제 #2
0
    protected void GetPoints(Vector3 chunkIndex)
    {
        chunkIndex *= chunkSize;
        int threadsPerAxis = Mathf.CeilToInt(PointsPerAxis / 8f);

        if (useNoise)
        {
            noiseDensityCompute.shaderKeywords = null;
            switch (noiseType)
            {
            case NoiseType.Perlin:
                noiseDensityCompute.EnableKeyword("PNOISE");
                break;

            case NoiseType.Simplex:
                noiseDensityCompute.EnableKeyword("SNOISE");
                break;

            default:
                Debug.LogError("INVALID OPTION");
                break;
            }

            noiseDensityCompute.SetVector("offset", chunkIndex);
            noiseDensityCompute.Dispatch(0, threadsPerAxis, threadsPerAxis, threadsPerAxis);
        }
        else
        {
            functionDensityCompute.SetVector("offset", chunkIndex);
            functionDensityCompute.Dispatch(0, threadsPerAxis, threadsPerAxis, threadsPerAxis);
        }
    }
예제 #3
0
 public static void EnableKeywords(this ComputeShader _computeShader, string[] _keywords, int _target)
 {
     for (int i = 0; i < _keywords.Length; i++)
     {
         _computeShader.EnableKeyword(_keywords[i], i + 1 == _target);
     }
 }
예제 #4
0
    void Start()
    {
#if UNITY_ANDROID && !UNITY_EDITOR
        format = GraphicsFormat.RGBA_ETC2_UNorm;
        shader.EnableKeyword("_COMPRESS_ETC2");
#else
        format = GraphicsFormat.RGBA_DXT5_UNorm;
        //shader.DisableKeyword("_COMPRESS_ETC2");
#endif
        kernelHandle = shader.FindKernel("CSMain");
        tex          = new RenderTexture(64, 64, 24)
        {
            format            = RenderTextureFormat.ARGB32,
            enableRandomWrite = true,
        };
        tex.Create();
        //tt.text = format.ToString() + SystemInfo.IsFormatSupported(format, FormatUsage.Linear).ToString() + SystemInfo.supportsComputeShaders + SystemInfo.copyTextureSupport;

        shader.SetTexture(kernelHandle, "Result", tex);
        shader.SetTexture(kernelHandle, "RenderTexture0", _mask);
        shader.SetInts("DestRect", DestRect);
        shader.Dispatch(kernelHandle, (256 / 4 + 7) / 8, (256 / 4 + 7) / 8, 1);
        copyTex = new Texture2D(256, 256, format, TextureCreationFlags.None);
        Graphics.CopyTexture(tex, 0, 0, 0, 0, 64, 64, copyTex, 0, 0, 0, 0);
        _mat             = GetComponent <MeshRenderer>().sharedMaterial;
        _mat.mainTexture = copyTex;
    }
        SubsurfaceScatteringParameters PrepareSubsurfaceScatteringParameters(HDCamera hdCamera)
        {
            var parameters = new SubsurfaceScatteringParameters();

            parameters.subsurfaceScatteringCS = m_SubsurfaceScatteringCS;
            parameters.subsurfaceScatteringCS.shaderKeywords = null;

            if (hdCamera.frameSettings.IsEnabled(FrameSettingsField.MSAA))
            {
                m_SubsurfaceScatteringCS.EnableKeyword("ENABLE_MSAA");
            }

            parameters.subsurfaceScatteringCSKernel = m_SubsurfaceScatteringKernel;
            parameters.needTemporaryBuffer          = NeedTemporarySubsurfaceBuffer() || hdCamera.frameSettings.IsEnabled(FrameSettingsField.MSAA);
            parameters.copyStencilForSplitLighting  = m_SSSCopyStencilForSplitLighting;
            parameters.combineLighting    = m_CombineLightingPass;
            parameters.texturingModeFlags = m_SSSTexturingModeFlags;
            parameters.numTilesX          = ((int)hdCamera.screenSize.x + 15) / 16;
            parameters.numTilesY          = ((int)hdCamera.screenSize.y + 15) / 16;
            parameters.numTilesZ          = hdCamera.viewCount;
            parameters.sampleBudget       = hdCamera.frameSettings.sssResolvedSampleBudget;

            parameters.worldScalesAndFilterRadiiAndThicknessRemaps = m_SSSWorldScalesAndFilterRadiiAndThicknessRemaps;
            parameters.shapeParamsAndMaxScatterDists = m_SSSShapeParamsAndMaxScatterDists;
            parameters.diffusionProfileHashes        = m_SSSDiffusionProfileHashes;

            parameters.coarseStencilBuffer = m_SharedRTManager.GetCoarseStencilBuffer();

            return(parameters);
        }
예제 #6
0
    void InitializeParticles()
    {
        // Max number of thread groups per dimension is 65535 in D3D11
        // D3D11_CS_DISPATCH_MAX_THREAD_GROUPS_PER_DIMENSION (65535).

        if (numberOfParticles > m_particleThreadsPerGroup * 65535)
        {
            numberOfParticles = m_particleThreadsPerGroup * 65535;
        }

        m_particleThreadGroups = numberOfParticles / m_particleThreadsPerGroup;
        Debug.Log("Particles: " + numberOfParticles + " Thread groups: " + m_particleThreadGroups);

        Particle[] data = new Particle[numberOfParticles];
        particleBuffer = new ComputeBuffer(data.Length, System.Runtime.InteropServices.Marshal.SizeOf <Particle>());
        particleBuffer.SetData(data);
        _particleCount = numberOfParticles;

        //initialize particles with random positions
        computeShader.SetInt("numberOfParticles", numberOfParticles);
        computeShader.SetBuffer(kernelParticleInit, "particleBuffer", particleBuffer);
        computeShader.SetBuffer(kernelParticleStep, "particleBuffer", particleBuffer);
        computeShader.EnableKeyword("Mode1");

        Dispatch(kernelParticleInit, m_particleThreadGroups, 1, 1);
    }
예제 #7
0
    void Start()
    {
        _kernel = shader.FindKernel("CSMain");

        //Quad texture
        RenderTexture tex = new RenderTexture(size, size, 0, GraphicsFormat.R32G32B32A32_SFloat);

        tex.enableRandomWrite = true;
        tex.Create();
        _mat.SetTexture("_MainTex", tex);
        shader.SetTexture(_kernel, "Result", tex);
        shader.SetInt("size", size);

        //Spheres
        particleArray = new Particle[spheres.Length];
        cBuffer       = new ComputeBuffer(particleArray.Length, 12 + 12);
        cBuffer.SetData(particleArray);
        shader.SetBuffer(_kernel, "particleBuffer", cBuffer);
        shader.SetInt("particleCount", particleArray.Length);

        //draw type
        switch (drawType)
        {
        case 1:
            shader.EnableKeyword("CURVEDSTAIGHTLINE");
            shader.DisableKeyword("DRAWLINE");
            shader.DisableKeyword("CIRCLES");
            break;

        case 2:
            shader.EnableKeyword("CIRCLES");
            shader.DisableKeyword("DRAWLINE");
            shader.DisableKeyword("CURVEDSTAIGHTLINE");
            break;

        default:
            shader.EnableKeyword("DRAWLINE");
            shader.DisableKeyword("CURVEDSTAIGHTLINE");
            shader.DisableKeyword("CIRCLES");
            break;
        }
    }
예제 #8
0
 //Compute Shader
 public static void EnableKeyword(this ComputeShader _computeShader, string _keyword, bool _enable)
 {
     if (_enable)
     {
         _computeShader.EnableKeyword(_keyword);
     }
     else
     {
         _computeShader.DisableKeyword(_keyword);
     }
 }
        SubsurfaceScatteringParameters PrepareSubsurfaceScatteringParameters(HDCamera hdCamera)
        {
            var parameters = new SubsurfaceScatteringParameters();

            parameters.subsurfaceScatteringCS = m_SubsurfaceScatteringCS;
            parameters.subsurfaceScatteringCS.shaderKeywords = null;

            if (hdCamera.frameSettings.IsEnabled(FrameSettingsField.MSAA))
            {
                m_SubsurfaceScatteringCS.EnableKeyword("ENABLE_MSAA");
            }

            parameters.subsurfaceScatteringCSKernel = m_SubsurfaceScatteringKernel;
            parameters.needTemporaryBuffer          = NeedTemporarySubsurfaceBuffer() || hdCamera.frameSettings.IsEnabled(FrameSettingsField.MSAA);
            parameters.copyStencilForSplitLighting  = m_SSSCopyStencilForSplitLighting;
            parameters.combineLighting = m_CombineLightingPass;
            parameters.numTilesX       = ((int)hdCamera.screenSize.x + 15) / 16;
            parameters.numTilesY       = ((int)hdCamera.screenSize.y + 15) / 16;
            parameters.numTilesZ       = hdCamera.viewCount;
            parameters.sampleBudget    = hdCamera.frameSettings.sssResolvedSampleBudget;

            return(parameters);
        }
예제 #10
0
    public void BuildPipeline()
    {
        if (IsInitialized)
        {
            return;
        }
        if (m_PathTracingShader == null)
        {
            return;
        }
        if (m_Camera == null)
        {
            return;
        }
        m_KernelIndex = m_PathTracingShader.FindKernel(m_KernelName);
        if (m_KernelIndex < 0)
        {
            return;
        }

        if (m_EnableNEE)
        {
            m_PathTracingShader.EnableKeyword("ENABLE_NEXT_EVENT_ESTIMATION");
        }
        else
        {
            m_PathTracingShader.DisableKeyword("ENABLE_NEXT_EVENT_ESTIMATION");
        }

        if (m_EnableThinLens)
        {
            m_PathTracingShader.EnableKeyword("ENABLE_THIN_LENS");
        }
        else
        {
            m_PathTracingShader.DisableKeyword("ENABLE_THIN_LENS");
        }

        if (m_EnableSampleTexture)
        {
            m_PathTracingShader.EnableKeyword("ENABLE_SAMPLE_TEXTURE");
        }
        else
        {
            m_PathTracingShader.DisableKeyword("ENABLE_SAMPLE_TEXTURE");
        }

        if (m_EnableTangentSpace)
        {
            m_PathTracingShader.EnableKeyword("ENABLE_TANGENT_SPACE");
        }
        else
        {
            m_PathTracingShader.DisableKeyword("ENABLE_TANGENT_SPACE");
        }

        m_RenderTexture = new RenderTexture(Screen.width, Screen.height, 0, RenderTextureFormat.ARGBFloat);
        m_RenderTexture.enableRandomWrite = true;
        m_RenderTexture.Create();

        m_DispatchThreadGroupsX = Mathf.CeilToInt((float)m_RenderTexture.width / kTileSize);
        m_DispatchThreadGroupsY = Mathf.CeilToInt((float)m_RenderTexture.height / kTileSize);

        List <PTMaterial> materials;
        List <Primitive>  primitives;
        List <Texture2D>  baseColorTextures = null;
        List <Texture2D>  mroTextures       = null;
        List <Texture2D>  normalTextures    = null;

        if (m_EnableSampleTexture)
        {
            baseColorTextures = new List <Texture2D>();
        }
        if (m_EnableTangentSpace)
        {
            mroTextures    = new List <Texture2D>();
            normalTextures = new List <Texture2D>();
        }
        CollectPrimitives(out materials, out primitives, ref baseColorTextures, ref mroTextures, ref normalTextures);
        BVH bvhTree = new BVH();

        bvhTree.Build(primitives);
        List <Sphere>   spheres;
        List <Quad>     quads;
        List <Cube>     cubes;
        List <Triangle> triangles;
        List <LBVHNode> bvh;
        int             bvhRoot = BuildLBVH(bvhTree, out bvh, out spheres, out quads, out cubes, out triangles);

        if (m_EnableSampleTexture)
        {
            m_baseColorTextureArray = CreateTextureArray(baseColorTextures);
            m_PathTracingShader.SetTexture(m_KernelIndex, "_Textures", m_baseColorTextureArray);
        }
        if (m_EnableTangentSpace)
        {
            m_mroTextureArray    = CreateTextureArray(mroTextures);
            m_normalTextureArray = CreateTextureArray(normalTextures);
            m_PathTracingShader.SetTexture(m_KernelIndex, "_MROTextures", m_mroTextureArray);
            m_PathTracingShader.SetTexture(m_KernelIndex, "_NormalTextures", m_normalTextureArray);
        }
        m_NodesBuffer     = CreateComputeBuffer <LBVHNode>(bvh);
        m_SpheresBuffer   = CreateComputeBuffer <Sphere>(spheres);
        m_QuadsBuffer     = CreateComputeBuffer <Quad>(quads);
        m_CubeBuffer      = CreateComputeBuffer <Cube>(cubes);
        m_TrianglesBuffer = CreateComputeBuffer <Triangle>(triangles);
        m_MaterialsBuffer = CreateComputeBuffer <PTMaterial>(materials);

        m_PathTracingShader.SetBuffer(m_KernelIndex, "_Spheres", m_SpheresBuffer);
        m_PathTracingShader.SetBuffer(m_KernelIndex, "_Quads", m_QuadsBuffer);
        m_PathTracingShader.SetBuffer(m_KernelIndex, "_Cubes", m_CubeBuffer);
        m_PathTracingShader.SetBuffer(m_KernelIndex, "_Triangles", m_TrianglesBuffer);
        m_PathTracingShader.SetBuffer(m_KernelIndex, "_BVHTree", m_NodesBuffer);
        m_PathTracingShader.SetBuffer(m_KernelIndex, "_Materials", m_MaterialsBuffer);

        m_PathTracingShader.SetInt("_BVHRootNodeIndex", bvhRoot);
        m_PathTracingShader.SetInt("_BVHNodeCount", bvh.Count);

        IsInitialized = true;

        m_PathTracingShader.SetTexture(m_KernelIndex, "_Result", m_RenderTexture);
        m_PathTracingShader.SetInt("_ScreenWidth", m_RenderTexture.width);
        m_PathTracingShader.SetInt("_ScreenHeight", m_RenderTexture.height);

        Debug.Log($"BVH Root:{bvhRoot}, BVH Childs:{bvh.Count}");
    }
    /// <summary>
    /// Generates a heightmap with fractal noise and a sine wave for farmland grooves, uses compute shaders.
    /// Author: Glyn Marcus Leine & Maurijn Besters
    /// </summary>
    public Texture2D CreateHeightmap(float gridX, float gridY)
    {
        if (!m_heightShader)
        {
            m_heightShader = Resources.Load <ComputeShader>("Compute/Height");
            if (!m_heightShader)
            {
                Debug.LogError("Could not load height compute shader.");
                return(null);
            }

            m_heightKernel = m_heightShader.FindKernel("CSHeight");
            m_heightShader.GetKernelThreadGroupSizes(m_heightKernel, out m_heightGlobal.x, out m_heightGlobal.y, out m_heightGlobal.z);
        }

        var generator = TerrainGenerator.instance;

        RenderTexture target = new RenderTexture(generator.textureWidth, generator.textureHeight, 1, RenderTextureFormat.ARGBFloat);

        target.enableRandomWrite = true;
        target.Create();

        if (generator.includeSineWave)
        {
            m_heightShader.EnableKeyword("SINE_WAVE_ON");
        }
        else
        {
            m_heightShader.DisableKeyword("SINE_WAVE_ON");
        }

        m_heightShader.SetTexture(m_heightKernel, "target", target);
        m_heightShader.SetFloats("resolutionData", generator.textureWidth, generator.textureHeight, 1f / generator.textureWidth, 1f / generator.textureHeight);
        m_heightShader.SetFloat("chunkSize", generator.maximumChunkSize);

        m_heightShader.SetInt("octaves", generator.PerlinOctaves);

        m_heightShader.SetFloat("amplitude", generator.PerlinBaseAmplitude);
        m_heightShader.SetFloat("persistence", generator.persistence);
        m_heightShader.SetFloat("lacunarity", generator.lacunarity);

        Vector2[] octaveOffsets = new Vector2[generator.PerlinOctaves];

        System.Random prng              = new System.Random(generator.Seed);
        Vector2       offset            = new Vector2(prng.Next(-100000, 100000) - generator.xOffset - (generator.maximumChunkSize * gridX), prng.Next(-100000, 100000) - generator.yOffset - (generator.maximumChunkSize * gridY));
        float         maxPossibleHeight = 0;
        float         amplitude         = generator.PerlinBaseAmplitude;

        for (int i = 0; i < generator.PerlinOctaves; i++)
        {
            octaveOffsets[i]   = new Vector2(offset.x, offset.y);
            maxPossibleHeight += amplitude;
            amplitude         *= generator.persistence;
        }

        ComputeBuffer octaveOffsetsBuffer = new ComputeBuffer(generator.PerlinOctaves, sizeof(float) * 2, ComputeBufferType.Structured, ComputeBufferMode.Dynamic);

        octaveOffsetsBuffer.SetData(octaveOffsets);

        m_heightShader.SetBuffer(m_heightKernel, "octaveOffsets", octaveOffsetsBuffer);

        m_heightShader.SetFloat("perlinScale", 1f / generator.PerlinScale);
        m_heightShader.SetFloat("normalizeScale", 1f / maxPossibleHeight);

        m_heightShader.SetFloat("halfSineAmplitude", generator.sinAmplitude * 0.5f);
        m_heightShader.SetFloat("sinePeriod", generator.sinPeriod);
        m_heightShader.SetFloat("chunkOffsetX", generator.xOffset - (generator.maximumChunkSize * gridX));
        m_heightShader.SetFloat("perlinNoiseWeight", generator.perlinNoiseWeight);

        Vector3Int dispatchGroupSize = new Vector3Int(generator.textureWidth / (int)m_heightGlobal.x, generator.textureHeight / (int)m_heightGlobal.y, 1);

        m_heightShader.Dispatch(m_heightKernel, dispatchGroupSize.x, dispatchGroupSize.y, dispatchGroupSize.z);

        Texture2D heightMapTexture = new Texture2D(generator.textureWidth, generator.textureHeight, TextureFormat.RGBAFloat, true);

        RenderTexture.active = target;

        heightMapTexture.ReadPixels(new Rect(0, 0, generator.textureWidth, generator.textureHeight), 0, 0, true);
        heightMapTexture.filterMode = FilterMode.Bilinear;
        heightMapTexture.wrapMode   = TextureWrapMode.Clamp;
        heightMapTexture.Apply(false, false);
        RenderTexture.active = null;
        target.Release();
        target.DiscardContents();
        octaveOffsetsBuffer.Release();
        octaveOffsetsBuffer.Dispose();

        return(heightMapTexture);
    }
예제 #12
0
        void UpdateFunctionOnGPU()
        {
            int resolution_ = resolution / 4;

            resolution_ *= 4;

            float step = size / (float)resolution_;

            isoValsShader.SetInt(resolutionId, resolution_);
            isoValsShader.SetFloat(stepId, step);

            // duration += Time.deltaTime;
            // isoValsShader.SetFloat(sId, (shapeSize * (((Mathf.Sin(5f * duration) + 2f) * 0.5f))));
            // isoValsShader.SetFloat(sId, shapeSize);

            isoValsShader.SetFloat(timeId, Time.time);
            isoValsShader.SetMatrix(gridToWorldID, this.transform.localToWorldMatrix);
            isoValsShader.SetMatrixArray(shapeToWorldID, shape.Select(v => v.transform.localToWorldMatrix.inverse).ToArray());
            isoValsShader.SetBuffer(0, isoValsId, isoValsBuffer);

            int groups = Mathf.CeilToInt(resolution_ / 4f);

            isoValsShader.EnableKeyword(FunctionLibrary.GetName(shapeFunction));
            isoValsShader.Dispatch(0, groups, groups, groups);
            isoValsShader.DisableKeyword(FunctionLibrary.GetName(shapeFunction));

            var bounds = new Bounds(Vector3.zero, Vector3.one * (size + step));

            if (showGrid)
            {
                transparencyMaterial.SetBuffer(isoValsId, isoValsBuffer);
                transparencyMaterial.SetFloat(stepId, step);
                transparencyMaterial.SetInt(resolutionId, resolution_);
                transparencyMaterial.SetMatrix(gridToWorldID, this.transform.localToWorldMatrix);
                transparencyMaterial.SetVector(viewDirID, -Camera.main.transform.forward);
                transparencyMaterial.SetFloat(pointBrightnessID, pointBrightness);
                transparencyMaterial.SetFloat(pointSizeID, pointSize);

                Graphics.DrawMeshInstancedProcedural(pointMesh, 0, transparencyMaterial, bounds, resolution_ * resolution_ * resolution_);
            }

            if (showVolume)
            {
                material.SetBuffer(isoValsId, isoValsBuffer);
                material.SetFloat(stepId, step);
                material.SetInt(resolutionId, resolution_);
                material.SetMatrix(gridToWorldID, this.transform.localToWorldMatrix);
                material.SetVector(viewDirID, -Camera.main.transform.forward);
                material.SetFloat(pointBrightnessID, pointBrightness);
                material.SetFloat(pointSizeID, pointSize);

                Graphics.DrawMeshInstancedProcedural(pointMesh, 0, material, bounds, resolution_ * resolution_ * resolution_);
            }

            // surface points
            surfacePointsShader.SetInt(resolutionId, resolution_);
            surfacePointsShader.SetMatrix(gridToWorldID, this.transform.localToWorldMatrix);
            surfacePointsShader.SetMatrixArray(shapeToWorldID, shape.Select(v => v.transform.localToWorldMatrix.inverse).ToArray());
            surfacePointsShader.SetFloat(stepId, step);
            surfacePointsShader.SetBuffer(0, isoValsId, isoValsBuffer);
            surfacePointsShader.SetBuffer(0, surfacePointsId, surfacePointsBuffer);
            surfacePointsShader.SetBuffer(0, normalsId, normalsBuffer);
            surfacePointsShader.EnableKeyword(FunctionLibrary.GetName(shapeFunction));
            surfacePointsShader.EnableKeyword(GetSurfacePointsFuncName(surfacePointsFunc));
            // surfacePointsShader.SetMatrixArray(shapeToWorldID, shape.Select(v => v.transform.localToWorldMatrix).ToArray());
            surfacePointsShader.Dispatch(0, groups, groups, groups);
            surfacePointsShader.DisableKeyword(FunctionLibrary.GetName(shapeFunction));
            surfacePointsShader.DisableKeyword(GetSurfacePointsFuncName(surfacePointsFunc));

            // var data = new Vector3[resolution_*resolution_*resolution_];
            // surfacePointsBuffer.GetData(data);
            // print(data[10]);

            if (showSurface)
            {
                surfacePointMaterial.SetFloat(stepId, step);
                surfacePointMaterial.SetInt(resolutionId, resolution_);
                surfacePointMaterial.SetMatrix(gridToWorldID, this.transform.localToWorldMatrix);
                surfacePointMaterial.SetVector(viewDirID, -Camera.main.transform.forward);
                surfacePointMaterial.SetFloat(pointSizeID, pointSize);
                surfacePointMaterial.SetBuffer(surfacePointsId, surfacePointsBuffer);
                surfacePointMaterial.SetBuffer(normalsId, normalsBuffer);

                Graphics.DrawMeshInstancedProcedural(pointMesh, 0, surfacePointMaterial, bounds, resolution_ * resolution_ * resolution_);
            }

            Mesh mesh = GetComponent <MeshFilter>().mesh;

            mesh.Clear();
            if (showMesh)
            {
                // construct mesh
                meshBuffer.SetCounterValue(0);

                int meshKernel = 0;
                meshShader.SetInt(resolutionId, resolution_);
                meshShader.SetMatrix(gridToWorldID, this.transform.localToWorldMatrix);
                meshShader.SetFloat(stepId, step);
                meshShader.SetBuffer(meshKernel, isoValsId, isoValsBuffer);
                meshShader.SetBuffer(meshKernel, surfacePointsId, surfacePointsBuffer);
                meshShader.SetBuffer(meshKernel, normalsId, normalsBuffer);
                meshShader.SetBuffer(meshKernel, meshId, meshBuffer);
                meshShader.EnableKeyword(FunctionLibrary.GetName(shapeFunction));
                meshShader.Dispatch(meshKernel, groups, groups, groups);
                meshShader.DisableKeyword(FunctionLibrary.GetName(shapeFunction));

                // Copy the count.
                ComputeBuffer.CopyCount(meshBuffer, argsBuffer, 0);

                // TODO: do not retrieve from GPU. write a compute shader to adjust count: https://gist.github.com/DuncanF/353509dd397ea5f292fa52d1b9b5133d
                // Retrieve it into array.
                int[] args = new int[4];
                argsBuffer.GetData(args);

                // Actual count in append buffer.
                args[0] *= 1; // verts per triangle
                // args[2] += 1; // verts per triangle

                argsBuffer.SetData(args);

                fixArgs.SetBuffer(0, "DrawCallArgs", argsBuffer);
                fixArgs.Dispatch(0, 1, 1, 1);

                argsBuffer.GetData(args);

                args[0] *= 2;

                var meshArr = new Vector4[args[0]];
                meshBuffer.GetData(meshArr);
                var verts3 = new Vector3[args[0]];
                // var verts4 = new Vector4[args[0]];
                var normals3 = new Vector3[args[0]];
                for (int i = 0; i < args[0]; i += 2)
                {
                    verts3[i / 2] = new Vector3(meshArr[i].x, meshArr[i].y, meshArr[i].z);
                    // verts4[i / 2] = meshArr[i];
                    normals3[i / 2] = new Vector3(meshArr[i + 1].x, meshArr[i + 1].y, meshArr[i + 1].z);
                }
                mesh.vertices = verts3;
                mesh.normals  = normals3;
                var tris = new int[verts3.Length];
                for (int i = 0; i < verts3.Length; i++)
                {
                    tris[i] = i;
                }
                mesh.triangles = tris;

                if (renderMode == RenderMode.Wireframe)
                {
                    var indices = new int[verts3.Length / 3 * 6];
                    for (int i = 0, j = 0; i < indices.Length; i += 6, j += 3)
                    {
                        indices[i]     = j;
                        indices[i + 1] = j + 1;

                        indices[i + 2] = j + 1;
                        indices[i + 3] = j + 2;

                        indices[i + 4] = j;
                        indices[i + 5] = j + 2;
                    }
                    mesh.SetIndices(indices, MeshTopology.Lines, 0);
                }


                // TODO: custom render shader (URP shader graph) that gets verts from buffer, use vert id, create variant of urp standard
                // see info at bottom for vert id info?: https://docs.unity3d.com/Manual/SL-ShaderSemantics.html
                // https://samdriver.xyz/article/compute-shader-intro
                // https://cyangamedev.wordpress.com/2020/06/05/urp-shader-code/
                // https://gist.github.com/phi-lira/225cd7c5e8545be602dca4eb5ed111ba

                // meshBufferFloat.SetData(verts4);

                // // if (showMesh) {
                // meshMaterial.SetPass(0);
                // meshMaterial.SetMatrix(gridToWorldID, this.transform.localToWorldMatrix);
                // meshMaterial.SetBuffer(meshId, meshBufferFloat);

                // Graphics.DrawProceduralIndirect(meshMaterial, bounds, MeshTopology.Triangles, argsBuffer, 0, null, null, UnityEngine.Rendering.ShadowCastingMode.On, true);
            }
        }