Пример #1
0
        /// <summary>
        /// Concatenates multiple tables into one single texture 2D array
        /// </summary>
        /// <param name="_tablesFileNames"></param>
        /// <param name="_targetFileName"></param>
        /// <param name="_foramt"></param>
        static void ExportTexture(FileInfo[] _tablesFileNames, FileInfo _targetFileName, ImageUtility.PIXEL_FORMAT _format)
        {
            // Load tables
            LTC[][,]        tables = new LTC[_tablesFileNames.Length][, ];
            for (int i = 0; i < _tablesFileNames.Length; i++)
            {
                int validResultsCount;
                LTC[,]  table = FitterForm.LoadTable(_tablesFileNames[i], out validResultsCount);
                if (validResultsCount != table.Length)
                {
                    throw new Exception("Not all table results are valid!");
                }

                tables[i] = table;
                if (i != 0 && (table.GetLength(0) != tables[0].GetLength(0) || table.GetLength(1) != tables[0].GetLength(1)))
                {
                    throw new Exception("Table dimensions mismatch!");
                }
            }

            // Create the Texture2DArray
            uint W = (uint)tables[0].GetLength(0);
            uint H = (uint)tables[0].GetLength(1);

            ImageUtility.ImagesMatrix M = new ImageUtility.ImagesMatrix();
            M.InitTexture2DArray(W, H, (uint)tables.Length, 1);
            M.AllocateImageFiles(_format, new ImageUtility.ColorProfile(ImageUtility.ColorProfile.STANDARD_PROFILE.LINEAR));

            for (int i = 0; i < tables.Length; i++)
            {
                LTC[,]  table = tables[i];
//              ImageUtility.ImageFile	I = new ImageUtility.ImageFile( W, H, _format, profile );
//              M[(uint) i][0][0] = I;

                double largest           = 0;
                ImageUtility.ImageFile I = M[(uint)i][0][0];
                I.WritePixels((uint _X, uint _Y, ref float4 _color) => {
                    LTC ltc = table[_X, _Y];

                    const double tol = 1e-6;
//                  if ( Mathf.Abs( ltc.invM[2,2] - 1 ) > tol )
//                      throw new Exception( "Not one!" );
                    if (Mathf.Abs(ltc.invM[0, 1]) > tol || Mathf.Abs(ltc.invM[1, 0]) > tol || Mathf.Abs(ltc.invM[1, 2]) > tol || Mathf.Abs(ltc.invM[2, 1]) > tol)
                    {
                        throw new Exception("Not zero!");
                    }

                    largest       = Math.Max(largest, Math.Abs(ltc.invM[2, 2] - 1));
                    double factor = 1.0 / ltc.invM[2, 2];

                    _color.x = (float)(factor * ltc.invM[0, 0]);
                    _color.y = (float)(factor * ltc.invM[0, 2]);
                    _color.z = (float)(factor * ltc.invM[1, 1]);
                    _color.w = (float)(factor * ltc.invM[2, 0]);
                });
            }
            M.DDSSaveFile(_targetFileName, ImageUtility.COMPONENT_FORMAT.AUTO);
        }
Пример #2
0
        void    Plot(int _roughnessIndex, int _row, int _column, ImageFile _image, PanelOutput _panel, Label _label)
        {
            _image.Clear(float4.One);

            // Determine range first
            int W = m_results.GetLength(0);

            float[] values = new float[W];
            float   min    = float.MaxValue;
            float   max    = -float.MaxValue;

            for (int X = 0; X < W; X++)
            {
                LTC    ltc  = m_results[_roughnessIndex, X];
                double term = ltc.invM[_row, _column];
                term     /= ltc.invM[1, 1];                             // Normalize by central term
                values[X] = (float)term;
                min       = Math.Min(min, values[X]);
                max       = Math.Max(max, values[X]);
            }
            float2 rangeY = float2.UnitY;

            rangeY.x = Math.Min(rangeY.x, min);
            rangeY.y = Math.Max(rangeY.y, max);

            // Plot graph and update UI
            float2 rangeX = new float2(0, 1);

            _image.PlotGraph(new float4(0, 0, 0, 1), rangeX, rangeY, ( float _X ) => {
                int X = Math.Min(W - 1, (int)(W * _X));
                return(values[X]);
            });
            _image.PlotAxes(float4.UnitW, rangeX, rangeY, 0.1f, 0.1f * (rangeY.y - rangeY.x));
            _label.Text     = "Coefficient m" + _row + "" + _column + " - Range [" + rangeY.x + ", " + rangeY.y + "]";
            _panel.m_bitmap = _image.AsBitmap;
            _panel.Refresh();
        }
