Пример #1
0
        private void UpdateTexture()
        {
            // create preview RT here and keep until the next Repaint
            if (m_previewRT != null)
            {
                RenderTexture.ReleaseTemporary(m_previewRT);
            }

            NoiseSettings noiseSettings = m_serializedNoise.targetObject as NoiseSettings;

            m_previewRT = RenderTexture.GetTemporary(512, 512, 0, RenderTextureFormat.ARGB32);
            RenderTexture tempRT = RenderTexture.GetTemporary(512, 512, 0, RenderTextureFormat.RFloat);

            RenderTexture prevActive = RenderTexture.active;

            NoiseUtils.Blit2D(noiseSettings, tempRT);

            NoiseUtils.BlitPreview2D(tempRT, m_previewRT);

            RenderTexture.active = prevActive;

            RenderTexture.ReleaseTemporary(tempRT);

            m_image.image = m_previewRT;
        }
Пример #2
0
        private void Export2D()
        {
            Texture2D texture = null;

            try
            {
                string path = EditorUtility.SaveFilePanel("Export Noise To Texture2D",
                                                          Application.dataPath,
                                                          "New Noise Texture2D.png",
                                                          "png");

                if (!path.StartsWith(Application.dataPath))
                {
                    Debug.LogError("You must specificy a path in your project's Assets folder to export a Noise Texture");
                }

                if (!string.IsNullOrEmpty(path))
                {
                    EditorUtility.DisplayProgressBar("Exporting Noise to Texture2D", "Making some noise...", 0.1f);

                    texture = NoiseUtils.BakeToTexture2D(m_noise, dims2D.x, dims2D.y, m_format, TextureCreationFlags.None);

                    byte[] bytes = ImageConversion.EncodeToPNG(texture);

                    System.IO.File.WriteAllBytes(path, bytes);

                    Texture2D.DestroyImmediate(texture);
                    texture = null;

                    string assetPath = path.Remove(0, Application.dataPath.Length - "Assets".Length);

                    AssetDatabase.Refresh();

                    EditorUtility.ClearProgressBar();

                    texture = AssetDatabase.LoadAssetAtPath <Texture2D>(assetPath);
                    EditorGUIUtility.PingObject(texture);
                }
            }
            catch (Exception e)
            {
                Debug.LogError(e);

                if (texture != null)
                {
                    Texture2D.DestroyImmediate(texture);
                }

                Debug.Log("Exception caught");

                EditorUtility.ClearProgressBar();
            }
        }
Пример #3
0
        private void Export3D()
        {
            Texture3D texture = null;

            var textureDims   = m_exportDims3D.value;
            var textureFormat = m_exportFormat.value;

            try
            {
                string path = EditorUtility.SaveFilePanel("Export Noise To Texture3D",
                                                          Application.dataPath,
                                                          "New Noise Texture3D.asset",
                                                          "asset");

                if (string.IsNullOrEmpty(path))
                {
                    return;
                }

                if (!path.StartsWith(Application.dataPath))
                {
                    Debug.LogError("You must specificy a path in your project's Assets folder to export a Noise Texture");
                }

                if (!string.IsNullOrEmpty(path) && path.StartsWith(Application.dataPath))
                {
                    EditorUtility.DisplayProgressBar("Exporting Noise to Texture3D", "Making some noise...", 0.1f);

                    texture = NoiseUtils.BakeToTexture3D(m_noiseUpdateTarget, textureDims.x, textureDims.y, textureDims.z, textureFormat, TextureCreationFlags.None);

                    AssetDatabase.CreateAsset(texture, path.Remove(0, Application.dataPath.Length - "Assets".Length));

                    AssetDatabase.Refresh();

                    EditorUtility.ClearProgressBar();

                    EditorGUIUtility.PingObject(texture);
                }
            }
            catch (Exception e)
            {
                Debug.LogError(e);

                if (texture != null)
                {
                    Texture2D.DestroyImmediate(texture);
                }

                EditorUtility.ClearProgressBar();
            }
        }
