Ejemplo n.º 1
0
    private void ProbeFinish()
    {
        EditorApplication.isPlaying = false;
        mset.SkyManager skmgr = mset.SkyManager.Get();
        foreach (mset.Sky sky in skmgr.SkiesToProbe)
        {
            if (sky.SpecularCube as Cubemap)
            {
                mset.CubeMipProcessor.CreateSubMips(sky.SpecularCube as Cubemap);
                mset.SHUtil.projectCube(ref sky.SH, sky.SpecularCube as Cubemap, 3, true);
                mset.SHUtil.convolve(ref sky.SH);
                sky.SH.copyToBuffer();
            }
            sky.Dirty = true;
        }
        proProbe           = null;
        freeProbe          = null;
        skmgr.SkiesToProbe = null;
        AssetDatabase.Refresh();

        skmgr.ShowSkybox = skmgr.ShowSkybox;
        skmgr.EditorUpdate(true);
        skmgr.ProbeExposures = Vector4.one;

        EditorUtility.ClearProgressBar();
        mset.SkyInspector.forceRefresh();

        if (DoneCallback != null)
        {
            DoneCallback();
        }
        DoneCallback = null;

        Close();
    }
Ejemplo n.º 2
0
    ///
    public void OnGUI()
    {
        GUILayout.BeginArea(new Rect(0, 0, position.width, position.height));
        uiScroll = EditorGUILayout.BeginScrollView(uiScroll, false, false, GUILayout.MinWidth(300), GUILayout.MaxWidth(position.width));

        float rightPad     = 23;
        float minWidth     = 315;
        float sectionWidth = position.width - rightPad;
        float logoSize     = 128;

        Rect logoRect = EditorGUILayout.BeginVertical(); {
            GUILayout.Space(32);
            drawSkyshopLogo(sectionWidth - logoSize, logoRect.y, logoSize);
        } EditorGUILayout.EndVertical();

        uiHideDuringCompute = false;        //EditorGUILayout.Toggle("Hide UI During Compute",uiHideDuringCompute);
        if (!uiHideDuringCompute || !ps.isPlaying())
        {
            // INPUT REF
            EditorGUILayout.BeginVertical(); {
                inSKY.previewWidth = Mathf.Max(328, (int)sectionWidth - 2);
                inSKY.drawGUI();
                outSIM.inputPath = outSKY.inputPath = inSKY.fullPath;
            } EditorGUILayout.EndVertical();

            // OUTPUT REF
            EditorGUILayout.BeginVertical("HelpBox", GUILayout.Width(sectionWidth), GUILayout.MinWidth(minWidth)); {
                uiRefOptions = EditorGUILayout.Foldout(uiRefOptions, "Output Cubemaps");
                if (uiRefOptions)
                {
                    outSKY.drawGUI(); EditorGUILayout.Space();
                    outSIM.drawGUI(); EditorGUILayout.Space();

                    EditorGUILayout.BeginHorizontal(); {
                        string newTip = "Create a new cubemap assets for each output slot and adds them to the project.";
                        if (GUILayout.Button(new GUIContent("New All ", newTip), GUILayout.Width(70), GUILayout.Height(18)))
                        {
                            outSKY.newCube();
                            outSIM.newCube();
                        }
                        string findTip = "Search project for all existing output cubemaps by input panorama name.";
                        if (GUILayout.Button(new GUIContent("Find All", findTip), GUILayout.Width(70), GUILayout.Height(18)))
                        {
                            outSKY.find();
                            outSIM.find();
                        }
                        string clearTip = "Deselect all target cubemaps from output slots.";
                        if (GUILayout.Button(new GUIContent("Clear All", clearTip), GUILayout.Width(80), GUILayout.Height(18)))
                        {
                            outSKY.clear();
                            outSIM.clear();
                        }
                        string reloadTip = "Reload all input and output slot textures and generate preview images for them.";
                        EditorGUI.BeginDisabledGroup(outSKY.fullPath.Length == 0 && outSIM.fullPath.Length == 0 && inSKY.fullPath.Length == 0);
                        {
                            if (GUILayout.Button(new GUIContent("Reload All", reloadTip), GUILayout.Width(85), GUILayout.Height(18)))
                            {
                                outSKY.reloadReference();
                                outSIM.reloadReference();
                                inSKY.reloadReference();
                            }
                        }
                        EditorGUI.EndDisabledGroup();
                    } EditorGUILayout.EndHorizontal();

                    EditorGUILayout.BeginHorizontal(); {
                        string   editLabel = "";
                        string   editTip   = "";
                        mset.Sky editSky   = null;

                        if (uiSelectedSky)
                        {
                            editSky   = uiSelectedSky;
                            editLabel = "Edit Selected";
                            editTip   = "Select cubemaps from the selected Sky as output targets.";
                        }
                        else
                        {
                            mset.SkyManager mgr = mset.SkyManager.Get();
                            if (mgr)
                            {
                                editSky = mgr.GlobalSky;
                            }
                            else
                            {
                                editSky = null;
                            }
                            editLabel = "Edit Global";
                            editTip   = "Select cubemaps from the current viewport Sky as output targets.";
                        }
                        EditorGUI.BeginDisabledGroup(editSky == null);
                        if (GUILayout.Button(new GUIContent(editLabel, editTip), GUILayout.Width(95), GUILayout.Height(32)))
                        {
                            if (editSky)
                            {
                                outSKY.HDR = editSky.HDRSky;
                                outSIM.HDR = editSky.HDRSpec;

                                if (editSky.SkyboxCube)
                                {
                                    outSKY.setReference(AssetDatabase.GetAssetPath(editSky.SkyboxCube), false, true);
                                }
                                else
                                {
                                    outSKY.clear();
                                }

                                if (editSky.SpecularCube)
                                {
                                    outSIM.setReference(AssetDatabase.GetAssetPath(editSky.SpecularCube), true, true);
                                }
                                else
                                {
                                    outSIM.clear();
                                }
                            }
                        }
                        EditorGUI.EndDisabledGroup();

                        string applyTip = "Change the selected Sky object to use Skyshop's current output cubemaps.";
                        EditorGUI.BeginDisabledGroup(uiSelectedSky == null);
                        if (GUILayout.Button(new GUIContent("Apply to Selected", applyTip), GUILayout.Width(120), GUILayout.Height(32)))
                        {
                            if (uiSelectedSky)
                            {
                                mset.EditorUtil.RegisterUndo(uiSelectedSky, "Apply to Selected Sky");
                                uiSelectedSky.SpecularCube    = outSIM.cube;
                                uiSelectedSky.SkyboxCube      = outSKY.cube;
                                uiSelectedSky.MasterIntensity = 1f;
                                uiSelectedSky.SkyIntensity    = 1f;
                                uiSelectedSky.DiffIntensity   = 1f;
                                uiSelectedSky.SpecIntensity   = 1f;
                                uiSelectedSky.HDRSky          = outSKY.HDR;
                                uiSelectedSky.HDRSpec         = outSIM.HDR;

                                SceneView.RepaintAll();
                            }
                        }
                        EditorGUI.EndDisabledGroup();

                        string addTip = "Create a new Sky object in the scene and assigns Skyshop's current output cubemaps to it.";
                        if (GUILayout.Button(new GUIContent("Add to Scene", addTip), GUILayout.Width(95), GUILayout.Height(32)))
                        {
                            mset.Sky skyScript = addSky(this.inSKY.skyName);
                            if (skyScript)
                            {
                                skyScript.SpecularCube    = outSIM.cube;
                                skyScript.SkyboxCube      = outSKY.cube;
                                skyScript.MasterIntensity = 1f;
                                skyScript.SkyIntensity    = 1f;
                                skyScript.DiffIntensity   = 1f;
                                skyScript.SpecIntensity   = 1f;
                                skyScript.HDRSky          = outSKY.HDR;
                                skyScript.HDRSpec         = outSIM.HDR;
                                skyScript.Apply();                                 //Add to Scene
                                SceneView.RepaintAll();
                            }
                        }
                    } EditorGUILayout.EndHorizontal();
                    EditorGUILayout.Space();
                }                // end if uiRefOptions
            } EditorGUILayout.EndVertical();

            // BASIC
            string tipExposure = "A multiplier on all the pixels in the Input Panorama during computation. Use for uniform brightness adjustment of results.";
            string tipQuality  = "Changes some advanced options to balance between image quality and computation speed.";

            EditorGUILayout.BeginVertical("HelpBox", GUILayout.Width(sectionWidth), GUILayout.MinWidth(minWidth)); {
                uiBasicOptions = EditorGUILayout.Foldout(uiBasicOptions, "Basic Options");
                if (uiBasicOptions)
                {
                    float newExposure = EditorGUILayout.FloatField(new GUIContent("Baked Exposure", "Baked Exposure -\n" + tipExposure), uiExposure, GUILayout.Width(300));
                    newExposure = Mathf.Max(0.0f, newExposure);
                    if (newExposure != uiExposure)
                    {
                        mset.EditorUtil.RegisterUndo(this, "Change Exposure");
                        uiExposure = newExposure;
                    }

                    mset.Quality newQuality = (mset.Quality)EditorGUILayout.EnumPopup(
                        new GUIContent("Quality", "Quality -\n" + tipQuality),
                        (mset.Quality)uiConvoQuality,
                        GUILayout.Width(300)
                        );

                    if (newQuality != uiConvoQuality)
                    {
                        mset.EditorUtil.RegisterUndo(this, "Change Quality");
                        uiConvoQuality = newQuality;
                        switch (uiConvoQuality)
                        {
                        case mset.Quality.ultra:        uiConvoSize = 64; break;

                        case mset.Quality.high:         uiConvoSize = 32; break;

                        case mset.Quality.medium:       uiConvoSize = 16; break;

                        case mset.Quality.low:          uiConvoSize = 8; break;
                        }
                    }

                    /*
                     * uiCubeSize = (TexSize)EditorGUILayout.EnumPopup(
                     *      new GUIContent("Output Size (cube)","Output Size -\n"+tipCubeSize),
                     *      (CubeSize)uiCubeSize,
                     *      GUILayout.Width(300)
                     * );*/

                    EditorGUILayout.Space();
                }                // end if uiBasicOptions
            } EditorGUILayout.EndVertical();

            // PRO MOVES
            string tipConvoSize    = "Resolution the input panorama is downsampled to for convolution, must be power of 2.\n\nWarning: High resolutions can lead to VERY long computation times!";
            string tipMipChain     = "If enabled, different specular gloss exponents are computed and stored in each mipmap level of the Specular Output cube.\n\nThis must be enabled for Gloss Maps to function in Marmoset Shaders.";
            string tipExponent     = "Gloss exponent used in computing the Specular Output cubemap. Value must be a power of 2, lower values result in a blurrier cubemap. Only available when \"Build Mip Chains\" is disabled.";
            string tipMaxExponent  = "Highest gloss exponent use in the specular mip chain. Other exponents in the chain are generated from this value.";
            string tipExponents    = "Displays a list of the specular gloss exponents used in the various mip levels of the Specular Output cube.";
            string tipResponsiveUI = "Enable if Unity is too unresponsive during computation. Will slow overall computation time.";
            string tipReflection   = "Highest gloss level in the specular mip chain is a polished mirror reflection pulled from the input panorama itself.";

            EditorGUILayout.BeginVertical("HelpBox", GUILayout.Width(sectionWidth), GUILayout.MinWidth(minWidth));
            {
                uiAdvancedOptions = EditorGUILayout.Foldout(uiAdvancedOptions, "Advanced Options");
                if (uiAdvancedOptions)
                {
                    int newConvoSize = EditorGUILayout.IntField(
                        new GUIContent("Convolution Size", "Convolution Size -\n" + tipConvoSize),
                        uiConvoSize,
                        GUILayout.Width(300)
                        );

                    if (newConvoSize < 2)
                    {
                        newConvoSize = 2;
                    }
                    newConvoSize += newConvoSize % 2;

                    if (newConvoSize != uiConvoSize)
                    {
                        mset.EditorUtil.RegisterUndo(this, "Change Convolution Size");
                        uiConvoSize    = newConvoSize;
                        uiConvoQuality = mset.Quality.custom;
                        switch (uiConvoSize)
                        {
                        case 8:  uiConvoQuality = mset.Quality.low; break;

                        case 16: uiConvoQuality = mset.Quality.medium; break;

                        case 32: uiConvoQuality = mset.Quality.high; break;

                        case 64: uiConvoQuality = mset.Quality.ultra; break;
                        }
                        ;
                    }
                    EditorGUILayout.Space();
                    mset.CubemapGUI.drawStaticGUI();

                    bool newMipChain = EditorGUILayout.Toggle(new GUIContent("Build Specular Mip Chain", "Specular Mip Chains -\n" + tipMipChain), uiMipChain);
                    if (newMipChain != uiMipChain)
                    {
                        mset.EditorUtil.RegisterUndo(this, "Toggle Specular Mip Chain");
                        uiMipChain = newMipChain;
                    }
                    if (uiMipChain)
                    {
                        bool newRefInSIM = EditorGUILayout.Toggle(new GUIContent("Highest Mip is Reflection", "Highest Mip is Reflection -\n" + tipReflection), uiReflectionInSIM);
                        if (newRefInSIM != uiReflectionInSIM)
                        {
                            mset.EditorUtil.RegisterUndo(this, "Toggle Mip Chain Reflection");
                            uiReflectionInSIM = newRefInSIM;
                        }
                        int newExponent = EditorGUILayout.IntField(
                            new GUIContent("Max Specular Exponent", "Specular Exponent -\n" + tipMaxExponent),
                            uiExponent,
                            GUILayout.Width(300)
                            );
                        newExponent = Mathf.Max(1, newExponent);
                        if (newExponent != uiExponent)
                        {
                            mset.EditorUtil.RegisterUndo(this, "Change Specular Exponent");
                            uiExponent = newExponent;
                        }

                        EditorGUI.BeginDisabledGroup(true);
                        string mipString;
                        if (uiReflectionInSIM)
                        {
                            mipString = "mirror";
                        }
                        else
                        {
                            mipString = uiExponent.ToString();
                        }
                        for (int i = 1; i < 4; ++i)
                        {
                            if ((1 << i) < uiExponent)
                            {
                                mipString += ", ";
                                mipString += (uiExponent >> i);
                                if (i == 3)
                                {
                                    mipString += "...";
                                }
                            }
                        }
                        EditorGUILayout.TextField(new GUIContent("Specular Exponents", "Specular Exponents -\n" + tipExponents), mipString, GUILayout.Width(300));
                        EditorGUI.EndDisabledGroup();
                    }
                    else
                    {
                        EditorGUI.BeginDisabledGroup(true);
                        EditorGUILayout.Toggle(new GUIContent("Highest Mip is Reflection", "Highest Mip is Reflection -\n" + tipReflection), false);
                        EditorGUI.EndDisabledGroup();
                        int newExponent = EditorGUILayout.IntField(
                            new GUIContent("Specular Exponent", "Specular Exponent -\n" + tipExponent),
                            uiExponent,
                            GUILayout.Width(300)
                            );
                        newExponent = Mathf.Max(1, newExponent);
                        if (newExponent != uiExponent)
                        {
                            mset.EditorUtil.RegisterUndo(this, "Change Specular Exponent");
                            uiExponent = newExponent;
                        }
                    }
                    EditorGUILayout.Space();

                    //TODO: Will anyone ever want this? Marmoset shaders need gamma compression as does sRGB sampling.
                    uiGammaCompress = true;

                    /*
                     * uiGammaCompress = EditorGUILayout.Toggle(new GUIContent(
                     *      "Gamma-Compress RGBM",
                     *      "Gamma-Compress RGBM -\nIf enabled, a gamma of 1/2.2 is applied to HDR data before it is encoded as RGBM. This adds dynamic range but also shader complexity. Leave enabled for Marmoset shaders."),
                     *      uiGammaCompress);
                     */

                    uiResponsiveUI = stepsPerFrame <= 1024 * 16;
                    uiResponsiveUI = EditorGUILayout.Toggle(new GUIContent("Keep UI Responsive", "Keep UI Responsive -\n" + tipResponsiveUI), uiResponsiveUI);
                    ulong newStepsPerFrame = stepsPerFrame;
                    if (uiResponsiveUI)
                    {
                        newStepsPerFrame = 1024 * 16;
                    }
                    else
                    {
                        newStepsPerFrame = 1024 * 256;
                    }

                    if (newStepsPerFrame != stepsPerFrame)
                    {
                        mset.EditorUtil.RegisterUndo(this, "Toggle Responsive UI");
                        stepsPerFrame = newStepsPerFrame;
                    }
                    EditorGUILayout.Space();


                    if (GUILayout.Button("Reset to Default", GUILayout.Width(120)))
                    {
                        uiConvoSize       = Mathf.Min(uiConvoSize, 16);
                        uiMipChain        = true;
                        uiReflectionInSIM = true;
                        uiResponsiveUI    = false;
                        uiGammaCompress   = true;
                        uiExponent        = 512;
                    }
                    EditorGUILayout.Space();
                }
            } EditorGUILayout.EndVertical();

            EditorGUILayout.Space();
            EditorGUILayout.Space();
        }

        //GENERATE
        bool generateGPU = false;
        bool generate    = false;
        bool cancel      = false;

        EditorGUILayout.BeginHorizontal(); {
            bool   hasPro        = UnityEditorInternal.InternalEditorUtility.HasPro();
            string tipGPUCompute = "Generates skybox and specular cubemaps. Specular convolution is performed on the GPU for greater speed and quality.\n\nNote: a different convolution equation is used, results may vary from CPU compute.";
            if (hasPro == false)
            {
                tipGPUCompute = "Requires Unity Pro :-(\n\n" + tipGPUCompute;
            }

            bool playing = ps.isPlaying();
            //if( ps.isPlaying() ) {
            //	cancel = GUILayout.Button("Abort", GUILayout.Width(130), GUILayout.Height(50));
            //} else
            {
                bool valid = true;
                if (inSKY.input == null)
                {
                    valid = false;
                }
                if (outSKY.cube == null && outSIM.cube == null)
                {
                    valid = false;
                }
                EditorGUILayout.BeginVertical();
                EditorGUI.BeginDisabledGroup(!valid);
                generate = GUILayout.Button(playing ? "Cancel" : "Compute", GUILayout.Width(130), GUILayout.Height(50));
                if (playing)
                {
                    cancel = generate; generate = false;
                }
                EditorGUI.EndDisabledGroup();

                EditorGUI.BeginDisabledGroup(!valid || !hasPro || playing);
                generateGPU = GUILayout.Button(new GUIContent("GPU Compute", "GPU Compute -\n" + tipGPUCompute), GUILayout.Width(130), GUILayout.Height(50));
                EditorGUI.EndDisabledGroup();
                EditorGUILayout.EndVertical();

                if (!valid)
                {
                    EditorGUILayout.BeginVertical();
                    if (inSKY.input == null)
                    {
                        EditorGUILayout.HelpBox("Input Panorama is missing.", MessageType.Error);
                    }
                    if (outSKY.cube == null && outSIM.cube == null)
                    {
                        EditorGUILayout.HelpBox("An Output Cubemap is needed.", MessageType.Error);
                    }
                    EditorGUILayout.EndVertical();
                }
            }
        } EditorGUILayout.EndHorizontal();
        if (cancel)
        {
            ps.pause();
            Repaint();

            inSKY.locked          =
                outSKY.locked     =
                    outSIM.locked = false;
            inSKY.updateBuffers();
        }

        progressRect       = GUILayoutUtility.GetRect(sectionWidth - 4, 16);
        progressRect.width = sectionWidth;
        progressRect.x     = 4;
        progressRect.y    += 2;

        //uiShowPreview = true;
        if (uiShowPreview)
        {
            EditorGUILayout.LabelField("Convolution Preview");
            float previewWidth  = position.width - rightPad;
            float previewHeight = previewWidth * 0.5f;
            mset.EditorUtil.GUILayout.drawTexture(4, 0, previewWidth, previewHeight, "", uiConvoPreview, false);
        }

        if (generate)
        {
            startConvo();
            ps.repaintMetric.begin();
        }

        if (generateGPU)
        {
            this.startConvoGPU();
            this.finishSKY();

            if (outSIM.cube)
            {
                Cubemap tempCube = this.outSKY.cube;
                if (tempCube == null)
                {
                    tempCube = new Cubemap(outSIM.cube.width, TextureFormat.ARGB32, false);
                    ps.IN.resampleToCube(ref tempCube, 0, outSIM.colorMode, true, uiExposure);
                    tempCube.Apply(false);
                    mset.AssetUtil.setLinear(new SerializedObject(tempCube), false);
                }

                mset.SkyProbe p = new mset.SkyProbe();
                p.maxExponent        = this.uiExponent;
                p.highestMipIsMirror = this.uiReflectionInSIM;
                p.generateMipChain   = this.uiMipChain;
                bool linear = UnityEditor.PlayerSettings.colorSpace == ColorSpace.Linear;
                p.convolve(this.outSIM.cube, tempCube, this.outSIM.HDR, this.outSKY.HDR, linear);
                outSIM.reloadReference();

                if (ps.buildMipChain)
                {
                    finishSIM();
                }
            }
            this.finishConvoGPU();
        }

        if (ps.isPlaying())
        {
            if (ps.curr == 0)
            {
                finishSKY();
            }
            if (ps.done())
            {
                ps.repaintMetric.end();
                finishConvo();
                Repaint();
                ps.pause();
            }
            else
            {
                ps.repaintMetric.end();
                //execute a subset of convolution steps, take a break to repaint the gui, then continue convolution
                stepConvo();
                EditorGUI.ProgressBar(progressRect, ps.progress(), "Convolution Progress " + Mathf.Floor(100f * ps.progress()) + "%");
                Repaint();
                ps.pendingRepaint = false;
                ps.repaintMetric.begin();
            }
        }

        if (ps.isPlaying() && !ps.done())
        {
            EditorGUI.ProgressBar(progressRect, ps.progress(), "Convolution Progress " + Mathf.Floor(100f * ps.progress()) + "%");
        }

        //DEBUG OPTIONS

        /*
         * EditorGUILayout.BeginVertical("HelpBox", GUILayout.Width(sectionWidth), GUILayout.MinWidth(minWidth)); {
         *      uiPerfReport = EditorGUILayout.Foldout(uiPerfReport,"Debug");
         *      if( uiPerfReport ) {
         *              uiShowPreview = EditorGUILayout.Toggle("Show Preview", uiShowPreview, GUILayout.Height(16));
         *              EditorGUILayout.Space();
         *
         *              string report = "Performance Report\n";
         *              report += ps.totalMetric.getString("Total",0);
         *              report += ps.initMetric.getString("Init",1);
         *              report += ps.blockMetric.getString("Coroutine Step",1);
         *              report += ps.passWriteMetric.getString("Cube Write",2);
         *              report += ps.repaintMetric.getString("Repaint", 1);
         *              report += ps.finishMetric.getString("Finalize", 1);
         *              EditorGUILayout.SelectableLabel(report, "HelpBox", GUILayout.Height(360));
         *              EditorGUILayout.Space();
         *              selectTest();
         *      }
         * }EditorGUILayout.EndVertical();
         */

        EditorGUILayout.BeginVertical("HelpBox", GUILayout.Width(sectionWidth), GUILayout.MinWidth(minWidth));
        {
            uiGIOptions = EditorGUILayout.Foldout(uiGIOptions, "Beast Global Illum Options");
            if (uiGIOptions)
            {
                mset.BeastConfig.DrawGUI();
                EditorGUILayout.Space();
            }
        } EditorGUILayout.EndVertical();


        EditorGUILayout.EndScrollView();
        GUILayout.EndArea();

        //GUIUtility.ExitGUI();
    }
