/// <summary> /// Renders a Popup using EditorGUILayout.Popup for all loaded FractalType implementations /// </summary> /// <param name="label"> Label prefix for the Popup </param> /// <param name="selectedName"> The currently selected FractalType name </param> public static string FractalTypePopup(GUIContent label, string selectedName) { string[] names = NoiseLib.GetFractalNames(); int index = NoiseLib.GetFractalIndex(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); }
/// <summary> /// Function that is called when an asset with the ".noisehlsltemplate" extension is imported by the AssetDatabase /// </summary> /// <param name = "ctx"> The context for the imported asset </param> public override void OnImportAsset(AssetImportContext ctx) { NoiseLib.GenerateHeaderFiles(); NoiseLib.GenerateShaders(); }
/// <summary> /// Returns a Material reference to the default blit material for the given Type of FractalType. /// </summary> /// <remarks> Usage is: Material mat = GetDefaultBlitMaterial( typeof(FbmFractalType) ); </remarks> /// <returns> A reference to the default blit Material for the specified Type of FractalType </return> /// <param name="fractalType"> The Type for a given FractalType </param> public static Material GetDefaultBlitMaterial(Type fractalType) { return(NoiseLib.GetGeneratedMaterial(typeof(NoiseBlitShaderGenerator), fractalType)); }
/// <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); }
public GeneratedShaderInfo(IFractalType fractalType, INoiseType noiseType) { this.fractalDesc = fractalType.GetDescription(); this.noiseDesc = noiseType.GetDescription(); this.noiseIncludeStr = string.Format("#include \"{0}\"", noiseDesc.sourcePath); if (!string.IsNullOrEmpty(fractalDesc.name)) { this.variantName = string.Format("{0}{1}", fractalDesc.name, noiseDesc.name); } else { this.variantName = noiseDesc.name; } // set the path of the generated file. this will be used when writing the file // to disk and when adding the include in any generated shaders that use this // fractal and noise type variant this.generatedIncludePath = string.Format("{0}/{1}/{2}.hlsl", noiseDesc.outputDir, fractalDesc.name, noiseDesc.name); this.outputDir = string.Format("{0}/{1}", noiseDesc.outputDir, fractalDesc.name); fractalStructName = string.Format("{0}FractalInput", fractalDesc.name); noiseStructName = string.Format("{0}NoiseInput", noiseDesc.name); numFractalInputs = fractalDesc.inputStructDefinition == null ? 0 : fractalDesc.inputStructDefinition.Count; numNoiseInputs = noiseDesc.inputStructDefinition == null ? 0 : noiseDesc.inputStructDefinition.Count; fractalParamStr = null; noiseParamStr = null; functionInputStr = ""; // construct include paths string additionalIncludePaths = "\n"; for (int i = 0; i < fractalDesc.additionalIncludePaths.Count; ++i) { additionalIncludePaths += $"#include \"{ fractalDesc.additionalIncludePaths[ i ] }\"\n"; } additionalIncludePaths += "\n"; // generate the string for the fractal type structure as it would appear as a parameter // in an HLSL function declaration if (numFractalInputs > 0) { fractalParamStr = string.Format("{0} {1}", fractalStructName, "fractalInput"); } // generate the string for the noise type structure as it would appear as a parameter // in an HLSL function declaration if (numNoiseInputs > 0) { noiseParamStr = string.Format("{0} {1}", noiseStructName, "noiseInput"); } // generate the argument string for an HLSL function declaration that would be // using this combination of noise and fractal type structure definitions functionParamStr = ""; if (fractalParamStr != null) { functionParamStr += fractalParamStr; functionInputStr += "fractalInput"; } if (fractalParamStr != null && noiseParamStr != null) { functionParamStr += ", "; functionInputStr += ", "; } if (noiseParamStr != null) { functionParamStr += noiseParamStr; functionInputStr += "noiseInput"; } fractalStructDef = ""; if (numFractalInputs > 0) { fractalStructDef = NoiseLib.BuildStructString(fractalStructName, fractalDesc.inputStructDefinition); string getDefaultFuncStr = NoiseLib.GetDefaultFunctionString(fractalStructName, fractalDesc.inputStructDefinition); fractalStructDef += $"\n\n{ getDefaultFuncStr }\n\n"; } noiseStructDef = ""; if (numNoiseInputs > 0) { noiseStructDef = NoiseLib.BuildStructString(noiseStructName, noiseDesc.inputStructDefinition); } // get input str construction getInputsStr = ""; getFractalInputStr = NoiseLib.GetInputFunctionCallString(fractalStructName); getNoiseInputStr = NoiseLib.GetInputFunctionCallString(fractalStructName); if (numFractalInputs > 0) { getInputsStr += getFractalInputStr; } if (numFractalInputs > 0 && numNoiseInputs > 0) { getInputsStr += ", "; } if (numNoiseInputs > 0) { getInputsStr += getNoiseInputStr; } // get default input str construction getDefaultInputsStr = ""; getDefaultFractalInputStr = NoiseLib.GetDefaultInputFunctionCallString(fractalStructName); getDefaultNoiseInputStr = NoiseLib.GetDefaultInputFunctionCallString(noiseStructName); if (numFractalInputs > 0) { getDefaultInputsStr += getDefaultFractalInputStr; } if (numFractalInputs > 0 && numNoiseInputs > 0) { getDefaultInputsStr += ", "; } if (numNoiseInputs > 0) { getDefaultInputsStr += getDefaultNoiseInputStr; } fractalPropertyDefStr = ""; if (fractalDesc.inputStructDefinition != null && fractalDesc.inputStructDefinition.Count > 0) { fractalPropertyDefStr = NoiseLib.GetPropertyDefinitionStr(fractalDesc.name, fractalDesc.inputStructDefinition); fractalPropertyDefStr += "\n" + NoiseLib.GetPropertyFunctionStr(fractalStructName, fractalDesc.name, fractalDesc.inputStructDefinition); } }
private TerrainToolsAnalytics.IBrushParameter[] UpdateAnalyticParameters() { m_AnalyticsData.Clear(); SerializedProperty transformSettings = noiseSettingsGUI.serializedNoise.FindProperty("transformSettings"); SerializedProperty domainSettings = noiseSettingsGUI.serializedNoise.FindProperty("domainSettings"); SerializedProperty fractalTypeName = domainSettings.FindPropertyRelative("fractalTypeName"); SerializedProperty fractalTypeParams = domainSettings.FindPropertyRelative("fractalTypeParams"); //Add Generic, Transform, and Domain type settings to be sent as analytic data m_AnalyticsData.AddRange(new TerrainToolsAnalytics.IBrushParameter[] { //Generic Settings new TerrainToolsAnalytics.BrushParameter <string> { Name = Styles.coordSpace.text, Value = m_toolSettings.coordSpace.ToString() }, //Transform Settings new TerrainToolsAnalytics.BrushParameter <Vector3> { Name = "Translation", Value = transformSettings.FindPropertyRelative("translation").vector3Value }, new TerrainToolsAnalytics.BrushParameter <Vector3> { Name = "Rotation", Value = transformSettings.FindPropertyRelative("rotation").vector3Value }, new TerrainToolsAnalytics.BrushParameter <Vector3> { Name = "Scale", Value = transformSettings.FindPropertyRelative("scale").vector3Value }, new TerrainToolsAnalytics.BrushParameter <bool> { Name = NoiseSettingsGUI.Styles.flipScaleX.text, Value = transformSettings.FindPropertyRelative("flipScaleX").boolValue }, new TerrainToolsAnalytics.BrushParameter <bool> { Name = NoiseSettingsGUI.Styles.flipScaleY.text, Value = transformSettings.FindPropertyRelative("flipScaleY").boolValue }, new TerrainToolsAnalytics.BrushParameter <bool> { Name = NoiseSettingsGUI.Styles.flipScaleZ.text, Value = transformSettings.FindPropertyRelative("flipScaleZ").boolValue }, //Domain new TerrainToolsAnalytics.BrushParameter <string> { Name = NoiseSettingsGUI.Styles.noiseType.text, Value = domainSettings.FindPropertyRelative("noiseTypeName").stringValue }, new TerrainToolsAnalytics.BrushParameter <string> { Name = NoiseSettingsGUI.Styles.fractalType.text, Value = domainSettings.FindPropertyRelative("fractalTypeName").stringValue } } ); //Add fractal specific settings to be sent as analytic data IFractalType fractalType = NoiseLib.GetFractalTypeInstance(fractalTypeName.stringValue); switch (domainSettings.FindPropertyRelative("fractalTypeName").stringValue) { case "Fbm": FbmFractalType.FbmFractalInput fbmFractalSettings = (FbmFractalType.FbmFractalInput)fractalType.FromSerializedString(fractalTypeParams.stringValue); m_AnalyticsData.AddRange(new TerrainToolsAnalytics.IBrushParameter[] { new TerrainToolsAnalytics.BrushParameter <float> { Name = FbmFractalType.Styles.octaves.text, Value = fbmFractalSettings.octaves }, new TerrainToolsAnalytics.BrushParameter <float> { Name = FbmFractalType.Styles.amplitude.text, Value = fbmFractalSettings.amplitude }, new TerrainToolsAnalytics.BrushParameter <float> { Name = FbmFractalType.Styles.persistence.text, Value = fbmFractalSettings.persistence }, new TerrainToolsAnalytics.BrushParameter <float> { Name = FbmFractalType.Styles.frequency.text, Value = fbmFractalSettings.frequency }, new TerrainToolsAnalytics.BrushParameter <float> { Name = FbmFractalType.Styles.lacunarity.text, Value = fbmFractalSettings.lacunarity }, new TerrainToolsAnalytics.BrushParameter <bool> { Name = FbmFractalType.Styles.domainWarpSettings.text, Value = fbmFractalSettings.warpEnabled }, new TerrainToolsAnalytics.BrushParameter <float> { Name = FbmFractalType.Styles.warpIterations.text, Value = fbmFractalSettings.warpIterations }, new TerrainToolsAnalytics.BrushParameter <float> { Name = FbmFractalType.Styles.warpStrength.text, Value = fbmFractalSettings.warpStrength }, new TerrainToolsAnalytics.BrushParameter <Vector4> { Name = FbmFractalType.Styles.warpOffsets.text, Value = fbmFractalSettings.warpOffsets }, }); break; case "Strata": StrataFractalType.StrataFractalInput strataFractalSettings = (StrataFractalType.StrataFractalInput)fractalType.FromSerializedString(fractalTypeParams.stringValue); m_AnalyticsData.AddRange(new TerrainToolsAnalytics.IBrushParameter[] { new TerrainToolsAnalytics.BrushParameter <float> { Name = StrataFractalType.Styles.octaves.text, Value = strataFractalSettings.octaves }, new TerrainToolsAnalytics.BrushParameter <float> { Name = StrataFractalType.Styles.amplitude.text, Value = strataFractalSettings.amplitude }, new TerrainToolsAnalytics.BrushParameter <float> { Name = StrataFractalType.Styles.persistence.text, Value = strataFractalSettings.persistence }, new TerrainToolsAnalytics.BrushParameter <float> { Name = StrataFractalType.Styles.frequency.text, Value = strataFractalSettings.frequency }, new TerrainToolsAnalytics.BrushParameter <float> { Name = StrataFractalType.Styles.lacunarity.text, Value = strataFractalSettings.lacunarity }, new TerrainToolsAnalytics.BrushParameter <bool> { Name = StrataFractalType.Styles.domainWarpSettings.text, Value = strataFractalSettings.warpEnabled }, new TerrainToolsAnalytics.BrushParameter <float> { Name = StrataFractalType.Styles.warpIterations.text, Value = strataFractalSettings.warpIterations }, new TerrainToolsAnalytics.BrushParameter <float> { Name = StrataFractalType.Styles.warpStrength.text, Value = strataFractalSettings.warpStrength }, new TerrainToolsAnalytics.BrushParameter <Vector4> { Name = StrataFractalType.Styles.warpOffsets.text, Value = strataFractalSettings.warpOffsets }, new TerrainToolsAnalytics.BrushParameter <float> { Name = StrataFractalType.Styles.strataOffset.text, Value = strataFractalSettings.strataOffset }, new TerrainToolsAnalytics.BrushParameter <float> { Name = StrataFractalType.Styles.strataScale.text, Value = strataFractalSettings.strataScale }, }); break; case "None": default: break; } return(m_AnalyticsData.ToArray()); }
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; }