Пример #4
0
        /// <summary>
        /// Renders an interactive Noise Preview along with tooltip icons and an optional Export button that opens a new ExportNoiseWindow.
        /// A background image is also rendered behind the preview that takes up the entire width of the EditorWindow currently being drawn.
        /// </summary>
        /// <param name = "minSize"> Minimum size for the Preview </param>
        /// <param name = "showExportButton"> Whether or not to render the Export button </param>
        public void DrawPreviewTexture(float minSize, bool showExportButton = true)
        {
            // Draw label with tooltip
            GUILayout.Label(Styles.noisePreview);

            float padding   = 4f;
            float iconWidth = 40f;
            int   size      = (int)Mathf.Min(minSize, EditorGUIUtility.currentViewWidth);
            Rect  totalRect = GUILayoutUtility.GetRect(EditorGUIUtility.currentViewWidth, size + padding * 2); // extra pixels for highlight border

            Color prev = GUI.color;

            GUI.color = new Color(.1f, .1f, .1f, 1f);
            GUI.DrawTexture(totalRect, Texture2D.whiteTexture, ScaleMode.StretchToFill, false);
            GUI.color = Color.white;

            // draw info icon
            // if(totalRect.Contains(Event.current.mousePosition))
            {
                Rect infoIconRect = new Rect(totalRect.x + padding, totalRect.y + padding, iconWidth, iconWidth);
                GUI.Label(infoIconRect, Styles.infoIcon);
                // GUI.Label( infoIconRect, Styles.noiseTooltip );
            }

            // draw export button
            float buttonWidth  = GUI.skin.button.CalcSize(Styles.export).x;
            float buttonHeight = EditorGUIUtility.singleLineHeight;
            Rect  exportRect   = new Rect(totalRect.xMax - buttonWidth - padding, totalRect.yMax - buttonHeight - padding, buttonWidth, buttonHeight);

            if (GUI.Button(exportRect, Styles.export))
            {
                serializedNoise.ApplyModifiedProperties();
                serializedNoise.Update();

                ExportNoiseWindow.ShowWindow(serializedNoise.targetObject as NoiseSettings);
            }

            float safeSpace   = Mathf.Max(iconWidth * 2, buttonWidth * 2) + padding * 4;
            float minWidth    = Mathf.Min(size, totalRect.width - safeSpace);
            Rect  previewRect = new Rect(totalRect.x + totalRect.width / 2 - minWidth / 2, totalRect.y + totalRect.height / 2 - minWidth / 2, minWidth, minWidth);

            EditorGUIUtility.AddCursorRect(previewRect, MouseCursor.Pan);

            if (previewRect.Contains(Event.current.mousePosition))
            {
                serializedNoise.Update();

                HandlePreviewTextureInput(previewRect);

                serializedNoise.ApplyModifiedProperties();
            }

            if (Event.current.type == EventType.Repaint)
            {
                // create preview RT here and keep until the next Repaint
                if (m_previewRT != null)
                {
                    RenderTexture.ReleaseTemporary(m_previewRT);
                }

                NoiseSettings noiseSettings = serializedNoise.targetObject as NoiseSettings;

                m_previewRT = RenderTexture.GetTemporary(512, 512, 0, RenderTextureFormat.ARGB32);
                RenderTexture tempRT = RenderTexture.GetTemporary(512, 512, 0, RenderTextureFormat.RFloat);

                RenderTexture prevActive = RenderTexture.active;

                NoiseUtils.Blit2D(noiseSettings, tempRT);

                NoiseUtils.BlitPreview2D(tempRT, m_previewRT);

                RenderTexture.active = prevActive;

                GUI.DrawTexture(previewRect, m_previewRT, ScaleMode.ScaleToFit, false);

                RenderTexture.ReleaseTemporary(tempRT);
            }

            GUI.color = prev;
        }
        public override void Eval(FilterContext fc)
        {
            if (m_noiseSettings == null)
            {
                m_noiseSettings = ScriptableObject.CreateInstance <NoiseSettings>();
            }

            m_noiseSettings.useTextureForPositions = m_useHeightmap;

            if (m_useHeightmap)
            {
                m_noiseSettings.positionTexture = fc.renderTextureCollection[FilterContext.Keywords.Heightmap];
            }

            Vector3 brushPosWS    = fc.brushPos;
            float   brushSize     = fc.brushSize;
            float   brushRotation = fc.brushRotation;

            // TODO(wyatt): remove magic number and tie it into NoiseSettingsGUI preview size somehow
            float previewSize = 1 / 512f;

            // get proper noise material from current noise settings
            NoiseSettings noiseSettings = m_noiseSettings;
            Material      mat           = NoiseUtils.GetDefaultBlitMaterial(noiseSettings);

            // setup the noise material with values in noise settings
            noiseSettings.SetupMaterial(mat);

            // convert brushRotation to radians
            brushRotation *= Mathf.PI / 180;

            // change pos and scale so they match the noiseSettings preview
            bool isWorldSpace = false == m_isLocalSpace;

            brushSize  = isWorldSpace ? brushSize * previewSize : 1;
            brushPosWS = isWorldSpace ? brushPosWS * previewSize : Vector3.zero;

            // // override noise transform
            Quaternion rotQ         = Quaternion.AngleAxis(-brushRotation, Vector3.up);
            Matrix4x4  translation  = Matrix4x4.Translate(brushPosWS);
            Matrix4x4  rotation     = Matrix4x4.Rotate(rotQ);
            Matrix4x4  scale        = Matrix4x4.Scale(Vector3.one * brushSize);
            Matrix4x4  noiseToWorld = translation * scale;

            mat.SetMatrix(NoiseSettings.ShaderStrings.transform, noiseSettings.trs * noiseToWorld);

            int pass = NoiseUtils.kNumBlitPasses * NoiseLib.GetNoiseIndex(noiseSettings.domainSettings.noiseTypeName);

            RenderTextureDescriptor desc = new RenderTextureDescriptor(fc.destinationRenderTexture.width, fc.destinationRenderTexture.height, RenderTextureFormat.RFloat);
            RenderTexture           rt   = RenderTexture.GetTemporary(desc);

            Graphics.Blit(fc.sourceRenderTexture, rt, mat, pass);

            Material blendMat = FilterUtility.blendModesMaterial;

            blendMat.SetTexture("_MainTex", fc.sourceRenderTexture);
            blendMat.SetTexture("_BlendTex", rt);

            Graphics.Blit(fc.sourceRenderTexture, fc.destinationRenderTexture, blendMat, 1);

            RenderTexture.ReleaseTemporary(rt);
        }