Пример #3
0
        static void     Export(FileInfo _tableFileName, FileInfo _targetFileName, string _BRDFName)
        {
            int validResultsCount;

            LTC[,]  table = FitterForm.LoadTable(_tableFileName, out validResultsCount);

            string sourceCode = "";

            // Export LTC matrices
            int tableSize  = table.GetLength(0);
            LTC defaultLTC = new LTC();

            defaultLTC.magnitude = 0.0;

                #if EXPORT_FOR_UNITY
            string tableName = "s_LtcMatrixData_" + _BRDFName;

            sourceCode += "using UnityEngine;\r\n"
                          + "using System;\r\n"
                          + "\r\n"
                          + "namespace UnityEngine.Experimental.Rendering.HDPipeline\r\n"
                          + "{\r\n"
                          + "    public partial class LTCAreaLight\r\n"
                          + "    {\r\n"
                          + "        // Table contains 3x3 matrix coefficients of M^-1 for the fitting of the " + _BRDFName + " BRDF using the LTC technique\r\n"
                          + "        // From \"Real-Time Polygonal-Light Shading with Linearly Transformed Cosines\" 2016 (https://eheitzresearch.wordpress.com/415-2/)\r\n"
                          + "        //\r\n"
                          + "        // The table is accessed via LTCAreaLight." + tableName + "[<roughnessIndex> + 64 * <thetaIndex>]    // Theta values are along the Y axis, Roughness values are along the X axis\r\n"
                          + "        //    • roughness = ( <roughnessIndex> / " + (tableSize - 1) + " )^2\r\n"
                          + "        //    • cosTheta = 1 - ( <thetaIndex> / " + (tableSize - 1) + " )^2\r\n"
                          + "        //\r\n"
                          + "        public static double[,]	"+ tableName + " = new double[k_LtcLUTResolution * k_LtcLUTResolution, k_LtcLUTMatrixDim * k_LtcLUTMatrixDim] {\r\n";

            for (int thetaIndex = 0; thetaIndex < tableSize; thetaIndex++)
            {
                string matrixRowString = "            ";
                for (int roughnessIndex = 0; roughnessIndex < tableSize; roughnessIndex++)
                {
                    LTC ltc = table[roughnessIndex, thetaIndex];
                    if (ltc == null)
                    {
                        ltc = defaultLTC;
                    }

                    string matrixString = ltc.invM[0, 0] + ", " + ltc.invM[0, 1] + ", " + ltc.invM[0, 2] + ", ";
                    matrixString += ltc.invM[1, 0] + ", " + ltc.invM[1, 1] + ", " + ltc.invM[1, 2] + ", ";
                    matrixString += ltc.invM[2, 0] + ", " + ltc.invM[2, 1] + ", " + ltc.invM[2, 2];

//                  string	matrixString  = ltc.M[0,0] + ", " + ltc.M[0,1] + ", " + ltc.M[0,2] + ", ";
//                          matrixString += ltc.M[1,0] + ", " + ltc.M[1,1] + ", " + ltc.M[1,2] + ", ";
//                          matrixString += ltc.M[2,0] + ", " + ltc.M[2,1] + ", " + ltc.M[2,2];

                    matrixRowString += "{ " + matrixString + " }, ";
                }

                // Compute theta
                float y        = (float)thetaIndex / (tableSize - 1);
                float cosTheta = 1 - y * y;

                matrixRowString += "   // Cos(theta) = " + cosTheta + "\r\n";

                sourceCode += matrixRowString;
            }
                #else
            string className = "LTCData_" + _BRDFName;

            sourceCode += "using System;\r\n"
                          + "\r\n"
                          + "namespace LTCAreaLight\r\n"
                          + "{\r\n"
                          + "    public partial class " + className + "\r\n"
                          + "    {\r\n"
                          + "        // Table contains 3x3 matrix coefficients of M^-1 for the fitting of the " + _BRDFName + " BRDF using the LTC technique\r\n"
                          + "        // From \"Real-Time Polygonal-Light Shading with Linearly Transformed Cosines\" 2016 (https://eheitzresearch.wordpress.com/415-2/)\r\n"
                          + "        //\r\n"
                          + "        // The table is accessed via LTCAreaLight." + className + "[64 * <roughnessIndex> + <thetaIndex>]    // Theta values are on X axis, Roughness values are on Y axis\r\n"
                          + "        //    • roughness = ( <roughnessIndex> / " + (tableSize - 1) + " )^2\r\n"
                          + "        //    • cosTheta = 1 - ( <thetaIndex> / " + (tableSize - 1) + " )^2\r\n"
                          + "        //\r\n"
                          + "        public static double[,]	s_invM = new double["+ tableSize + " * " + tableSize + ", 3 * 3] {\r\n";

            for (int roughnessIndex = 0; roughnessIndex < tableSize; roughnessIndex++)
            {
//				string	matrixRowString = "            { ";
                string matrixRowString = "            ";
                for (int thetaIndex = 0; thetaIndex < tableSize; thetaIndex++)
                {
                    LTC ltc = table[roughnessIndex, thetaIndex];
                    if (ltc == null)
                    {
                        ltc = defaultLTC;
                    }

                    string matrixString = ltc.invM[0, 0] + ", " + ltc.invM[0, 1] + ", " + ltc.invM[0, 2] + ", ";
                    matrixString += ltc.invM[1, 0] + ", " + ltc.invM[1, 1] + ", " + ltc.invM[1, 2] + ", ";
                    matrixString += ltc.invM[2, 0] + ", " + ltc.invM[2, 1] + ", " + ltc.invM[2, 2];
//					matrixRowString += (thetaIndex == 0 ? "{ " : ", { ") + matrixString + " }";
                    matrixRowString += "{ " + matrixString + " }, ";
                }

//              // Compute roughness
//              float	perceptualRoughness = (float) roughnessIndex / (tableSize-1);
//              float	alpha = perceptualRoughness * perceptualRoughness;
//
// //				matrixRowString += " },\r\n";
//              matrixRowString += "   // Roughness = " + alpha + "\r\n";

                throw new Exception("Ta mère!");
                sourceCode += matrixRowString;
            }
                #endif

            sourceCode += "        };\r\n";

            // Export LTC amplitude and fresnel
            //
//        public static float[] s_LtcGGXMagnitudeData = new float[k_LtcLUTResolution * k_LtcLUTResolution]
//        public static float[] s_LtcGGXFresnelData = new float[k_LtcLUTResolution * k_LtcLUTResolution]

            sourceCode += "\r\n";
            sourceCode += "        // NOTE: Formerly, we needed to also export and create a table for the BRDF's amplitude factor + fresnel coefficient\r\n";
            sourceCode += "        //    but it turns out these 2 factors are actually already precomputed and available in the FGD table corresponding\r\n";
            sourceCode += "        //    to the " + _BRDFName + " BRDF, therefore they are no longer exported...\r\n";

            // Close class and namespace
            sourceCode += "    }\r\n";
            sourceCode += "}\r\n";

            // Write content
//			FileInfo	targetFileName = new FileInfo( Path.Combine( Path.GetDirectoryName( _tableFileName.FullName ), Path.GetFileNameWithoutExtension( _tableFileName.FullName ) + ".cs" ) );
            using (StreamWriter W = _targetFileName.CreateText())
                W.Write(sourceCode);
        }