예제 #1
0
        /// <summary>
        /// Save the actual data in table as a raw file to be loaded and used during run time.
        /// </summary>
        private void SaveAsRaw(int size, int channels, string fileName, RenderTexture rtex)
        {
            ComputeBuffer buffer = new ComputeBuffer(size, sizeof(float) * channels);

            CBUtility.ReadFromRenderTexture(rtex, channels, buffer, m_readData);

            float[] data = new float[size * channels];

            buffer.GetData(data);

            byte[] byteArray = new byte[size * 4 * channels];
            System.Buffer.BlockCopy(data, 0, byteArray, 0, byteArray.Length);
            System.IO.File.WriteAllBytes(Application.dataPath + m_filePath + fileName + ".raw", byteArray);

            buffer.Release();
        }
예제 #2
0
    public static void SaveAsRaw(int size, CBUtility.Channels channels, string fileName, string filePath, RenderTexture rtex, ComputeShader readDataComputeShader)
    {
        var channelsSize = (byte)channels;
        var buffer       = new ComputeBuffer(size, sizeof(float) * channelsSize);

        CBUtility.ReadFromRenderTexture(rtex, channels, buffer, readDataComputeShader);

        var data = new float[size * channelsSize];

        buffer.GetData(data);

        var byteArray = new byte[size * 4 * channelsSize];

        Buffer.BlockCopy(data, 0, byteArray, 0, byteArray.Length);
        File.WriteAllBytes(Application.dataPath + filePath + fileName + ".raw", byteArray);

        buffer.Release();
    }
예제 #3
0
    public static void SaveAs8bit(int width, int height, CBUtility.Channels channels, string fileName, string filePath, RenderTexture rtex, ComputeShader readDataComputeShader, float scale = 1.0f)
    {
        var channelsSize = (byte)channels;
        var buffer       = new ComputeBuffer(width * height, sizeof(float) * channelsSize);

        CBUtility.ReadFromRenderTexture(rtex, channels, buffer, readDataComputeShader);

        var data = new float[width * height * channelsSize];

        buffer.GetData(data);

        var texture = new Texture2D(width, height);

        for (int x = 0; x < width; x++)
        {
            for (int y = 0; y < height; y++)
            {
                var color = new Color(0, 0, 0, 1);

                color.r = data[(x + y * width) * channelsSize + 0];

                if (channelsSize > 1)
                {
                    color.g = data[(x + y * width) * channelsSize + 1];
                }

                if (channelsSize > 2)
                {
                    color.b = data[(x + y * width) * channelsSize + 2];
                }

                texture.SetPixel(x, y, color * scale);
            }
        }

        texture.Apply();

        var bytes = texture.EncodeToPNG();

        File.WriteAllBytes(Application.dataPath + filePath + fileName + ".png", bytes);

        buffer.Release();
    }
예제 #4
0
        private void ReadFromGPU(int numGrids)
        {
            if (!this.disableReadBack && this.readSdr == null)
            {
                Ocean.LogWarning("Trying to read GPU displacement data but the read shader is null");
            }
            bool flag = SystemInfo.graphicsShaderLevel >= 50 && SystemInfo.supportsComputeShaders;

            if (!this.disableReadBack && this.readSdr != null && this.m_readBuffer != null && flag)
            {
                InterpolatedArray2f[] readDisplacements = this.DisplacementBuffer.GetReadDisplacements();
                if (numGrids > 0)
                {
                    CBUtility.ReadFromRenderTexture(this.m_displacementMaps[0], 3, this.m_readBuffer, this.readSdr);
                    this.m_readBuffer.GetData(readDisplacements[0].Data);
                }
                else
                {
                    readDisplacements[0].Clear();
                }
                if (numGrids > 1)
                {
                    CBUtility.ReadFromRenderTexture(this.m_displacementMaps[1], 3, this.m_readBuffer, this.readSdr);
                    this.m_readBuffer.GetData(readDisplacements[1].Data);
                }
                else
                {
                    readDisplacements[1].Clear();
                }
                if (numGrids > 2)
                {
                    CBUtility.ReadFromRenderTexture(this.m_displacementMaps[2], 3, this.m_readBuffer, this.readSdr);
                    this.m_readBuffer.GetData(readDisplacements[2].Data);
                }
                else
                {
                    readDisplacements[2].Clear();
                }
                if (numGrids > 3)
                {
                }
            }
        }