Пример #6
0
        //===================================================================================================
        //
        //      APPLY BRUSH
        //
        //===================================================================================================

        private void ApplyBrushInternal(PaintContext ctx, BrushTransform brushXform, Vector3 brushPosWS,
                                        float brushRotation, float brushStrength, float brushSize, Texture brushTexture)
        {
            brushPosWS.y = 0;

            /*
             *  blit steps
             *  1. blit noise to intermediate RT, this includes all the noise transformations and filters,
             *     using the appropriate noise material. do this with NoiseUtils.Blit2D?
             *  2. use that noise texture and mult it with brushmask to paint height on terrain
             */

            // TODO(wyatt): remove magic number and tie it into NoiseSettingsGUI preview size somehow
            float previewSize = 1 / 512f;

            // get proper noise material from current noise settings
            NoiseSettings noiseSettings = this.noiseSettings;
            Material      matNoise      = NoiseUtils.GetDefaultBlitMaterial(noiseSettings);

            // setup the noise material with values in noise settings
            noiseSettings.SetupMaterial(matNoise);

            // convert brushRotation to radians
            brushRotation *= Mathf.PI / 180;

            // change pos and scale so they match the noiseSettings preview
            bool isWorldSpace = (m_toolSettings.coordSpace == CoordinateSpace.World);

            brushSize  = isWorldSpace ? brushSize * previewSize : 1;
            brushPosWS = isWorldSpace ? brushPosWS * previewSize : Vector3.zero;

            // // override noise transform
            Quaternion rotQ         = Quaternion.AngleAxis(-brushRotation, Vector3.up);
            Matrix4x4  translation  = Matrix4x4.Translate(brushPosWS);
            Matrix4x4  rotation     = Matrix4x4.Rotate(rotQ);
            Matrix4x4  scale        = Matrix4x4.Scale(Vector3.one * brushSize);
            Matrix4x4  noiseToWorld = translation * scale;

            matNoise.SetMatrix(NoiseSettings.ShaderStrings.transform,
                               noiseSettings.trs * noiseToWorld);

            // render the noise field to a texture
            // TODO(wyatt): Handle the 3D case. Would need to blit to Volume Texture
            int rtW = ctx.destinationRenderTexture.width;
            int rtH = ctx.destinationRenderTexture.height;
            RenderTextureFormat     rtF     = RenderTextureFormat.RFloat;
            RenderTextureDescriptor rtDesc  = new RenderTextureDescriptor(rtW, rtH, rtF);
            RenderTexture           noiseRT = RenderTexture.GetTemporary(rtDesc);

            RenderTexture tempRT = RenderTexture.GetTemporary(noiseRT.descriptor);
            RenderTexture prev   = RenderTexture.active;

            RenderTexture.active = tempRT;

            int noisePass = NoiseUtils.kNumBlitPasses * NoiseLib.GetNoiseIndex(noiseSettings.domainSettings.noiseTypeName);

            Graphics.Blit(tempRT, matNoise, noisePass);

            RenderTexture.active = noiseRT;

            // if(noiseSettings.filterSettings.filterStack != null)
            // {
            //     noiseSettings.filterSettings.filterStack.Eval(tempRT, noiseRT);
            // }
            // else
            {
                Graphics.Blit(tempRT, noiseRT);
            }

            RenderTexture.active = prev;

            RenderTexture.ReleaseTemporary(tempRT);

            // then add the result to the heightmap using the noise height tool shader
            Material matFinal = paintMaterial;

            TerrainPaintUtility.SetupTerrainToolMaterialProperties(ctx, brushXform, matFinal);
            // set brush params
            Vector4 brushParams = new Vector4(0.01f * brushStrength, 0.0f, brushSize, 1 / brushSize);

            matFinal.SetVector("_BrushParams", brushParams);
            matFinal.SetTexture("_BrushTex", brushTexture);
            matFinal.SetTexture("_NoiseTex", noiseRT);
            matFinal.SetVector("_WorldHeightRemap", m_toolSettings.worldHeightRemap);
            Graphics.Blit(ctx.sourceRenderTexture, ctx.destinationRenderTexture, matFinal, 0);

            RenderTexture.ReleaseTemporary(noiseRT);
        }
