override public void GenerateHeightField(int currentFrame, ExtendedHeightField extendedHeightField)
    {
        Profiler.BeginSample("Clear Height Field");
        extendedHeightField.Clear();
        Profiler.EndSample();

        Profiler.BeginSample("Set Point Map");
        waveParticles.setPointMap(currentFrame, ref pointMap);
        Profiler.EndSample();

        Profiler.BeginSample("Convolve Wave Particles");
        for (int row = 0; row < heightFieldInfo.VertRes; row++)
        {
            for (int col = 0; col < heightFieldInfo.HoriRes; col++)
            {
                int index = row * heightFieldInfo.HoriRes + col;
                for (int y = 0; y < kernelHeight; y++)
                {
                    for (int x = 0; x < kernelWidth; x++)
                    {
                        int y_index = (y - (kernelHeight / 2)) + row;
                        int x_index = (x - (kernelWidth / 2)) + col;
                        if (y_index > 0 && y_index < heightFieldInfo.VertRes && x_index > 0 && x_index < heightFieldInfo.HoriRes)
                        {
                            int fresh_index = (y_index * heightFieldInfo.HoriRes) + (x_index);
                            extendedHeightField.heightMap[index] += (Color)(pointMap.heightMap[fresh_index] * kernel[(y * kernelWidth) + x]);
                        }
                    }
                }
            }
        }
        extendedHeightField.ApplyCPUHeightMap();
        Profiler.EndSample();
    }
    override public void Initialise(ExtendedHeightField.HeightFieldInfo hf, ParticleContainer wp)
    {
        heightFieldInfo = hf;
        pointMap        = new ExtendedHeightField(hf.Width, hf.Height, hf.HoriRes, hf.VertRes);
        pointMap.textureHeightMap.name = "Point Map Texture";
        waveParticles = wp;

        kernelWidth  = Mathf.CeilToInt((WaveParticle.RADIUS / heightFieldInfo.Width) * heightFieldInfo.HoriRes);
        kernelHeight = Mathf.CeilToInt((WaveParticle.RADIUS / heightFieldInfo.Height) * heightFieldInfo.VertRes);
        kernel       = creatKernel(kernelWidth, kernelHeight, heightFieldInfo);
    }
    override public void GenerateHeightField(int currentFrame, ExtendedHeightField extendedHeightField)
    {
        Profiler.BeginSample("Clear Height Field");
        extendedHeightField.Clear();
        Profiler.EndSample();

        Profiler.BeginSample("Set Point Map");
        waveParticles.setPointMap(currentFrame, ref pointMap);
        Profiler.EndSample();

        Profiler.BeginSample("Convolve Wave Particles");
        convolveWaveParticles();
        extendedHeightField.UpdateTexture(convolvedTexture);
        Profiler.EndSample();
    }
    override public void GenerateHeightField(int currentFrame, ExtendedHeightField extendedHeightField)
    {
        extendedHeightField.Clear();

        foreach (WaveParticle waveParticle in waveParticles)
        {
            Vector2 waveParticlePosition = waveParticle.getPosition(currentFrame);
            int     xPos = Mathf.RoundToInt((waveParticlePosition.x / heightFieldInfo.Width) * heightFieldInfo.HoriRes);
            int     yPos = Mathf.RoundToInt((waveParticlePosition.y / heightFieldInfo.Height) * heightFieldInfo.VertRes);
            for (int y = 0; y < sectionWidth; y++)
            {
                for (int x = 0; x < sectionHeight; x++)
                {
                    int col = (x - (sectionWidth / 2)) + xPos;
                    int row = (y - (sectionHeight / 2)) + yPos;

                    if (row > 0 && row < heightFieldInfo.VertRes && col > 0 && col < heightFieldInfo.HoriRes)
                    {
                        int     index    = row * heightFieldInfo.HoriRes + col;
                        Vector2 position = new Vector2(heightFieldInfo.UnitX * col, heightFieldInfo.UnitY * row);
                        Vector2 diff     = position - waveParticlePosition;
                        float   abs_diff = diff.magnitude;
                        if (abs_diff > WaveParticle.RADIUS)
                        {
                            // Don't need to do rest of calculation based on rectangle function.
                            continue;
                        }
                        // Caclulate vertical displacement
                        float piOverRadius   = Mathf.PI / WaveParticle.RADIUS;
                        float y_displacement = (waveParticle.amplitude * 0.5f) * (Mathf.Cos(abs_diff * piOverRadius) + 1);

                        Vector2 longitudinalComponent;
                        {
                            float   dotproduct = Vector2.Dot(waveParticle.velocity.normalized, diff);
                            Vector2 Li         = -Mathf.Sin(dotproduct * piOverRadius) * waveParticle.velocity.normalized;
                            longitudinalComponent = y_displacement * Li;
                        }
                        float x_displacement = longitudinalComponent.x;
                        float z_displacement = longitudinalComponent.y;
                        extendedHeightField.heightMap[index] += new Color(x_displacement, y_displacement, z_displacement, 1f);
                    }
                }
            }
        }
    }