예제 #5
0
        /// <summary>
        /// Saves a 8 bit version of the table.
        /// Only used to get a visible image for debugging.
        /// </summary>
        private void SaveAs8bit(int width, int height, int channels, string fileName, RenderTexture rtex, float scale = 1.0f)
        {
            ComputeBuffer buffer = new ComputeBuffer(width * height, sizeof(float) * channels);

            CBUtility.ReadFromRenderTexture(rtex, channels, buffer, m_readData);

            float[] data = new float[width * height * channels];

            buffer.GetData(data);

            Texture2D tex = new Texture2D(width, height);

            for (int x = 0; x < width; x++)
            {
                for (int y = 0; y < height; y++)
                {
                    Color col = new Color(0, 0, 0, 1);

                    col.r = data[(x + y * width) * channels + 0];

                    if (channels > 1)
                    {
                        col.g = data[(x + y * width) * channels + 1];
                    }

                    if (channels > 2)
                    {
                        col.b = data[(x + y * width) * channels + 2];
                    }

                    tex.SetPixel(x, y, col * scale);
                }
            }

            tex.Apply();

            byte[] bytes = tex.EncodeToPNG();

            System.IO.File.WriteAllBytes(Application.dataPath + m_filePath + fileName + ".png", bytes);

            buffer.Release();
        }
    private void PrecomputeSkyboxAlltogether()
    {
        int  texDepth  = (int)_skyboxLUTSize.z;
        int  texWidth  = (int)_skyboxLUTSize.x;
        int  texHeight = (int)_skyboxLUTSize.y;
        int  floatSize = sizeof(float);
        int  channels  = 4;
        int  texSize   = texWidth * texHeight * texDepth;
        bool firstTime = false;

        if (_skyboxData == null)
        {
            firstTime   = true;
            _skyboxData = new float[texSize * channels];
        }

        ComputeBuffer buffer = new ComputeBuffer(texSize, floatSize * channels); // 4 bytes for float and 4 channels

        CBUtility.ReadFromRenderTexture(_skyboxLUT2, channels, buffer, FrostbiteReadShader);
        float[] data = new float[texSize * channels];
        buffer.GetData(data);

        if (firstTime)
        {
            for (int i = 0; i < _skyboxData.Length; ++i)
            {
                _skyboxData[i] = data[i];
            }
        }
        else
        {
            for (int i = 0; i < _skyboxData.Length; ++i)
            {
                _skyboxData[i] += data[i];
            }
        }

        buffer.Release();
    }
