Ejemplo n.º 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);
        }
        /// <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);
        }
        protected override void OnEval(FilterContext fc, RenderTexture sourceRenderTexture, RenderTexture destinationRenderTexture)
        {
            if (m_noiseSettings == null)
            {
                m_noiseSettings = ScriptableObject.CreateInstance <NoiseSettings>();
            }

            m_noiseSettings.useTextureForPositions = m_useHeightmap;

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

            Vector3 brushPosWS = fc.brushPos - m_lastBrushPosition;

            brushPosWS.y        = 0;
            m_lastBrushPosition = fc.brushPos;
            float brushSize     = fc.brushSize;
            float brushRotation = fc.brushRotation - m_lastRotation;

            m_lastRotation = 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);

            // 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;

            // compensate for the difference between the size of the rotated brush and the square noise RT
            var brushTransform  = GetBrushTransform(fc);
            var scaleMultiplier = new Vector2(
                1.0f / (fc.brushSize / brushTransform.GetBrushXYBounds().width),
                1.0f / (fc.brushSize / brushTransform.GetBrushXYBounds().height));

            Quaternion rotQ = Quaternion.AngleAxis(-brushRotation, Vector3.up);

            // accumulate transformation delta
            m_noiseToWorld *= Matrix4x4.TRS(brushPosWS, rotQ, Vector3.one);

            mat.SetMatrix(NoiseSettings.ShaderStrings.transform, noiseSettings.trs * m_noiseToWorld * Matrix4x4.Scale(new Vector3(scaleMultiplier.x, 1.0f, scaleMultiplier.y) * brushSize));

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

            var desc = destinationRenderTexture.descriptor;

            desc.graphicsFormat = NoiseUtils.singleChannelFormat;
            desc.sRGB           = false;
            RTHandle rt = RTUtils.GetTempHandle(desc);

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

            Material blendMat = FilterUtility.blendModesMaterial;

            blendMat.SetTexture("_BlendTex", rt);
            Graphics.Blit(sourceRenderTexture, destinationRenderTexture, blendMat, 1);
            RTUtils.Release(rt);
        }
Ejemplo n.º 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);
        }
        private void ApplyBrushInternal(Terrain terrain, PaintContext ctx, BrushTransform brushXform, Vector3 brushPosWS,
                                        float brushRotation, float brushStrength, float brushSize, Texture brushTexture)
        {
            var prevRT = RenderTexture.active;

            var brushPositionOffset = brushPosWS - m_lastBrushPosition;

            m_lastBrushPosition   = brushPosWS;
            brushPositionOffset.y = 0;

            var rotationDelta = brushRotation - m_lastRotation;

            m_lastRotation = brushRotation;

            //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);

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

            brushSize           = isWorldSpace ? brushSize * previewSize : 1;
            brushPositionOffset = isWorldSpace ? brushPositionOffset * previewSize : Vector3.zero;
            var brushTransform  = NoiseFilter.GetBrushTransform(rotationDelta, brushSize);
            var scaleMultiplier = new Vector2(
                1.0f / (brushSize / brushTransform.GetBrushXYBounds().width),
                1.0f / (brushSize / brushTransform.GetBrushXYBounds().height));

            // // override noise transform
            Quaternion rotQ = Quaternion.AngleAxis(-rotationDelta, Vector3.up);

            // accumulate transformation delta
            m_noiseToWorld *= Matrix4x4.TRS(brushPositionOffset, rotQ, Vector3.one);

            matNoise.SetMatrix(NoiseSettings.ShaderStrings.transform, noiseSettings.trs * m_noiseToWorld * Matrix4x4.Scale(new Vector3(scaleMultiplier.x, 1.0f, scaleMultiplier.y) * brushSize));

            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;
        }