Ejemplo n.º 5
0
    public WaveParticleSystem(float particleSpeed, float particleRadius, int maxNumParticles, int horRes, int vertRes, float height, float width, float waveParticleKillThreshold)
    {
        _particleSpeed             = particleSpeed;
        _particleRadius            = particleRadius;
        _numParticles              = maxNumParticles;
        _waveParticleKillThreshold = waveParticleKillThreshold;
        _currentFrame              = 0;
        // TODO: move all relvant code to do with this to here!
        _frameCycleLength = WaveParticle.FRAME_CYCLE_LENGTH;

        _extendedHeightField = new ExtendedHeightField(width, height, horRes, vertRes);
        _extendedHeightField.Clear();

        _particleContainer = SplatEnumToInstance(_splatImplementationChoice);
        _particleContainer.Initialise(maxNumParticles, waveParticleKillThreshold);
        _heightFieldGenerator = ConvEnumToInstance(_convolutionImplementationChoice);
        _heightFieldGenerator.Initialise(_extendedHeightField.heightFieldInfo, _particleContainer);
    }
    override public void Initialise(ExtendedHeightField.HeightFieldInfo hf, ParticleContainer wp)
    {
        heightFieldInfo = hf;
        pointMap        = new ExtendedHeightField(hf.Width, hf.Height, hf.HoriRes, hf.VertRes);

        convolvedTexture            = new Texture2D(heightFieldInfo.HoriRes, heightFieldInfo.VertRes, TextureFormat.RGBAFloat, false);
        convolvedTexture.anisoLevel = 1;
        convolvedTexture.filterMode = FilterMode.Point;
        convolvedTexture.wrapMode   = TextureWrapMode.Clamp;
        convolvedTexture.name       = "Convolved Texture";

        shaderTexture = new RenderTexture(heightFieldInfo.HoriRes, heightFieldInfo.VertRes, 24, RenderTextureFormat.ARGBFloat);
        shaderTexture.antiAliasing     = 1;
        shaderTexture.anisoLevel       = 0;
        shaderTexture.autoGenerateMips = false;
        shaderTexture.wrapMode         = TextureWrapMode.Clamp;
        shaderTexture.filterMode       = FilterMode.Point;


        int kernelWidth  = Mathf.CeilToInt((WaveParticle.RADIUS / heightFieldInfo.Width) * heightFieldInfo.HoriRes);
        int kernelHeight = Mathf.CeilToInt((WaveParticle.RADIUS / heightFieldInfo.Height) * heightFieldInfo.VertRes);

        Color[] kernelArray = Convolution2DFastHeightFieldGenerator.creatKernel(kernelHeight, kernelWidth, heightFieldInfo);

        kernel = new Texture2D(kernelWidth, kernelHeight, TextureFormat.RGBAFloat, false);
        kernel.SetPixels(kernelArray);
        kernel.Apply();

        convolutionMaterial = new Material(Shader.Find("Unlit/2DFunction"));
        convolutionMaterial.SetTexture(Shader.PropertyToID("_KernelTex"), kernel);
        convolutionMaterial.SetFloat(Shader.PropertyToID("_Width"), heightFieldInfo.Width);
        convolutionMaterial.SetFloat(Shader.PropertyToID("_Height"), heightFieldInfo.Height);
        convolutionMaterial.SetInt(Shader.PropertyToID("_HoriRes"), heightFieldInfo.HoriRes);
        convolutionMaterial.SetInt(Shader.PropertyToID("_VertRes"), heightFieldInfo.VertRes);
        convolutionMaterial.SetFloat(Shader.PropertyToID("_ParticleRadii"), WaveParticle.RADIUS);
        convolutionMaterial.SetFloat(Shader.PropertyToID("_KernelWidth"), kernelWidth);
        convolutionMaterial.SetFloat(Shader.PropertyToID("_KernelHeight"), kernelHeight);

        waveParticles = wp;
    }