Ejemplo n.º 3
0
 public void freeMem()
 {
     if(locked) return;
     UnityEngine.Object.DestroyImmediate(preview,false);
     UnityEngine.Object.DestroyImmediate(tempTexture,false);
     preview = null;
     tempTexture = null;
     cube = null;
     input = null;
     srInput = null;
     probe = null;
 }
Ejemplo n.º 4
0
 // REFERENCE
 public void clear()
 {
     if(locked) return;
     cube = null;
     input = null;
     srInput = null;
     probe = null;
     dir = "";
     skyName = "";
     fullPath = "";
     prettyPath = "";
     assetLinear = false;
 }
Ejemplo n.º 5
0
        private void renderProbeCallback(object data)
        {
            int faceSize = (int)data;
            if( faceSize == -1 ) return;

            fullPath = suggestPath(inputPath, true);
            updatePath();
            if( probe == null ) probe = new SkyProbe();
            probe.cube = new Cubemap(faceSize, TextureFormat.ARGB32, this.mipmapped);
            probe.capture(Selection.activeTransform, this.HDR);
            setReference(probe.cube, false, true);
            mset.Util.setLinear(srInput, false);
        }
Ejemplo n.º 6
0
    private void ProbeUpdate()
    {
        mset.SkyManager skmgr = mset.SkyManager.Get();
        if (UnityEditor.EditorApplication.isPlaying && skmgr.SkiesToProbe != null)
        {
            if (firstFrame)
            {
                if (skmgr.ProbeOnlyStatic)
                {
                    //hide dynamics
                    Renderer[] rends = GameObject.FindObjectsOfType <Renderer>();
                    foreach (Renderer rend in rends)
                    {
                        if (!rend.gameObject.isStatic)
                        {
                            rend.gameObject.SetActive(false);
                        }
                    }
                }
                firstFrame = false;
            }

            if (useCubeRT)
            {
                if (proProbe == null)
                {
                    proProbe = new mset.SkyProbe();
                }

                //Run the whole loop in place and finish
                bool success = true;
                int  i       = 0;
                foreach (mset.Sky targetSky in skmgr.SkiesToProbe)
                {
                    i++;
                    SetProgress((float)i / (float)skmgr.SkiesToProbe.Length);

                    //NOTE: we don't allocate new cubemaps at this stage. That's on you, buddy.
                    Cubemap targetCube = targetSky.SpecularCube as Cubemap;
                    if (targetCube == null)
                    {
                        continue;
                    }

                    Transform at = targetSky.transform;
                    proProbe.maxExponent = skmgr.ProbeExponent;
                    proProbe.exposures   = skmgr.ProbeExposures;
                    bool linear = UnityEditor.PlayerSettings.colorSpace == ColorSpace.Linear;

                    bool k = proProbe.capture(targetCube, at.position, at.rotation, targetSky.HDRSpec, linear, true);
                    if (!k)
                    {
                        Debug.LogWarning("Failed to capture with RenderTextures, falling back to ReadPixels.");
                        useCubeRT = false;
                        success   = false;
                        break;
                    }
                }
                if (success)
                {
                    CueProbeFinish();
                }
            }

            if (!useCubeRT)
            {
                //Create a game object and let the update loop run until DoneCallback gets called
                if (freeProbe == null)
                {
                    GameObject go = new GameObject();
                    go.name = "FreeProbe Object";
                    go.AddComponent <Camera>();
                    freeProbe = go.AddComponent <mset.FreeProbe>();
                    skmgr.GameApplySkies(true);
                    Shader.SetGlobalVector("_UniformOcclusion", skmgr.ProbeExposures);
                    freeProbe.linear      = UnityEditor.PlayerSettings.colorSpace == ColorSpace.Linear;
                    freeProbe.maxExponent = skmgr.ProbeExponent;
                    freeProbe.exposures   = skmgr.ProbeExposures;
                    freeProbe.QueueSkies(skmgr.SkiesToProbe);
                    freeProbe.ProgressCallback = this.SetProgress;
                    freeProbe.DoneCallback     = this.CueProbeFinish;
                    freeProbe.RunQueue();
                }
            }
        }
    }
