From 10bde21ee0f5e07792e4e4dd5e0f79ae9d6a9f59 Mon Sep 17 00:00:00 2001 From: Thomas Tu Date: Tue, 24 Feb 2026 09:05:33 -0500 Subject: [PATCH 01/10] Add dedicated render pass to render the selection picker lookup texture on URP --- Content/Shader/EdgePickerURP.shader | 65 +++++++ Content/Shader/EdgePickerURP.shader.meta | 9 + Content/Shader/FacePickerURP.shader | 73 ++++++++ Content/Shader/FacePickerURP.shader.meta | 9 + Content/Shader/ProBuilderCG_URP.cginc | 71 ++++++++ Content/Shader/VertexPickerURP.shader | 79 ++++++++ Content/Shader/VertexPickerURP.shader.meta | 9 + Runtime/Core/SelectionPickerRendererURP.cs | 169 ++++++++++++++++++ .../Core/SelectionPickerRendererURP.cs.meta | 2 + Runtime/Core/URPSelectionPickerPass.cs | 105 +++++++++++ Runtime/Core/URPSelectionPickerPass.cs.meta | 2 + .../Core/URPSelectionPickerRenderFeature.cs | 23 +++ .../URPSelectionPickerRenderFeature.cs.meta | 2 + 13 files changed, 618 insertions(+) create mode 100644 Content/Shader/EdgePickerURP.shader create mode 100644 Content/Shader/EdgePickerURP.shader.meta create mode 100644 Content/Shader/FacePickerURP.shader create mode 100644 Content/Shader/FacePickerURP.shader.meta create mode 100644 Content/Shader/ProBuilderCG_URP.cginc create mode 100644 Content/Shader/VertexPickerURP.shader create mode 100644 Content/Shader/VertexPickerURP.shader.meta create mode 100644 Runtime/Core/SelectionPickerRendererURP.cs create mode 100644 Runtime/Core/SelectionPickerRendererURP.cs.meta create mode 100644 Runtime/Core/URPSelectionPickerPass.cs create mode 100644 Runtime/Core/URPSelectionPickerPass.cs.meta create mode 100644 Runtime/Core/URPSelectionPickerRenderFeature.cs create mode 100644 Runtime/Core/URPSelectionPickerRenderFeature.cs.meta diff --git a/Content/Shader/EdgePickerURP.shader b/Content/Shader/EdgePickerURP.shader new file mode 100644 index 000000000..a967eb388 --- /dev/null +++ b/Content/Shader/EdgePickerURP.shader @@ -0,0 +1,65 @@ +Shader "Hidden/ProBuilder/EdgePickerURP" +{ + Properties {} + + SubShader + { + Tags + { + "ProBuilderPicker"="EdgePass" + "RenderType"="Opaque" + "RenderPipeline"="UniversalPipeline" + "Queue"="Geometry" + "IgnoreProjector"="True" + "DisableBatching"="True" + } + + Pass + { + Name "Edges" + // Tags { "LightMode"="SRPDefaultUnlit" } + Tags { "LightMode"="ProBuilderPickerA" } + ZTest LEqual + ZWrite On + Cull Off + Blend Off + + HLSLPROGRAM + #pragma vertex vert + #pragma fragment frag + + #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl" + #include "ProBuilderCG_URP.cginc" + + struct Attributes + { + float4 positionOS : POSITION; + float4 color : COLOR; + }; + + struct Varyings + { + float4 positionCS : SV_POSITION; + float4 color : COLOR; + }; + + Varyings vert(Attributes input) + { + Varyings output; + + output.positionCS = UnityObjectToClipPosWithOffset(input.positionOS.xyz); + output.color = input.color; + return output; + } + + half4 frag(Varyings input) : SV_Target + { + clip(input.color.a - 0.75); + return input.color; + } + ENDHLSL + } + } + + Fallback "Hidden/ProBuilder/EdgePicker" +} diff --git a/Content/Shader/EdgePickerURP.shader.meta b/Content/Shader/EdgePickerURP.shader.meta new file mode 100644 index 000000000..97dfba536 --- /dev/null +++ b/Content/Shader/EdgePickerURP.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 5a6aaaf03bf583c4e9adee705d3255d7 +ShaderImporter: + externalObjects: {} + defaultTextures: [] + nonModifiableTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Content/Shader/FacePickerURP.shader b/Content/Shader/FacePickerURP.shader new file mode 100644 index 000000000..8f6bda313 --- /dev/null +++ b/Content/Shader/FacePickerURP.shader @@ -0,0 +1,73 @@ +Shader "Hidden/ProBuilder/FacePickerURP" +{ + Properties + { + _Tint ("Picker Color", Color) = (1,1,1,1) + } + + SubShader + { + Tags + { + "ProBuilderPicker"="Base" + "RenderType"="Opaque" + "RenderPipeline"="UniversalPipeline" + "Queue"="Geometry" + "DisableBatching"="True" + } + + Pass + { + Name "Base" + // Tags { "LightMode"="SRPDefaultUnlit" } + Tags { "LightMode"="ProBuilderPickerA" } + ZTest LEqual + ZWrite On + Cull Off + Blend Off + + HLSLPROGRAM + #pragma vertex vert + #pragma fragment frag + + #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl" + #include "ProBuilderCG_URP.cginc" + + CBUFFER_START(UnityPerMaterial) + float4 _Tint; + CBUFFER_END + + struct Attributes + { + float4 positionOS : POSITION; + float4 color : COLOR; + }; + + struct Varyings + { + float4 positionCS : SV_POSITION; + float4 color : COLOR; + }; + + Varyings vert(Attributes input) + { + Varyings output; + VertexPositionInputs positions = GetVertexPositionInputs(input.positionOS); + + output.positionCS = positions.positionCS; + output.color = input.color; + + return output; + } + + half4 frag(Varyings input) : SV_Target + { + return input.color; + } + ENDHLSL + } + } + + // Fallback to built-in renderer version + Fallback "Hidden/ProBuilder/VertexPicker" +} diff --git a/Content/Shader/FacePickerURP.shader.meta b/Content/Shader/FacePickerURP.shader.meta new file mode 100644 index 000000000..d80f61b10 --- /dev/null +++ b/Content/Shader/FacePickerURP.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 9cb691ed12f573842860b94cad8331e1 +ShaderImporter: + externalObjects: {} + defaultTextures: [] + nonModifiableTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Content/Shader/ProBuilderCG_URP.cginc b/Content/Shader/ProBuilderCG_URP.cginc new file mode 100644 index 000000000..3f1f69b0a --- /dev/null +++ b/Content/Shader/ProBuilderCG_URP.cginc @@ -0,0 +1,71 @@ +// ProBuilderCG_URP.cginc - URP-compatible version of ProBuilderCG.cginc +// Must be included AFTER: #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl" +// so that TransformObjectToWorld, TransformWorldToView, UNITY_MATRIX_P, unity_OrthoParams are available. + +// Is the camera in orthographic mode? (1 yes, 0 no) +#define ORTHO (1 - UNITY_MATRIX_P[3][3]) + +// How far to pull vertices towards camera in orthographic mode +const float ORTHO_CAM_OFFSET = .0001; + +inline float3 UnityObjectToViewPosURP(float3 pos) +{ + return TransformWorldToView(TransformObjectToWorld(pos)); +} + +inline float4 ClipToScreen(float4 v) +{ + v.xy /= v.w; + v.xy = v.xy * .5 + .5; + v.xy *= _ScreenParams.xy; + return v; +} + +inline float4 ScreenToClip(float4 v) +{ + v.z -= ORTHO_CAM_OFFSET * ORTHO; + v.xy /= _ScreenParams.xy; + v.xy = (v.xy - .5) / .5; + v.xy *= v.w; + return v; +} + +inline float4 UnityObjectToClipPosWithOffset(float3 pos) +{ + float4 ret = float4(UnityObjectToViewPosURP(pos), 1); + //Offsetting the edges to avoid z-fighting problems + //Do not offset when using orthographic camera as XY are + //screen coords, this would shift the rendering + ret.xyz *= lerp(.99, 1, unity_OrthoParams.w); + //Moving edges closer + //.99 is not sufficient for Orthographic Camera + ret.z *= lerp(1, 0.95, unity_OrthoParams.w); + return mul(UNITY_MATRIX_P, ret); +} + +inline float4 UnityObjectToClipPosWithOffsetMetal(float3 pos) +{ + float4 ret = float4(UnityObjectToViewPosURP(pos), 1); + ret *= lerp(.99, .95, ORTHO); + return mul(UNITY_MATRIX_P, ret); +} + +inline float4 GetPickerColor(float4 pos, float2 texcoord1) +{ + // convert vertex to screen space, add pixel-unit xy to vertex, then transform back to clip space. + float4 clip = pos; + + clip.xy /= clip.w; + clip.xy = clip.xy * .5 + .5; + clip.xy *= _ScreenParams.xy; + + clip.xy += texcoord1.xy * 3.5; + clip.z -= .0001 * (1 - UNITY_MATRIX_P[3][3]); + + clip.xy /= _ScreenParams.xy; + clip.xy = (clip.xy - .5) / .5; + clip.xy *= clip.w; + + return clip; +} + diff --git a/Content/Shader/VertexPickerURP.shader b/Content/Shader/VertexPickerURP.shader new file mode 100644 index 000000000..9f5dd8666 --- /dev/null +++ b/Content/Shader/VertexPickerURP.shader @@ -0,0 +1,79 @@ +Shader "Hidden/ProBuilder/VertexPickerURP" +{ + Properties {} + + SubShader + { + Tags + { + "ProBuilderPicker"="VertexPass" + "RenderType"="Opaque" + "RenderPipeline"="UniversalPipeline" + "Queue"="Geometry" + "IgnoreProjector"="True" + "DisableBatching"="True" + } + + Pass + { + Name "Vertices" + // Tags { "LightMode"="SRPDefaultUnlit" } + Tags { "LightMode"="ProBuilderPickerA" } + + ZTest LEqual + ZWrite On + Cull Off + Blend Off + Offset -1, -1 + + HLSLPROGRAM + #pragma vertex vert + #pragma fragment frag + + #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl" + #include "ProBuilderCG_URP.cginc" + + struct Attributes + { + float4 positionOS : POSITION; + float3 normalOS : NORMAL; + float4 color : COLOR; + float2 uv0 : TEXCOORD0; + float2 uv1 : TEXCOORD1; + }; + + struct Varyings + { + float4 positionCS : SV_POSITION; + float2 uv : TEXCOORD0; + float4 color : COLOR; + }; + + Varyings vert(Attributes input) + { + Varyings output; + + float3 positionWS = TransformObjectToWorld(input.positionOS.xyz); + float3 positionVS = TransformWorldToView(positionWS); + + output.positionCS = float4(positionVS, 1); + output.positionCS.xyz *= lerp(0.99, 0.95, ORTHO); + output.positionCS = mul(UNITY_MATRIX_P, output.positionCS); + + output.positionCS = GetPickerColor(output.positionCS, input.uv1); + output.uv = input.uv0.xy; + output.color = input.color; + + return output; + } + + half4 frag(Varyings input) : SV_Target + { + return input.color; + } + ENDHLSL + } + } + + Fallback "Hidden/ProBuilder/VertexPicker" +} diff --git a/Content/Shader/VertexPickerURP.shader.meta b/Content/Shader/VertexPickerURP.shader.meta new file mode 100644 index 000000000..ad3833d40 --- /dev/null +++ b/Content/Shader/VertexPickerURP.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 488491a14dff2924db58a2ddc0b9e26f +ShaderImporter: + externalObjects: {} + defaultTextures: [] + nonModifiableTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Runtime/Core/SelectionPickerRendererURP.cs b/Runtime/Core/SelectionPickerRendererURP.cs new file mode 100644 index 000000000..da6bd9162 --- /dev/null +++ b/Runtime/Core/SelectionPickerRendererURP.cs @@ -0,0 +1,169 @@ +using UnityEditor; +using UnityEngine.Rendering; +using UObject = UnityEngine.Object; +using static UnityEngine.Rendering.RenderPipeline; + +#if URP_7_1_0_OR_NEWER +using UnityEngine.Rendering.Universal; +#endif + +namespace UnityEngine.ProBuilder +{ + internal partial class SelectionPickerRenderer + { + + internal class SelectionPickerRendererURP : ISelectionPickerRenderer + { + public static Camera temporaryCamera; + + /// + /// Render the camera with a replacement shader and return the resulting image. + /// RenderTexture is always initialized with no gamma conversion (RenderTextureReadWrite.Linear) + /// + /// + /// + /// + /// + /// + /// + public Texture2D RenderLookupTexture( + Camera camera, + Shader shader, + string tag, + int width = -1, + int height = -1) + { +#if URP_7_1_0_OR_NEWER + bool autoSize = width < 0 || height < 0; + + int _width = autoSize ? (int)camera.pixelRect.width : width; + int _height = autoSize ? (int)camera.pixelRect.height : height; + + GameObject go = new GameObject(); + Camera renderCam = go.AddComponent(); + temporaryCamera = renderCam; + renderCam.CopyFrom(camera); + + renderCam.renderingPath = RenderingPath.Forward; + renderCam.enabled = false; + renderCam.clearFlags = CameraClearFlags.SolidColor; + renderCam.backgroundColor = Color.white; + renderCam.allowHDR = false; + renderCam.allowMSAA = false; + renderCam.forceIntoRenderTexture = true; + + renderCam.GetUniversalAdditionalCameraData(); + + RenderTextureDescriptor descriptor = new RenderTextureDescriptor() + { + width = _width, + height = _height, + colorFormat = renderTextureFormat, + autoGenerateMips = false, + depthBufferBits = 16, + dimension = UnityEngine.Rendering.TextureDimension.Tex2D, + enableRandomWrite = false, + memoryless = RenderTextureMemoryless.None, + sRGB = false, + useMipMap = false, + volumeDepth = 1, + msaaSamples = 1 + }; + + + RenderTexture rt = RenderTexture.GetTemporary(descriptor); +#if PB_DEBUG + /* Debug.Log(string.Format("antiAliasing {0}\nautoGenerateMips {1}\ncolorBuffer {2}\ndepth {3}\ndepthBuffer {4}\ndimension {5}\nenableRandomWrite {6}\nformat {7}\nheight {8}\nmemorylessMode {9}\nsRGB {10}\nuseMipMap {11}\nvolumeDepth {12}\nwidth {13}", + RenderTexture.active.antiAliasing, + RenderTexture.active.autoGenerateMips, + RenderTexture.active.colorBuffer, + RenderTexture.active.depth, + RenderTexture.active.depthBuffer, + RenderTexture.active.dimension, + RenderTexture.active.enableRandomWrite, + RenderTexture.active.format, + RenderTexture.active.height, + RenderTexture.active.memorylessMode, + RenderTexture.active.sRGB, + RenderTexture.active.useMipMap, + RenderTexture.active.volumeDepth, + RenderTexture.active.width)); + */ +#endif + var request = new StandardRequest() + { + destination = rt + }; + RenderPipelineManager.beginCameraRendering += CustomRenderPass1; + + if (RenderPipeline.SupportsRenderRequest(renderCam, request) == false) + Debug.LogWarning("RenderRequest not supported."); + + RenderPipeline.SubmitRenderRequest(renderCam, request); + RenderTexture prev = RenderTexture.active; + RenderTexture.active = rt; + + Texture2D img = new Texture2D(_width, _height, textureFormat, false, false); + img.ReadPixels(new Rect(0, 0, _width, _height), 0, 0); + img.Apply(); + //FlipTexture2DVertical(img); + + SaveTexture(img, "Assets/Tmp/SelectionPickerTexture.png"); + + RenderTexture.active = prev; + RenderTexture.ReleaseTemporary(rt); + RenderPipelineManager.beginCameraRendering -= CustomRenderPass1; + temporaryCamera = null; + UObject.DestroyImmediate(go); + + return img; +#else + return null; +#endif + } + + /// Flips the texture vertically in place (swap rows). + static void FlipTexture2DVertical(Texture2D tex) + { + int w = tex.width; + int h = tex.height; + Color[] pixels = tex.GetPixels(); + for (int y = 0; y < h / 2; y++) + { + int top = y * w; + int bot = (h - 1 - y) * w; + for (int x = 0; x < w; x++) + { + var t = pixels[top + x]; + pixels[top + x] = pixels[bot + x]; + pixels[bot + x] = t; + } + } + tex.SetPixels(pixels); + tex.Apply(); + } + + internal static bool SaveTexture(Texture2D texture, string path) + { + byte[] bytes = texture.EncodeToPNG(); + + if (string.IsNullOrEmpty(path)) + return false; + + System.IO.File.WriteAllBytes(path, bytes); + AssetDatabase.Refresh(); + return true; + } + + static void CustomRenderPass1(ScriptableRenderContext ctx, Camera camera) + { + if (camera != temporaryCamera) + return; + var customPass = new URPSelectionPickerPass(-1); + customPass.renderPassEvent = RenderPassEvent.AfterRendering; + + camera.GetUniversalAdditionalCameraData().scriptableRenderer.EnqueuePass(customPass); + } + } + } +} diff --git a/Runtime/Core/SelectionPickerRendererURP.cs.meta b/Runtime/Core/SelectionPickerRendererURP.cs.meta new file mode 100644 index 000000000..3981e7621 --- /dev/null +++ b/Runtime/Core/SelectionPickerRendererURP.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 10d0f8b62703b4d48a0f6af6b6773163 \ No newline at end of file diff --git a/Runtime/Core/URPSelectionPickerPass.cs b/Runtime/Core/URPSelectionPickerPass.cs new file mode 100644 index 000000000..483417cd8 --- /dev/null +++ b/Runtime/Core/URPSelectionPickerPass.cs @@ -0,0 +1,105 @@ +using System.Collections.Generic; +using UnityEngine; +using UnityEngine.Rendering; +using UnityEngine.Rendering.RenderGraphModule; +using UnityEngine.Rendering.Universal; + +namespace UnityEngine.ProBuilder +{ + class URPSelectionPickerPass : ScriptableRenderPass + { + // Layer mask used to filter objects to put in the renderer list. + private LayerMask m_LayerMask; + + // List of shader tags used to build the renderer list. + private List m_ShaderTagIdList = new List(); + + public URPSelectionPickerPass(LayerMask layerMask) + { + m_LayerMask = layerMask; + } + + // This class stores the data needed by the pass, passed as parameter to the delegate function that executes the pass. + private class PassData + { + public RendererListHandle rendererListHandle; + } + + // Sample utility method that showcases how to create a renderer list via the RenderGraph API. + private void InitRendererLists(ContextContainer frameData, ref PassData passData, RenderGraph renderGraph) + { + // Access the relevant frame data from the Universal Render Pipeline. + UniversalRenderingData universalRenderingData = frameData.Get(); + UniversalCameraData cameraData = frameData.Get(); + UniversalLightData lightData = frameData.Get(); + + var sortFlags = cameraData.defaultOpaqueSortFlags; + RenderQueueRange renderQueueRange = RenderQueueRange.opaque; + FilteringSettings filterSettings = new FilteringSettings(renderQueueRange, m_LayerMask); + + ShaderTagId[] forwardOnlyShaderTagIds = new ShaderTagId[] + { + new ShaderTagId("ProBuilderPickerA"), + //new ShaderTagId("UniversalForwardOnly"), + //new ShaderTagId("UniversalForward"), + //new ShaderTagId("SRPDefaultUnlit"), // Legacy shaders (do not have a gbuffer pass) are considered forward-only for backward compatibility. + //new ShaderTagId("LightweightForward") // Legacy shaders (do not have a gbuffer pass) are considered forward-only for backward compatibility. + }; + + m_ShaderTagIdList.Clear(); + + foreach (ShaderTagId sid in forwardOnlyShaderTagIds) + m_ShaderTagIdList.Add(sid); + + DrawingSettings drawSettings = RenderingUtils.CreateDrawingSettings(m_ShaderTagIdList, + universalRenderingData, cameraData, lightData, sortFlags); + + var param = new RendererListParams(universalRenderingData.cullResults, drawSettings, filterSettings); + passData.rendererListHandle = renderGraph.CreateRendererList(param); + } + + // This static method is used to execute the pass and passed as the RenderFunc delegate to the RenderGraph render pass. + static void ExecutePass(PassData data, RasterGraphContext context) + { + context.cmd.ClearRenderTarget(RTClearFlags.Color, Color.white, 1, 0); + + context.cmd.DrawRendererList(data.rendererListHandle); + } + + // This is where the renderGraph handle can be accessed. + // Each ScriptableRenderPass can use the RenderGraph handle to add multiple render passes to the render graph. + public override void RecordRenderGraph(RenderGraph renderGraph, ContextContainer frameData) + { + string passName = "Custom Render Pass"; + + // This simple pass clears the current active color texture, then renders the scene geometry associated to the m_LayerMask layer. + // Add scene geometry to your own custom layers and experiment switching the layer mask in the render feature UI. + // You can use the frame debugger to inspect the pass output. + + // add a raster render pass to the render graph, specifying the name and the data type that will be passed to the ExecutePass function + using (var builder = renderGraph.AddRasterRenderPass(passName, out var passData)) + { + // UniversalResourceData contains all the texture handles used by the renderer, including the active color and depth textures + // The active color and depth textures are the main color and depth buffers that the camera renders into. + UniversalResourceData resourceData = frameData.Get(); + + // Fill up the passData with the data needed by the pass. + InitRendererLists(frameData, ref passData, renderGraph); + + // Optional check to make sure the rendererList is valid. If it isn't, the pass will not execute (instead of the render graph possibly throwing an error). + if (!passData.rendererListHandle.IsValid()) + return; + + // We declare the RendererList we just created as an input dependency to this pass, via UseRendererList(). + builder.UseRendererList(passData.rendererListHandle); + + // Setup as a render target via UseTextureFragment and UseTextureFragmentDepth, which are the equivalent of using the old cmd.SetRenderTarget(color,depth) + builder.SetRenderAttachment(resourceData.activeColorTexture, 0); + builder.SetRenderAttachmentDepth(resourceData.activeDepthTexture, AccessFlags.Write); + + // Assign the ExecutePass function to the render pass delegate, which will be called by the render graph when executing the pass. + builder.SetRenderFunc(static (PassData data, RasterGraphContext context) => ExecutePass(data, context)); + } + } + } +} diff --git a/Runtime/Core/URPSelectionPickerPass.cs.meta b/Runtime/Core/URPSelectionPickerPass.cs.meta new file mode 100644 index 000000000..00f64d4a6 --- /dev/null +++ b/Runtime/Core/URPSelectionPickerPass.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: ab752184a0d6df845ae5fc6966304066 \ No newline at end of file diff --git a/Runtime/Core/URPSelectionPickerRenderFeature.cs b/Runtime/Core/URPSelectionPickerRenderFeature.cs new file mode 100644 index 000000000..c83af6b52 --- /dev/null +++ b/Runtime/Core/URPSelectionPickerRenderFeature.cs @@ -0,0 +1,23 @@ +using UnityEngine; +using UnityEngine.Rendering.Universal; + +namespace UnityEngine.ProBuilder +{ + class CustomPassFeature : ScriptableRendererFeature + { + URPSelectionPickerPass customPass; + public LayerMask m_LayerMask; + + + public override void Create() + { + customPass = new URPSelectionPickerPass(m_LayerMask); + customPass.renderPassEvent = RenderPassEvent.AfterRendering; + } + + public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData) + { + renderer.EnqueuePass(customPass); + } + } +} diff --git a/Runtime/Core/URPSelectionPickerRenderFeature.cs.meta b/Runtime/Core/URPSelectionPickerRenderFeature.cs.meta new file mode 100644 index 000000000..2f5866985 --- /dev/null +++ b/Runtime/Core/URPSelectionPickerRenderFeature.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: ec1254965d75036429e441b88861c535 \ No newline at end of file From 570fb5baa6f624271cee694b6fbf0bc69263821b Mon Sep 17 00:00:00 2001 From: Thomas Tu Date: Tue, 24 Feb 2026 10:10:50 -0500 Subject: [PATCH 02/10] Add code path to selection picker to handle URP --- Content/Resources/Materials/EdgePickerURP.mat | 60 +++++++++++++++++++ .../Materials/EdgePickerURP.mat.meta | 8 +++ Content/Resources/Materials/FacePickerURP.mat | 60 +++++++++++++++++++ .../Materials/FacePickerURP.mat.meta | 8 +++ .../Resources/Materials/VertexPickerURP.mat | 60 +++++++++++++++++++ .../Materials/VertexPickerURP.mat.meta | 8 +++ Runtime/Core/BuiltinMaterials.cs | 18 ++++-- Runtime/Core/SelectionPickerRenderer.cs | 15 ++++- Runtime/Core/URPSelectionPickerPass.cs | 14 +---- 9 files changed, 233 insertions(+), 18 deletions(-) create mode 100644 Content/Resources/Materials/EdgePickerURP.mat create mode 100644 Content/Resources/Materials/EdgePickerURP.mat.meta create mode 100644 Content/Resources/Materials/FacePickerURP.mat create mode 100644 Content/Resources/Materials/FacePickerURP.mat.meta create mode 100644 Content/Resources/Materials/VertexPickerURP.mat create mode 100644 Content/Resources/Materials/VertexPickerURP.mat.meta diff --git a/Content/Resources/Materials/EdgePickerURP.mat b/Content/Resources/Materials/EdgePickerURP.mat new file mode 100644 index 000000000..a56ae3c3e --- /dev/null +++ b/Content/Resources/Materials/EdgePickerURP.mat @@ -0,0 +1,60 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &-6385779826880740979 +MonoBehaviour: + m_ObjectHideFlags: 11 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: d0353a89b1f911e48b9e16bdc9f2e058, type: 3} + m_Name: + m_EditorClassIdentifier: Unity.RenderPipelines.Universal.Editor::UnityEditor.Rendering.Universal.AssetVersion + version: 10 +--- !u!21 &2100000 +Material: + serializedVersion: 8 + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: EdgePickerURP + m_Shader: {fileID: 4800000, guid: 5a6aaaf03bf583c4e9adee705d3255d7, type: 3} + m_Parent: {fileID: 0} + m_ModifiedSerializedProperties: 0 + m_ValidKeywords: [] + m_InvalidKeywords: [] + m_LightmapFlags: 5 + m_EnableInstancingVariants: 0 + m_DoubleSidedGI: 0 + m_CustomRenderQueue: -1 + stringTagMap: {} + disabledShaderPasses: + - MOTIONVECTORS + m_LockedProperties: + m_SavedProperties: + serializedVersion: 3 + m_TexEnvs: + - unity_Lightmaps: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - unity_LightmapsInd: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - unity_ShadowMasks: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + m_Ints: [] + m_Floats: + - _QueueControl: 0 + - _QueueOffset: 0 + m_Colors: + - _BaseColor: {r: 0, g: 0, b: 0, a: 1} + - _Tint: {r: 1, g: 0, b: 0, a: 1} + m_BuildTextureStacks: [] + m_AllowLocking: 1 diff --git a/Content/Resources/Materials/EdgePickerURP.mat.meta b/Content/Resources/Materials/EdgePickerURP.mat.meta new file mode 100644 index 000000000..b6a287698 --- /dev/null +++ b/Content/Resources/Materials/EdgePickerURP.mat.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 70d1a6407fa29bb44b936d5325490696 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 2100000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Content/Resources/Materials/FacePickerURP.mat b/Content/Resources/Materials/FacePickerURP.mat new file mode 100644 index 000000000..1641e54b6 --- /dev/null +++ b/Content/Resources/Materials/FacePickerURP.mat @@ -0,0 +1,60 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!21 &2100000 +Material: + serializedVersion: 8 + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: FacePickerURP + m_Shader: {fileID: 4800000, guid: 9cb691ed12f573842860b94cad8331e1, type: 3} + m_Parent: {fileID: 0} + m_ModifiedSerializedProperties: 0 + m_ValidKeywords: [] + m_InvalidKeywords: [] + m_LightmapFlags: 5 + m_EnableInstancingVariants: 0 + m_DoubleSidedGI: 0 + m_CustomRenderQueue: -1 + stringTagMap: {} + disabledShaderPasses: + - MOTIONVECTORS + m_LockedProperties: + m_SavedProperties: + serializedVersion: 3 + m_TexEnvs: + - unity_Lightmaps: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - unity_LightmapsInd: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - unity_ShadowMasks: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + m_Ints: [] + m_Floats: + - _QueueControl: 0 + - _QueueOffset: 0 + m_Colors: + - _BaseColor: {r: 0, g: 0, b: 0, a: 1} + - _Tint: {r: 1, g: 1, b: 1, a: 1} + m_BuildTextureStacks: [] + m_AllowLocking: 1 +--- !u!114 &4155378413201584216 +MonoBehaviour: + m_ObjectHideFlags: 11 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: d0353a89b1f911e48b9e16bdc9f2e058, type: 3} + m_Name: + m_EditorClassIdentifier: Unity.RenderPipelines.Universal.Editor::UnityEditor.Rendering.Universal.AssetVersion + version: 10 diff --git a/Content/Resources/Materials/FacePickerURP.mat.meta b/Content/Resources/Materials/FacePickerURP.mat.meta new file mode 100644 index 000000000..a98652630 --- /dev/null +++ b/Content/Resources/Materials/FacePickerURP.mat.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 0143c5b21b48c1643bc5417c60bbf848 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 2100000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Content/Resources/Materials/VertexPickerURP.mat b/Content/Resources/Materials/VertexPickerURP.mat new file mode 100644 index 000000000..f5f29bfe0 --- /dev/null +++ b/Content/Resources/Materials/VertexPickerURP.mat @@ -0,0 +1,60 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &-8161258857830796102 +MonoBehaviour: + m_ObjectHideFlags: 11 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: d0353a89b1f911e48b9e16bdc9f2e058, type: 3} + m_Name: + m_EditorClassIdentifier: Unity.RenderPipelines.Universal.Editor::UnityEditor.Rendering.Universal.AssetVersion + version: 10 +--- !u!21 &2100000 +Material: + serializedVersion: 8 + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: VertexPickerURP + m_Shader: {fileID: 4800000, guid: 488491a14dff2924db58a2ddc0b9e26f, type: 3} + m_Parent: {fileID: 0} + m_ModifiedSerializedProperties: 0 + m_ValidKeywords: [] + m_InvalidKeywords: [] + m_LightmapFlags: 5 + m_EnableInstancingVariants: 0 + m_DoubleSidedGI: 0 + m_CustomRenderQueue: -1 + stringTagMap: {} + disabledShaderPasses: + - MOTIONVECTORS + m_LockedProperties: + m_SavedProperties: + serializedVersion: 3 + m_TexEnvs: + - unity_Lightmaps: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - unity_LightmapsInd: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - unity_ShadowMasks: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + m_Ints: [] + m_Floats: + - _QueueControl: 0 + - _QueueOffset: 0 + m_Colors: + - _BaseColor: {r: 0, g: 0, b: 0, a: 1} + - _Tint: {r: 1, g: 0, b: 0, a: 1} + m_BuildTextureStacks: [] + m_AllowLocking: 1 diff --git a/Content/Resources/Materials/VertexPickerURP.mat.meta b/Content/Resources/Materials/VertexPickerURP.mat.meta new file mode 100644 index 000000000..557809505 --- /dev/null +++ b/Content/Resources/Materials/VertexPickerURP.mat.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: eae7185451278b54bb78d0d5ff3f9452 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 2100000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Runtime/Core/BuiltinMaterials.cs b/Runtime/Core/BuiltinMaterials.cs index 2772c75fb..0a7349186 100644 --- a/Runtime/Core/BuiltinMaterials.cs +++ b/Runtime/Core/BuiltinMaterials.cs @@ -69,13 +69,23 @@ public static class BuiltinMaterials static Material s_UnityDefaultDiffuse; static Material s_ShapePreviewMaterial; +#if URP_7_1_0_OR_NEWER + static string k_EdgePickerShader = "Hidden/ProBuilder/EdgePickerURP"; + static string k_VertexPickerShader = "Hidden/ProBuilder/VertexPickerURP"; + static string k_FacePickerShader = "Shader Graphs/FacePickerURP"; + + static string k_EdgePickerMaterial = "Materials/EdgePickerURP"; + static string k_FacePickerMaterial = "Materials/FacePickerURP"; + static string k_VertexPickerMaterial = "Materials/VertexPickerURP"; +#else + static string k_EdgePickerShader = "Hidden/ProBuilder/EdgePicker";; + static string k_FacePickerShader = "Hidden/ProBuilder/FacePicker"; + static string k_VertexPickerShader = "Hidden/ProBuilder/VertexPicker"; + static string k_EdgePickerMaterial = "Materials/EdgePicker"; static string k_FacePickerMaterial = "Materials/FacePicker"; static string k_VertexPickerMaterial = "Materials/VertexPicker"; - - static string k_EdgePickerShader = "Hidden/ProBuilder/EdgePicker"; - static string k_FacePickerShader = "Hidden/ProBuilder/FacePicker"; - static string k_VertexPickerShader = "Hidden/ProBuilder/VertexPicker"; +#endif static void Init() { diff --git a/Runtime/Core/SelectionPickerRenderer.cs b/Runtime/Core/SelectionPickerRenderer.cs index a0c1da16a..adb929122 100644 --- a/Runtime/Core/SelectionPickerRenderer.cs +++ b/Runtime/Core/SelectionPickerRenderer.cs @@ -165,9 +165,9 @@ static ISelectionPickerRenderer pickerRenderer { if (s_PickerRenderer == null) s_PickerRenderer = - ShouldUseHDRP()? - (ISelectionPickerRenderer)new SelectionPickerRendererHDRP() - : new SelectionPickerRendererStandard(); + ShouldUseHDRP() ? new SelectionPickerRendererHDRP() + : ShouldUseURP() ? new SelectionPickerRendererURP() + : new SelectionPickerRendererStandard(); return s_PickerRenderer; } } @@ -853,6 +853,15 @@ static bool ShouldUseHDRP() return true; #else return false; +#endif + } + + static bool ShouldUseURP() + { +#if URP_7_1_0_OR_NEWER + return true; +#else + return false; #endif } } diff --git a/Runtime/Core/URPSelectionPickerPass.cs b/Runtime/Core/URPSelectionPickerPass.cs index 483417cd8..c528ab0b2 100644 --- a/Runtime/Core/URPSelectionPickerPass.cs +++ b/Runtime/Core/URPSelectionPickerPass.cs @@ -8,15 +8,11 @@ namespace UnityEngine.ProBuilder { class URPSelectionPickerPass : ScriptableRenderPass { - // Layer mask used to filter objects to put in the renderer list. - private LayerMask m_LayerMask; - // List of shader tags used to build the renderer list. private List m_ShaderTagIdList = new List(); public URPSelectionPickerPass(LayerMask layerMask) { - m_LayerMask = layerMask; } // This class stores the data needed by the pass, passed as parameter to the delegate function that executes the pass. @@ -35,15 +31,11 @@ private void InitRendererLists(ContextContainer frameData, ref PassData passData var sortFlags = cameraData.defaultOpaqueSortFlags; RenderQueueRange renderQueueRange = RenderQueueRange.opaque; - FilteringSettings filterSettings = new FilteringSettings(renderQueueRange, m_LayerMask); + FilteringSettings filterSettings = new FilteringSettings(renderQueueRange, -1); ShaderTagId[] forwardOnlyShaderTagIds = new ShaderTagId[] { - new ShaderTagId("ProBuilderPickerA"), - //new ShaderTagId("UniversalForwardOnly"), - //new ShaderTagId("UniversalForward"), - //new ShaderTagId("SRPDefaultUnlit"), // Legacy shaders (do not have a gbuffer pass) are considered forward-only for backward compatibility. - //new ShaderTagId("LightweightForward") // Legacy shaders (do not have a gbuffer pass) are considered forward-only for backward compatibility. + new ShaderTagId("ProBuilderPickerA") }; m_ShaderTagIdList.Clear(); @@ -70,7 +62,7 @@ static void ExecutePass(PassData data, RasterGraphContext context) // Each ScriptableRenderPass can use the RenderGraph handle to add multiple render passes to the render graph. public override void RecordRenderGraph(RenderGraph renderGraph, ContextContainer frameData) { - string passName = "Custom Render Pass"; + string passName = "ProBuilder Selection Picker Pass"; // This simple pass clears the current active color texture, then renders the scene geometry associated to the m_LayerMask layer. // Add scene geometry to your own custom layers and experiment switching the layer mask in the render feature UI. From b6c5ab504864c0b045ad706d62895a6b66cb4a22 Mon Sep 17 00:00:00 2001 From: Thomas Tu Date: Tue, 24 Feb 2026 10:12:07 -0500 Subject: [PATCH 03/10] Add missing meta file --- Content/Shader/ProBuilderCG_URP.cginc.meta | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 Content/Shader/ProBuilderCG_URP.cginc.meta diff --git a/Content/Shader/ProBuilderCG_URP.cginc.meta b/Content/Shader/ProBuilderCG_URP.cginc.meta new file mode 100644 index 000000000..f776a271b --- /dev/null +++ b/Content/Shader/ProBuilderCG_URP.cginc.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: a4ae1db7ad643084b8270d7590883b2c +ShaderImporter: + externalObjects: {} + defaultTextures: [] + nonModifiableTextures: [] + userData: + assetBundleName: + assetBundleVariant: From e7ef43e52bdfdfb04cf758d813af8bc13fca2969 Mon Sep 17 00:00:00 2001 From: Thomas Tu Date: Tue, 24 Feb 2026 10:35:49 -0500 Subject: [PATCH 04/10] Update version define for URP + clean up --- Runtime/Core/BuiltinMaterials.cs | 4 +-- Runtime/Core/SelectionPickerRenderer.cs | 2 +- Runtime/Core/SelectionPickerRendererURP.cs | 32 +++---------------- Runtime/Core/URPSelectionPickerPass.cs | 3 +- .../Core/URPSelectionPickerRenderFeature.cs | 2 ++ Runtime/Unity.ProBuilder.asmdef | 10 +++++- 6 files changed, 20 insertions(+), 33 deletions(-) diff --git a/Runtime/Core/BuiltinMaterials.cs b/Runtime/Core/BuiltinMaterials.cs index 0a7349186..57f5e1933 100644 --- a/Runtime/Core/BuiltinMaterials.cs +++ b/Runtime/Core/BuiltinMaterials.cs @@ -69,7 +69,7 @@ public static class BuiltinMaterials static Material s_UnityDefaultDiffuse; static Material s_ShapePreviewMaterial; -#if URP_7_1_0_OR_NEWER +#if PB_URP_MODE static string k_EdgePickerShader = "Hidden/ProBuilder/EdgePickerURP"; static string k_VertexPickerShader = "Hidden/ProBuilder/VertexPickerURP"; static string k_FacePickerShader = "Shader Graphs/FacePickerURP"; @@ -78,7 +78,7 @@ public static class BuiltinMaterials static string k_FacePickerMaterial = "Materials/FacePickerURP"; static string k_VertexPickerMaterial = "Materials/VertexPickerURP"; #else - static string k_EdgePickerShader = "Hidden/ProBuilder/EdgePicker";; + static string k_EdgePickerShader = "Hidden/ProBuilder/EdgePicker"; static string k_FacePickerShader = "Hidden/ProBuilder/FacePicker"; static string k_VertexPickerShader = "Hidden/ProBuilder/VertexPicker"; diff --git a/Runtime/Core/SelectionPickerRenderer.cs b/Runtime/Core/SelectionPickerRenderer.cs index adb929122..ab209e02f 100644 --- a/Runtime/Core/SelectionPickerRenderer.cs +++ b/Runtime/Core/SelectionPickerRenderer.cs @@ -858,7 +858,7 @@ static bool ShouldUseHDRP() static bool ShouldUseURP() { -#if URP_7_1_0_OR_NEWER +#if PB_URP_MODE return true; #else return false; diff --git a/Runtime/Core/SelectionPickerRendererURP.cs b/Runtime/Core/SelectionPickerRendererURP.cs index da6bd9162..4ae6ca100 100644 --- a/Runtime/Core/SelectionPickerRendererURP.cs +++ b/Runtime/Core/SelectionPickerRendererURP.cs @@ -1,10 +1,10 @@ using UnityEditor; using UnityEngine.Rendering; -using UObject = UnityEngine.Object; -using static UnityEngine.Rendering.RenderPipeline; -#if URP_7_1_0_OR_NEWER +#if PB_URP_MODE using UnityEngine.Rendering.Universal; +using UObject = UnityEngine.Object; +using static UnityEngine.Rendering.RenderPipeline; #endif namespace UnityEngine.ProBuilder @@ -33,7 +33,7 @@ public Texture2D RenderLookupTexture( int width = -1, int height = -1) { -#if URP_7_1_0_OR_NEWER +#if PB_URP_MODE bool autoSize = width < 0 || height < 0; int _width = autoSize ? (int)camera.pixelRect.width : width; @@ -106,9 +106,6 @@ public Texture2D RenderLookupTexture( Texture2D img = new Texture2D(_width, _height, textureFormat, false, false); img.ReadPixels(new Rect(0, 0, _width, _height), 0, 0); img.Apply(); - //FlipTexture2DVertical(img); - - SaveTexture(img, "Assets/Tmp/SelectionPickerTexture.png"); RenderTexture.active = prev; RenderTexture.ReleaseTemporary(rt); @@ -122,27 +119,6 @@ public Texture2D RenderLookupTexture( #endif } - /// Flips the texture vertically in place (swap rows). - static void FlipTexture2DVertical(Texture2D tex) - { - int w = tex.width; - int h = tex.height; - Color[] pixels = tex.GetPixels(); - for (int y = 0; y < h / 2; y++) - { - int top = y * w; - int bot = (h - 1 - y) * w; - for (int x = 0; x < w; x++) - { - var t = pixels[top + x]; - pixels[top + x] = pixels[bot + x]; - pixels[bot + x] = t; - } - } - tex.SetPixels(pixels); - tex.Apply(); - } - internal static bool SaveTexture(Texture2D texture, string path) { byte[] bytes = texture.EncodeToPNG(); diff --git a/Runtime/Core/URPSelectionPickerPass.cs b/Runtime/Core/URPSelectionPickerPass.cs index c528ab0b2..9533a31f7 100644 --- a/Runtime/Core/URPSelectionPickerPass.cs +++ b/Runtime/Core/URPSelectionPickerPass.cs @@ -1,5 +1,5 @@ +#if PB_URP_MODE using System.Collections.Generic; -using UnityEngine; using UnityEngine.Rendering; using UnityEngine.Rendering.RenderGraphModule; using UnityEngine.Rendering.Universal; @@ -95,3 +95,4 @@ public override void RecordRenderGraph(RenderGraph renderGraph, ContextContainer } } } +#endif diff --git a/Runtime/Core/URPSelectionPickerRenderFeature.cs b/Runtime/Core/URPSelectionPickerRenderFeature.cs index c83af6b52..876c59622 100644 --- a/Runtime/Core/URPSelectionPickerRenderFeature.cs +++ b/Runtime/Core/URPSelectionPickerRenderFeature.cs @@ -1,3 +1,4 @@ +#if PB_URP_MODE using UnityEngine; using UnityEngine.Rendering.Universal; @@ -21,3 +22,4 @@ public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingD } } } +#endif diff --git a/Runtime/Unity.ProBuilder.asmdef b/Runtime/Unity.ProBuilder.asmdef index adfece40c..89b3aebd5 100644 --- a/Runtime/Unity.ProBuilder.asmdef +++ b/Runtime/Unity.ProBuilder.asmdef @@ -1,9 +1,12 @@ { "name": "Unity.ProBuilder", + "rootNamespace": "", "references": [ "Unity.ProBuilder.Poly2Tri", "Unity.ProBuilder.KdTree", - "Unity.RenderPipelines.HighDefinition.Runtime" + "Unity.RenderPipelines.HighDefinition.Runtime", + "Unity.RenderPipelines.Universal.Runtime", + "Unity.RenderPipelines.Core.Runtime" ], "includePlatforms": [], "excludePlatforms": [], @@ -22,6 +25,11 @@ "name": "com.unity.modules.particlesystem", "expression": "1.0.0", "define": "USING_PARTICLE_SYSTEM" + }, + { + "name": "com.unity.render-pipelines.universal", + "expression": "17.0.0", + "define": "PB_URP_MODE" } ], "noEngineReferences": false From 345a070885f0ffbee1994bf6749400b1ae4295e1 Mon Sep 17 00:00:00 2001 From: Thomas Tu Date: Tue, 24 Feb 2026 15:36:49 -0500 Subject: [PATCH 05/10] Fix compiler issue + shader clean up --- Content/Shader/EdgePickerURP.shader | 1 - Content/Shader/FacePickerURP.shader | 2 +- Content/Shader/ProBuilderCG_URP.cginc | 21 ++++++++++----------- Content/Shader/VertexPickerURP.shader | 9 +-------- Runtime/Core/SelectionPickerRendererURP.cs | 20 +++++--------------- 5 files changed, 17 insertions(+), 36 deletions(-) diff --git a/Content/Shader/EdgePickerURP.shader b/Content/Shader/EdgePickerURP.shader index a967eb388..d226a9bf1 100644 --- a/Content/Shader/EdgePickerURP.shader +++ b/Content/Shader/EdgePickerURP.shader @@ -46,7 +46,6 @@ Shader "Hidden/ProBuilder/EdgePickerURP" Varyings vert(Attributes input) { Varyings output; - output.positionCS = UnityObjectToClipPosWithOffset(input.positionOS.xyz); output.color = input.color; return output; diff --git a/Content/Shader/FacePickerURP.shader b/Content/Shader/FacePickerURP.shader index 8f6bda313..043f0249d 100644 --- a/Content/Shader/FacePickerURP.shader +++ b/Content/Shader/FacePickerURP.shader @@ -52,7 +52,7 @@ Shader "Hidden/ProBuilder/FacePickerURP" Varyings vert(Attributes input) { Varyings output; - VertexPositionInputs positions = GetVertexPositionInputs(input.positionOS); + VertexPositionInputs positions = GetVertexPositionInputs(input.positionOS.xyz); output.positionCS = positions.positionCS; output.color = input.color; diff --git a/Content/Shader/ProBuilderCG_URP.cginc b/Content/Shader/ProBuilderCG_URP.cginc index 3f1f69b0a..a14197ede 100644 --- a/Content/Shader/ProBuilderCG_URP.cginc +++ b/Content/Shader/ProBuilderCG_URP.cginc @@ -8,11 +8,6 @@ // How far to pull vertices towards camera in orthographic mode const float ORTHO_CAM_OFFSET = .0001; -inline float3 UnityObjectToViewPosURP(float3 pos) -{ - return TransformWorldToView(TransformObjectToWorld(pos)); -} - inline float4 ClipToScreen(float4 v) { v.xy /= v.w; @@ -30,22 +25,26 @@ inline float4 ScreenToClip(float4 v) return v; } -inline float4 UnityObjectToClipPosWithOffset(float3 pos) +inline float4 UnityObjectToClipPosWithOffset(float3 positionOS) { - float4 ret = float4(UnityObjectToViewPosURP(pos), 1); + VertexPositionInputs positions = GetVertexPositionInputs(positionOS); + + float4 ret = float4(positions.positionVS, 1); //Offsetting the edges to avoid z-fighting problems //Do not offset when using orthographic camera as XY are //screen coords, this would shift the rendering - ret.xyz *= lerp(.99, 1, unity_OrthoParams.w); + ret.xyz *= lerp(0.99, 0.95, ORTHO); //Moving edges closer //.99 is not sufficient for Orthographic Camera - ret.z *= lerp(1, 0.95, unity_OrthoParams.w); + ret.w *= lerp(1, 0.95, unity_OrthoParams.w); return mul(UNITY_MATRIX_P, ret); } -inline float4 UnityObjectToClipPosWithOffsetMetal(float3 pos) +inline float4 UnityObjectToClipPosWithOffsetMetal(float3 positionOS) { - float4 ret = float4(UnityObjectToViewPosURP(pos), 1); + VertexPositionInputs positions = GetVertexPositionInputs(positionOS); + + float4 ret = float4(positions.positionVS, 1); ret *= lerp(.99, .95, ORTHO); return mul(UNITY_MATRIX_P, ret); } diff --git a/Content/Shader/VertexPickerURP.shader b/Content/Shader/VertexPickerURP.shader index 9f5dd8666..41f23f8a0 100644 --- a/Content/Shader/VertexPickerURP.shader +++ b/Content/Shader/VertexPickerURP.shader @@ -52,14 +52,7 @@ Shader "Hidden/ProBuilder/VertexPickerURP" Varyings vert(Attributes input) { Varyings output; - - float3 positionWS = TransformObjectToWorld(input.positionOS.xyz); - float3 positionVS = TransformWorldToView(positionWS); - - output.positionCS = float4(positionVS, 1); - output.positionCS.xyz *= lerp(0.99, 0.95, ORTHO); - output.positionCS = mul(UNITY_MATRIX_P, output.positionCS); - + output.positionCS = UnityObjectToClipPosWithOffset(input.positionOS.xyz); output.positionCS = GetPickerColor(output.positionCS, input.uv1); output.uv = input.uv0.xy; output.color = input.color; diff --git a/Runtime/Core/SelectionPickerRendererURP.cs b/Runtime/Core/SelectionPickerRendererURP.cs index 4ae6ca100..ca6e1abe3 100644 --- a/Runtime/Core/SelectionPickerRendererURP.cs +++ b/Runtime/Core/SelectionPickerRendererURP.cs @@ -94,7 +94,7 @@ public Texture2D RenderLookupTexture( { destination = rt }; - RenderPipelineManager.beginCameraRendering += CustomRenderPass1; + RenderPipelineManager.beginCameraRendering += CustomRenderPass; if (RenderPipeline.SupportsRenderRequest(renderCam, request) == false) Debug.LogWarning("RenderRequest not supported."); @@ -109,7 +109,7 @@ public Texture2D RenderLookupTexture( RenderTexture.active = prev; RenderTexture.ReleaseTemporary(rt); - RenderPipelineManager.beginCameraRendering -= CustomRenderPass1; + RenderPipelineManager.beginCameraRendering -= CustomRenderPass; temporaryCamera = null; UObject.DestroyImmediate(go); @@ -119,19 +119,8 @@ public Texture2D RenderLookupTexture( #endif } - internal static bool SaveTexture(Texture2D texture, string path) - { - byte[] bytes = texture.EncodeToPNG(); - - if (string.IsNullOrEmpty(path)) - return false; - - System.IO.File.WriteAllBytes(path, bytes); - AssetDatabase.Refresh(); - return true; - } - - static void CustomRenderPass1(ScriptableRenderContext ctx, Camera camera) +#if PB_URP_MODE + static void CustomRenderPass(ScriptableRenderContext ctx, Camera camera) { if (camera != temporaryCamera) return; @@ -140,6 +129,7 @@ static void CustomRenderPass1(ScriptableRenderContext ctx, Camera camera) camera.GetUniversalAdditionalCameraData().scriptableRenderer.EnqueuePass(customPass); } +#endif } } } From 2400a2bde2b81a5113d5c81068b48bfd062978e3 Mon Sep 17 00:00:00 2001 From: Thomas Tu Date: Mon, 2 Mar 2026 14:43:36 -0500 Subject: [PATCH 06/10] Set package requirement for URP shaders --- Content/Shader/EdgePickerURP.shader | 5 +++++ Content/Shader/FacePickerURP.shader | 5 +++++ Content/Shader/VertexPickerURP.shader | 5 +++++ 3 files changed, 15 insertions(+) diff --git a/Content/Shader/EdgePickerURP.shader b/Content/Shader/EdgePickerURP.shader index d226a9bf1..f7af9e2b6 100644 --- a/Content/Shader/EdgePickerURP.shader +++ b/Content/Shader/EdgePickerURP.shader @@ -4,6 +4,11 @@ Shader "Hidden/ProBuilder/EdgePickerURP" SubShader { + PackageRequirements + { + "com.unity.render-pipelines.universal": "17.0" + } + Tags { "ProBuilderPicker"="EdgePass" diff --git a/Content/Shader/FacePickerURP.shader b/Content/Shader/FacePickerURP.shader index 043f0249d..1568da56f 100644 --- a/Content/Shader/FacePickerURP.shader +++ b/Content/Shader/FacePickerURP.shader @@ -7,6 +7,11 @@ Shader "Hidden/ProBuilder/FacePickerURP" SubShader { + PackageRequirements + { + "com.unity.render-pipelines.universal": "17.0" + } + Tags { "ProBuilderPicker"="Base" diff --git a/Content/Shader/VertexPickerURP.shader b/Content/Shader/VertexPickerURP.shader index 41f23f8a0..66f6e2a3c 100644 --- a/Content/Shader/VertexPickerURP.shader +++ b/Content/Shader/VertexPickerURP.shader @@ -4,6 +4,11 @@ Shader "Hidden/ProBuilder/VertexPickerURP" SubShader { + PackageRequirements + { + "com.unity.render-pipelines.universal": "17.0" + } + Tags { "ProBuilderPicker"="VertexPass" From c9fe9bce5e487477ad0828b108743a3c79eb2cfe Mon Sep 17 00:00:00 2001 From: Thomas Tu Date: Wed, 4 Mar 2026 13:07:47 -0500 Subject: [PATCH 07/10] Fix FacePickerURP shader so it doesn't picked hidden faces --- Content/Shader/FacePickerURP.shader | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/Content/Shader/FacePickerURP.shader b/Content/Shader/FacePickerURP.shader index 1568da56f..4fa8fdd0f 100644 --- a/Content/Shader/FacePickerURP.shader +++ b/Content/Shader/FacePickerURP.shader @@ -1,10 +1,5 @@ Shader "Hidden/ProBuilder/FacePickerURP" { - Properties - { - _Tint ("Picker Color", Color) = (1,1,1,1) - } - SubShader { PackageRequirements @@ -24,11 +19,10 @@ Shader "Hidden/ProBuilder/FacePickerURP" Pass { Name "Base" - // Tags { "LightMode"="SRPDefaultUnlit" } Tags { "LightMode"="ProBuilderPickerA" } ZTest LEqual ZWrite On - Cull Off + Cull Back Blend Off HLSLPROGRAM @@ -38,10 +32,6 @@ Shader "Hidden/ProBuilder/FacePickerURP" #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl" #include "ProBuilderCG_URP.cginc" - CBUFFER_START(UnityPerMaterial) - float4 _Tint; - CBUFFER_END - struct Attributes { float4 positionOS : POSITION; @@ -57,8 +47,8 @@ Shader "Hidden/ProBuilder/FacePickerURP" Varyings vert(Attributes input) { Varyings output; - VertexPositionInputs positions = GetVertexPositionInputs(input.positionOS.xyz); + VertexPositionInputs positions = GetVertexPositionInputs(input.positionOS.xyz); output.positionCS = positions.positionCS; output.color = input.color; From 0473b0260f213529ad4f2e337437be60eff13899 Mon Sep 17 00:00:00 2001 From: Thomas Tu Date: Wed, 4 Mar 2026 14:21:14 -0500 Subject: [PATCH 08/10] Fix typo and EdgePicker shader for URP --- Content/Shader/EdgePickerURP.shader | 5 +---- Content/Shader/ProBuilderCG_URP.cginc | 2 +- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/Content/Shader/EdgePickerURP.shader b/Content/Shader/EdgePickerURP.shader index f7af9e2b6..719f6d49a 100644 --- a/Content/Shader/EdgePickerURP.shader +++ b/Content/Shader/EdgePickerURP.shader @@ -22,9 +22,8 @@ Shader "Hidden/ProBuilder/EdgePickerURP" Pass { Name "Edges" - // Tags { "LightMode"="SRPDefaultUnlit" } Tags { "LightMode"="ProBuilderPickerA" } - ZTest LEqual + ZTest Less ZWrite On Cull Off Blend Off @@ -64,6 +63,4 @@ Shader "Hidden/ProBuilder/EdgePickerURP" ENDHLSL } } - - Fallback "Hidden/ProBuilder/EdgePicker" } diff --git a/Content/Shader/ProBuilderCG_URP.cginc b/Content/Shader/ProBuilderCG_URP.cginc index a14197ede..80041567b 100644 --- a/Content/Shader/ProBuilderCG_URP.cginc +++ b/Content/Shader/ProBuilderCG_URP.cginc @@ -33,7 +33,7 @@ inline float4 UnityObjectToClipPosWithOffset(float3 positionOS) //Offsetting the edges to avoid z-fighting problems //Do not offset when using orthographic camera as XY are //screen coords, this would shift the rendering - ret.xyz *= lerp(0.99, 0.95, ORTHO); + ret.xyz *= lerp(0.99, 0.95, unity_OrthoParams.w); //Moving edges closer //.99 is not sufficient for Orthographic Camera ret.w *= lerp(1, 0.95, unity_OrthoParams.w); From 9e42026aed93259667d0ff2130c3559a65681614 Mon Sep 17 00:00:00 2001 From: Thomas Tu Date: Wed, 4 Mar 2026 14:23:09 -0500 Subject: [PATCH 09/10] Swap .cginc extension to .hlsl --- Content/Shader/EdgePickerURP.shader | 2 +- Content/Shader/FacePickerURP.shader | 2 +- Content/Shader/ProBuilderCG_URP.cginc.meta | 9 --------- .../{ProBuilderCG_URP.cginc => ProBuilderCG_URP.hlsl} | 0 Content/Shader/ProBuilderCG_URP.hlsl.meta | 7 +++++++ Content/Shader/VertexPickerURP.shader | 2 +- 6 files changed, 10 insertions(+), 12 deletions(-) delete mode 100644 Content/Shader/ProBuilderCG_URP.cginc.meta rename Content/Shader/{ProBuilderCG_URP.cginc => ProBuilderCG_URP.hlsl} (100%) create mode 100644 Content/Shader/ProBuilderCG_URP.hlsl.meta diff --git a/Content/Shader/EdgePickerURP.shader b/Content/Shader/EdgePickerURP.shader index 719f6d49a..cf46efba4 100644 --- a/Content/Shader/EdgePickerURP.shader +++ b/Content/Shader/EdgePickerURP.shader @@ -33,7 +33,7 @@ Shader "Hidden/ProBuilder/EdgePickerURP" #pragma fragment frag #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl" - #include "ProBuilderCG_URP.cginc" + #include "ProBuilderCG_URP.hlsl" struct Attributes { diff --git a/Content/Shader/FacePickerURP.shader b/Content/Shader/FacePickerURP.shader index 4fa8fdd0f..d0a37418e 100644 --- a/Content/Shader/FacePickerURP.shader +++ b/Content/Shader/FacePickerURP.shader @@ -30,7 +30,7 @@ Shader "Hidden/ProBuilder/FacePickerURP" #pragma fragment frag #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl" - #include "ProBuilderCG_URP.cginc" + #include "ProBuilderCG_URP.hlsl" struct Attributes { diff --git a/Content/Shader/ProBuilderCG_URP.cginc.meta b/Content/Shader/ProBuilderCG_URP.cginc.meta deleted file mode 100644 index f776a271b..000000000 --- a/Content/Shader/ProBuilderCG_URP.cginc.meta +++ /dev/null @@ -1,9 +0,0 @@ -fileFormatVersion: 2 -guid: a4ae1db7ad643084b8270d7590883b2c -ShaderImporter: - externalObjects: {} - defaultTextures: [] - nonModifiableTextures: [] - userData: - assetBundleName: - assetBundleVariant: diff --git a/Content/Shader/ProBuilderCG_URP.cginc b/Content/Shader/ProBuilderCG_URP.hlsl similarity index 100% rename from Content/Shader/ProBuilderCG_URP.cginc rename to Content/Shader/ProBuilderCG_URP.hlsl diff --git a/Content/Shader/ProBuilderCG_URP.hlsl.meta b/Content/Shader/ProBuilderCG_URP.hlsl.meta new file mode 100644 index 000000000..43d284a56 --- /dev/null +++ b/Content/Shader/ProBuilderCG_URP.hlsl.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: ee82fff19db555c45baac786068d84fe +ShaderIncludeImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Content/Shader/VertexPickerURP.shader b/Content/Shader/VertexPickerURP.shader index 66f6e2a3c..5cd352f48 100644 --- a/Content/Shader/VertexPickerURP.shader +++ b/Content/Shader/VertexPickerURP.shader @@ -36,7 +36,7 @@ Shader "Hidden/ProBuilder/VertexPickerURP" #pragma fragment frag #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl" - #include "ProBuilderCG_URP.cginc" + #include "ProBuilderCG_URP.hlsl" struct Attributes { From fcab6899809c455d1d06c58bd3dee33286aefa78 Mon Sep 17 00:00:00 2001 From: thomas-tu <45040865+thomas-tu@users.noreply.github.com> Date: Thu, 5 Mar 2026 09:01:11 -0500 Subject: [PATCH 10/10] Add changelog entry --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4d5186fc1..f4d75e854 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ### Fixed - [UUM-133861] Fixed "Look rotation viewing vector is zero" log being spammed when holding shift while using a create tool such as Create Sprite. +- [UUM-133859] Fixed an issue in URP projects where the Editor would recompile scripts when after a rectangle selection in ProBuilder. - Fixed warnings related to obsolete API calls with Unity 6.4 and onwards. ## [6.0.9] - 2026-01-30