Ejemplo n.º 7
0
    void Start()
    {
        waterMaterial = GetComponent <Renderer>().material;
        waveParticles.Initialise(numWaveParticles, waveParticleKillThreshold);
        {
            int   horRes  = 100;
            int   vertRes = 100;
            float height  = 8;
            float width   = 8;
            extendedHeightField = new ExtendedHeightField(width, height, horRes, vertRes);
            extendedHeightField.Clear();
        }

        _mesh     = GetComponent <MeshFilter>().mesh;
        vertices  = new Vector3[extendedHeightField.HoriRes * extendedHeightField.VertRes];
        uv        = new Vector2[extendedHeightField.HoriRes * extendedHeightField.VertRes];
        triangles = new int[(extendedHeightField.HoriRes - 1) * (extendedHeightField.VertRes - 1) * 6];

        heightFieldGenerator = HeightFieldGeneratorSelector.CreateAndInitialise(selectedHeightFieldGenerator, extendedHeightField.heightFieldInfo, waveParticles);


        // Initialise and set-up the mesh the wave particles will be rendered to
        {
            GenerateMeshFromHeightMap(extendedHeightField, vertices, uv, triangles, _mesh);
            Renderer rend = GetComponent <Renderer>();
            if (rend != null)
            {
                rend.material = waterMaterial;
                waterMaterial.SetTexture(Shader.PropertyToID("_MainTex"), extendedHeightField.textureHeightMap);
                waterMaterial.SetFloat(Shader.PropertyToID("_UnitX"), extendedHeightField.UnitX);
                waterMaterial.SetFloat(Shader.PropertyToID("_UnitY"), extendedHeightField.UnitY);
                waterMaterial.SetFloat(Shader.PropertyToID("_HoriResInverse"), 1f / ((float)extendedHeightField.HoriRes));
                waterMaterial.SetFloat(Shader.PropertyToID("_VertResInverse"), 1f / ((float)extendedHeightField.VertRes));
                waterMaterial.SetInt(Shader.PropertyToID("_VertexEnabled"), _useGpuForVertices ? 1 : 0);
            }
        }

        _hasStarted = true;
    }
Ejemplo n.º 8
0
    void GenerateMeshFromHeightMap(ExtendedHeightField heightMap, Vector3[] verticesOut, Vector2[] uvOut, int[] trianglesOut, Mesh mesh)
    {
        if (needFreshMesh)
        {
            if (!_useGpuForVertices)
            {
                for (int row = 0; row < heightMap.VertRes; row++)
                {
                    for (int col = 0; col < heightMap.HoriRes; col++)
                    {
                        int     index        = row * heightMap.HoriRes + col;
                        Vector4 displacement = heightMap.heightMap[index];

                        verticesOut[index].x = (col * heightMap.UnitX + displacement.x) - (0.5f * heightMap.Width);
                        verticesOut[index].y = displacement.y;
                        verticesOut[index].z = (row * heightMap.UnitY + displacement.z) - (0.5f * heightMap.Height);

                        uvOut[index].x = (col * heightMap.UnitX + displacement.x) / heightMap.Width;
                        uvOut[index].y = (row * heightMap.UnitY + displacement.z) / heightMap.Height;
                    }
                }
            }
            else
            {
                for (int row = 0; row < heightMap.VertRes; row++)
                {
                    for (int col = 0; col < heightMap.HoriRes; col++)
                    {
                        int index = row * heightMap.HoriRes + col;
                        verticesOut[index].x = (col * heightMap.UnitX) - (0.5f * heightMap.Width);
                        verticesOut[index].y = 0;
                        verticesOut[index].z = (row * heightMap.UnitY) - (0.5f * heightMap.Height);

                        uvOut[index].x = (col * heightMap.UnitX) / heightMap.Width;
                        uvOut[index].y = (row * heightMap.UnitY) / heightMap.Height;
                    }
                }
            }

            {
                int triangle_index = 0;
                for (int row = 0; row < heightMap.VertRes - 1; row++)
                {
                    for (int col = 0; col < heightMap.HoriRes - 1; col++)
                    {
                        int vertIndex = row * heightMap.HoriRes + col;
                        trianglesOut[triangle_index++] = vertIndex;
                        trianglesOut[triangle_index++] = vertIndex + heightMap.HoriRes;
                        trianglesOut[triangle_index++] = vertIndex + heightMap.HoriRes + 1;
                        trianglesOut[triangle_index++] = vertIndex;
                        trianglesOut[triangle_index++] = vertIndex + heightMap.HoriRes + 1;
                        trianglesOut[triangle_index++] = vertIndex + 1;
                    }
                }
            }
        }

        mesh.Clear();

        mesh.vertices  = vertices;
        mesh.uv        = uv;
        mesh.triangles = triangles;
        mesh.RecalculateBounds();
        mesh.RecalculateNormals();
    }
 public abstract void GenerateHeightField(int currentFrame, ExtendedHeightField extendedHeightField);