Ejemplo n.º 7
0
    private void ProbeFinish()
    {
        EditorApplication.isPlaying = false;
        mset.SkyManager skmgr = mset.SkyManager.Get();
        foreach(mset.Sky sky in skmgr.SkiesToProbe) {
            if(sky.SpecularCube as Cubemap) {
                mset.CubeMipProcessor.CreateSubMips(sky.SpecularCube as Cubemap);
                mset.SHUtil.projectCube(ref sky.SH, sky.SpecularCube as Cubemap, 3, true);
                mset.SHUtil.convolve( ref sky.SH );
                sky.SH.copyToBuffer();
            }
            sky.Dirty = true;
        }
        proProbe = null;
        freeProbe = null;
        skmgr.SkiesToProbe = null;
        AssetDatabase.Refresh();

        skmgr.ShowSkybox = skmgr.ShowSkybox;
        skmgr.EditorUpdate(true);
        skmgr.ProbeExposures = Vector4.one;

        EditorUtility.ClearProgressBar();
        mset.SkyInspector.forceRefresh();

        if(DoneCallback != null) DoneCallback();
        DoneCallback = null;

        Close();
    }
Ejemplo n.º 8
0
    private void ProbeUpdate()
    {
        mset.SkyManager skmgr = mset.SkyManager.Get();
        if(UnityEditor.EditorApplication.isPlaying && skmgr.SkiesToProbe != null) {

            if(firstFrame) {
                if(skmgr.ProbeOnlyStatic) {
                    //hide dynamics
                    Renderer[] rends = GameObject.FindObjectsOfType<Renderer>();
                    foreach(Renderer rend in rends) {
                        if(!rend.gameObject.isStatic) rend.gameObject.SetActive(false);
                    }
                }
                firstFrame = false;
            }

            if(useCubeRT) {
                if(proProbe == null) {
                    proProbe = new mset.SkyProbe();
                }

                //Run the whole loop in place and finish
                bool success = true;
                int i = 0;
                foreach( mset.Sky targetSky in skmgr.SkiesToProbe ) {
                    i++;
                    SetProgress((float)i / (float)skmgr.SkiesToProbe.Length);

                    //NOTE: we don't allocate new cubemaps at this stage. That's on you, buddy.
                    Cubemap targetCube = targetSky.SpecularCube as Cubemap;
                    if(targetCube == null) continue;

                    Transform at = targetSky.transform;
                    proProbe.maxExponent = skmgr.ProbeExponent;
                    proProbe.exposures = skmgr.ProbeExposures;
                    bool linear = UnityEditor.PlayerSettings.colorSpace == ColorSpace.Linear;

                    bool k = proProbe.capture(targetCube, at.position, at.rotation, targetSky.HDRSpec, linear, true);
                    if(!k) {
                        Debug.LogWarning("Failed to capture with RenderTextures, falling back to ReadPixels.");
                        useCubeRT = false;
                        success = false;
                        break;
                    }
                }
                if(success) {
                    CueProbeFinish();
                }
            }

            if(!useCubeRT) {
                //Create a game object and let the update loop run until DoneCallback gets called
                if(freeProbe == null) {
                    GameObject go = new GameObject();
                    go.name = "FreeProbe Object";
                    go.AddComponent<Camera>();
                    freeProbe = go.AddComponent<mset.FreeProbe>();
                    skmgr.GameApplySkies(true);
                    Shader.SetGlobalVector("_UniformOcclusion", skmgr.ProbeExposures);
                    freeProbe.linear = UnityEditor.PlayerSettings.colorSpace == ColorSpace.Linear;
                    freeProbe.maxExponent = skmgr.ProbeExponent;
                    freeProbe.exposures = skmgr.ProbeExposures;
                    freeProbe.QueueSkies(skmgr.SkiesToProbe);
                    freeProbe.ProgressCallback = this.SetProgress;
                    freeProbe.DoneCallback = this.CueProbeFinish;
                    freeProbe.RunQueue();
                }
            }
        }
    }
