|
1 | | -# Example: How to create a custom rendering effect using the Render Objects Renderer Feature |
| 1 | +--- |
| 2 | +uid: urp-how-to-custom-effect-render-objects |
| 3 | +--- |
2 | 4 |
|
3 | | -URP draws objects in the **DrawOpaqueObjects** and **DrawTransparentObjects** passes. You might need to draw objects at a different point in the frame rendering, or interpret and write rendering data (like depth and stencil) in alternate ways. The [Render Objects Renderer Feature](renderer-feature-render-objects.md) lets you do such customizations by letting you draw objects on a certain layer, at a certain time, with specific overrides. |
| 5 | +# Example of creating a custom rendering effect using a Render Objects Renderer Feature in URP |
4 | 6 |
|
5 | | -The example on this page describes how to create a custom rendering effect with the Render Objects Renderer Feature. |
| 7 | +The [Render Objects Renderer Feature](renderer-feature-render-objects) lets you draw objects at a specific point in the frame rendering loop. You can interpret and write rendering data such as depth and stencil in different ways, or draw a set of GameObjects at a certain time. |
6 | 8 |
|
7 | | -## Example overview |
| 9 | +The following example uses a Render Objects Renderer Feature to draw a GameObject in a different color if it's behind other GameObjects. |
8 | 10 |
|
9 | | -The example on this page demonstrates how to implement the following effect: |
| 11 | + |
10 | 12 |
|
11 | | -* There is a character in the Scene. |
| 13 | +First, create a GameObject and attach it to a new [layer](https://docs.unity3d.com/Manual/Layers.html). |
12 | 14 |
|
13 | | -  |
| 15 | +1. Create a GameObject in your scene. |
| 16 | +1. In the **Inspector** window, open the **Layer** dropdown and add a new layer. You can call the layer **DrawBehind**. |
| 17 | +1. Set the GameObject to the new layer. |
14 | 18 |
|
15 | | -* When the character goes behind GameObjects, Unity draws the character silhouette with a different Material. |
| 19 | +Next, create a Render Objects Renderer Feature that renders only the new layer, on top of the scene. |
16 | 20 |
|
17 | | -  |
| 21 | +1. In the **Project** window, select the [URP Renderer asset](../universalrp-asset) your project uses, for example **Settings** > **PC_Renderer**. |
| 22 | +1. To create a Render Objects Renderer Feature, select **Add Renderer Feature** in the **Inspector** window, then select **Render Objects**. |
| 23 | +1. To make the Renderer Feature draw only the layer with the GameObject, open the **Render Objects (Render Objects)** dropdown, then set **Layer Mask** to the layer. |
| 24 | +1. Set **Event** to the **AfterRenderingOpaques** injection point. For more information about custom pass injection points, refer to [Custom Pass injection points](../customize/custom-pass-injection-points). |
18 | 25 |
|
19 | | -## Prerequisites |
| 26 | +Next, adjust the Renderer Feature so it renders only the parts hidden behind other GameObjects, and in a different color. |
20 | 27 |
|
21 | | -This example requires the following: |
| 28 | +1. Open the **Overrides** dropdown, then select **Depth** and set **Depth Test** to **Greater**. |
22 | 29 |
|
23 | | -* A Unity project with the URP package installed. |
| 30 | + The Renderer Feature now only renders a pixel if its depth is greater than the current pixel in the depth buffer, which means the new pixel is behind another GameObject. |
24 | 31 |
|
25 | | -* The **Scriptable Render Pipeline Settings** property refers to a URP asset (**Project Settings** > **Graphics** > **Scriptable Render Pipeline Settings**). |
| 32 | +1. [Create a new material](../shaders-in-universalrp) that uses the **Universal Render Pipeline/Unlit** shader. |
| 33 | +1. Set the **Base Map** color to a color of your choice. |
| 34 | +1. In the Renderer Feature, in the **Overrides** section, set **Material** to the material you created. |
26 | 35 |
|
27 | | -## Create example Scene and GameObjects<a name="example-objects"></a> |
| 36 | +When you move the GameObject behind other GameObjects, Unity now renders the hidden parts in the color you selected. |
28 | 37 |
|
29 | | -To follow the steps in this example, create a new Scene with the following GameObjects: |
| 38 | + |
30 | 39 |
|
31 | | -1. Create a Cube. Set its **Scale** values so that it looks like a wall. |
| 40 | +## Fix overlapping areas of a GameObject |
32 | 41 |
|
33 | | -  |
| 42 | +If you use a complex GameObject, the Renderer Feature might draw overlapping parts as though they're hidden. This is because the depth of one part is greater than the overlapping part. |
34 | 43 |
|
35 | | -2. Create a Material and assign it the `Universal Render Pipeline/Lit` shader. Select the base color (for example, red). Call the Material `Character`. |
| 44 | + |
36 | 45 |
|
37 | | -3. Create a basic character and assign it the Character Material. In this example, the character consists of three capsules: the big capsule in the center represents the body, and the two smaller capsules represent the hands. |
| 46 | +To fix this issue, disable rendering the whole GameObject, and create a new Renderer Feature that renders the non-hidden parts. Follow these steps: |
38 | 47 |
|
39 | | -  |
| 48 | +1. In the URP Renderer asset, open the **Opaque Layer Mask** dropdown and disable the layer you added. |
40 | 49 |
|
41 | | - To make it easier to manipulate the character in the Scene, add the three Capsules as child GameObjects under the Character GameObject. |
| 50 | + Unity now doesn't draw the layer in the opaque render pass. The Renderer Feature still draws the hidden parts, because it's in a different render pass. |
42 | 51 |
|
43 | | -  |
| 52 | +  |
44 | 53 |
|
45 | | -4. Create a Material and assign it the `Universal Render Pipeline/Unlit` shader. Select the base color that you would like the character to have when it's behind GameObjects (for example, blue). Call the Material `CharacterBehindObjects`. |
| 54 | +1. Add a new Render Objects Renderer Feature. |
| 55 | +1. Set **Layer Mask** to the new layer, so this Renderer Feature draws the GameObject. |
| 56 | +1. Set **Event** to the **AfterRenderingOpaques** injection point. |
| 57 | +1. To avoid the first Renderer Feature affecting the depth calculations in the new Renderer Feature, disable **Write Depth** in the **Overrides** section of the first Renderer Feature. |
46 | 58 |
|
47 | | -Now you have the setup necessary to follow the steps in this example. |
| 59 | +The first Renderer Feature draws the hidden parts, and the second Renderer Feature draws the rest of the GameObject. |
48 | 60 |
|
49 | | -## Example implementation |
| 61 | + |
50 | 62 |
|
51 | | -This section assumes that you created a Scene as described in section [Example Scene and GameObjects](#example-objects). |
| 63 | +## Additional resources |
52 | 64 |
|
53 | | -The example implementation uses two Render Objects Renderer Features: one to draw parts of the character that are behind other GameObjects, and another one to draw the parts of the character that are in front of other GameObjects. |
54 | | - |
55 | | -### Create a Renderer Feature to draw the character behind GameObjects |
56 | | - |
57 | | -Follow these steps to create a Renderer Feature to draw the character behind GameObjects. |
58 | | - |
59 | | -1. Select a URP Renderer. |
60 | | - |
61 | | -  |
62 | | - |
63 | | -2. In the Inspector, click **Add Renderer Feature** and select **Render Objects**. |
64 | | - |
65 | | -  |
66 | | - |
67 | | - Select the **Name** field and enter the name of the new Renderer Feature, for example, **DrawCharacterBehind**. |
68 | | - |
69 | | -3. This example uses Layers to filter the GameObjects to render. Create a new Layer and call it **Character**. |
70 | | - |
71 | | -  |
72 | | - |
73 | | -4. Select the **Character** GameObject and assign it to the `Character` Layer. To do this, open the Layer drop down and select `Character`. |
74 | | -  |
75 | | - |
76 | | -5. In the `DrawCharacterBehind` Renderer Feature, in **Filters** > **Layer Mask**, select `Character`. With this setting, this Renderer Feature renders GameObjects only in the Layer `Character`. |
77 | | - |
78 | | -6. In **Overrides** > **Material**, select the `CharacterBehindObjects` Material. |
79 | | - |
80 | | - The Renderer Feature overrides the Material of a GameObject with the selected Material. |
81 | | - |
82 | | -  |
83 | | - |
84 | | -7. The intended behavior is that the Renderer Feature renders the character with the `CharacterBehindObjects` Material only when the character is behind other GameObjects. |
85 | | - |
86 | | - To achieve this, select the **Depth** check box, and set the **Depth Test** property to **Greater**. |
87 | | - |
88 | | -  |
89 | | - |
90 | | -With these settings, Unity renders the character with the `CharacterBehindObjects` Material only when the character is behind another GameObject. However, Unity also renders parts of the character using the `CharacterBehindObjects` Material, because some parts of the character occlude the character itself. |
91 | | - |
92 | | - |
93 | | - |
94 | | -### Create an extra Renderer Feature to avoid the self see-through effect |
95 | | - |
96 | | -The settings in the previous section result in the self see-through effect for the following reason: |
97 | | - |
98 | | -* When performing the Opaque rendering pass of the URP Renderer, Unity renders all GameObjects belonging to the character with the `Character` Material and writes depth values to the Depth buffer. This happens before Unity starts executing the `DrawCharacterBehind` Renderer Feature, because, by default, new Render Objects Renderer Features have the value **AfterRenderingOpaques** in the **Event** property. |
99 | | - |
100 | | - The **Event** property defines the injection point where Unity injects Render Passes from the Render Objects Renderer Feature. The event when URP Renderer draws GameObjects in the **Opaque Layer Mask** is the **BeforeRenderingOpaques** event. |
101 | | - |
102 | | -* When executing the `DrawCharacterBehind` Renderer Feature, Unity performs the depth test using the condition specified in the **Depth Test** property. In the following screenshot, a bigger capsule occludes part of the smaller capsule, and the depth test passes for that part of the smaller capsule. The Renderer Feature overrides the Material for that part. |
103 | | - |
104 | | -  |
105 | | - |
106 | | -The following steps describe how to avoid such behavior and ensure that Unity draws all parts of the character with proper Materials. |
107 | | - |
108 | | -1. In the URP asset, in **Filtering** > **Opaque Layer Mask**, clear the check mark next to the `Character` Layer. |
109 | | - |
110 | | -  |
111 | | - |
112 | | - Now Unity does not render the character unless it's behind a GameObject. |
113 | | - |
114 | | -  |
115 | | - |
116 | | -2. Add a new Render Objects Renderer Feature, and call it `Character`. |
117 | | - |
118 | | -3. In the `Character` Renderer Feature, in **Filters** > **Layer Mask**, select the `Character` Layer. |
119 | | - |
120 | | -  |
121 | | - |
122 | | - Now Unity renders the character with the `Character` Material even when the character is behind GameObjects. |
123 | | - |
124 | | - This happens because the `DrawCharacterBehind` Renderer Feature writes values to the depth buffer. When Unity executes the `Character` Renderer Feature, the pixels on the character appear to be in front of the pixels that Unity has drawn previously, and Unity draws on top of those pixels. |
125 | | - |
126 | | -4. In the `DrawCharacterBehind` Renderer Feature, In **Overrides** > **Depth**, clear the **Write Depth** check box. With this setting, the `DrawCharacterBehind` Renderer Feature does not make changes to the depth buffer and the `Character` Renderer Feature does not draw the character when it's behind GameObjects. |
127 | | - |
128 | | -  |
129 | | - |
130 | | -The example is complete. When the character goes behind GameObjects, Unity draws the character silhouette with the `CharacterBehindObjects` Material. |
131 | | - |
132 | | - |
133 | | - |
134 | | -With the extra `Character` Renderer Feature, Unity renders GameObjects as follows: |
135 | | - |
136 | | -1. URP Renderer does not render the `Character` GameObject in the **BeforeRenderingOpaques** event, because the `Character` Layer is excluded from the **Opaque Layer Mask** list. |
137 | | - |
138 | | -2. The `DrawCharacterBehind` Renderer Feature draws parts of the character that are behind other GameObjects. This happens in the **AfterRenderingOpaques** event. |
139 | | - |
140 | | -3. The `Character` Renderer Feature draws parts of the character that are in front of other GameObjects. This happens in the **AfterRenderingOpaques** event, and after executing the `DrawCharacterBehind` Renderer Feature. |
141 | | - |
142 | | -To see another use case of the Render Objects Renderer Feature, refer to the **Object Occlusion** Scene in the [Universal Rendering Examples](https://github.com/Unity-Technologies/UniversalRenderingExamples) project. |
| 65 | +- [Renderer Objects Renderer Feature reference](renderer-feature-render-objects) |
0 commit comments