Beispiel #1
0
        /// <summary>
        /// Bakes 3D noise defined by the given NoiseSettings instance into a Texture3D instance and returns
        /// a reference to it.
        /// </summary>
        /// <param name = "noise"> An instance of NoiseSettings defining the type of noise to bake </param>
        /// <param name = "width"> The width of the baked Texture3D </param>
        /// <param name = "height"> The height of the baked Texture3D </param>
        /// <param name = "depth"> The depth of the baked Texture3D </param>
        /// <param name = "format"> The GraphicsFormat for the baked Texture3D. In most cases, you will want to use GraphicsFormat.R16_UNorm </param>
        /// <param name = "flags"> TextureCreation flags for the baked Texture3D. </param>
        /// <returns> A reference to the baked Texture3D instance </returns>
        /// <remarks>
        /// Be careful when specifying TextureCreation flags. If you specify that mipmaps should be generated for
        /// a Texture3D, that will use a lot more memory than if you were generating mipmaps for a Texture2D.
        /// </remarks>
        public static Texture3D BakeToTexture3D(NoiseSettings noise, int width, int height, int depth,
                                                GraphicsFormat format      = GraphicsFormat.R16_UNorm,
                                                TextureCreationFlags flags = TextureCreationFlags.None)
        {
            Material mat = GetDefaultBlitMaterial(noise);

            if (mat == null)
            {
                return(null);
            }

            RenderTexture sliceRT = RenderTexture.GetTemporary(width, height, 0, GraphicsFormat.R16_UNorm);
            Texture2D     slice2D = new Texture2D(width, height, format, flags);

            Color[] colors = new Color[width * height * depth];

            noise.SetupMaterial(mat);
            int pass = NoiseLib.GetNoiseIndex(noise);

            RenderTexture.active = sliceRT;

            List <Color[]> sliceColors = new List <Color[]>(depth);

            for (int i = 0; i < depth; ++i)
            {
                float uvy = ((float)i + 0.5f) / depth;
                mat.SetFloat("_UVY", uvy);

                Graphics.Blit(null, sliceRT, mat, pass * kNumBlitPasses + 1);

                slice2D.ReadPixels(new Rect(0, 0, width, height), 0, 0);

                sliceColors.Add(slice2D.GetPixels(0, 0, width, height));
            }

            int pixPerSlice = width * height;

            for (int sliceID = 0; sliceID < sliceColors.Count; ++sliceID)
            {
                for (int pixelID = 0; pixelID < sliceColors[sliceID].Length; ++pixelID)
                {
                    int pixel = (pixPerSlice * sliceID) + pixelID;
                    colors[pixel] = sliceColors[sliceID][pixelID];
                }
            }

            bool mipChain = ((int)flags & (int)TextureCreationFlags.MipChain) != 0;

            Texture3D texture = new Texture3D(width, height, depth, format, flags);

            texture.SetPixels(colors);
            texture.Apply(mipChain);

            RenderTexture.active = null;
            RenderTexture.ReleaseTemporary(sliceRT);

            return(texture);
        }
Beispiel #2
0
        /*============================================================================================
        *
        *   UI Helpers
        *
        *  ============================================================================================*/

        /// <summary>
        /// Renders a Popup using EditorGUILayout.Popup for all loaded NoiseType implementations
        /// </summary>
        /// <param name="label"> Label prefix for the Popup </param>
        /// <param name="selectedName"> The currently selected NoiseType name </param>
        public static string NoiseTypePopup(GUIContent label, string selectedName)
        {
            string[] names = NoiseLib.GetNoiseNames();
            int      index = NoiseLib.GetNoiseIndex(selectedName);

            index = index < 0 ? 0 : index;

            int    newIndex = EditorGUILayout.Popup(label, index, names);
            string newName  = names[newIndex];

            if (newName.CompareTo(selectedName) != 0)
            {
                selectedName = newName;
            }

            return(selectedName);
        }
        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);
        }
Beispiel #4
0
        /// <summary>
        /// Blits 2D noise defined by the given NoiseSettings instance into the destination RenderTexture
        /// using the provided Material.
        /// </summary>
        /// <param name = "noise"> An instance of NoiseSettings defining the type of noise to render </param>
        /// <param name = "dest"> The destination RenderTexture that the noise will be rendered into. </param>
        /// <param name = "mat"> The Material to be used for rendering the noise </param>
        public static void Blit2D(NoiseSettings noise, RenderTexture dest, Material mat)
        {
            int pass = NoiseLib.GetNoiseIndex(noise.domainSettings.noiseTypeName);

            INTERNAL_Blit2D(noise, dest, mat, pass * kNumBlitPasses + 0);
        }
Beispiel #5
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);
        }
Beispiel #6
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;
        }