Пример #7
0
        //===================================================================================================
        //
        //      APPLY BRUSH
        //
        //===================================================================================================

        private void ApplyBrushInternal(Terrain terrain, PaintContext ctx, BrushTransform brushXform, Vector3 brushPosWS,
                                        float brushRotation, float brushStrength, float brushSize, Texture brushTexture)
        {
            var prevRT = RenderTexture.active;

            brushPosWS.y = 0;

            /*
             *  blit steps
             *  1. blit noise to intermediate RT, this includes all the noise transformations and filters,
             *  using the appropriate noise material. do this with NoiseUtils.Blit2D?
             *  2. use that noise texture and mult it with brushmask to paint height on terrain
             */

            // TODO(wyatt): remove magic number and tie it into NoiseSettingsGUI preview size somehow
            float previewSize = 1 / 512f;

            // get proper noise material from current noise settings
            NoiseSettings noiseSettings = this.noiseSettings;
            Material      matNoise      = NoiseUtils.GetDefaultBlitMaterial(noiseSettings);

            // setup the noise material with values in noise settings
            noiseSettings.SetupMaterial(matNoise);

            // convert brushRotation to radians
            brushRotation *= Mathf.PI / 180;

            // change pos and scale so they match the noiseSettings preview
            bool isWorldSpace = (m_toolSettings.coordSpace == CoordinateSpace.World);

            brushSize  = isWorldSpace ? brushSize * previewSize : 1;
            brushPosWS = isWorldSpace ? brushPosWS * previewSize : Vector3.zero;

            // // override noise transform
            var rotQ         = Quaternion.AngleAxis(-brushRotation, Vector3.up);
            var translation  = Matrix4x4.Translate(brushPosWS);
            var rotation     = Matrix4x4.Rotate(rotQ);
            var scale        = Matrix4x4.Scale(Vector3.one * brushSize);
            var noiseToWorld = translation * scale;

            matNoise.SetMatrix(NoiseSettings.ShaderStrings.transform,
                               noiseSettings.trs * noiseToWorld);

            var noisePass = NoiseUtils.kNumBlitPasses * NoiseLib.GetNoiseIndex(noiseSettings.domainSettings.noiseTypeName);

            // render the noise field to a texture
            // TODO(wyatt): Handle the 3D case. Would need to blit to Volume Texture
            var rtDesc = ctx.destinationRenderTexture.descriptor;

            rtDesc.graphicsFormat = NoiseUtils.singleChannelFormat;
            rtDesc.sRGB           = false;
            var noiseRT = RTUtils.GetTempHandle(rtDesc);

            RenderTexture.active = noiseRT; // keep this
            Graphics.Blit(noiseRT, matNoise, noisePass);

            // then add the result to the heightmap using the noise height tool shader
            Material matFinal  = paintMaterial;
            var      brushMask = RTUtils.GetTempHandle(ctx.sourceRenderTexture.width, ctx.sourceRenderTexture.height, 0, FilterUtility.defaultFormat);

            Utility.SetFilterRT(commonUI, ctx.sourceRenderTexture, brushMask, matFinal);
            TerrainPaintUtility.SetupTerrainToolMaterialProperties(ctx, brushXform, matFinal);
            // set brush params
            Vector4 brushParams = new Vector4(0.01f * brushStrength, 0.0f, brushSize, 1 / brushSize);

            matFinal.SetVector("_BrushParams", brushParams);
            matFinal.SetTexture("_BrushTex", brushTexture);
            matFinal.SetTexture("_NoiseTex", noiseRT);
            matFinal.SetVector("_WorldHeightRemap", m_toolSettings.worldHeightRemap);
            Graphics.Blit(ctx.sourceRenderTexture, ctx.destinationRenderTexture, matFinal, 0);

            RTUtils.Release(noiseRT);
            RTUtils.Release(brushMask);

            RenderTexture.active = prevRT;
        }
        private void ApplyBrushInternal(Terrain terrain, PaintContext ctx, BrushTransform brushTransform)
        {
            Init();

            Vector3       brushPos = new Vector3(commonUI.raycastHitUnderCursor.point.x, 0, commonUI.raycastHitUnderCursor.point.z);
            FilterContext fc       = new FilterContext(terrain, brushPos, commonUI.brushSize, commonUI.brushRotation);

            fc.renderTextureCollection.GatherRenderTextures(ctx.sourceRenderTexture.width, ctx.sourceRenderTexture.height);
            RenderTexture filterMaskRT = commonUI.GetBrushMask(fc, ctx.sourceRenderTexture);

            m_rtCollection.ReleaseRenderTextures();
            m_rtCollection.GatherRenderTextures(ctx.sourceRenderTexture.width, ctx.sourceRenderTexture.height, 16);

            Graphics.Blit(ctx.sourceRenderTexture, m_rtCollection[RenderTextureIDs.sourceHeight]);

            Material mat = GetMaterial();

            Matrix4x4 toolMatrix = Matrix4x4.TRS(Vector3.zero, toolSettings.rotation, toolSettings.scale);

            Bounds modelBounds   = activeMesh.bounds;
            float  maxModelScale = Mathf.Max(Mathf.Max(modelBounds.size.x, modelBounds.size.y), modelBounds.size.z);
            // maxModelScale *= Mathf.Sqrt( 2 + maxModelScale * maxModelScale / 4 ) * .5f; // mult so the mesh fits a little better within the camera / stamp texture bounds
            // maxModelScale /= 1.414f;
            float x   = .5f;
            float y   = .5f;
            float xy  = Mathf.Sqrt(x * x + y * y);
            float z   = .5f;
            float xyz = Mathf.Sqrt(xy * xy + z * z);

            maxModelScale *= xyz;

            // build the model matrix to transform the mesh with. we want to scale it to fit in the brush bounds and also center it in the brush bounds
            Matrix4x4 model = toolMatrix * Matrix4x4.Scale(Vector3.one / maxModelScale) * Matrix4x4.Translate(-modelBounds.center);

            // get the world bounds here so we can calculate the needed offset along the up axis
            // Bounds worldBounds = MeshUtility.TransformBounds( model, activeMesh.bounds );
            // float localHeightOffset = Mathf.Min( worldBounds.extents.y, toolSettings.stampHeight / brushUI.terrainUnderCursor.terrainData.size.y  * .5f );
            // Matrix4x4 localHeightOffsetMatrix = Matrix4x4.Translate( Vector3.up * localHeightOffset );
            // apply the local height offset
            // model = localHeightOffsetMatrix * model;

            Vector3 translate = Vector3.up * (toolSettings.stampHeight) / commonUI.terrainUnderCursor.terrainData.size.y;

            // translate = translate / brushUI.brushStrength * .5f;
            model = Matrix4x4.Translate(translate) * model;

            // actually render the mesh to texture to be used with the tool shader
            TerrainTools.MeshUtility.RenderTopdownProjection(activeMesh, model,
                                                             m_rtCollection[RenderTextureIDs.meshStamp],
                                                             TerrainTools.MeshUtility.defaultProjectionMaterial,
                                                             TerrainTools.MeshUtility.ShaderPass.Height);
            NoiseUtils.BlitPreview2D(m_rtCollection[RenderTextureIDs.meshStamp], m_rtCollection[RenderTextureIDs.meshStampPreview]);

            // generate a mask for the mesh to be used in the compositing shader
            TerrainTools.MeshUtility.RenderTopdownProjection(activeMesh, model,
                                                             m_rtCollection[RenderTextureIDs.meshStampMask],
                                                             TerrainTools.MeshUtility.defaultProjectionMaterial,
                                                             TerrainTools.MeshUtility.ShaderPass.Mask);

            // perform actual composite of mesh stamp and terrain source heightmap
            float   brushStrength = Event.current.control ? -commonUI.brushStrength : commonUI.brushStrength;
            Vector4 brushParams   = new Vector4(brushStrength, toolSettings.blendAmount, (commonUI.raycastHitUnderCursor.point.y - commonUI.terrainUnderCursor.GetPosition().y) / commonUI.terrainUnderCursor.terrainData.size.y * .5f, toolSettings.stampHeight / commonUI.terrainUnderCursor.terrainData.size.y * .5f);

            mat.SetVector("_BrushParams", brushParams);
            mat.SetTexture("_MeshStampTex", m_rtCollection[RenderTextureIDs.meshStamp]);
            mat.SetTexture("_FilterTex", filterMaskRT);
            mat.SetTexture("_MeshMaskTex", m_rtCollection[RenderTextureIDs.meshStampMask]);
            mat.SetFloat("_TerrainHeight", commonUI.terrainUnderCursor.terrainData.size.y);
            TerrainPaintUtility.SetupTerrainToolMaterialProperties(ctx, brushTransform, mat);
            Graphics.Blit(ctx.sourceRenderTexture, ctx.destinationRenderTexture, mat, 0);
            Graphics.Blit(ctx.destinationRenderTexture, m_rtCollection[RenderTextureIDs.combinedHeight]);

            // restore old render target
            RenderTexture.active = ctx.oldRenderTexture;
        }