private void ApplyBrushInternal(PaintContext paintContext, IBrushRenderUnderCursor brushRender, float brushStrength, Texture brushTexture, BrushTransform brushTransform, Terrain terrain) { Material mat = TerrainPaintUtility.GetBuiltinPaintMaterial(); float terrainHeight = Mathf.Clamp01((m_HeightWorldSpace - terrain.transform.position.y) / terrain.terrainData.size.y); Vector4 brushParams = new Vector4(brushStrength * 0.01f, 0.5f * terrainHeight, 0.0f, 0.0f); 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(paintContext.sourceRenderTexture.width, paintContext.sourceRenderTexture.height); RenderTexture filterMaskRT = commonUI.GetBrushMask(fc, paintContext.sourceRenderTexture); mat.SetTexture("_FilterTex", filterMaskRT); mat.SetTexture("_BrushTex", brushTexture); mat.SetVector("_BrushParams", brushParams); brushRender.SetupTerrainToolMaterialProperties(paintContext, brushTransform, mat); brushRender.RenderBrush(paintContext, mat, (int)TerrainPaintUtility.BuiltinPaintMaterialPasses.SetHeights); }
public override bool OnPaint(Terrain terrain, IOnPaint editContext) { commonUI.OnPaint(terrain, editContext); if (!commonUI.allowPaint) { return(true); } using (IBrushRenderUnderCursor brushRender = new BrushRenderUIGroupUnderCursor(commonUI, "SharpenPeak", editContext.brushTexture)) { if (brushRender.CalculateBrushTransform(out BrushTransform brushXform)) { PaintContext paintContext = brushRender.AcquireHeightmap(true, brushXform.GetBrushXYBounds(), 1); 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(paintContext.sourceRenderTexture.width, paintContext.sourceRenderTexture.height); RenderTexture filterMaskRT = commonUI.GetBrushMask(fc, paintContext.sourceRenderTexture); Material mat = GetPaintMaterial(); // apply brush Vector4 brushParams = new Vector4( commonUI.brushStrength, m_ErosionStrength, m_MixStrength, 0.0f); mat.SetTexture("_BrushTex", editContext.brushTexture); mat.SetTexture("_FilterTex", filterMaskRT); mat.SetVector("_BrushParams", brushParams); brushRender.SetupTerrainToolMaterialProperties(paintContext, brushXform, mat); brushRender.RenderBrush(paintContext, mat, 0); } } return(false); }
protected override void OnDrawGUI(Rect rect, FilterContext filterContext) { //Calculate dimensions float epsilonLabelWidth = GUI.skin.label.CalcSize(epsilonLabel).x; float modeLabelWidth = GUI.skin.label.CalcSize(modeLabel).x; float strengthLabelWidth = GUI.skin.label.CalcSize(strengthLabel).x; float curveLabelWidth = GUI.skin.label.CalcSize(curveLabel).x; float labelWidth = Mathf.Max(Mathf.Max(Mathf.Max(modeLabelWidth, epsilonLabelWidth), strengthLabelWidth), curveLabelWidth) + 4.0f; //Strength Slider Rect strengthLabelRect = new Rect(rect.x, rect.y, labelWidth, EditorGUIUtility.singleLineHeight); EditorGUI.LabelField(strengthLabelRect, strengthLabel); Rect strengthSliderRect = new Rect(strengthLabelRect.xMax, strengthLabelRect.y, rect.width - labelWidth, strengthLabelRect.height); m_FilterStrength = EditorGUI.Slider(strengthSliderRect, m_FilterStrength, 0.0f, 1.0f); //Epsilon (kernel size) Slider Rect epsilonLabelRect = new Rect(rect.x, strengthSliderRect.yMax, labelWidth, EditorGUIUtility.singleLineHeight); EditorGUI.LabelField(epsilonLabelRect, epsilonLabel); Rect epsilonSliderRect = new Rect(epsilonLabelRect.xMax, epsilonLabelRect.y, rect.width - labelWidth, epsilonLabelRect.height); m_Epsilon = EditorGUI.Slider(epsilonSliderRect, m_Epsilon, 1.0f, 20.0f); //Value Remap Curve Rect curveLabelRect = new Rect(rect.x, epsilonSliderRect.yMax, labelWidth, EditorGUIUtility.singleLineHeight); EditorGUI.LabelField(curveLabelRect, curveLabel); Rect curveRect = new Rect(curveLabelRect.xMax, curveLabelRect.y, rect.width - labelWidth, curveLabelRect.height); EditorGUI.BeginChangeCheck(); m_RemapCurve = EditorGUI.CurveField(curveRect, m_RemapCurve); if (EditorGUI.EndChangeCheck()) { var tex = GetRemapTexture(); Utility.AnimationCurveToRenderTexture(m_RemapCurve, ref tex); } }
public override bool OnPaint(Terrain terrain, IOnPaint editContext) { commonUI.OnPaint(terrain, editContext); if (commonUI.allowPaint) { Texture brushTexture = editContext.brushTexture; using (IBrushRenderUnderCursor brushRender = new BrushRenderUIGroupUnderCursor(commonUI, "PaintHoles", brushTexture)) { Vector2 halfTexelOffset = new Vector2(0.5f / terrain.terrainData.holesResolution, 0.5f / terrain.terrainData.holesResolution); BrushTransform brushXform = TerrainPaintUtility.CalculateBrushTransform(terrain, editContext.uv - halfTexelOffset, commonUI.brushSize, commonUI.brushRotation); PaintContext paintContext = brushRender.AquireHolesTexture(true, brushXform.GetBrushXYBounds()); PaintContext paintContextHeight = brushRender.AcquireHeightmap(false, brushXform.GetBrushXYBounds()); // filter stack 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(paintContextHeight.sourceRenderTexture.width, paintContextHeight.sourceRenderTexture.height); RenderTexture filterMaskRT = commonUI.GetBrushMask(fc, paintContextHeight.sourceRenderTexture); Material mat = GetPaintHolesMaterial(); // hold control key to erase float brushStrength = Event.current.control ? commonUI.brushStrength : -commonUI.brushStrength; Vector4 brushParams = new Vector4(brushStrength, 0.0f, 0.0f, 0.0f); mat.SetTexture("_BrushTex", editContext.brushTexture); mat.SetTexture("_FilterTex", filterMaskRT); mat.SetVector("_BrushParams", brushParams); brushRender.SetupTerrainToolMaterialProperties(paintContext, brushXform, mat); brushRender.RenderBrush(paintContext, mat, (int)TerrainPaintUtility.BuiltinPaintMaterialPasses.PaintHoles); TerrainPaintUtility.EndPaintHoles(paintContext, "Terrain Paint - Paint Holes"); } } return(true); }
public override void Eval(FilterContext fc) { ComputeShader cs = GetComputeShader(); int kidx = cs.FindKernel("AspectRemap"); //using 1s here so we don't need a multiple-of-8 texture in the compute shader (probably not optimal?) int[] numWorkGroups = { 1, 1, 1 }; Texture2D remapTex = GetRemapTexture(); float rotRad = (fc.properties["brushRotation"] - 90.0f) * Mathf.Deg2Rad; cs.SetTexture(kidx, "In_BaseMaskTex", fc.sourceRenderTexture); cs.SetTexture(kidx, "In_HeightTex", fc.renderTextureCollection["heightMap"]); cs.SetTexture(kidx, "OutputTex", fc.destinationRenderTexture); cs.SetTexture(kidx, "RemapTex", remapTex); cs.SetInt("RemapTexRes", remapTex.width); cs.SetFloat("EffectStrength", m_EffectStrength); cs.SetVector("TextureResolution", new Vector4(fc.sourceRenderTexture.width, fc.sourceRenderTexture.height, 0.0f, 0.0f)); cs.SetVector("AspectValues", new Vector4(Mathf.Cos(rotRad), Mathf.Sin(rotRad), m_Epsilon, 0.0f)); cs.Dispatch(kidx, fc.sourceRenderTexture.width / numWorkGroups[0], fc.sourceRenderTexture.height / numWorkGroups[1], numWorkGroups[2]); }
public override void Eval(FilterContext fc) { FilterUtility.builtinMaterial.SetVector("_ClampRange", range); Graphics.Blit(fc.sourceRenderTexture, fc.destinationRenderTexture, FilterUtility.builtinMaterial, ( int )FilterUtility.BuiltinPasses.Clamp); }
public override bool OnPaint(Terrain terrain, IOnPaint editContext) { commonUI.OnPaint(terrain, editContext); if (!commonUI.allowPaint) { return(true); } if (Event.current.type == EventType.MouseDown) { m_PrevBrushPos = editContext.uv; return(false); } if (Event.current.type == EventType.MouseDrag && m_PreviousEvent == EventType.MouseDrag) { Vector2 uv = editContext.uv; if (commonUI.ScatterBrushStamp(ref terrain, ref uv)) { Material mat = GetPaintMaterial(); Vector2 smudgeDir = uv - m_PrevBrushPos; BrushTransform brushXform = TerrainPaintUtility.CalculateBrushTransform(terrain, uv, commonUI.brushSize, commonUI.brushRotation); Vector4 brushParams = new Vector4(commonUI.brushStrength, smudgeDir.x, smudgeDir.y, 0); mat.SetTexture("_BrushTex", editContext.brushTexture); mat.SetVector("_BrushParams", brushParams); //smudge splat map if (m_AffectMaterials) { for (int i = 0; i < terrain.terrainData.terrainLayers.Length; i++) { TerrainLayer layer = terrain.terrainData.terrainLayers[i]; if (layer == null) { continue; // nothing to paint if the layer is NULL } PaintContext sampleContext = TerrainPaintUtility.BeginPaintTexture(terrain, brushXform.GetBrushXYBounds(), layer); 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(sampleContext.sourceRenderTexture.width, sampleContext.sourceRenderTexture.height); RenderTexture filterMaskRT = commonUI.GetBrushMask(fc, sampleContext.sourceRenderTexture); mat.SetTexture("_FilterTex", filterMaskRT); Graphics.Blit(sampleContext.sourceRenderTexture, sampleContext.destinationRenderTexture, mat, 0); TerrainPaintUtility.EndPaintTexture(sampleContext, "Terrain Paint - Smudge Brush (Texture)"); } } //smudge the height map if (m_AffectHeight) { PaintContext paintContext = TerrainPaintUtility.BeginPaintHeightmap(terrain, brushXform.GetBrushXYBounds(), 1); 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(paintContext.sourceRenderTexture.width, paintContext.sourceRenderTexture.height); RenderTexture filterMaskRT = commonUI.GetBrushMask(fc, paintContext.sourceRenderTexture); mat.SetTexture("_FilterTex", filterMaskRT); TerrainPaintUtility.SetupTerrainToolMaterialProperties(paintContext, brushXform, mat); Graphics.Blit(paintContext.sourceRenderTexture, paintContext.destinationRenderTexture, mat, 0); TerrainPaintUtility.EndPaintHeightmap(paintContext, "Terrain Paint - Smudge Brush (Height)"); } m_PrevBrushPos = uv; } } m_PreviousEvent = Event.current.type; return(false); }
/// <summary> /// Draw the GUI for the Filter /// </summary> /// <param name="rect">The Rect where the GUI should be drawn</param> /// <param name="filterContext">The FilterContext related to the current evaluation. Use this to show different information in the Filter GUI</param> protected virtual void OnDrawGUI(Rect rect, FilterContext filterContext) { }
protected override void OnEval(FilterContext filterContext, RenderTexture sourceRenderTexture, RenderTexture destinationRenderTexture) { Graphics.Blit(sourceRenderTexture, destinationRenderTexture, FilterUtility.builtinMaterial, ( int )FilterUtility.BuiltinPasses.Negate); }
protected override void OnDrawGUI(Rect rect, FilterContext filterContext) => value = EditorGUI.FloatField(rect, value);
private void ApplyBrushInternal(Terrain terrain, Vector2 uv, Texture brushTexture, float brushSpacing) { //get the target position & height float targetHeight = terrain.terrainData.GetInterpolatedHeight(uv.x, uv.y) / terrain.terrainData.size.y; Vector3 targetPos = new Vector3(uv.x, uv.y, targetHeight); if (terrain != m_StartTerrain) { //figure out the stroke vector in uv,height space Vector2 targetWorld = transformToWorld(terrain, uv); Vector2 targetUVs = transformToUVSpace(m_StartTerrain, targetWorld); targetPos.x = targetUVs.x; targetPos.y = targetUVs.y; } Vector3 stroke = targetPos - m_StartPoint; float strokeLength = stroke.magnitude; int numSplats; switch (pathToolProperties.paintMode) { case PaintMode.Paint: numSplats = 1; break; case PaintMode.Stroke: numSplats = (int)(strokeLength / (0.1f * Mathf.Max(brushSpacing, 0.01f))); break; default: throw new System.Exception(string.Format("Unsupported paint mode {0}", pathToolProperties.paintMode)); } Terrain currTerrain = m_StartTerrain; Material mat = GetPaintMaterial(); Vector2 posOffset = new Vector2(0.0f, 0.0f); Vector2 currUV = new Vector2(); Vector4 brushParams = new Vector4(); Vector2 jitterVec = new Vector2(-stroke.z, stroke.x); //perpendicular to stroke direction jitterVec.Normalize(); for (int i = 0; i < numSplats; i++) { float pct = (float)i / (float)numSplats; float widthScale = pathToolProperties.widthProfile.Evaluate(pct); float heightOffset = pathToolProperties.heightProfile.Evaluate(pct) / currTerrain.terrainData.size.y; float strengthScale = pathToolProperties.strengthProfile.Evaluate(pct); float jitterOffset = pathToolProperties.jitterProfile.Evaluate(pct) / Mathf.Max(currTerrain.terrainData.size.x, currTerrain.terrainData.size.z); Vector3 currPos = m_StartPoint + pct * stroke; //add in jitter offset (needs to happen before tile correction) currPos.x += posOffset.x + jitterOffset * jitterVec.x; currPos.y += posOffset.y + jitterOffset * jitterVec.y; if (currPos.x >= 1.0f && (currTerrain.rightNeighbor != null)) { currTerrain = currTerrain.rightNeighbor; currPos.x -= 1.0f; posOffset.x -= 1.0f; } if (currPos.x <= 0.0f && (currTerrain.leftNeighbor != null)) { currTerrain = currTerrain.leftNeighbor; currPos.x += 1.0f; posOffset.x += 1.0f; } if (currPos.y >= 1.0f && (currTerrain.topNeighbor != null)) { currTerrain = currTerrain.topNeighbor; currPos.y -= 1.0f; posOffset.y -= 1.0f; } if (currPos.y <= 0.0f && (currTerrain.bottomNeighbor != null)) { currTerrain = currTerrain.bottomNeighbor; currPos.y += 1.0f; posOffset.y += 1.0f; } currUV.x = currPos.x; currUV.y = currPos.y; int finalBrushSize = (int)(widthScale * (float)commonUI.brushSize); float finalHeight = (m_StartPoint + pct * stroke).z + heightOffset; using (IBrushRenderWithTerrain brushRenderWithTerrain = new BrushRenderWithTerrainUiGroup(commonUI, "PathTool", brushTexture)) { if (brushRenderWithTerrain.CalculateBrushTransform(currTerrain, currUV, finalBrushSize, out BrushTransform brushTransform)) { Rect brushBounds = brushTransform.GetBrushXYBounds(); PaintContext paintContext = brushRenderWithTerrain.AcquireHeightmap(true, currTerrain, brushBounds); mat.SetTexture("_BrushTex", brushTexture); brushParams.x = commonUI.brushStrength * strengthScale; brushParams.y = 0.5f * finalHeight; mat.SetVector("_BrushParams", brushParams); FilterContext fc = new FilterContext(terrain, currPos, finalBrushSize, commonUI.brushRotation); fc.renderTextureCollection.GatherRenderTextures(paintContext.sourceRenderTexture.width, paintContext.sourceRenderTexture.height); RenderTexture filterMaskRT = commonUI.GetBrushMask(fc, paintContext.sourceRenderTexture); mat.SetTexture("_FilterTex", filterMaskRT); brushRenderWithTerrain.SetupTerrainToolMaterialProperties(paintContext, brushTransform, mat); brushRenderWithTerrain.RenderBrush(paintContext, mat, 0); } } } }
public virtual void Eval(FilterContext filterContext) { }
public override void OnSceneGUI(Terrain terrain, IOnSceneGUI editContext) { commonUI.OnSceneGUI2D(terrain, editContext); #if UNITY_2019_1_OR_NEWER // Don't paint if eyedropper is selected if (m_EyedropperSelected) { EditorGUIUtility.AddCursorRect(new Rect(0, 0, Screen.width, Screen.height), MouseCursor.CustomCursor); editContext.Repaint(); return; } #endif // We're only doing painting operations, early out if it's not a repaint if (!editContext.hitValidTerrain && !commonUI.isInUse) { return; } // update brush UI group commonUI.OnSceneGUI(terrain, editContext); // Don't render preview if this isn't a repaint. losing performance if we do if (Event.current.type != EventType.Repaint) { return; } Texture brushTexture = editContext.brushTexture; using (IBrushRenderPreviewUnderCursor brushRender = new BrushRenderPreviewUIGroupUnderCursor(commonUI, "PaintTextureTool", brushTexture)) { if (brushRender.CalculateBrushTransform(out BrushTransform brushTransform)) //cute. { RenderTexture tmpRT = RenderTexture.active; Rect brushBounds = brushTransform.GetBrushXYBounds(); PaintContext heightmapContext = brushRender.AcquireHeightmap(false, brushBounds, 1); Material brushMaterial = GetBrushPreviewMaterial(); if (commonUI.brushMaskFilterStack.filters.Count > 0) { // Evaluate the brush mask filter stack 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(heightmapContext.sourceRenderTexture.width, heightmapContext.sourceRenderTexture.height); RenderTexture filterMaskRT = commonUI.GetBrushMask(fc, heightmapContext.sourceRenderTexture); //Composite the brush texture onto the filter stack result RenderTexture compRT = RenderTexture.GetTemporary(filterMaskRT.descriptor); Material blendMat = GetBlendMaterial(); blendMat.SetTexture("_BlendTex", editContext.brushTexture); blendMat.SetVector("_BlendParams", new Vector4(0.0f, 0.0f, -(commonUI.brushRotation * Mathf.Deg2Rad), 0.0f)); TerrainPaintUtility.SetupTerrainToolMaterialProperties(heightmapContext, brushTransform, blendMat); Graphics.Blit(filterMaskRT, compRT, blendMat, 0); RenderTexture.active = tmpRT; BrushTransform identityBrushTransform = TerrainPaintUtility.CalculateBrushTransform(commonUI.terrainUnderCursor, commonUI.raycastHitUnderCursor.textureCoord, commonUI.brushSize, 0.0f); TerrainPaintUtility.SetupTerrainToolMaterialProperties(heightmapContext, identityBrushTransform, brushMaterial); TerrainPaintUtilityEditor.DrawBrushPreview(heightmapContext, TerrainPaintUtilityEditor.BrushPreview.SourceRenderTexture, compRT, identityBrushTransform, brushMaterial, 0); RenderTexture.ReleaseTemporary(compRT); } brushRender.RenderBrushPreview(heightmapContext, TerrainPaintUtilityEditor.BrushPreview.SourceRenderTexture, brushTransform, TerrainPaintUtilityEditor.GetDefaultBrushPreviewMaterial(), 0); } } }
protected override void OnDrawGUI(Rect rect, FilterContext filterContext) { if (m_noiseSettings == null) { m_noiseSettings = ScriptableObject.CreateInstance <NoiseSettings>(); } GUIContent localLabel = NoiseFilter.localLabel; GUIContent worldLabel = NoiseFilter.worldLabel; GUIContent heightmapLabel = NoiseFilter.heightmapLabel; GUIContent editLabel = NoiseFilter.editLabel; float editWith = GUI.skin.label.CalcSize(editLabel).x + 20f; Rect editRect = new Rect(rect.xMax - editWith, rect.y, editWith, rect.height); Rect labelRect = rect; labelRect.width = GUI.skin.label.CalcSize(coordinateLabel).x; Rect worldRect = labelRect; worldRect.x = labelRect.xMax; worldRect.width = GUI.skin.button.CalcSize(worldLabel).x + 10f; Rect localRect = worldRect; localRect.x = worldRect.xMax; localRect.width = GUI.skin.button.CalcSize(localLabel).x + 10f; Rect heightmapRect = localRect; heightmapRect.x = localRect.xMax + 10f; heightmapRect.width = GUI.skin.button.CalcSize(heightmapLabel).x + 10f; if (editRect.xMin < heightmapRect.xMax + 10f) { worldRect.x -= labelRect.width; localRect.x -= labelRect.width; heightmapRect.x -= labelRect.width; labelRect.width = 0; } editRect.x = Mathf.Max(editRect.x, heightmapRect.xMax + 4f); if (editRect.xMax > rect.xMax) { worldLabel = NoiseFilter.worldShortLabel; localLabel = NoiseFilter.localShortLabel; heightmapLabel = NoiseFilter.heightmapShortLabel; worldRect.width = GUI.skin.label.CalcSize(worldLabel).x + 10f; localRect.width = GUI.skin.label.CalcSize(localLabel).x + 10f; heightmapRect.width = GUI.skin.label.CalcSize(heightmapLabel).x + 10f; localRect.x = worldRect.xMax; heightmapRect.x = localRect.xMax + 10f; editRect.x = rect.xMax - editWith; } editRect.x = Mathf.Max(heightmapRect.xMax + 4f, editRect.x); if (editRect.xMax > rect.xMax) { editLabel = editShortLabel; editRect.width = GUI.skin.label.CalcSize(editLabel).x + 10f; } GUI.Label(labelRect, coordinateLabel); if (GUI.Toggle(worldRect, !m_isLocalSpace, worldLabel, GUI.skin.button)) { m_isLocalSpace = false; } if (GUI.Toggle(localRect, m_isLocalSpace, localLabel, GUI.skin.button)) { m_isLocalSpace = true; } m_useHeightmap = GUI.Toggle(heightmapRect, m_useHeightmap, heightmapLabel, GUI.skin.button); m_noiseSettings.useTextureForPositions = m_useHeightmap; if (GUI.Button(editRect, editLabel)) { NoiseWindow wnd = NoiseWindow.Create(m_noiseSettings, m_noiseSource); wnd.noiseEditorView.onSettingsChanged += (noise) => { m_noiseSettings.Copy(noise); }; wnd.noiseEditorView.onSourceAssetChanged += (noise) => { m_noiseSource = noise; }; wnd.onDisableCallback += () => { m_window = null; }; m_window = wnd; } }
protected override void OnSceneGUI(SceneView sceneView, FilterContext filterContext) { Quaternion windRot = Quaternion.AngleAxis(filterContext.brushRotation, new Vector3(0.0f, 1.0f, 0.0f)); Handles.ArrowHandleCap(0, filterContext.brushPos, windRot, 0.5f * filterContext.brushSize, EventType.Repaint); }
/// <summary> /// Evaluate the Filter. Override this function for custom Filter logic /// </summary> /// <param name="filterContext"></param> /// <param name="source"></param> /// <param name="dest"></param> protected virtual void OnEval(FilterContext filterContext, RenderTexture source, RenderTexture dest) { Graphics.Blit(source, dest); }
/// <summary> /// Called before OnEval. Use this to set up anything needed before Filter evaluation and to also tell the system /// whether or not the Filter is supported based on current hardware, the data provided by the provided /// FilterContext, etc. Do this by returning True or False. /// </summary> /// <param name="filterContext">The FilterContext related to the current evaluation</param> /// <returns>Whether or not the Filter is supported and should be evaluated. True = supported and is okay to evaluate. /// False = the Filter is not supported with the current hardware and should be skipped</returns> public virtual bool ValidateFilter(FilterContext filterContext, out string message) { message = string.Empty; return(true); }
/// <summary> /// Handle SceneView related logic or rendering /// </summary> /// <param name="terrain">The target Terrain</param> /// <param name="brushContext">The current brush parameters</param> protected virtual void OnSceneGUI(SceneView sceneView, FilterContext filterContext) { }
public override void Eval(FilterContext fc) { FilterUtility.builtinMaterial.SetVector("_RemapRanges", new Vector4(fromRange.x, fromRange.y, toRange.x, toRange.y)); Graphics.Blit(fc.sourceRenderTexture, fc.destinationRenderTexture, FilterUtility.builtinMaterial, ( int )FilterUtility.BuiltinPasses.Remap); }
protected override void OnEval(FilterContext fc, RenderTexture sourceRenderTexture, RenderTexture destinationRenderTexture) { FilterUtility.builtinMaterial.SetVector("_ClampRange", range); Graphics.Blit(sourceRenderTexture, destinationRenderTexture, FilterUtility.builtinMaterial, ( int )FilterUtility.BuiltinPasses.Clamp); }
public override bool OnPaint(Terrain terrain, IOnPaint editContext) { #if UNITY_2019_1_OR_NEWER if (m_EyedropperSelected && m_LayerList != null) { Texture2D[] splatmaps = terrain.terrainData.alphamapTextures; int splatOffset = 0; foreach (Texture2D splatmap in splatmaps) { Color pixel = splatmap.GetPixelBilinear(editContext.uv.x, editContext.uv.y); if (pixel.r > .5f) { m_SelectedTerrainLayer = terrain.terrainData.terrainLayers[0 + splatOffset]; m_LayerList.index = 0 + splatOffset; break; } else if (pixel.g > .5f) { m_SelectedTerrainLayer = terrain.terrainData.terrainLayers[1 + splatOffset]; m_LayerList.index = 1 + splatOffset; break; } else if (pixel.b > .5f) { m_SelectedTerrainLayer = terrain.terrainData.terrainLayers[2 + splatOffset]; m_LayerList.index = 2 + splatOffset; break; } else if (pixel.a > .5f) { m_SelectedTerrainLayer = terrain.terrainData.terrainLayers[3 + splatOffset]; m_LayerList.index = 3 + splatOffset; break; } splatOffset += 4; } return(true); } #endif commonUI.OnPaint(terrain, editContext); if (commonUI.allowPaint) { Texture brushTexture = editContext.brushTexture; using (IBrushRenderUnderCursor brushRender = new BrushRenderUIGroupUnderCursor(commonUI, "PaintTextureTool", brushTexture)) { if (brushRender.CalculateBrushTransform(out BrushTransform brushTransform)) { Rect brushRect = brushTransform.GetBrushXYBounds(); PaintContext paintContext = brushRender.AcquireTexture(true, brushRect, m_SelectedTerrainLayer); if (paintContext != null) { PaintContext heightContext = brushRender.AcquireHeightmap(false, brushRect); // Evaluate the brush mask filter stack 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(heightContext.sourceRenderTexture.width, heightContext.sourceRenderTexture.height); RenderTexture filterMaskRT = commonUI.GetBrushMask(fc, heightContext.sourceRenderTexture); Material mat = GetPaintMaterial(); // apply brush float targetAlpha = m_TargetStrength; float s = commonUI.InvertStrength ? -commonUI.brushStrength : commonUI.brushStrength; Vector4 brushParams = new Vector4(s, targetAlpha, 0.0f, 0.0f); mat.SetTexture("_BrushTex", editContext.brushTexture); mat.SetVector("_BrushParams", brushParams); mat.SetTexture("_FilterTex", filterMaskRT); brushRender.SetupTerrainToolMaterialProperties(paintContext, brushTransform, mat); brushRender.RenderBrush(paintContext, mat, 0); } } } } return(true); }
public override bool OnPaint(Terrain terrain, IOnPaint editContext) { commonUI.OnPaint(terrain, editContext); if (commonUI.allowPaint) { Texture brushTexture = editContext.brushTexture; using (IBrushRenderUnderCursor brushRender = new BrushRenderUIGroupUnderCursor(commonUI, "Twist", brushTexture)) { if (brushRender.CalculateBrushTransform(out BrushTransform brushXform)) { float finalTwistAmount = m_TwistAmount * -0.001f; //scale to a reasonable value and negate so default mode is clockwise if (Event.current.shift) { finalTwistAmount *= -1.0f; } Material mat = GetPaintMaterial(); Vector4 brushParams = new Vector4(commonUI.brushStrength, 0.0f, finalTwistAmount, 0.0f); mat.SetTexture("_BrushTex", editContext.brushTexture); mat.SetVector("_BrushParams", brushParams); //twist splat map if (m_AffectMaterials) { for (int i = 0; i < terrain.terrainData.terrainLayers.Length; i++) { TerrainLayer layer = terrain.terrainData.terrainLayers[i]; PaintContext paintContext = brushRender.AcquireTexture(true, brushXform.GetBrushXYBounds(), layer); 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(paintContext.sourceRenderTexture.width, paintContext.sourceRenderTexture.height); RenderTexture filterMaskRT = commonUI.GetBrushMask(fc, paintContext.sourceRenderTexture); mat.SetTexture("_FilterTex", filterMaskRT); paintContext.sourceRenderTexture.filterMode = FilterMode.Bilinear; brushRender.SetupTerrainToolMaterialProperties(paintContext, brushXform, mat); brushRender.RenderBrush(paintContext, mat, 0); brushRender.Release(paintContext); } } //twist height map if (m_AffectHeight) { PaintContext paintContext = brushRender.AcquireHeightmap(true, brushXform.GetBrushXYBounds(), 1); 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(paintContext.sourceRenderTexture.width, paintContext.sourceRenderTexture.height); RenderTexture filterMaskRT = commonUI.GetBrushMask(fc, paintContext.sourceRenderTexture); mat.SetTexture("_FilterTex", filterMaskRT); paintContext.sourceRenderTexture.filterMode = FilterMode.Bilinear; ApplyBrushInternal(brushRender, paintContext, commonUI.brushStrength, finalTwistAmount, brushTexture, brushXform); brushRender.Release(paintContext); } } } } return(false); }
protected override void OnEval(FilterContext filterContext, RenderTexture source, RenderTexture dest) { FilterUtility.builtinMaterial.SetFloat("_Add", value); Graphics.Blit(source, dest, FilterUtility.builtinMaterial, (int)FilterUtility.BuiltinPasses.Add); }
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; }
//=================================================================================================== // // APPLY BRUSH // //=================================================================================================== private void ApplyBrushInternal(Terrain terrain, 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); Vector3 brushPos = new Vector3(commonUI.raycastHitUnderCursor.point.x, 0, commonUI.raycastHitUnderCursor.point.z); FilterContext fc = new FilterContext(terrain, brushPos, brushSize, brushRotation); fc.renderTextureCollection.GatherRenderTextures(ctx.sourceRenderTexture.width, ctx.sourceRenderTexture.height); RenderTexture filterMaskRT = commonUI.GetBrushMask(fc, ctx.sourceRenderTexture); // 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.SetTexture("_FilterTex", filterMaskRT); matFinal.SetVector("_WorldHeightRemap", m_toolSettings.worldHeightRemap); Graphics.Blit(ctx.sourceRenderTexture, ctx.destinationRenderTexture, matFinal, 0); RenderTexture.ReleaseTemporary(noiseRT); }
protected override void OnEval(FilterContext fc, RenderTexture sourceRenderTexture, RenderTexture destinationRenderTexture) { FilterUtility.builtinMaterial.SetFloat("_Min", value); Graphics.Blit(sourceRenderTexture, destinationRenderTexture, FilterUtility.builtinMaterial, ( int )FilterUtility.BuiltinPasses.Min); }
protected override void OnDrawGUI(Rect rect, FilterContext filterContext) { range = EditorGUI.Vector2Field(rect, "", range); }
public override void Eval(FilterContext fc) { Graphics.Blit(fc.sourceRenderTexture, fc.destinationRenderTexture, FilterUtility.builtinMaterial, ( int )FilterUtility.BuiltinPasses.Negate); }
public override void Eval(FilterContext fc) { FilterUtility.builtinMaterial.SetFloat("_Max", value); Graphics.Blit(fc.sourceRenderTexture, fc.destinationRenderTexture, FilterUtility.builtinMaterial, ( int )FilterUtility.BuiltinPasses.Max); }
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); }