Ejemplo n.º 9
0
    ///
    public void OnGUI()
    {
        GUILayout.BeginArea(new Rect(0,0,position.width,position.height));
        uiScroll = EditorGUILayout.BeginScrollView(uiScroll, false, false,GUILayout.MinWidth(300),GUILayout.MaxWidth(position.width) );

        float rightPad = 23;
        float minWidth = 315;
        float sectionWidth = position.width - rightPad;
        float logoSize = 128;

        Rect logoRect = EditorGUILayout.BeginVertical(); {
            GUILayout.Space(32);
            drawSkyshopLogo(sectionWidth - logoSize, logoRect.y, logoSize);
        } EditorGUILayout.EndVertical();

        uiHideDuringCompute = false;//EditorGUILayout.Toggle("Hide UI During Compute",uiHideDuringCompute);
        if( !uiHideDuringCompute || !ps.isPlaying() ) {
            // INPUT REF
            EditorGUILayout.BeginVertical(); {
                inSKY.previewWidth = Mathf.Max(328,(int)sectionWidth-2);
                inSKY.drawGUI();
                outSIM.inputPath = outSKY.inputPath = inSKY.fullPath;
            } EditorGUILayout.EndVertical();

            // OUTPUT REF
            EditorGUILayout.BeginVertical("HelpBox",GUILayout.Width(sectionWidth), GUILayout.MinWidth(minWidth)); {
                uiRefOptions = EditorGUILayout.Foldout(uiRefOptions,"Output Cubemaps");
                if( uiRefOptions ) {
                    outSKY.drawGUI(); EditorGUILayout.Space();
                    outSIM.drawGUI(); EditorGUILayout.Space();

                    EditorGUILayout.BeginHorizontal();{
                        string newTip = "Create a new cubemap assets for each output slot and adds them to the project.";
                        if (GUILayout.Button(new GUIContent("New All ", newTip), GUILayout.Width(70), GUILayout.Height(18))) {
                            outSKY.newCube();
                            outSIM.newCube();
                        }
                        string findTip = "Search project for all existing output cubemaps by input panorama name.";
                        if (GUILayout.Button(new GUIContent("Find All", findTip), GUILayout.Width(70), GUILayout.Height(18))) {
                            outSKY.find();
                            outSIM.find();
                        }
                        string clearTip = "Deselect all target cubemaps from output slots.";
                        if (GUILayout.Button(new GUIContent("Clear All", clearTip), GUILayout.Width(80), GUILayout.Height(18))) {
                            outSKY.clear();
                            outSIM.clear();
                        }
                        string reloadTip = "Reload all input and output slot textures and generate preview images for them.";
                        EditorGUI.BeginDisabledGroup(outSKY.fullPath.Length == 0 && outSIM.fullPath.Length == 0 && inSKY.fullPath.Length == 0);
                        {
                            if (GUILayout.Button(new GUIContent("Reload All", reloadTip), GUILayout.Width(85), GUILayout.Height(18))) {
                                outSKY.reloadReference();
                                outSIM.reloadReference();
                                inSKY.reloadReference();
                            }
                        }
                        EditorGUI.EndDisabledGroup();
                    } EditorGUILayout.EndHorizontal();

                    EditorGUILayout.BeginHorizontal();{

                        string editLabel = "";
                        string editTip = "";
                        mset.Sky editSky = null;

                        if( uiSelectedSky ) {
                            editSky = uiSelectedSky;
                            editLabel = "Edit Selected";
                            editTip = "Select cubemaps from the selected Sky as output targets.";
                        } else {
                            mset.SkyManager mgr = mset.SkyManager.Get();
                            if(mgr) editSky = mgr.GlobalSky;
                            else 	editSky = null;
                            editLabel = "Edit Global";
                            editTip = "Select cubemaps from the current viewport Sky as output targets.";
                        }
                        EditorGUI.BeginDisabledGroup(editSky == null);
                        if( GUILayout.Button( new GUIContent(editLabel, editTip), GUILayout.Width(95), GUILayout.Height(32) ) ) {
                            if( editSky ) {
                                outSKY.HDR = editSky.HDRSky;
                                outSIM.HDR = editSky.HDRSpec;
                                outSKY.setReference( AssetDatabase.GetAssetPath(editSky.SkyboxCube), false, true );
                                outSIM.setReference( AssetDatabase.GetAssetPath(editSky.SpecularCube), true, true );
                            }
                        }
                        EditorGUI.EndDisabledGroup();

                        string applyTip = "Change the selected Sky object to use Skyshop's current output cubemaps.";
                        EditorGUI.BeginDisabledGroup(uiSelectedSky == null);
                        if( GUILayout.Button( new GUIContent("Apply to Selected", applyTip), GUILayout.Width(120), GUILayout.Height(32) ) ) {
                            if( uiSelectedSky ) {
                                mset.EditorUtil.RegisterUndo(uiSelectedSky, "Apply to Selected Sky");
                                uiSelectedSky.SpecularCube = outSIM.cube;
                                uiSelectedSky.SkyboxCube = outSKY.cube;
                                uiSelectedSky.MasterIntensity = 1f;
                                uiSelectedSky.SkyIntensity = 1f;
                                uiSelectedSky.DiffIntensity = 1f;
                                uiSelectedSky.SpecIntensity = 1f;
                                uiSelectedSky.HDRSky =  outSKY.HDR;
                                uiSelectedSky.HDRSpec = outSIM.HDR;

                                SceneView.RepaintAll();
                            }
                        }
                        EditorGUI.EndDisabledGroup();

                        string addTip = "Create a new Sky object in the scene and assigns Skyshop's current output cubemaps to it.";
                        if( GUILayout.Button( new GUIContent("Add to Scene", addTip), GUILayout.Width(95), GUILayout.Height(32) ) ){
                            mset.Sky skyScript = addSky(this.inSKY.skyName);
                            if( skyScript ) {
                                skyScript.SpecularCube = outSIM.cube;
                                skyScript.SkyboxCube = outSKY.cube;
                                skyScript.MasterIntensity = 1f;
                                skyScript.SkyIntensity = 1f;
                                skyScript.DiffIntensity = 1f;
                                skyScript.SpecIntensity = 1f;
                                skyScript.HDRSky =  outSKY.HDR;
                                skyScript.HDRSpec = outSIM.HDR;
                                skyScript.Apply(); //Add to Scene
                                SceneView.RepaintAll();
                            }
                        }
                    }EditorGUILayout.EndHorizontal();
                    EditorGUILayout.Space();
                }// end if uiRefOptions
            }EditorGUILayout.EndVertical();

            // BASIC
            string tipExposure = "A multiplier on all the pixels in the Input Panorama during computation. Use for uniform brightness adjustment of results.";
            string tipQuality =  "Changes some advanced options to balance between image quality and computation speed.";

            EditorGUILayout.BeginVertical("HelpBox",GUILayout.Width(sectionWidth), GUILayout.MinWidth(minWidth)); {
                uiBasicOptions = EditorGUILayout.Foldout(uiBasicOptions,"Basic Options");
                if( uiBasicOptions ) {
                    float newExposure = EditorGUILayout.FloatField(new GUIContent("Baked Exposure","Baked Exposure -\n"+tipExposure), uiExposure, GUILayout.Width(300));
                    newExposure = Mathf.Max(0.0f, newExposure);
                    if( newExposure != uiExposure ) {
                        mset.EditorUtil.RegisterUndo(this,"Change Exposure");
                        uiExposure = newExposure;
                    }

                    mset.Quality newQuality = (mset.Quality)EditorGUILayout.EnumPopup(
                        new GUIContent("Quality","Quality -\n"+tipQuality),
                        (mset.Quality)uiConvoQuality,
                        GUILayout.Width(300)
                    );

                    if( newQuality != uiConvoQuality ) {
                        mset.EditorUtil.RegisterUndo(this,"Change Quality");
                        uiConvoQuality = newQuality;
                        switch(uiConvoQuality) {
                            case mset.Quality.ultra: 	uiConvoSize =  64; break;
                            case mset.Quality.high: 	uiConvoSize =  32; break;
                            case mset.Quality.medium: 	uiConvoSize =  16; break;
                            case mset.Quality.low: 		uiConvoSize =  8; break;
                        }
                    }
                    /*
                    uiCubeSize = (TexSize)EditorGUILayout.EnumPopup(
                        new GUIContent("Output Size (cube)","Output Size -\n"+tipCubeSize),
                        (CubeSize)uiCubeSize,
                        GUILayout.Width(300)
                    );*/

                    EditorGUILayout.Space();
                }// end if uiBasicOptions
            }EditorGUILayout.EndVertical();

            // PRO MOVES
            string tipConvoSize = "Resolution the input panorama is downsampled to for convolution, must be power of 2.\n\nWarning: High resolutions can lead to VERY long computation times!";
            string tipMipChain = "If enabled, different specular gloss exponents are computed and stored in each mipmap level of the Specular Output cube.\n\nThis must be enabled for Gloss Maps to function in Marmoset Shaders.";
            string tipExponent = "Gloss exponent used in computing the Specular Output cubemap. Value must be a power of 2, lower values result in a blurrier cubemap. Only available when \"Build Mip Chains\" is disabled.";
            string tipMaxExponent = "Highest gloss exponent use in the specular mip chain. Other exponents in the chain are generated from this value.";
            string tipExponents = "Displays a list of the specular gloss exponents used in the various mip levels of the Specular Output cube.";
            string tipResponsiveUI = "Enable if Unity is too unresponsive during computation. Will slow overall computation time.";
            string tipReflection = "Highest gloss level in the specular mip chain is a polished mirror reflection pulled from the input panorama itself.";

            EditorGUILayout.BeginVertical("HelpBox",GUILayout.Width(sectionWidth), GUILayout.MinWidth(minWidth));
            {
                uiAdvancedOptions = EditorGUILayout.Foldout(uiAdvancedOptions,"Advanced Options");
                if( uiAdvancedOptions ) {
                    int newConvoSize = EditorGUILayout.IntField(
                        new GUIContent("Convolution Size", "Convolution Size -\n" + tipConvoSize),
                        uiConvoSize,
                        GUILayout.Width(300)
                    );

                    if( newConvoSize < 2 ) newConvoSize = 2;
                    newConvoSize += newConvoSize % 2;

                    if( newConvoSize != uiConvoSize ) {
                        mset.EditorUtil.RegisterUndo(this,"Change Convolution Size");
                        uiConvoSize = newConvoSize;
                        uiConvoQuality = mset.Quality.custom;
                        switch( uiConvoSize ) {
                            case 8:  uiConvoQuality = mset.Quality.low; break;
                            case 16: uiConvoQuality = mset.Quality.medium; break;
                            case 32: uiConvoQuality = mset.Quality.high; break;
                            case 64: uiConvoQuality = mset.Quality.ultra; break;
                        };
                    }
                    EditorGUILayout.Space();
                    mset.CubemapGUI.drawStaticGUI();

                    bool newMipChain = EditorGUILayout.Toggle(new GUIContent("Build Specular Mip Chain","Specular Mip Chains -\n" + tipMipChain),uiMipChain);
                    if( newMipChain != uiMipChain ) {
                        mset.EditorUtil.RegisterUndo(this,"Toggle Specular Mip Chain");
                        uiMipChain = newMipChain;
                    }
                    if(uiMipChain) {
                        bool newRefInSIM = EditorGUILayout.Toggle(new GUIContent("Highest Mip is Reflection","Highest Mip is Reflection -\n" + tipReflection),uiReflectionInSIM);
                        if( newRefInSIM != uiReflectionInSIM ) {
                            mset.EditorUtil.RegisterUndo(this,"Toggle Mip Chain Reflection");
                            uiReflectionInSIM = newRefInSIM;
                        }
                        int newExponent = EditorGUILayout.IntField(
                            new GUIContent("Max Specular Exponent","Specular Exponent -\n" + tipMaxExponent),
                            uiExponent,
                            GUILayout.Width(300)
                            );
                        newExponent = Mathf.Max(1, newExponent);
                        if( newExponent != uiExponent ) {
                            mset.EditorUtil.RegisterUndo(this, "Change Specular Exponent");
                            uiExponent = newExponent;
                        }

                        EditorGUI.BeginDisabledGroup(true);
                        string mipString;
                        if( uiReflectionInSIM ) mipString = "mirror";
                        else 					mipString = uiExponent.ToString();
                        for(int i=1; i<4; ++i) {
                            if((1<<i) < uiExponent){
                                mipString += ", ";
                                mipString += (uiExponent >> i);
                                if(i==3) mipString += "...";
                            }
                        }
                        EditorGUILayout.TextField(new GUIContent("Specular Exponents","Specular Exponents -\n"+tipExponents), mipString, GUILayout.Width(300));
                        EditorGUI.EndDisabledGroup();
                    } else {
                        EditorGUI.BeginDisabledGroup(true);
                        EditorGUILayout.Toggle(new GUIContent("Highest Mip is Reflection","Highest Mip is Reflection -\n" + tipReflection),false);
                        EditorGUI.EndDisabledGroup();
                        int newExponent = EditorGUILayout.IntField(
                            new GUIContent("Specular Exponent","Specular Exponent -\n" + tipExponent),
                            uiExponent,
                            GUILayout.Width(300)
                        );
                        newExponent = Mathf.Max(1, newExponent);
                        if( newExponent != uiExponent ) {
                            mset.EditorUtil.RegisterUndo(this, "Change Specular Exponent");
                            uiExponent = newExponent;
                        }
                    }
                    EditorGUILayout.Space();

                    //TODO: Will anyone ever want this? Marmoset shaders need gamma compression as does sRGB sampling.
                    uiGammaCompress = true;
                    /*
                    uiGammaCompress = EditorGUILayout.Toggle(new GUIContent(
                        "Gamma-Compress RGBM",
                        "Gamma-Compress RGBM -\nIf enabled, a gamma of 1/2.2 is applied to HDR data before it is encoded as RGBM. This adds dynamic range but also shader complexity. Leave enabled for Marmoset shaders."),
                        uiGammaCompress);
                    */

                    uiResponsiveUI = stepsPerFrame <= 1024*16;
                    uiResponsiveUI = EditorGUILayout.Toggle(new GUIContent("Keep UI Responsive","Keep UI Responsive -\n"+tipResponsiveUI), uiResponsiveUI);
                    ulong newStepsPerFrame = stepsPerFrame;
                    if( uiResponsiveUI ) newStepsPerFrame = 1024*16;
                    else 				 newStepsPerFrame = 1024*256;

                    if( newStepsPerFrame != stepsPerFrame ) {
                        mset.EditorUtil.RegisterUndo(this,"Toggle Responsive UI");
                        stepsPerFrame = newStepsPerFrame;
                    }
                    EditorGUILayout.Space();

                    if( GUILayout.Button("Reset to Default", GUILayout.Width(120)) ) {
                        uiConvoSize = Mathf.Min(uiConvoSize, 16);
                        uiMipChain = true;
                        uiReflectionInSIM = true;
                        uiResponsiveUI = false;
                        uiGammaCompress = true;
                        uiExponent = 512;
                    }
                    EditorGUILayout.Space();

                }
            }EditorGUILayout.EndVertical();

            EditorGUILayout.Space();
            EditorGUILayout.Space();
        }

        //GENERATE
        bool generateGPU = false;
        bool generate = false;
        bool cancel = false;
        EditorGUILayout.BeginHorizontal(); {
            bool hasPro = UnityEditorInternal.InternalEditorUtility.HasPro();
            string tipGPUCompute = "Generates skybox and specular cubemaps. Specular convolution is performed on the GPU for greater speed and quality.\n\nNote: a different convolution equation is used, results may vary from CPU compute.";
            if( hasPro == false ) tipGPUCompute = "Requires Unity Pro :-(\n\n" + tipGPUCompute;

            bool playing = ps.isPlaying();
            //if( ps.isPlaying() ) {
            //	cancel = GUILayout.Button("Abort", GUILayout.Width(130), GUILayout.Height(50));
            //} else
            {
                bool valid = true;
                if( inSKY.input == null ) {
                    valid = false;
                }
                if( outSKY.cube == null && outSIM.cube == null ) {
                    valid = false;
                }
                EditorGUILayout.BeginVertical();
                    EditorGUI.BeginDisabledGroup(!valid);
                        generate = GUILayout.Button(playing ? "Cancel" : "Compute", GUILayout.Width(130), GUILayout.Height(50));
                        if(playing) {cancel = generate; generate = false; }
                    EditorGUI.EndDisabledGroup();

                    EditorGUI.BeginDisabledGroup(!valid || !hasPro || playing);
                        generateGPU = GUILayout.Button(new GUIContent("GPU Compute","GPU Compute -\n" + tipGPUCompute), GUILayout.Width(130), GUILayout.Height(50));
                    EditorGUI.EndDisabledGroup();
                EditorGUILayout.EndVertical();

                if( !valid ) {
                    EditorGUILayout.BeginVertical();
                    if( inSKY.input == null ) {
                        EditorGUILayout.HelpBox("Input Panorama is missing.", MessageType.Error);

                    }
                    if( outSKY.cube == null && outSIM.cube == null ) {
                        EditorGUILayout.HelpBox("An Output Cubemap is needed.", MessageType.Error);
                    }
                    EditorGUILayout.EndVertical();
                }
            }
        }EditorGUILayout.EndHorizontal();
        if( cancel ) {
            ps.pause();
            Repaint();

            inSKY.locked =
            outSKY.locked =
            outSIM.locked = false;
            inSKY.updateBuffers();
        }

        progressRect = GUILayoutUtility.GetRect(sectionWidth - 4,16);
        progressRect.width = sectionWidth;
        progressRect.x = 4;
        progressRect.y += 2;

        //uiShowPreview = true;
        if( uiShowPreview ) {
            EditorGUILayout.LabelField("Convolution Preview");
            float previewWidth = position.width - rightPad;
            float previewHeight = previewWidth*0.5f;
            mset.EditorUtil.GUILayout.drawTexture( 4, 0, previewWidth, previewHeight, "", uiConvoPreview, false);
        }

        if( generate ) {
            startConvo();
            ps.repaintMetric.begin();
        }

        if( generateGPU ) {
            this.startConvoGPU();
            this.finishSKY();

            if(outSIM.cube) {
                Cubemap tempCube = this.outSKY.cube;
                if(tempCube == null) {
                    tempCube = new Cubemap(outSIM.cube.width, TextureFormat.ARGB32, false);
                    ps.IN.resampleToCube(ref tempCube, 0, outSIM.colorMode, true, uiExposure);
                    tempCube.Apply(false);
                    mset.AssetUtil.setLinear(new SerializedObject(tempCube), false);
                }

                mset.SkyProbe p = new mset.SkyProbe();
                p.maxExponent = this.uiExponent;
                p.highestMipIsMirror = this.uiReflectionInSIM;
                p.generateMipChain = this.uiMipChain;
                bool linear = UnityEditor.PlayerSettings.colorSpace == ColorSpace.Linear;
                p.convolve(this.outSIM.cube, tempCube, this.outSIM.HDR, this.outSKY.HDR, linear);
                outSIM.reloadReference();

                if( ps.buildMipChain ) {
                    finishSIM();
                }
            }
            this.finishConvoGPU();
        }

        if( ps.isPlaying() ) {
            if( ps.curr == 0 ) { finishSKY(); }
            if( ps.done() ) {
                ps.repaintMetric.end();
                finishConvo();
                Repaint();
                ps.pause();
            } else {
                ps.repaintMetric.end();
                //execute a subset of convolution steps, take a break to repaint the gui, then continue convolution
                stepConvo();
                EditorGUI.ProgressBar(progressRect, ps.progress(), "Convolution Progress " + Mathf.Floor(100f * ps.progress()) + "%");
                Repaint();
                ps.pendingRepaint = false;
                ps.repaintMetric.begin();
            }
        }

        if( ps.isPlaying() && !ps.done() ) {
            EditorGUI.ProgressBar(progressRect, ps.progress(), "Convolution Progress " + Mathf.Floor(100f * ps.progress()) + "%");
        }

        //DEBUG OPTIONS
        /*
        EditorGUILayout.BeginVertical("HelpBox", GUILayout.Width(sectionWidth), GUILayout.MinWidth(minWidth)); {
            uiPerfReport = EditorGUILayout.Foldout(uiPerfReport,"Debug");
            if( uiPerfReport ) {
                uiShowPreview = EditorGUILayout.Toggle("Show Preview", uiShowPreview, GUILayout.Height(16));
                EditorGUILayout.Space();

                string report = "Performance Report\n";
                report += ps.totalMetric.getString("Total",0);
                report += ps.initMetric.getString("Init",1);
                report += ps.blockMetric.getString("Coroutine Step",1);
                report += ps.passWriteMetric.getString("Cube Write",2);
                report += ps.repaintMetric.getString("Repaint", 1);
                report += ps.finishMetric.getString("Finalize", 1);
                EditorGUILayout.SelectableLabel(report, "HelpBox", GUILayout.Height(360));
                EditorGUILayout.Space();
                selectTest();
            }
        }EditorGUILayout.EndVertical();
        */

        EditorGUILayout.BeginVertical("HelpBox",GUILayout.Width(sectionWidth), GUILayout.MinWidth(minWidth));
        {
            uiGIOptions = EditorGUILayout.Foldout(uiGIOptions,"Beast Global Illum Options");
            if( uiGIOptions ) {
                mset.BeastConfig.DrawGUI();
                EditorGUILayout.Space();
            }
        }EditorGUILayout.EndVertical();

        EditorGUILayout.EndScrollView();
        GUILayout.EndArea();

        //GUIUtility.ExitGUI();
    }