예제 #7
0
        /// <summary>
        /// Updates the <see cref="TerrainQuad.ZMin"/> and <see cref="TerrainQuad.ZMax"/> values.
        /// Used to create a better fitting bounding box.
        /// Is not essental and can be disabled if retriving the heights data from the GPU is causing performance issues.
        /// </summary>
        private void UpdateMinMax()
        {
            // If no quads need read back or if disabled return
            if (NeedsReadBackDictionary.Count == 0 || !EnableReadBack)
            {
                return;
            }

            // Make a copy of all the keys of the tiles that need to be read back
            var ids = new Tile.Id[NeedsReadBackDictionary.Count];

            NeedsReadBackDictionary.Keys.CopyTo(ids, 0);

            // Sort the keys by there level, lowest -> highest
            Array.Sort(ids, new Tile.ComparerID());

            var count = 0;

            // Foreach key read back the tiles data until the maxReadBacksPerFrame limit is reached
            foreach (var id in ids)
            {
                var treeZ = NeedsReadBackDictionary[id];

                // If elevations container already contains key then data has been read back before so just reapply the [min, max] values to TerranQuad
                if (ElevationsDicionary.ContainsKey(id))
                {
                    var info = ElevationsDicionary.Get(id);

                    treeZ.TerrainQuad.ZMin = info.Min;
                    treeZ.TerrainQuad.ZMax = info.Max;

                    NeedsReadBackDictionary.Remove(id);
                }
                else
                {
                    // If for some reason the tile is null remove from container and continue
                    if (treeZ.Tile == null)
                    {
                        NeedsReadBackDictionary.Remove(id);

                        continue;
                    }

                    var slot = treeZ.Tile.Slot[0] as GPUTileStorage.GPUSlot;

                    // If for some reason this is not a GPUSlot remove and continue
                    if (slot == null)
                    {
                        NeedsReadBackDictionary.Remove(id);

                        continue;
                    }

                    var texture = slot.Texture;
                    var size    = texture.width * texture.height;

                    var elevationInfo = new ElevationInfo();
                    elevationInfo.Elevations = new float[size];

                    // Read back heights data from texture
                    CBUtility.ReadFromRenderTexture(texture, CBUtility.Channels.R, ElevationsBuffer, GodManager.Instance.ReadData);

                    // Copy into elevations info
                    ElevationsBuffer.GetData(elevationInfo.Elevations);

                    // Find the min/max values
                    for (int i = 0; i < size; i++)
                    {
                        if (elevationInfo.Elevations[i] < elevationInfo.Min)
                        {
                            elevationInfo.Min = elevationInfo.Elevations[i];
                        }
                        if (elevationInfo.Elevations[i] > elevationInfo.Max)
                        {
                            elevationInfo.Max = elevationInfo.Elevations[i];
                        }
                    }

                    // Update TerrainQuad
                    treeZ.TerrainQuad.ZMin = elevationInfo.Min;
                    treeZ.TerrainQuad.ZMax = elevationInfo.Max;

                    // Store elevations to prevent having to read back again soon
                    // Add to end of container
                    ElevationsDicionary.AddLast(id, elevationInfo);
                    NeedsReadBackDictionary.Remove(id);

                    count++;

                    // If the number of rad back to do per frame has hit the limit stop loop.
                    if (count >= MaxReadBacksPerFrame)
                    {
                        break;
                    }
                }
            }

            // If the number of elevation info to store has exceded limit remove from start of container
            while (ElevationsDicionary.Count() > MaxStoredElevations)
            {
                ElevationsDicionary.RemoveFirst();
            }
        }
