One shader, two render pipelines
A Shader Script shader works on URP and on HDRP. This page explains how, and what differs between the two.
How it works
Every shader class is translated into shader code for both render pipelines. When Unity imports the shader, it keeps the code for the render pipelines installed in the project, so a URP project doesn't pay for HDRP code and vice versa. With both pipelines installed, the shader works with whichever is active.
The Create menu's URP and HDRP templates only differ in the pipeline-specific attributes they list as comments. The resulting shaders work on both pipelines.
Pipeline-specific attributes
Most attributes apply to both render pipelines. The ones that exist only on one pipeline are in their own namespace:
Ahilevich.ShaderScript.Urp:WorkflowMode,ReceiveShadows,SpecularHighlights,EnvironmentReflections,DetailMap,DetailScale.Ahilevich.ShaderScript.Hdrp:Material,ClearCoat,Refraction,DepthOffset,Tessellation,Distortion, and theDiffusionProfileproperty type.
A pipeline-specific attribute has no effect on the other pipeline, so a shader can use attributes of both.
Pipeline-specific code
Branch on IsUrp or IsHdrp, compile-time constants, when the code must differ. The branch for the other pipeline is removed from the compiled shader, but it must still compile on both pipelines.
OUT.emission = IsHdrp ? EmissionColor.rgb * 1000 : EmissionColor.rgb;
What differs
| Topic | URP | HDRP |
|---|---|---|
| World-space positions | Absolute. | Relative to the camera. Use ShaderApi.GetAbsolutePositionWS for positions that must stay fixed in the world, and the ShaderApi view-direction functions instead of subtracting from WorldSpaceCameraPos. |
| Light units | Arbitrary units: an emission of 1 is visibly bright. | Physical units with camera exposure: the same emission looks dark. Scale emission up on HDRP, or use ShaderLib.ApplyExposureWeight. |
LitFragmentOutput HDRP fields |
Ignored. | Used by the material type and features. |
| Built-in variables | All available. | The matrices and ScaledScreenParams listed as URP-only don't exist; use the ShaderApi transforms. |
| Ambient and fog functions | Return the scene's values. | Return 0. |
| Multiply blending | Supported. | Fullscreen shaders only. |
FragmentInput.uv4 to uv7 |
Available. | Unity 6000.3 or later. |
| Passes | URP's set. | HDRP's set, with more passes, including ray tracing. |
The Material Inspector
The Material Inspector follows the active render pipeline: on URP it looks like URP's Lit or Unlit Inspector, on HDRP like HDRP's. The settings it shows use each pipeline's own names, and so do the material properties behind them. For example, the surface type is stored in _Surface on URP and in _SurfaceType on HDRP.
Keep that in mind when you set a shader's surface settings from a script. From a Material Inspector plugin, the GuiPluginContext methods such as IsTransparent read them the same way on both pipelines. See Material Inspector.