/// <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); }
/*============================================================================================ * * 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); }
/// <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); }
//=================================================================================================== // // 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); }
//=================================================================================================== // // 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; }