예제 #8
0
        private void GenerateWavesSpectrum()
        {
            // Slope variance due to all waves, by integrating over the full spectrum.
            // Used by the BRDF rendering model

            var theoreticSlopeVariance = 0.0f;
            var k = 5e-3f;

            while (k < 1e3f)
            {
                var nextK = k * 1.001f;

                theoreticSlopeVariance += k * k * Spectrum(k, 0, true) * (nextK - k);

                k = nextK;
            }

            var spectrum01 = new float[FourierGridSize * FourierGridSize * 4];
            var spectrum23 = new float[FourierGridSize * FourierGridSize * 4];

            int   idx;
            float i;
            float j;
            float totalSlopeVariance = 0.0f;

            Vector2 sample12XY = Vector2.zero;
            Vector2 sample12ZW = Vector2.zero;
            Vector2 sample34XY = Vector2.zero;
            Vector2 sample34ZW = Vector2.zero;

            Random.InitState(0);

            for (int x = 0; x < FourierGridSize; x++)
            {
                for (int y = 0; y < FourierGridSize; y++)
                {
                    idx = x + y * FourierGridSize;
                    i   = (x >= FourierGridSize / 2) ? (float)(x - FourierGridSize) : (float)x;
                    j   = (y >= FourierGridSize / 2) ? (float)(y - FourierGridSize) : (float)y;

                    sample12XY = GetSpectrumSample(i, j, GridSizes.x, Mathf.PI / GridSizes.x);
                    sample12ZW = GetSpectrumSample(i, j, GridSizes.y, Mathf.PI * MapSize / GridSizes.x);
                    sample34XY = GetSpectrumSample(i, j, GridSizes.z, Mathf.PI * MapSize / GridSizes.y);
                    sample34ZW = GetSpectrumSample(i, j, GridSizes.w, Mathf.PI * MapSize / GridSizes.z);

                    spectrum01[idx * 4 + 0] = sample12XY.x;
                    spectrum01[idx * 4 + 1] = sample12XY.y;
                    spectrum01[idx * 4 + 2] = sample12ZW.x;
                    spectrum01[idx * 4 + 3] = sample12ZW.y;

                    spectrum23[idx * 4 + 0] = sample34XY.x;
                    spectrum23[idx * 4 + 1] = sample34XY.y;
                    spectrum23[idx * 4 + 2] = sample34ZW.x;
                    spectrum23[idx * 4 + 3] = sample34ZW.y;

                    i *= 2.0f * Mathf.PI;
                    j *= 2.0f * Mathf.PI;

                    totalSlopeVariance += GetSlopeVariance(i / GridSizes.x, j / GridSizes.x, sample12XY);
                    totalSlopeVariance += GetSlopeVariance(i / GridSizes.y, j / GridSizes.y, sample12ZW);
                    totalSlopeVariance += GetSlopeVariance(i / GridSizes.z, j / GridSizes.z, sample34XY);
                    totalSlopeVariance += GetSlopeVariance(i / GridSizes.w, j / GridSizes.w, sample34ZW);
                }
            }

            //Write floating point data into render texture
            var buffer = new ComputeBuffer(FourierGridSize * FourierGridSize, sizeof(float) * 4);

            buffer.SetData(spectrum01);
            CBUtility.WriteIntoRenderTexture(Spectrum01, CBUtility.Channels.RGBA, buffer, GodManager.Instance.WriteData);

            buffer.SetData(spectrum23);
            CBUtility.WriteIntoRenderTexture(Spectrum23, CBUtility.Channels.RGBA, buffer, GodManager.Instance.WriteData);

            buffer.Release();

            var varianceShader = GodManager.Instance.Variance;

            varianceShader.SetFloat("_SlopeVarianceDelta", 0.5f * (theoreticSlopeVariance - totalSlopeVariance));
            varianceShader.SetFloat("_VarianceSize", (float)VarianceSize);
            varianceShader.SetFloat("_Size", MapSize);
            varianceShader.SetVector("_GridSizes", GridSizes);
            varianceShader.SetTexture(0, "_Spectrum01", Spectrum01);
            varianceShader.SetTexture(0, "_Spectrum23", Spectrum23);
            varianceShader.SetTexture(0, "des", Variance);

            varianceShader.Dispatch(0, VarianceSize / 4, VarianceSize / 4, VarianceSize / 4);

            // Find the maximum value for slope variance

            buffer = new ComputeBuffer(VarianceSize * VarianceSize * VarianceSize, sizeof(float));
            CBUtility.ReadFromRenderTexture(Variance, CBUtility.Channels.R, buffer, GodManager.Instance.ReadData);

            var varianceData = new float[VarianceSize * VarianceSize * VarianceSize];

            buffer.GetData(varianceData);

            MaxSlopeVariance = 0.0f;

            for (int v = 0; v < VarianceSize * VarianceSize * VarianceSize; v++)
            {
                MaxSlopeVariance = Mathf.Max(MaxSlopeVariance, varianceData[v]);
            }

            buffer.Release();
        }
    public void SaveTextureAsKTX(RenderTexture rtex, String name, bool tile3D = false)
    {
        int texDepth  = rtex.volumeDepth;
        int texWidth  = rtex.width;
        int texHeight = rtex.height;
        int floatSize = sizeof(float);
        int channels  = 4;

        bool tileEnabled = tile3D && texDepth > 1;

        if (tileEnabled)
        {
            texWidth *= texDepth;
            texDepth  = 1;
        }


        int texSize = texWidth * texHeight * texDepth;

        ComputeBuffer buffer = new ComputeBuffer(texSize, floatSize * channels); // 4 bytes for float and 4 channels

        CBUtility.ReadFromRenderTexture(rtex, channels, buffer, FrostbiteReadShader);

        float[] data = new float[texSize * channels];

        buffer.GetData(data);

        Byte[] header =
        {
            0xAB, 0x4B, 0x54, 0x58, // first four bytes of Byte[12] identifier
            0x20, 0x31, 0x31, 0xBB, // next four bytes of Byte[12] identifier
            0x0D, 0x0A, 0x1A, 0x0A, // final four bytes of Byte[12] identifier
            0x01, 0x02, 0x03, 0x04, // Byte[4] endianess (Big endian in this case)
        };

        FileStream   fs     = new FileStream("Assets/Textures/" + name + ".ktx", FileMode.OpenOrCreate);
        BinaryWriter writer = new BinaryWriter(fs);

        writer.Write(header);

        UInt32 glType               = 0x140B; // HALF
        UInt32 glTypeSize           = 2;      // 2 bytes
        UInt32 glFormat             = 0x1908; // RGBA
        UInt32 glInterformat        = 0x881A; // RGBA FLOAT16
        UInt32 glBaseInternalFormat = 0x1908; // RGBA
        UInt32 width         = (UInt32)texWidth;
        UInt32 height        = (UInt32)texHeight;
        UInt32 depth         = (UInt32)(texDepth == 1 ? 0 : texDepth);
        UInt32 numOfArrElem  = 0;
        UInt32 numOfFace     = 1;
        UInt32 numOfMip      = 1;
        UInt32 bytesOfKeyVal = 0;

        writer.Write(glType);
        writer.Write(glTypeSize);
        writer.Write(glFormat);
        writer.Write(glInterformat);
        writer.Write(glBaseInternalFormat);
        writer.Write(width);
        writer.Write(height);
        writer.Write(depth);
        writer.Write(numOfArrElem);
        writer.Write(numOfFace);
        writer.Write(numOfMip);
        writer.Write(bytesOfKeyVal);

        UInt32 imageSize = (UInt32)(texSize * channels * glTypeSize);

        writer.Write(imageSize);

        if (tileEnabled)
        {
            for (int j = 0; j < rtex.height; j++)
            {
                for (int k = 0; k < rtex.volumeDepth; k++)
                {
                    for (int i = 0; i < rtex.width; i++)
                    {
                        int startIndex = k * rtex.width * rtex.height * channels + j * rtex.width * channels + i * channels;
                        writer.Write(Half.GetBytes((Half)data[startIndex]));
                        writer.Write(Half.GetBytes((Half)data[startIndex + 1]));
                        writer.Write(Half.GetBytes((Half)data[startIndex + 2]));
                        writer.Write(Half.GetBytes((Half)data[startIndex + 3]));
                    }
                }
            }
        }
        else
        {
            for (int i = 0; i < data.Length; ++i)
            {
                writer.Write(Half.GetBytes((Half)data[i]));
            }
        }

        writer.Close();
        fs.Close();
        buffer.Release();
    }