Ejemplo n.º 10
0
    public void setPointMap(int currentFrame, ref ExtendedHeightField pointMap)
    {
        bool antiAliased = false;

        Profiler.BeginSample("Clear Point Map");
        pointMap.Clear();
        Profiler.EndSample();

        Profiler.BeginSample("Get Point Map Raw");
        var pointMapRaw = pointMap.heightMap;

        Profiler.EndSample();

        Profiler.BeginSample("Get Height Field Info");
        var heightFieldInfo = pointMap.heightFieldInfo;

        Profiler.EndSample();

        Profiler.BeginSample("For Each Wave Particle");
        foreach (var waveParticle in this)
        {
            Profiler.BeginSample("Splat Wave Particle");
            if (antiAliased)
            {
                Vector2 waveParticlePosition = waveParticle.getPosition(currentFrame);
                float   xpos = (waveParticlePosition.x / heightFieldInfo.Width) * heightFieldInfo.HoriRes;
                float   ypos = (waveParticlePosition.y / heightFieldInfo.Height) * heightFieldInfo.VertRes;

                int col0;
                int col1;
                int row0;
                int row1;
                {
                    int col = Mathf.RoundToInt(xpos);
                    int row = Mathf.RoundToInt(ypos);
                    col0 = col - 1;
                    row0 = row - 1;
                    col1 = col;
                    row1 = row;
                }

                float width0  = 0.5f + col1 - xpos;
                float width1  = 0.5f + xpos - col1;
                float height0 = 0.5f + row1 - ypos;
                float height1 = 0.5f + ypos - row1;

                bool col0InRange = col0 < heightFieldInfo.HoriRes && col0 > 0;
                bool col1InRange = col1 < heightFieldInfo.HoriRes && col1 > 0;

                bool row0InRange = row0 < heightFieldInfo.VertRes && row0 > 0;
                bool row1InRange = row1 < heightFieldInfo.VertRes && row1 > 0;

                if (col0InRange && row0InRange)
                {
                    pointMapRaw[(row0 * heightFieldInfo.HoriRes) + col0].g += waveParticle.amplitude * width0 * height0;
                }
                if (col1InRange && row0InRange)
                {
                    pointMapRaw[(row0 * heightFieldInfo.HoriRes) + col1].g += waveParticle.amplitude * width1 * height0;
                }
                if (col0InRange && row1InRange)
                {
                    pointMapRaw[(row1 * heightFieldInfo.HoriRes) + col0].g += waveParticle.amplitude * width0 * height1;
                }
                if (col1InRange && row1InRange)
                {
                    pointMapRaw[(row1 * heightFieldInfo.HoriRes) + col1].g += waveParticle.amplitude * width1 * height1;
                }
            }
            else
            {
                Vector2 waveParticlePosition = waveParticle.getPosition(currentFrame);
                int     xPos  = Mathf.RoundToInt((waveParticlePosition.x / heightFieldInfo.Width) * heightFieldInfo.HoriRes);
                int     yPos  = Mathf.RoundToInt((waveParticlePosition.y / heightFieldInfo.Height) * heightFieldInfo.VertRes);
                int     index = (yPos * heightFieldInfo.HoriRes) + xPos;
                if (xPos < heightFieldInfo.HoriRes && xPos > 0 && yPos < heightFieldInfo.VertRes && yPos > 0)
                {
                    pointMapRaw[index].g += waveParticle.amplitude;
                }
            }
            Profiler.EndSample();
        }
        Profiler.EndSample();

        Profiler.BeginSample("Apply CPU Height Map");
        pointMap.ApplyCPUHeightMap();
        Profiler.EndSample();
    }
Ejemplo n.º 11
0
 public override void GenerateHeightField(int currentFrame, ExtendedHeightField extendedHeightField)
 {
     return;
 }
Ejemplo n.º 12
0
    public void setPointMap(int currentFrame, ref ExtendedHeightField pointMap)
    {
        Profiler.BeginSample("Set Point Map Internal");
        Profiler.BeginSample("Initialisation");
        ///
        /// Initialise _splatTexture if it hasn't been yet.
        ///
        if (_splatTexture == null)
        {
            if (antiAliased == AntiAlias.SCALE)
            {
                _splatTexture = new RenderTexture(pointMap.HoriRes * antiAliasFactor, pointMap.VertRes * antiAliasFactor, 24, RenderTextureFormat.ARGBFloat);
            }
            else
            {
                _splatTexture = new RenderTexture(pointMap.HoriRes, pointMap.VertRes, 24, RenderTextureFormat.ARGBFloat);
            }
            _splatTexture.enableRandomWrite = true;
        }

        if (!_splatTexture.IsCreated())
        {
            _splatTexture.Create();
        }
        Profiler.EndSample();

        Profiler.BeginSample("Intitialise Splatter");
        ///
        /// Initialise the SplatParticles GPU Compute Kernel to splat the particles to a texture
        ///
        _gpuSplatParticles.SetTexture(kernel_SplatParticles, SPLAT_TEXTURE, _splatTexture);
        _gpuSplatParticles.SetBuffer(kernel_SplatParticles, WAVE_PARTICLE_BUFFER, _waveParticlesBuffer);
        _gpuSplatParticles.SetFloat(FIXED_DELTA_TIME, Time.fixedDeltaTime);
        _gpuSplatParticles.SetInt(CURRENT_FRAME, currentFrame);
        _gpuSplatParticles.SetFloat(PARTICLE_SPEED, WaveParticle.PARTICLE_SPEED);
        _gpuSplatParticles.SetInt(HORI_RES, pointMap.HoriRes);
        _gpuSplatParticles.SetInt(VERT_RES, pointMap.VertRes);
        _gpuSplatParticles.SetFloat(PLANE_WIDTH, pointMap.Width);
        _gpuSplatParticles.SetFloat(PLANE_HEIGHT, pointMap.Height);
        _gpuSplatParticles.SetInt(ANTI_ALIASED, (int)antiAliased);
        _gpuSplatParticles.SetInt(ANTI_ALIAS_FACTOR, antiAliasFactor);

        ///
        /// Dispatch the kernel that splats wave particles to the _splatTexture
        ///
        _gpuSplatParticles.Dispatch(kernel_SplatParticles, ((int)_particleContainerSize) / THREAD_GROUPS_X, 1, 1);
        Profiler.EndSample();

        Profiler.BeginSample("Do the splatting");
        if (antiAliased == AntiAlias.SCALE)
        {
            ///
            /// As we have SCALE anti-aliasing, we need to downscale the texture to a new one.
            ///

            downsampleMaterial.SetInt(DOWNSAMPLE_ANTI_ALIAS_FACTOR_ID, antiAliasFactor);
            downsampleMaterial.SetInt(DOWNSAMPLE_TEXTURE_WIDTH_ID, pointMap.HoriRes);
            downsampleMaterial.SetInt(DOWNSAMPLE_TEXTURE_HEIGHT_ID, pointMap.VertRes);

            if (outputTexture == null || downscaleRenderTexture == null)
            {
                pointMap.InitialiseTexture(out outputTexture, name: "Downscale Output Texture");

                // Set the texture to the active one so that it's values can be read back out to the pointMapTexture
                downscaleRenderTexture = new RenderTexture(pointMap.HoriRes, pointMap.VertRes, 24, RenderTextureFormat.ARGBFloat);
            }

            if (!downscaleRenderTexture.IsCreated())
            {
                downscaleRenderTexture.Create();
            }

            RenderTexture.active = downscaleRenderTexture;

            GL.Clear(true, true, Color.black);

            // Blit what is stored in the _splatTexture to downscaleRenderTexture
            Graphics.Blit(_splatTexture, downscaleRenderTexture, downsampleMaterial);

            // Read back values from the render texture
            outputTexture.ReadPixels(new Rect(0, 0, outputTexture.width, outputTexture.height), 0, 0, false);
            outputTexture.Apply();


            RenderTexture.active = _splatTexture;
            downscaleRenderTexture.Release();

            GL.Clear(true, true, Color.black);

            RenderTexture.active = null;
            pointMap.UpdateTexture(outputTexture);
        }
        else
        {
            // Copy RenderTexture to a Texture2D
            RenderTexture.active = _splatTexture;

            if (outputTexture == null)
            {
                pointMap.InitialiseTexture(out outputTexture, name: "Point Map Texture");
            }

            // Read back values from the render texture
            outputTexture.ReadPixels(new Rect(0, 0, outputTexture.width, outputTexture.height), 0, 0, false);
            outputTexture.Apply();

            pointMap.UpdateTexture(outputTexture);

            GL.Clear(true, true, Color.black);
            RenderTexture.active = null;
        }
        Profiler.EndSample();
        Profiler.EndSample();
    }