예제 #10
0
        private void GenerateWavesSpectrum()
        {
            // Slope variance due to all waves, by integrating over the full spectrum.
            // Used by the BRDF rendering model
            float theoreticSlopeVariance = 0.0f;
            float k = 5e-3f;

            while (k < 1e3f)
            {
                float nextK = k * 1.001f;
                theoreticSlopeVariance += k * k * Spectrum(k, 0, true) * (nextK - k);
                k = nextK;
            }

            float[] spectrum01 = new float[m_fourierGridSize * m_fourierGridSize * 4];
            float[] spectrum23 = new float[m_fourierGridSize * m_fourierGridSize * 4];

            int     idx;
            float   i;
            float   j;
            float   totalSlopeVariance = 0.0f;
            Vector2 sample12XY;
            Vector2 sample12ZW;
            Vector2 sample34XY;
            Vector2 sample34ZW;

            Random.InitState(0);


            for (int x = 0; x < m_fourierGridSize; x++)
            {
                for (int y = 0; y < m_fourierGridSize; y++)
                {
                    idx = x + y * m_fourierGridSize;
                    i   = (x >= m_fourierGridSize / 2) ? (float)(x - m_fourierGridSize) : (float)x;
                    j   = (y >= m_fourierGridSize / 2) ? (float)(y - m_fourierGridSize) : (float)y;

                    sample12XY = GetSpectrumSample(i, j, m_gridSizes.x, Mathf.PI / m_gridSizes.x);
                    sample12ZW = GetSpectrumSample(i, j, m_gridSizes.y, Mathf.PI * m_fsize / m_gridSizes.x);
                    sample34XY = GetSpectrumSample(i, j, m_gridSizes.z, Mathf.PI * m_fsize / m_gridSizes.y);
                    sample34ZW = GetSpectrumSample(i, j, m_gridSizes.w, Mathf.PI * m_fsize / m_gridSizes.z);

                    spectrum01[idx * 4 + 0] = sample12XY.x;
                    spectrum01[idx * 4 + 1] = sample12XY.y;
                    spectrum01[idx * 4 + 2] = sample12ZW.x;
                    spectrum01[idx * 4 + 3] = sample12ZW.y;

                    spectrum23[idx * 4 + 0] = sample34XY.x;
                    spectrum23[idx * 4 + 1] = sample34XY.y;
                    spectrum23[idx * 4 + 2] = sample34ZW.x;
                    spectrum23[idx * 4 + 3] = sample34ZW.y;

                    i *= 2.0f * Mathf.PI;
                    j *= 2.0f * Mathf.PI;

                    totalSlopeVariance += GetSlopeVariance(i / m_gridSizes.x, j / m_gridSizes.x, sample12XY);
                    totalSlopeVariance += GetSlopeVariance(i / m_gridSizes.y, j / m_gridSizes.y, sample12ZW);
                    totalSlopeVariance += GetSlopeVariance(i / m_gridSizes.z, j / m_gridSizes.z, sample34XY);
                    totalSlopeVariance += GetSlopeVariance(i / m_gridSizes.w, j / m_gridSizes.w, sample34ZW);
                }
            }

            //Write floating point data into render texture
            ComputeBuffer buffer = new ComputeBuffer(m_fourierGridSize * m_fourierGridSize, sizeof(float) * 4);

            buffer.SetData(spectrum01);
            CBUtility.WriteIntoRenderTexture(m_spectrum01, 4, buffer, World.WriteData);

            buffer.SetData(spectrum23);
            CBUtility.WriteIntoRenderTexture(m_spectrum23, 4, buffer, World.WriteData);

            buffer.Release();

            m_varianceShader.SetFloat("_SlopeVarianceDelta", 0.5f * (theoreticSlopeVariance - totalSlopeVariance));
            m_varianceShader.SetFloat("_VarianceSize", (float)m_varianceSize);
            m_varianceShader.SetFloat("_Size", m_fsize);
            m_varianceShader.SetVector("_GridSizes", m_gridSizes);
            m_varianceShader.SetTexture(0, "_Spectrum01", m_spectrum01);
            m_varianceShader.SetTexture(0, "_Spectrum23", m_spectrum23);
            m_varianceShader.SetTexture(0, "des", m_variance);

            m_varianceShader.Dispatch(0, m_varianceSize / 4, m_varianceSize / 4, m_varianceSize / 4);

            //Find the maximum value for slope variance

            buffer = new ComputeBuffer(m_varianceSize * m_varianceSize * m_varianceSize, sizeof(float));
            CBUtility.ReadFromRenderTexture(m_variance, 1, buffer, World.ReadData);

            float[] varianceData = new float[m_varianceSize * m_varianceSize * m_varianceSize];
            buffer.GetData(varianceData);

            m_maxSlopeVariance = 0.0f;
            for (int v = 0; v < m_varianceSize * m_varianceSize * m_varianceSize; v++)
            {
                m_maxSlopeVariance = Mathf.Max(m_maxSlopeVariance, varianceData[v]);
            }

            buffer.Release();
        }