From 35110489b1a1fbb5efff281541cf516b6d2b871a Mon Sep 17 00:00:00 2001 From: Reach Platform Support Date: Fri, 22 Aug 2025 20:14:37 +0000 Subject: [PATCH 01/36] [Port] [6000.2] DOCG - General Bug Bash Aug 2025 PR --- .../Documentation~/Eye-Index-Node.md | 3 ++- .../Documentation~/Fresnel-Effect-Node.md | 9 ++++++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/Packages/com.unity.shadergraph/Documentation~/Eye-Index-Node.md b/Packages/com.unity.shadergraph/Documentation~/Eye-Index-Node.md index ad416ba5f01..ad888ae2474 100644 --- a/Packages/com.unity.shadergraph/Documentation~/Eye-Index-Node.md +++ b/Packages/com.unity.shadergraph/Documentation~/Eye-Index-Node.md @@ -2,7 +2,8 @@ ## Description -Provides access to the **Eye Index** when stereo rendering is enabled. +Provides access to the **Eye Index** when stereo rendering is enabled. The **Eye Index** node outputs a value of `0` for the left eye and `1` for the right eye. + ## Ports diff --git a/Packages/com.unity.shadergraph/Documentation~/Fresnel-Effect-Node.md b/Packages/com.unity.shadergraph/Documentation~/Fresnel-Effect-Node.md index 4b31739c3f6..95d7400dc44 100644 --- a/Packages/com.unity.shadergraph/Documentation~/Fresnel-Effect-Node.md +++ b/Packages/com.unity.shadergraph/Documentation~/Fresnel-Effect-Node.md @@ -2,7 +2,14 @@ ## Description -**Fresnel Effect** is the effect of differing reflectance on a surface depending on viewing angle, where as you approach the grazing angle more light is reflected. The **Fresnel Effect** node approximates this by calculating the angle between the surface normal and the view direction. The wider this angle is, the greater the return value will be. This effect is often used to achieve rim lighting, common in many art styles. +**Fresnel Effect** is the effect of differing reflectance on a surface depending on viewing angle, where as you approach the grazing angle more light is reflected. This effect is often used to achieve rim lighting, common in many art styles. + +The **Fresnel Effect** node approximates this by calculating the angle between the surface normal and the view direction. The output value is a floating-point number between `0` and `1`. This value represents the viewing angle relative to the surface and the Fresnel effect that is being calculated: + +**0**: The viewing angle is 0° from the surface normal, as if you are looking straight at the object. +**1**: The viewing angle is 90° from the surface normal, as if you are looking along the surface or edge of the object. + +A low Fresnel value (output value of `0`) means the surface appears as if viewed from the front, with minimal rim highlighting. A high Fresnel value(`1`) means the surface appears as if viewed from the side, with a strong rim highlight. ## Ports From f135fcad73d0d93068a272e3c1a69d1861c7efcc Mon Sep 17 00:00:00 2001 From: Reach Platform Support Date: Fri, 22 Aug 2025 20:14:38 +0000 Subject: [PATCH 02/36] [Port] [6000.2] DOCG-7358 Scene Color Node docs improvements --- .../Documentation~/Scene-Color-Node.md | 35 +++++++++---------- 1 file changed, 17 insertions(+), 18 deletions(-) diff --git a/Packages/com.unity.shadergraph/Documentation~/Scene-Color-Node.md b/Packages/com.unity.shadergraph/Documentation~/Scene-Color-Node.md index a33f6540be0..953f99047f4 100644 --- a/Packages/com.unity.shadergraph/Documentation~/Scene-Color-Node.md +++ b/Packages/com.unity.shadergraph/Documentation~/Scene-Color-Node.md @@ -1,34 +1,33 @@ -# Scene Color Node +# Scene Color node -## Description +The Scene Color node samples the color buffer of the current camera, using the screen space coordinates you input. -Provides access to the current **Camera**'s color buffer using input **UV**, which is expected to be normalized screen coordinates. +If you use the Universal Render Pipeline (URP), the node samples the opaque texture, which is a copy of the color buffer before Unity renders transparent objects. For more information, refer to [Universal Render Pipeline asset reference](https://docs.unity3d.com/Manual/urp/universalrp-asset.html). -The behavior of the Scene Color node isn't defined globally. The executed HLSL code for the Scene Color node is defined per **Render Pipeline**, and different **Render Pipelines** can produce different results. Custom **Render Pipelines** that wish to support the Scene Color node need to explicitly define the behavior for it. If the behavior is undefined, the Scene Color node returns 0 (black). +To make sure the Scene Color node outputs the correct values, follow these steps: -In the **Universal Render Pipeline** the Scene Color node returns the value of the **Camera Opaque Texture**. Refer to the **Universal Render Pipeline** for more documentation on this feature. The contents of this texture are only available for **Transparent** objects. Set the **Surface Type** dropdown on the [**Graph Settings** tab](Graph-Settings-Tab.md) of the [**Graph Inspector**](Internal-inspector.md) to **Transparent** to receive the correct values from this node. +1. Connect the node to the fragment [shader stage](Shader-Stage.md). The Scene Color node doesn't support the vertex shader stage. +2. In the **Graph Settings** tab of the [**Graph Inspector**](Internal-inspector.md) window, set **Surface Type** to **Transparent**. Otherwise, the node samples the color buffer before Unity renders all the opaque contents in the scene. ->[!NOTE] ->You can only use the Scene Color node in the **Fragment** [Shader Stage](Shader-Stage.md). +## Render pipeline support -#### Supported Unity render pipelines +The Scene Color node supports the following render pipelines: -The following table indicates which render pipelines support the Scene Color node. When used with unsupported render pipelines, the Scene Color node returns 0 (black). +- Universal Render Pipeline (URP) +- High Definition Render Pipeline (HDRP) -|Pipeline | Supported | -|:--------------------------------|:----------| -| Built-in Render Pipeline | No | -| Universal Render Pipeline | Yes | -| High Definition Render Pipeline | Yes | +If you use the Scene Color node with an unsupported pipeline, it returns 0 (black). ## Ports -| Name | Direction | Type | Binding | Description | +| **Name** | **Direction** | **Type** | **Binding** | **Description** | |:-----|:----------|:---------|:----------------|:------------| -| UV | Input | Vector 4 | Screen Position | Normalized screen coordinates | -| Out | Output | Vector 3 | None | Output value | +| **UV** | Input | Vector 4 | Screen position | The normalized screen space coordinates to sample from. | +| **Out** | Output | Vector 3 | None | The color value from the color buffer at the **UV** coordinates. | -## Generated Code Example +## Generated code example + +The HLSL code this node generates depends on the render pipeline you use. If you use your own custom render pipeline, you must define the behavior of the node yourself. Otherwise, the node returns a value of 0 (black). The following example code represents one possible outcome of this node. From cbae7e507e17be1968bc20a99184258b7b6a00f4 Mon Sep 17 00:00:00 2001 From: Reach Platform Support Date: Fri, 22 Aug 2025 20:14:38 +0000 Subject: [PATCH 03/36] [Port] [6000.2] DOCG-7309 Branch node docs improvements --- .../Documentation~/Branch-Node.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/Packages/com.unity.shadergraph/Documentation~/Branch-Node.md b/Packages/com.unity.shadergraph/Documentation~/Branch-Node.md index 10152860c73..460dd770d6b 100644 --- a/Packages/com.unity.shadergraph/Documentation~/Branch-Node.md +++ b/Packages/com.unity.shadergraph/Documentation~/Branch-Node.md @@ -1,17 +1,17 @@ -# Branch Node +# Branch node -## Description +The Branch node adds a dynamic branch to the shader, which outputs a different value depending on whether the input is true or false. -Provides a dynamic branch to the shader. If input **Predicate** is true, this node returns input **True**, otherwise it returns input **False**. The **Branch Node** evaluates the **Predicate** per vertex or per pixel depending on shader stage. Both sides of the branch are evaluated in the shader, and the branch not used is discarded. +Both sides of the branch are evaluated in the shader, and the output from the unused path is discarded. ## Ports -| Name | Direction | Type | Binding | Description | +| **Name** | **Direction** | **Type** | **Binding** | **Description** | |:----------|:----------|:---------------|:--------|:------------| -| Predicate | Input | Boolean | None | Determines which input to return. | -| True | Input | Dynamic Vector | None | Returned if **Predicate** is true. | -| False | Input | Dynamic Vector | None | Returned if **Predicate** is false. | -| Out | Output | Dynamic Vector | None | Output value | +| **Predicate** | Input | Boolean | None | The input to test the value of. If you input a float, all values are evaluated as `true` except `0`. | +| **True** | Input | Dynamic Vector | None | The value to output as **Out** if **Predicate** is true. | +| **False** | Input | Dynamic Vector | None | The value to output as **Out** if **Predicate** is false. | +| **Out** | Output | Dynamic Vector | None | Outputs either **True** or **False**. | ## Generated Code Example From 72ac3ea696d5e609b4b1fc9b9ae0b505b99064fa Mon Sep 17 00:00:00 2001 From: Mark Green Date: Fri, 22 Aug 2025 20:14:38 +0000 Subject: [PATCH 04/36] [Port] [6000.2] DOCG-7283 Improve Replace Color node docs --- .../Documentation~/Replace-Color-Node.md | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/Packages/com.unity.shadergraph/Documentation~/Replace-Color-Node.md b/Packages/com.unity.shadergraph/Documentation~/Replace-Color-Node.md index 5534cfe1ffe..e85467cf9c0 100644 --- a/Packages/com.unity.shadergraph/Documentation~/Replace-Color-Node.md +++ b/Packages/com.unity.shadergraph/Documentation~/Replace-Color-Node.md @@ -1,21 +1,19 @@ -# Replace Color Node +# Replace Color node -## Description - -Replaces values in input **In** equal to input **From** to the value of input **To**. Input **Range** can be used to define a wider range of values around input **From** to replace. Input **Fuzziness** can be used to soften the edges around the selection similar to anti-aliasing. +The Replace Color node replaces a color in the input with another color. ## Ports -| Name | Direction | Type | Binding | Description | +| **Name** | **Direction** | **Type** | **Binding** | **Description** | |:------------ |:-------------|:-----|:---|:---| -| In | Input | Vector 3 | None | Input value | -| From | Input | Vector 3 | Color | Color to replace | -| To | Input | Vector 3 | Color | Color to replace with | -| Range | Input | Float | None | Replace colors within this range from input **From** | -| Fuzziness | Input | Float | None | Soften edges around selection | -| Out | Output | Vector 3 | None | Output value | +| **In** | Input | Vector 3 | None | Sets the input you want to replace a color in. For example, a texture. | +| **From** | Input | Vector 3 | Color | Sets the color to replace. | +| **To** | Input | Vector 3 | Color | Sets the color to replace **From** with. | +| **Range** | Input | Float | None | Sets the range around **From** to replace. For example, if you set **From** to (0, 0, 0) and **Range** to 0.1, Unity replaces colors from (0, 0, 0) to (0.1, 0.1, 0.1) with **To**. | +| **Fuzziness** | Input | Float | None | Sets how much to soften the boundary between the replaced color and the rest of the colors. | +| **Out** | Output | Vector 3 | None | The **In** input, with the **From** color replaced with the **To** color. | -## Generated Code Example +## Generated code example The following example code represents one possible outcome of this node. @@ -23,6 +21,8 @@ The following example code represents one possible outcome of this node. void Unity_ReplaceColor_float(float3 In, float3 From, float3 To, float Range, float Fuzziness, out float3 Out) { float Distance = distance(From, In); + + // Use max to avoid division by zero Out = lerp(To, In, saturate((Distance - Range) / max(Fuzziness, 1e-5f))); } ``` From 4fdbd2f32c6e5a79f25c1c2bc1d86a9f0031d766 Mon Sep 17 00:00:00 2001 From: Mark Green Date: Fri, 22 Aug 2025 20:14:38 +0000 Subject: [PATCH 05/36] [Port] [6000.2] DOCG-7073 Custom interpolator node docs improvements --- .../Documentation~/Custom-Interpolators.md | 62 ++++++++----------- 1 file changed, 25 insertions(+), 37 deletions(-) diff --git a/Packages/com.unity.shadergraph/Documentation~/Custom-Interpolators.md b/Packages/com.unity.shadergraph/Documentation~/Custom-Interpolators.md index 91ed8318d32..eabcb1a1885 100644 --- a/Packages/com.unity.shadergraph/Documentation~/Custom-Interpolators.md +++ b/Packages/com.unity.shadergraph/Documentation~/Custom-Interpolators.md @@ -1,65 +1,53 @@ -# Custom Interpolators +# Add a custom interpolator -## Description +To pass custom data from the vertex shader to the fragment shader, add a custom interpolator to the vertex context of the Master Stack. -The Custom Interpolator feature provides fine-grained control over the specific calculations Shader Graph uses to bring data from the vertex stage to the pixel stage. - -There are two target audiences for Custom Interpolators: +There are two target audiences for custom interpolators: * Technical Directors and Lead Technical Artists setting up environments for their teams. * Graphics programmers helping artists to optimize content performance. +**Note:** If you use the Built-In Render Pipeline, refer to [Input vertex data into a shader](https://docs.unity3d.com/Manual/SL-VertexProgramInputs.html) instead. ## Supported data types -Custom interpolators support float, vec2, vec3, and vec4 options. + +Custom interpolators support float, vector 2, vector 3, and vector 4 types. ## Channel limits -The Custom Interpolator feature supports a maximum of 32 channels. A channel is equivalent to four floats. Each float is an interpolator variable. -Different platforms and GPUs have different interpolator variable limits. Exceeding the interpolator limitations of your target platform prevents your shaders from compiling. For detailed information about the number of interpolators supported by common interfaces, see the Unity documentation on [Shader semantics](https://docs.unity3d.com/Manual/SL-ShaderSemantics.html), and view the section **Interpolator count limits**. Test your Custom Interpolators on your target configuration to ensure that your content compiles properly. -Technical directors can set warnings and errors to help their team members avoid creating graphs with too many channels to be compatible with their target pipeline, platform, or GPU. See **Creating channel warnings and errors** below. -## How to use -To use this feature, create a Custom Interpolator block in the Vertex context of the Master Stack and set a name and a data type. Create a vertex node to write data to that interpolator. Use the interpolator in your graph, then connect your graph to the relevant block in the Fragment context. -These instructions include a contextual example illustrating the process of using a Custom Interpolator to fetch per-vertex data from a texture. -To read the HLSL you use to replicate this behavior with the Built In Render Pipeline, see the Unity documentation on [Shader semantics](https://docs.unity3d.com/Manual/SL-ShaderSemantics.html) and view the section **Vertex ID: SV_VertexID**. +A custom interpolator supports a maximum of 32 channels. A channel is equivalent to four floats. Each float is an interpolator variable. -### Creating channel warnings and errors +Different platforms and GPUs may have different limits, which might prevent your shaders compiling. Test your custom interpolators on your build targets to make sure your shaders compile properly. For more information, refer to the **Interpolator count limits** section in [Input vertex data into a shader](https://docs.unity3d.com/Manual/SL-VertexProgramInputs.html). -It is not possible to limit the number of channels a user can create in a Shader Graph. However, it is possible to create alerts to let users know when they are close to or exceeding a certain number of channels. -The **Warning Threshold** lets users know that they are approaching the channel limit, and the **Error Threshold** informs them if they have reached or surpassed that limit. The **Warning Threshold** value must be between 8 and 32 channels. The **Error Threshold** value must be higher than the **Warning Threshold**, and has a minimum value of 8 channels. -To configure these parameters, go to the Unity Editor [Project Settings](https://docs.unity3d.com/Manual/comp-ManagerGroup.html) menu and open the **Custom Interpolator Channel Settings**. +You can't limit the number of channels another user creates in a shader graph. However, to warn users about the limits, go to [Project Settings](https://docs.unity3d.com/Manual/comp-ManagerGroup.html) and set the following: -### Adding a Custom Interpolator block to the Master Stack +- **Warning Threshold** to tell users when they approach the channel limit. The range is 8 to 32 channels. +- **Error Threshold** to tell users when they reach or exceed the channel limit. The minimum value is 8 channels, and it must be higher than the **Warning Threshold**. -![](images/custom-interpolators-3.gif) ![](images/custom-interpolators-2.png) +## Add a custom interpolator block to the Master Stack -1. Right-click in the **Vertex** contex to create a block node. +1. Right-click in the **Vertex** context to create a block node. 2. Select **Custom Interpolator**. -3. Select a data type. -4. Enter a name for this interpolator. +3. In the **Node Settings** tab of the **Graph Inspector** window, select a data type, for example **Vector 4**. +4. In the same tab, enter a name for the interpolator. -In the illustrated example, you use the Vector 4 (vec4) data type. +## Write data to the interpolator -### Writing data to the interpolator +1. Right-click in your graph to create a node. +2. Select the type, for example **Vertex ID**. - ![](images/custom-interpolators-1.png) + Custom interpolator blocks support many types of data, so you can connect the data from many other nodes including UV nodes and color nodes. -1. Right-click in your graph to create a node. -2. Select the type **Vertex ID**. -3. Connect this node to the Custom Interpolator block. +3. Connect the node to the custom interpolator block. -In the example, you write Vertex ID values from your graph into the Custom Interpolator. +The graph now writes Vertex ID values into the custom interpolator. -### Reading data from the interpolator +## Read data from the interpolator 1. Right-click in your graph to create a node. 2. Select **Custom Interpolator**. -3. Connect the Custom Interpolator node to the relevant block in the Fragment context. - - ![](images/custom-interpolators-4.png) - -In this example, you connect to the **Base Color** block in order to pass the Vertex ID from the vertex shader to the fragment shader and use it as color output. +3. Connect the **Custom Interpolator** node to the relevant block in the **Fragment** context, for example **Base Color** to use the Vertex ID as color output. -### Deleting the block from the Master Stack +## Delete a custom interpolator -If you delete a Custom Interpolator which is associated with nodes that are still in your graph, Unity displays an alert. If you want to keep using these nodes, you can create a new Custom Interpolator and associate them with it. This prevents the alert from appearing. +If you delete a custom interpolator that's associated with nodes that are still in your graph, Unity displays an alert. If you want to keep using these nodes, you can create a new custom interpolator and associate the nodes with it. This prevents the alert from appearing. From ae4b0e532cc509dd53dafd2286beb6890255bcfa Mon Sep 17 00:00:00 2001 From: Reach Platform Support Date: Fri, 22 Aug 2025 20:14:38 +0000 Subject: [PATCH 06/36] [Port] [6000.2] DOCG-7115 Improve Scene Depth Difference node docs --- .../Scene-Depth-Difference-Node.md | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/Packages/com.unity.shadergraph/Documentation~/Scene-Depth-Difference-Node.md b/Packages/com.unity.shadergraph/Documentation~/Scene-Depth-Difference-Node.md index 165dabe773e..ee7ed98b9dc 100644 --- a/Packages/com.unity.shadergraph/Documentation~/Scene-Depth-Difference-Node.md +++ b/Packages/com.unity.shadergraph/Documentation~/Scene-Depth-Difference-Node.md @@ -1,19 +1,19 @@ -# Scene Depth Difference +# Scene Depth Difference node -## Description - -Provide a difference between a World Space Position and a Depth value for a given UV. +The Scene Depth Difference node returns the difference in depth between a world space position and a value from the depth buffer. ## Ports -| Name | Direction | Type | Binding | Description | -|:-------|:-----------|:------|:--------|:------------| -| Scene UV | Input | Vector4 | None | UV where to sample the depth. | -| Position WS | Input | Vector3 | None | The world space position to compare with scene depth. | -| Out | Output | Float | None | The difference between PositionWS and the depth. The difference is given relative to camera with **Eye** mode, in depth-buffer-value with **Raw** mode and in Linear value remap between 0 and 1 with the **Linear01** Mode. | +| **Name** | **Direction** | **Type** | **Binding** | **Description** | +|-|-|-|-|-| +| **Scene UV** | Input | Vector 4 | None | Sets the normalized coordinates at which to fetch the scene depth from the depth buffer. The default is the normalized x, y coordinates of the fragment in screen space. For more information about the options, refer to the [Screen Position node](Screen-Position-Node.md). | +| **Position WS** | Input | Vector 3 | None | Sets the world space position to compare the depth value at **Scene UV** to. The default is the x, y, z position of the fragment in world space. | +| **Out** | Output | Float | None | The difference in depth between **Scene UV** and **Position WS**. The value depends on the **Sampling mode** property. The distance is negative if the depth value from **Scene UV** is closer to the camera than the depth from **Position WS**. | -## Controls +## Sampling modes -| Name | Type | Options | Description | -|:------------ |:-------------|:-----|:---| -| Mode | Dropdown | Select **Linear01** to have a value between 0 and 1, **Eye** to have a World-Space value comparable to unit used on the scene and **Raw** if it's used with SceneDepthBuffer. | +| **Name** | **Description** | +|----------|------------------------------------| +| **Linear 01** | Returns the distance in linear normalized space. The minimum distance is 0, and the maximum distance is 1. | +| **Raw** | Returns the distance in the non-linear space the depth buffer uses. The minimum distance is 0, and the maximum distance is 1. | +| **Eye** | Returns the distance in meters. | From 14623e07d5f950ad10135665402fc3c3112767e8 Mon Sep 17 00:00:00 2001 From: Reach Platform Support Date: Fri, 22 Aug 2025 20:14:38 +0000 Subject: [PATCH 07/36] [Port] [6000.2] DOCG-7438 Improve Emission node docs --- .../Documentation~/Emission-Node.md | 46 ++++++++++++------- 1 file changed, 29 insertions(+), 17 deletions(-) diff --git a/Packages/com.unity.shadergraph/Documentation~/Emission-Node.md b/Packages/com.unity.shadergraph/Documentation~/Emission-Node.md index bf108042bec..94c2c1f3537 100644 --- a/Packages/com.unity.shadergraph/Documentation~/Emission-Node.md +++ b/Packages/com.unity.shadergraph/Documentation~/Emission-Node.md @@ -1,30 +1,42 @@ -# Emission Node +# Emission node -The Emission Node allows you to apply emission in your Shader Graph. +The Emission node outputs a color that makes a material appear as a visible source of light. ## Render pipeline compatibility -| **Node** | **Universal Render Pipeline (URP)** | **High Definition Render Pipeline (HDRP)** | -| -------- | ----------------------------------- | ------------------------------------------ | -| Emission | No | Yes | +The Emission node is compatible only with the High Definition Render Pipeline (HDRP). ## Ports -| Name | Direction | Type | Description | -| :------------ | :-------- | :------------- | :----------------------------------------------------------- | -| **color** | Input | LDR Color(RGB) | Sets the low dynamic range (LDR) color of the emission. | -| **intensity** | Input | Float | Sets the intensity of the emission color. | -| **output** | Output | HDR Color(RGB) | Outputs the high dynamic range (HDR) color that this Node produces. | +| **Name** | **Direction** | **Type** | **Description** | +|-|-|-|-| +| **Color** | Input | Low dynamic range (LDR) RGB color | Sets the low dynamic range (LDR) color to make emissive. | +| **Intensity** | Input | Float | Sets the intensity of the emission of the output color. | +| **Exposure Weight** | Input | Float | Sets how much the [exposure](https://docs.unity3d.com/Packages/com.unity.render-pipelines.high-definition@latest/index.html?subfolder=/manual/Override-Exposure.html) of the scene affects emission. The range is between 0 and 1. A value of 0 means that exposure does not affect this part of the emission. A value of 1 means that exposure fully affects this part of the emission. | +| **Output** | Output | High dynamic range (HDR) RGB color | The emissive color. | -## Notes +## Properties -### Emission Unit +| **Name** | **Description** | +|-|-| +| **Intensity Unit** | Sets the unit of the **Intensity** property. For more information, refer to [Understand physical light units](https://docs.unity3d.com/Packages/com.unity.render-pipelines.high-definition@latest/index.html?subfolder=/manual/Physical-Light-Units.html). The options are:
  • **Nits**: Sets the units as nits, which is a measure of luminance, the surface power of a light source.
  • **EV100**: Sets the units as EV100, which is a measure of exposure value.
| +| **Normalize Color** | Adjusts the intensity of the input color so the red, green, and blue values look similar. As a result, colors are more balanced in the **Output**. | -You can use two [physical light units](https://docs.unity3d.com/Packages/com.unity.render-pipelines.high-definition@latest/index.html?subfolder=/manual/Physical-Light-Units.html) to control the strength of the emission: +## Generated code example -* [Nits](https://docs.unity3d.com/Packages/com.unity.render-pipelines.high-definition@latest/index.html?subfolder=/manual/Physical-Light-Units.html%23Nits). -* [EV100](https://docs.unity3d.com/Packages/com.unity.render-pipelines.high-definition@latest/index.html?subfolder=/manual/Physical-Light-Units.html%23EV). +```hlsl +float3 Unity_HDRP_GetEmissionHDRColor_float(float3 ldrColor, float luminanceIntensity, float exposureWeight) +{ + // Convert the LDR color. This line is generated only if Normalize Color is enabled. + ldrColor = ldrColor * rcp(max(Luminance(ldrColor), 1e-6)); + float3 hdrColor = ldrColor * luminanceIntensity; + float inverseExposureMultiplier = GetInverseCurrentExposureMultiplier(); + hdrColor = lerp(hdrColor * inverseExposureMultiplier, hdrColor, exposureWeight); + return hdrColor; +} +``` -### Exposure Weight -You can use Exposure Weight to determine how exposure affects emission. It is a value between **0** and **1** where. A value of **0** means that exposure does not effect this part of the emission. A value of **1** means that exposure fully affects this part of the emission. +## Additional resources + +- [Add light emission to a material](https://docs.unity3d.com/Manual/StandardShaderMaterialParameterEmission.html) From bc50e01c8e6106fa9dededb37c9ca2bbe99ecefe Mon Sep 17 00:00:00 2001 From: Reach Platform Support Date: Fri, 22 Aug 2025 20:14:38 +0000 Subject: [PATCH 08/36] [Port] [6000.2] DOCG-7342 Improvements to Dither node docs --- .../Documentation~/Dither-Node.md | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/Packages/com.unity.shadergraph/Documentation~/Dither-Node.md b/Packages/com.unity.shadergraph/Documentation~/Dither-Node.md index d82a83adfa8..63b8a9e161f 100644 --- a/Packages/com.unity.shadergraph/Documentation~/Dither-Node.md +++ b/Packages/com.unity.shadergraph/Documentation~/Dither-Node.md @@ -1,20 +1,20 @@ -# Dither Node +# Dither node -## Description +The Dither node adds a structured form of noise to the input. Use the Dither node to reduce the color bands that might appear if you move from a high number of colors to a low number (quantizing), or to simulate transparency by adding random alpha pixels to an opaque object. -Dither is an intentional form of noise used to randomize quantization error. It is used to prevent large-scale patterns such as color banding in images. The **Dither** node applies dithering in screen-space to ensure a uniform distribution of the pattern. This can be adjusted by connecting another node to input **Screen Position**. +The Dither node applies dithering in screen space to ensure a uniform distribution of the pattern. To change the space the node uses, connect another node to the **Screen Position** input, such as a [UV node](UV-Nodes.md). -This [Node](Node.md) is commonly used as an input to **Alpha Clip Threshold** on the [Master Node](Master-Stack.md) to give the appearance of transparency to an opaque item. This is useful for creating geometry that appears to be transparent but has the advantages of rendering as opaque, such as writing depth or being rendered in deferred. +To use a dither pattern for transparency, connect the Dither node to the **Alpha Clip Threshold** input in the [Master Stack](Master-Stack.md). As a result, when you adjust the overall alpha value of the material, some pixels are discarded because the alpha value is lower than their alpha clip threshold. This technique is useful for creating geometry that appears to be transparent but has the advantages of rendering as opaque, such as writing to the depth buffer or rendering using a deferred [rendering path](https://docs.unity3d.com/Manual/built-in-rendering-paths.html). ## Ports -| Name | Direction | Type | Binding | Description | +| **Name** | **Direction** | **Type** | **Binding** | **Description** | |:------------ |:-------------|:-----|:---|:---| -| In | Input | Dynamic Vector | None | Input value | -| Screen Position | Input | Vector 4 | Screen Position | Coordinates used to apply dither pattern | -| Out | Output | Dynamic Vector | None | Output value | +| **In** | Input | Dynamic vector | None | The input to dither. The noise stays within the overall minimum and maximum range of the input values. | +| **Screen Position** | Input | Vector 4 | Screen Position | The coordinates Unity uses to calculate the dither pattern. For more information about the options, refer to the [Screen Position node](Screen-Position-Node.md). | +| **Out** | Output | Dynamic vector | None | The dithered output. | -## Generated Code Example +## Generated code example The following example code represents one possible outcome of this node. @@ -33,3 +33,4 @@ void Unity_Dither_float4(float4 In, float4 ScreenPosition, out float4 Out) Out = In - DITHER_THRESHOLDS[index]; } ``` + From 86c068607eb14a3884b9d32cdebb34f40b7f0ad0 Mon Sep 17 00:00:00 2001 From: Brian Elgaard Bennett Date: Fri, 22 Aug 2025 20:14:38 +0000 Subject: [PATCH 09/36] [Backport] OutOfMemory exception in the console and unreleased memory when baking Adaptive Probe Volumes --- .../ProbeGIBaking.LightTransport.cs | 44 ++++++---- .../ProbeVolume/ProbeGIBaking.Placement.cs | 22 ++++- .../ProbeGIBaking.Serialization.cs | 81 ++++++++++++++++--- .../ProbeGIBaking.VirtualOffset.cs | 15 +++- .../Lighting/ProbeVolume/ProbeGIBaking.cs | 38 +++++++-- 5 files changed, 162 insertions(+), 38 deletions(-) diff --git a/Packages/com.unity.render-pipelines.core/Editor/Lighting/ProbeVolume/ProbeGIBaking.LightTransport.cs b/Packages/com.unity.render-pipelines.core/Editor/Lighting/ProbeVolume/ProbeGIBaking.LightTransport.cs index 46df8365cf4..d0511b70b6d 100644 --- a/Packages/com.unity.render-pipelines.core/Editor/Lighting/ProbeVolume/ProbeGIBaking.LightTransport.cs +++ b/Packages/com.unity.render-pipelines.core/Editor/Lighting/ProbeVolume/ProbeGIBaking.LightTransport.cs @@ -1005,27 +1005,36 @@ internal static void BakeAdjustmentVolume(ProbeVolumeBakingSet bakingSet, ProbeA if (!failed) { - for (int c = 0; c < bakingCells.Length; c++) + // Validate baking cells size before any global state modifications + var chunkSizeInProbes = ProbeBrickPool.GetChunkSizeInProbeCount(); + var hasVirtualOffsets = m_BakingSet.settings.virtualOffsetSettings.useVirtualOffset; + var hasRenderingLayers = m_BakingSet.useRenderingLayers; + + if (ValidateBakingCellsSize(bakingCells, chunkSizeInProbes, hasVirtualOffsets, hasRenderingLayers)) { - ref var cell = ref bakingCells[c]; - ComputeValidityMasks(cell); - } - - // Write result to disk - WriteBakingCells(bakingCells); + for (int c = 0; c < bakingCells.Length; c++) + { + ref var cell = ref bakingCells[c]; + ComputeValidityMasks(cell); + } - // Reload everything - AssetDatabase.SaveAssets(); - AssetDatabase.Refresh(); + // Attempt to write the result to disk + if (WriteBakingCells(bakingCells)) + { + // Reload everything + AssetDatabase.SaveAssets(); + AssetDatabase.Refresh(); - if (m_BakingSet.hasDilation) - { - // Force reloading of data - foreach (var data in prv.perSceneDataList) - data.Initialize(); + if (m_BakingSet.hasDilation) + { + // Force reloading of data + foreach (var data in prv.perSceneDataList) + data.Initialize(); - InitDilationShaders(); - PerformDilation(); + InitDilationShaders(); + PerformDilation(); + } + } } } } @@ -1045,6 +1054,7 @@ internal static void BakeAdjustmentVolume(ProbeVolumeBakingSet bakingSet, ProbeA bakingSet.settings.virtualOffsetSettings.useVirtualOffset = savedVirtualOffset; bakingSet.useRenderingLayers = savedRenderingLayers; + m_BakingBatch?.Dispose(); m_BakingBatch = null; m_BakingSet = null; } diff --git a/Packages/com.unity.render-pipelines.core/Editor/Lighting/ProbeVolume/ProbeGIBaking.Placement.cs b/Packages/com.unity.render-pipelines.core/Editor/Lighting/ProbeVolume/ProbeGIBaking.Placement.cs index 112732aac4c..4f1d0ce9b61 100644 --- a/Packages/com.unity.render-pipelines.core/Editor/Lighting/ProbeVolume/ProbeGIBaking.Placement.cs +++ b/Packages/com.unity.render-pipelines.core/Editor/Lighting/ProbeVolume/ProbeGIBaking.Placement.cs @@ -3,7 +3,7 @@ using Unity.Collections; using UnityEngine.SceneManagement; using UnityEditor; - +using System.Runtime.InteropServices; using Brick = UnityEngine.Rendering.ProbeBrickIndex.Brick; namespace UnityEngine.Rendering @@ -187,7 +187,8 @@ static NativeList ApplySubdivisionResults(ProbeSubdivisionResult result int positionStart = positions.Length; ConvertBricksToPositions(bricks, out var probePositions, out var brickSubdivLevels); - DeduplicateProbePositions(in probePositions, in brickSubdivLevels, m_BakingBatch, positions, out var probeIndices); + if (!DeduplicateProbePositions(in probePositions, in brickSubdivLevels, m_BakingBatch, positions, out var probeIndices)) + return new NativeList(Allocator.Persistent); BakingCell cell = new BakingCell() { @@ -206,9 +207,22 @@ static NativeList ApplySubdivisionResults(ProbeSubdivisionResult result return positions; } - private static void DeduplicateProbePositions(in Vector3[] probePositions, in int[] brickSubdivLevel, BakingBatch batch, + // We know that the current limitation on native containers is this. When an integer overflow bug (https://jira.unity3d.com/browse/UUM-113721) has been fixed, we can raise the limit + // This and related work is tracked by https://jira.unity3d.com/browse/GFXLIGHT-1738 + static readonly long k_MaxNumberOfPositions = 67180350; + + static bool DeduplicateProbePositions(in Vector3[] probePositions, in int[] brickSubdivLevel, BakingBatch batch, NativeList uniquePositions, out int[] indices) { + long numberOfPositions = (long)probePositions.Length + batch.positionToIndex.Count; + if (numberOfPositions > k_MaxNumberOfPositions) + { + Debug.LogError($"The number of Adaptive Probe Volume (APV) probes Unity generated exceeds the current system limit of {k_MaxNumberOfPositions} probes per Baking Set. Reduce density either by adjusting the general Probe Spacing in the Lighting window, or by modifying the Adaptive Probe Volumes in the scene to limit where the denser subdivision levels are used."); + indices = null; + + return false; + } + indices = new int[probePositions.Length]; int uniqueIndex = batch.positionToIndex.Count; @@ -234,6 +248,8 @@ private static void DeduplicateProbePositions(in Vector3[] probePositions, in in uniqueIndex++; } } + + return true; } static ProbeSubdivisionResult GetBricksFromLoaded() diff --git a/Packages/com.unity.render-pipelines.core/Editor/Lighting/ProbeVolume/ProbeGIBaking.Serialization.cs b/Packages/com.unity.render-pipelines.core/Editor/Lighting/ProbeVolume/ProbeGIBaking.Serialization.cs index e44748d4704..150525aeff7 100644 --- a/Packages/com.unity.render-pipelines.core/Editor/Lighting/ProbeVolume/ProbeGIBaking.Serialization.cs +++ b/Packages/com.unity.render-pipelines.core/Editor/Lighting/ProbeVolume/ProbeGIBaking.Serialization.cs @@ -726,6 +726,63 @@ static void ExtractBakingCells() static long AlignRemainder16(long count) => count % 16L; + /// + /// Calculates support data chunk size based on provided configuration. + /// + /// Number of probes per chunk + /// Whether virtual offsets are enabled + /// Whether rendering layers are enabled + /// The size in bytes of a single support data chunk + static int CalculateSupportDataChunkSize(int chunkSizeInProbes, bool hasVirtualOffsets, bool hasRenderingLayers) + { + int supportPositionChunkSize = UnsafeUtility.SizeOf() * chunkSizeInProbes; + int supportValidityChunkSize = UnsafeUtility.SizeOf() * chunkSizeInProbes; + int supportTouchupChunkSize = UnsafeUtility.SizeOf() * chunkSizeInProbes; + int supportLayerMaskChunkSize = hasRenderingLayers ? UnsafeUtility.SizeOf() * chunkSizeInProbes : 0; + int supportOffsetsChunkSize = hasVirtualOffsets ? UnsafeUtility.SizeOf() * chunkSizeInProbes : 0; + + return supportPositionChunkSize + supportValidityChunkSize + + supportOffsetsChunkSize + supportLayerMaskChunkSize + supportTouchupChunkSize; + } + + /// + /// Validates that the baking cells can be written without exceeding system limits. + /// This method performs size calculations without accessing any global state. + /// + /// Array of baking cells to validate + /// Number of probes per chunk + /// Whether virtual offsets are enabled + /// Whether rendering layers are enabled + /// True if cells can be written safely, false if they exceed limits + static bool ValidateBakingCellsSize(BakingCell[] bakingCells, int chunkSizeInProbes, bool hasVirtualOffsets, bool hasRenderingLayers) + { + if (bakingCells == null || bakingCells.Length == 0) + return true; + + int supportDataChunkSize = CalculateSupportDataChunkSize(chunkSizeInProbes, hasVirtualOffsets, hasRenderingLayers); + + // Calculate total chunks count - need to call AnalyzeBrickForIndirectionEntries to get shChunkCount + // Create a copy to avoid modifying the original cells during validation + var tempCells = new BakingCell[bakingCells.Length]; + int totalChunksCount = 0; + for (var i = 0; i < bakingCells.Length; ++i) + { + tempCells[i] = bakingCells[i]; // Shallow copy is sufficient for this validation + AnalyzeBrickForIndirectionEntries(ref tempCells[i]); + totalChunksCount += tempCells[i].shChunkCount; + } + + // Perform the critical size check + long supportDataTotalSize = (long)totalChunksCount * supportDataChunkSize; + if (supportDataTotalSize > int.MaxValue) + { + Debug.LogError($"The size of the Adaptive Probe Volume (APV) baking set chunks exceed the current system limit of {int.MaxValue}, unable to save the baked cell assets. Reduce density either by adjusting the general Probe Spacing in the Lighting window, or by modifying the Adaptive Probe Volumes in the scene to limit where the denser subdivision levels are used."); + return false; + } + + return true; + } + static void WriteNativeArray(System.IO.FileStream fs, NativeArray array) where T : struct { unsafe @@ -736,7 +793,7 @@ static void WriteNativeArray(System.IO.FileStream fs, NativeArray array) w } /// - /// This method converts a list of baking cells into 5 separate assets: + /// This method attempts to convert a list of baking cells into 5 separate assets: /// 2 assets per baking state: /// CellData: a binary flat file containing L0L1 probes data /// CellOptionalData: a binary flat file containing L2 probe data (when present) @@ -745,7 +802,7 @@ static void WriteNativeArray(System.IO.FileStream fs, NativeArray array) w /// CellSharedData: a binary flat file containing bricks data /// CellSupportData: a binary flat file containing debug data (stripped from player builds if building without debug shaders) /// - unsafe static void WriteBakingCells(BakingCell[] bakingCells) + static unsafe bool WriteBakingCells(BakingCell[] bakingCells) { m_BakingSet.GetBlobFileNames(m_BakingSet.lightingScenario, out var cellDataFilename, out var cellBricksDataFilename, out var cellOptionalDataFilename, out var cellProbeOcclusionDataFilename, out var cellSharedDataFilename, out var cellSupportDataFilename); @@ -846,16 +903,16 @@ unsafe static void WriteBakingCells(BakingCell[] bakingCells) // Brick data using var bricks = new NativeArray(m_TotalCellCounts.bricksCount, Allocator.Persistent, NativeArrayOptions.UninitializedMemory); - // CellSupportData - m_BakingSet.supportPositionChunkSize = sizeof(Vector3) * chunkSizeInProbes; - m_BakingSet.supportValidityChunkSize = sizeof(float) * chunkSizeInProbes; - m_BakingSet.supportOffsetsChunkSize = hasVirtualOffsets ? sizeof(Vector3) * chunkSizeInProbes : 0; - m_BakingSet.supportTouchupChunkSize = sizeof(float) * chunkSizeInProbes; - m_BakingSet.supportLayerMaskChunkSize = hasRenderingLayers ? sizeof(byte) * chunkSizeInProbes : 0; + // CellSupportData - use pure helper function for calculation + m_BakingSet.supportPositionChunkSize = UnsafeUtility.SizeOf() * chunkSizeInProbes; + m_BakingSet.supportValidityChunkSize = UnsafeUtility.SizeOf() * chunkSizeInProbes; + m_BakingSet.supportOffsetsChunkSize = hasVirtualOffsets ? UnsafeUtility.SizeOf() * chunkSizeInProbes : 0; + m_BakingSet.supportTouchupChunkSize = UnsafeUtility.SizeOf() * chunkSizeInProbes; + m_BakingSet.supportLayerMaskChunkSize = hasRenderingLayers ? UnsafeUtility.SizeOf() * chunkSizeInProbes : 0; - m_BakingSet.supportDataChunkSize = m_BakingSet.supportPositionChunkSize + m_BakingSet.supportValidityChunkSize + m_BakingSet.supportOffsetsChunkSize + m_BakingSet.supportLayerMaskChunkSize + m_BakingSet.supportTouchupChunkSize; - var supportDataTotalSize = m_TotalCellCounts.chunksCount * m_BakingSet.supportDataChunkSize; - using var supportData = new NativeArray(supportDataTotalSize, Allocator.Persistent, NativeArrayOptions.UninitializedMemory); + m_BakingSet.supportDataChunkSize = CalculateSupportDataChunkSize(chunkSizeInProbes, hasVirtualOffsets, hasRenderingLayers); + long supportDataTotalSize = (long)m_TotalCellCounts.chunksCount * m_BakingSet.supportDataChunkSize; + using var supportData = new NativeArray((int)supportDataTotalSize, Allocator.Persistent, NativeArrayOptions.UninitializedMemory); var sceneStateHash = m_BakingSet.GetBakingHashCode(); var startCounts = new CellCounts(); @@ -1093,6 +1150,8 @@ unsafe static void WriteBakingCells(BakingCell[] bakingCells) m_BakingSet.cellSupportDataAsset = new ProbeVolumeStreamableAsset(kAPVStreamingAssetsPath, cellSupportDescs, m_BakingSet.supportDataChunkSize, bakingSetGUID, AssetDatabase.AssetPathToGUID(cellSupportDataFilename)); EditorUtility.SetDirty(m_BakingSet); + + return true; } unsafe static void WriteDilatedCells(List cells) diff --git a/Packages/com.unity.render-pipelines.core/Editor/Lighting/ProbeVolume/ProbeGIBaking.VirtualOffset.cs b/Packages/com.unity.render-pipelines.core/Editor/Lighting/ProbeVolume/ProbeGIBaking.VirtualOffset.cs index 9f9204c4e78..821eccab346 100644 --- a/Packages/com.unity.render-pipelines.core/Editor/Lighting/ProbeVolume/ProbeGIBaking.VirtualOffset.cs +++ b/Packages/com.unity.render-pipelines.core/Editor/Lighting/ProbeVolume/ProbeGIBaking.VirtualOffset.cs @@ -340,8 +340,19 @@ static internal void RecomputeVOForDebugOnly() // Make sure unloading happens. prv.PerformPendingOperations(); - // Write back the assets. - WriteBakingCells(m_BakingBatch.cells.ToArray()); + // Validate baking cells size before writing + var bakingCellsArray = m_BakingBatch.cells.ToArray(); + var chunkSizeInProbes = ProbeBrickPool.GetChunkSizeInProbeCount(); + var hasVirtualOffsets = m_BakingSet.settings.virtualOffsetSettings.useVirtualOffset; + var hasRenderingLayers = m_BakingSet.useRenderingLayers; + + if (ValidateBakingCellsSize(bakingCellsArray, chunkSizeInProbes, hasVirtualOffsets, hasRenderingLayers)) + { + // Write back the assets. + WriteBakingCells(bakingCellsArray); + } + + m_BakingBatch?.Dispose(); m_BakingBatch = null; foreach (var data in prv.perSceneDataList) diff --git a/Packages/com.unity.render-pipelines.core/Editor/Lighting/ProbeVolume/ProbeGIBaking.cs b/Packages/com.unity.render-pipelines.core/Editor/Lighting/ProbeVolume/ProbeGIBaking.cs index de20efb7d8e..feb9cc5eae6 100644 --- a/Packages/com.unity.render-pipelines.core/Editor/Lighting/ProbeVolume/ProbeGIBaking.cs +++ b/Packages/com.unity.render-pipelines.core/Editor/Lighting/ProbeVolume/ProbeGIBaking.cs @@ -268,15 +268,15 @@ internal int GetBakingHashCode() } } - class BakingBatch + class BakingBatch : IDisposable { public Dictionary> cellIndex2SceneReferences = new (); public List cells = new (); // Used to retrieve probe data from it's position in order to fix seams - public Dictionary positionToIndex = new (); + public NativeHashMap positionToIndex; // Allow to get a mapping to subdiv level with the unique positions. It stores the minimum subdiv level found for a given position. // Can be probably done cleaner. - public Dictionary uniqueBrickSubdiv = new (); + public NativeHashMap uniqueBrickSubdiv; // Mapping for explicit invalidation, whether it comes from the auto finding of occluders or from the touch up volumes // TODO: This is not used yet. Will soon. public Dictionary invalidatedPositions = new (); @@ -306,6 +306,19 @@ public BakingBatch(Vector3Int cellCount) maxBrickCount = cellCount * ProbeReferenceVolume.CellSize(ProbeReferenceVolume.instance.GetMaxSubdivision()); inverseScale = ProbeBrickPool.kBrickCellCount / ProbeReferenceVolume.instance.MinBrickSize(); offset = ProbeReferenceVolume.instance.ProbeOffset(); + + // Initialize NativeHashMaps with reasonable initial capacity + // Using a larger capacity to reduce allocations during baking + positionToIndex = new NativeHashMap(100000, Allocator.Persistent); + uniqueBrickSubdiv = new NativeHashMap(100000, Allocator.Persistent); + } + + public void Dispose() + { + if (positionToIndex.IsCreated) + positionToIndex.Dispose(); + if (uniqueBrickSubdiv.IsCreated) + uniqueBrickSubdiv.Dispose(); } public int GetProbePositionHash(Vector3 position) @@ -1202,6 +1215,7 @@ static void OnBakeCancelled() static void CleanBakeData() { s_BakeData.Dispose(); + m_BakingBatch?.Dispose(); m_BakingBatch = null; s_AdjustmentVolumes = null; @@ -1478,6 +1492,15 @@ static void ApplyPostBakeOperations() // Use the globalBounds we just computed, as the one in probeRefVolume doesn't include scenes that have never been baked probeRefVolume.globalBounds = globalBounds; + // Validate baking cells size before any state modifications + var bakingCellsArray = m_BakedCells.Values.ToArray(); + var chunkSizeInProbes = ProbeBrickPool.GetChunkSizeInProbeCount(); + var hasVirtualOffsets = m_BakingSet.settings.virtualOffsetSettings.useVirtualOffset; + var hasRenderingLayers = m_BakingSet.useRenderingLayers; + + if (!ValidateBakingCellsSize(bakingCellsArray, chunkSizeInProbes, hasVirtualOffsets, hasRenderingLayers)) + return; // Early exit if validation fails + PrepareCellsForWriting(isBakingSceneSubset); m_BakingSet.chunkSizeInBricks = ProbeBrickPool.GetChunkSizeInBrickCount(); @@ -1488,9 +1511,13 @@ static void ApplyPostBakeOperations() m_BakingSet.scenarios.TryAdd(m_BakingSet.lightingScenario, new ProbeVolumeBakingSet.PerScenarioDataInfo()); - // Convert baking cells to runtime cells + // Attempt to convert baking cells to runtime cells + bool succeededWritingBakingCells; using (new BakingCompleteProfiling(BakingCompleteProfiling.Stages.WriteBakedData)) - WriteBakingCells(m_BakedCells.Values.ToArray()); + succeededWritingBakingCells = WriteBakingCells(m_BakedCells.Values.ToArray()); + + if (!succeededWritingBakingCells) + return; // Reset internal structures depending on current bake. Debug.Assert(probeRefVolume.EnsureCurrentBakingSet(m_BakingSet)); @@ -1534,6 +1561,7 @@ static void ApplyPostBakeOperations() } // Mark stuff as up to date + m_BakingBatch?.Dispose(); m_BakingBatch = null; foreach (var probeVolume in GetProbeVolumeList()) probeVolume.OnBakeCompleted(); From 7ff6c4ac301ebae0aec915ed8dfb9c8b05f93669 Mon Sep 17 00:00:00 2001 From: Reach Platform Support Date: Fri, 22 Aug 2025 20:14:38 +0000 Subject: [PATCH 10/36] [Port] [6000.2] DOCG-7257: Fix typo --- .../com.unity.shadergraph/Documentation~/TableOfContents.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Packages/com.unity.shadergraph/Documentation~/TableOfContents.md b/Packages/com.unity.shadergraph/Documentation~/TableOfContents.md index ac08576d624..77741b179a8 100644 --- a/Packages/com.unity.shadergraph/Documentation~/TableOfContents.md +++ b/Packages/com.unity.shadergraph/Documentation~/TableOfContents.md @@ -313,7 +313,7 @@ * [Forest Stream Construction Tutorial ](Shader-Graph-Sample-Production-Ready-Tutorial.md) * [UGUI Shaders](Shader-Graph-Sample-UGUI-Shaders.md) * [Getting started](Shader-Graph-Sample-UGUI-Shaders-Getting-Started.md) - * [Custom UI componenents](Shader-Graph-Sample-UGUI-Shaders-Custom-UI-components.md) + * [Custom UI components](Shader-Graph-Sample-UGUI-Shaders-Custom-UI-components.md) * [Custom nodes](Shader-Graph-Sample-UGUI-Shaders-Custom-nodes.md) * [Subgraph nodes](Shader-Graph-Sample-UGUI-Shaders-Subgraph-nodes.md) * [Examples](Shader-Graph-Sample-UGUI-Shaders-Examples.md) From 2086c6471e11c71019a05bc97e09110d4e5adf8d Mon Sep 17 00:00:00 2001 From: Reach Platform Support Date: Fri, 22 Aug 2025 20:14:38 +0000 Subject: [PATCH 11/36] [Port] [6000.2] DOCG-7262: Link to latest version of Manual docs --- .../Documentation~/materialvariant-SG.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Packages/com.unity.shadergraph/Documentation~/materialvariant-SG.md b/Packages/com.unity.shadergraph/Documentation~/materialvariant-SG.md index d51ba458f62..94e589ec01a 100644 --- a/Packages/com.unity.shadergraph/Documentation~/materialvariant-SG.md +++ b/Packages/com.unity.shadergraph/Documentation~/materialvariant-SG.md @@ -2,6 +2,6 @@ When you create materials in a project, you might want to create variations based on a single material: outfits with different color schemes, damaged and undamaged versions of scenery, or shiny and weathered instances of props. -You can use Material Variants to manage these variations. For more information on Material Variants in Unity, see [Material Variants](https://docs.unity3d.com/2022.2/Documentation/Manual/materialvariant-landingpage.html) in the Unity User Manual. +You can use Material Variants to manage these variations. For more information on Material Variants in Unity, see [Material Variants](https://docs.unity3d.com/Manual/materialvariant-landingpage.html) in the Unity User Manual. -You can create a Material Variant from any Shader Graph material. For more information on how to create a Material Variant, see [Create, modify, and apply Material Variants](https://docs.unity3d.com/2022.2/Documentation/Manual/materialvariant-tasks.html) in the User Manual. +You can create a Material Variant from any Shader Graph material. For more information on how to create a Material Variant, see [Create, modify, and apply Material Variants](https://docs.unity3d.com/Manual/materialvariant-tasks.html) in the User Manual. From b258639bcfa02a8a9b1f55570e2b272480a70362 Mon Sep 17 00:00:00 2001 From: Myeongseon Kim Date: Tue, 26 Aug 2025 14:47:07 +0000 Subject: [PATCH 12/36] [Port] [6000.2] Add conditional shader renaming for Autodesk Interactive shaders to MaterialUpgrader --- .../Editor/MaterialUpgrader.cs | 10 ++++--- ...UniversalRenderPipelineMaterialUpgrader.cs | 27 +++++++++++++++++++ .../AutodeskInteractiveMasked.shadergraph | 2 +- 3 files changed, 34 insertions(+), 5 deletions(-) diff --git a/Packages/com.unity.render-pipelines.core/Editor/MaterialUpgrader.cs b/Packages/com.unity.render-pipelines.core/Editor/MaterialUpgrader.cs index de1841763cd..ec52b772675 100644 --- a/Packages/com.unity.render-pipelines.core/Editor/MaterialUpgrader.cs +++ b/Packages/com.unity.render-pipelines.core/Editor/MaterialUpgrader.cs @@ -49,10 +49,12 @@ public class MaterialUpgrader /// /// Retrieves path to new shader. /// - public string NewShaderPath - { - get => m_NewShader; - } + public string NewShaderPath => m_NewShader; + + /// + /// Retrieves path to old shader. + /// + public string OldShaderPath => m_OldShader; MaterialFinalizer m_Finalizer; diff --git a/Packages/com.unity.render-pipelines.universal/Editor/UniversalRenderPipelineMaterialUpgrader.cs b/Packages/com.unity.render-pipelines.universal/Editor/UniversalRenderPipelineMaterialUpgrader.cs index 287c1658e2e..c9ab8e5570b 100644 --- a/Packages/com.unity.render-pipelines.universal/Editor/UniversalRenderPipelineMaterialUpgrader.cs +++ b/Packages/com.unity.render-pipelines.universal/Editor/UniversalRenderPipelineMaterialUpgrader.cs @@ -755,6 +755,14 @@ public static void UpdateSurfaceBlendModes(Material material) /// public class AutodeskInteractiveUpgrader : MaterialUpgrader { + enum LegacyRenderingMode + { + Opaque, + Cutout, + Fade, // Old school alpha-blending mode, fresnel does not affect amount of transparency + Transparent // Physically plausible transparency mode, implemented as alpha pre-multiply + } + /// /// Constructor for the autodesk interactive upgrader. /// @@ -776,6 +784,25 @@ public override void Convert(Material srcMaterial, Material dstMaterial) dstMaterial.SetFloat("_UseAoMap", srcMaterial.GetTexture("_OcclusionMap") ? 1.0f : .0f); dstMaterial.SetVector("_UvOffset", srcMaterial.GetTextureOffset("_MainTex")); dstMaterial.SetVector("_UvTiling", srcMaterial.GetTextureScale("_MainTex")); + + var legacyRenderingMode = (LegacyRenderingMode)srcMaterial.GetFloat("_Mode"); + switch (legacyRenderingMode) + { + case LegacyRenderingMode.Opaque: + RenameShader(OldShaderPath, GraphicsSettings.GetRenderPipelineSettings().autodeskInteractiveShader.name, UniversalRenderPipelineMaterialUpgrader.DisableKeywords); + break; + case LegacyRenderingMode.Cutout: + RenameShader(OldShaderPath, GraphicsSettings.GetRenderPipelineSettings().autodeskInteractiveMaskedShader.name, UniversalRenderPipelineMaterialUpgrader.DisableKeywords); + dstMaterial.SetFloat("_UseOpacityMap", .0f); + dstMaterial.SetFloat("_OpacityThreshold", srcMaterial.GetFloat("_Cutoff")); + break; + case LegacyRenderingMode.Fade: + case LegacyRenderingMode.Transparent: + RenameShader(OldShaderPath, GraphicsSettings.GetRenderPipelineSettings().autodeskInteractiveTransparentShader.name, UniversalRenderPipelineMaterialUpgrader.DisableKeywords); + dstMaterial.SetFloat("_UseOpacityMap", .0f); + dstMaterial.SetFloat("_Opacity", srcMaterial.GetColor("_Color").a); + break; + } } } } diff --git a/Packages/com.unity.render-pipelines.universal/Shaders/AutodeskInteractive/AutodeskInteractiveMasked.shadergraph b/Packages/com.unity.render-pipelines.universal/Shaders/AutodeskInteractive/AutodeskInteractiveMasked.shadergraph index c6870011554..e3f40b34382 100644 --- a/Packages/com.unity.render-pipelines.universal/Shaders/AutodeskInteractive/AutodeskInteractiveMasked.shadergraph +++ b/Packages/com.unity.render-pipelines.universal/Shaders/AutodeskInteractive/AutodeskInteractiveMasked.shadergraph @@ -88,7 +88,7 @@ "typeInfo": { "fullName": "UnityEditor.ShaderGraph.BooleanShaderProperty" }, - "JSONnodeData": "{\n \"m_Name\": \"UseOpacityMap\",\n \"m_GeneratePropertyBlock\": true,\n \"m_Guid\": {\n \"m_GuidSerialized\": \"86ed0329-e72d-4828-b2fe-4f3d4ba88ac4\"\n },\n \"m_DefaultReferenceName\": \"Boolean_8A2B8817\",\n \"m_OverrideReferenceName\": \"\",\n \"m_Precision\": 0,\n \"m_Value\": false,\n \"m_Hidden\": false\n}" + "JSONnodeData": "{\n \"m_Name\": \"UseOpacityMap\",\n \"m_GeneratePropertyBlock\": true,\n \"m_Guid\": {\n \"m_GuidSerialized\": \"86ed0329-e72d-4828-b2fe-4f3d4ba88ac4\"\n },\n \"m_DefaultReferenceName\": \"_UseOpacityMap\",\n \"m_OverrideReferenceName\": \"\",\n \"m_Precision\": 0,\n \"m_Value\": false,\n \"m_Hidden\": false\n}" }, { "typeInfo": { From ecde8ef7ddd248edb7eccb825487a355e871e966 Mon Sep 17 00:00:00 2001 From: Reach Platform Support Date: Tue, 26 Aug 2025 14:47:08 +0000 Subject: [PATCH 13/36] [Port] [6000.2] DOCG-7288 port descript fix --- .../Documentation~/Circle-Pupil-Animation-Node.md | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/Packages/com.unity.shadergraph/Documentation~/Circle-Pupil-Animation-Node.md b/Packages/com.unity.shadergraph/Documentation~/Circle-Pupil-Animation-Node.md index db4e37329f3..953c09123af 100644 --- a/Packages/com.unity.shadergraph/Documentation~/Circle-Pupil-Animation-Node.md +++ b/Packages/com.unity.shadergraph/Documentation~/Circle-Pupil-Animation-Node.md @@ -12,9 +12,8 @@ This node applies a deformation to a normalized IrisUV coordinate to simulate th | name | **Direction** | type | description | | -------------------------- | ------------- | ------- | ------------------------------------------------------------ | -| **IrisUV** | Input | Vector2 | Position of the fragment to shade in object space. | -| **Pupil Radius** | Input | float | Direction of the incident ray in object space. Either from the camera in rasterization or from the previous bounce in ray tracing. | -| **Maximal Pupil Aperture** | Input | float | The normal of the eye surface in object space. | -| **Minimal Pupil Aperture** | Input | float | The index of refraction of the eye (**1.333** by default). | -| **Pupil Apertur** | Input | float | Distance between the end of the cornea and the iris plane. For the default model, this value should be **0.02** | -| **IrisUV** | Output | Vector2 | Position of the refracted point on the iris plane in object space. | +| **Iris UV** | Input | Vector2 | Normalized UV coordinates that can be used to sample either a texture or procedurally generate an Iris Texture. | +| **Pupil Radius** | Input | float | Radius of the pupil in the iris texture as a percentage. | +| **Pupil Aperture** | Input | float | Set the current diameter of the pupil opening. | +| **Maximal Pupil Aperture** | Input | float | Define the largest size the pupil opening can reach. | +| **Minimal Pupil Aperture** | Input | float | Define the smallest size the pupil opening can reach. | \ No newline at end of file From c3ff062b728affd87fc3289932c6a31d25920b5b Mon Sep 17 00:00:00 2001 From: Reach Platform Support Date: Tue, 26 Aug 2025 14:47:08 +0000 Subject: [PATCH 14/36] [Port] [6000.2] DOCG-7195 Update volumetric fog with light layers note --- .../Documentation~/Understand-Fog.md | 1 + 1 file changed, 1 insertion(+) diff --git a/Packages/com.unity.render-pipelines.high-definition/Documentation~/Understand-Fog.md b/Packages/com.unity.render-pipelines.high-definition/Documentation~/Understand-Fog.md index a1471f2239a..8c20b22cd88 100644 --- a/Packages/com.unity.render-pipelines.high-definition/Documentation~/Understand-Fog.md +++ b/Packages/com.unity.render-pipelines.high-definition/Documentation~/Understand-Fog.md @@ -12,3 +12,4 @@ Instead of using a constant color, fog can use the background sky as a source fo Optionally, you can enable volumetric fog for GameObjects close to the camera. It realistically simulates the interaction of lights with fog, which allows for physically plausible rendering of glow and crepuscular rays, which are beams of light that stream through gaps in objects like clouds and trees from a central point. +**Note:** Volumetric fog doesn't support [light rendering layers](Rendering-Layers). From 7f48fd99c4d635f590c47347937bfc3e9d0d5444 Mon Sep 17 00:00:00 2001 From: Kenny Tan Date: Tue, 2 Sep 2025 21:44:53 +0000 Subject: [PATCH 15/36] [6000.2][UUM-111385] Fix WebGL 2D with shadowed lighting --- .../2D/ShaderGraph/Nodes/LightTextureNode.cs | 9 +++- .../2D/Passes/Utility/RendererLighting.cs | 30 ++++++++---- .../Runtime/2D/Renderer2D.cs | 7 --- .../Runtime/2D/Rendergraph/DrawLight2DPass.cs | 8 +-- .../2D/Rendergraph/GlobalPropertiesPass.cs | 22 ++++----- .../2D/Rendergraph/Renderer2DRendergraph.cs | 6 ++- .../2D/Include/ShapeLightVariables.hlsl | 4 -- .../Shaders/2D/Light2D.shader | 49 ++++++++++++------- 8 files changed, 78 insertions(+), 57 deletions(-) diff --git a/Packages/com.unity.render-pipelines.universal/Editor/2D/ShaderGraph/Nodes/LightTextureNode.cs b/Packages/com.unity.render-pipelines.universal/Editor/2D/ShaderGraph/Nodes/LightTextureNode.cs index 690836143c6..a817eef1f21 100644 --- a/Packages/com.unity.render-pipelines.universal/Editor/2D/ShaderGraph/Nodes/LightTextureNode.cs +++ b/Packages/com.unity.render-pipelines.universal/Editor/2D/ShaderGraph/Nodes/LightTextureNode.cs @@ -87,9 +87,16 @@ public override void CollectShaderProperties(PropertyCollector properties, Gener overrideReferenceName = GetVariableName(), generatePropertyBlock = false, defaultType = Texture2DShaderProperty.DefaultType.White, - // value = m_Texture, modifiable = false }); + + properties.AddShaderProperty(new Texture2DShaderProperty + { + defaultType = Texture2DShaderProperty.DefaultType.White, + generatePropertyBlock = false, + overrideReferenceName = "_DefaultWhiteTex", + displayName = "DefaultWhiteTex", + }); } } } diff --git a/Packages/com.unity.render-pipelines.universal/Runtime/2D/Passes/Utility/RendererLighting.cs b/Packages/com.unity.render-pipelines.universal/Runtime/2D/Passes/Utility/RendererLighting.cs index 2e0b74dcedf..d334cb19943 100644 --- a/Packages/com.unity.render-pipelines.universal/Runtime/2D/Passes/Utility/RendererLighting.cs +++ b/Packages/com.unity.render-pipelines.universal/Runtime/2D/Passes/Utility/RendererLighting.cs @@ -12,8 +12,10 @@ internal static class RendererLighting private static readonly ShaderTagId k_NormalsRenderingPassName = new ShaderTagId("NormalsRendering"); public static readonly Color k_NormalClearColor = new Color(0.5f, 0.5f, 0.5f, 1.0f); private static readonly string k_UsePointLightCookiesKeyword = "USE_POINT_LIGHT_COOKIES"; + private static readonly string k_UseSpriteLight = "USE_SPRITE_LIGHT"; private static readonly string k_LightQualityFastKeyword = "LIGHT_QUALITY_FAST"; private static readonly string k_UseNormalMap = "USE_NORMAL_MAP"; + private static readonly string k_UseShadowMap = "USE_SHADOW_MAP"; private static readonly string k_UseAdditiveBlendingKeyword = "USE_ADDITIVE_BLENDING"; private static readonly string k_UseVolumetric = "USE_VOLUMETRIC"; @@ -192,14 +194,14 @@ internal static void GetTransparencySortingMode(Renderer2DData rendererData, Cam } } - private static bool CanRenderLight(IRenderPass2D pass, Light2D light, int blendStyleIndex, int layerToRender, bool isVolume, ref Mesh lightMesh, ref Material lightMaterial) + private static bool CanRenderLight(IRenderPass2D pass, Light2D light, int blendStyleIndex, int layerToRender, bool isVolume, bool hasShadows, ref Mesh lightMesh, ref Material lightMaterial) { if (light != null && light.lightType != Light2D.LightType.Global && light.blendStyleIndex == blendStyleIndex && light.IsLitLayer(layerToRender)) { lightMesh = light.lightMesh; if (lightMesh == null) return false; - lightMaterial = pass.rendererData.GetLightMaterial(light, isVolume); + lightMaterial = pass.rendererData.GetLightMaterial(light, isVolume, hasShadows); if (lightMaterial == null) return false; return true; @@ -222,7 +224,7 @@ internal static void RenderLight(IRenderPass2D pass, CommandBuffer cmd, Light2D { Mesh lightMesh = null; Material lightMaterial = null; - if (!CanRenderLight(pass, light, blendStyleIndex, layerToRender, isVolume, ref lightMesh, ref lightMaterial)) + if (!CanRenderLight(pass, light, blendStyleIndex, layerToRender, isVolume, hasShadows, ref lightMesh, ref lightMaterial)) return; // For Batching. @@ -659,7 +661,7 @@ private static void SetBlendModes(Material material, BlendMode src, BlendMode ds material.SetFloat(k_DstBlendID, (float)dst); } - private static uint GetLightMaterialIndex(Light2D light, bool isVolume) + private static uint GetLightMaterialIndex(Light2D light, bool isVolume, bool useShadows) { var isPoint = light.isPointLight; var bitIndex = 0; @@ -671,14 +673,18 @@ private static uint GetLightMaterialIndex(Light2D light, bool isVolume) bitIndex++; var pointCookieBit = (isPoint && light.lightCookieSprite != null && light.lightCookieSprite.texture != null) ? 1u << bitIndex : 0u; bitIndex++; + var spriteLightBit = (light.lightType == Light2D.LightType.Sprite) ? 1u << bitIndex : 0u; + bitIndex++; var fastQualityBit = (light.normalMapQuality == Light2D.NormalMapQuality.Fast) ? 1u << bitIndex : 0u; bitIndex++; var useNormalMap = light.normalMapQuality != Light2D.NormalMapQuality.Disabled ? 1u << bitIndex : 0u; + bitIndex++; + var useShadowMap = useShadows ? 1u << bitIndex : 0u; - return fastQualityBit | pointCookieBit | additiveBit | shapeBit | volumeBit | useNormalMap; + return fastQualityBit | pointCookieBit | spriteLightBit | additiveBit | shapeBit | volumeBit | useNormalMap | useShadowMap; } - private static Material CreateLightMaterial(Renderer2DData rendererData, Light2D light, bool isVolume) + private static Material CreateLightMaterial(Renderer2DData rendererData, Light2D light, bool isVolume, bool useShadows) { if (!GraphicsSettings.TryGetRenderPipelineSettings(out var resources)) return null; @@ -712,22 +718,28 @@ private static Material CreateLightMaterial(Renderer2DData rendererData, Light2D if (isPoint && light.lightCookieSprite != null && light.lightCookieSprite.texture != null) material.EnableKeyword(k_UsePointLightCookiesKeyword); + if (light.lightType == Light2D.LightType.Sprite) + material.EnableKeyword(k_UseSpriteLight); + if (light.normalMapQuality == Light2D.NormalMapQuality.Fast) material.EnableKeyword(k_LightQualityFastKeyword); if (light.normalMapQuality != Light2D.NormalMapQuality.Disabled) material.EnableKeyword(k_UseNormalMap); + if (useShadows) + material.EnableKeyword(k_UseShadowMap); + return material; } - public static Material GetLightMaterial(this Renderer2DData rendererData, Light2D light, bool isVolume) + internal static Material GetLightMaterial(this Renderer2DData rendererData, Light2D light, bool isVolume, bool useShadows) { - var materialIndex = GetLightMaterialIndex(light, isVolume); + var materialIndex = GetLightMaterialIndex(light, isVolume, useShadows); if (!rendererData.lightMaterials.TryGetValue(materialIndex, out var material)) { - material = CreateLightMaterial(rendererData, light, isVolume); + material = CreateLightMaterial(rendererData, light, isVolume, useShadows); rendererData.lightMaterials[materialIndex] = material; } diff --git a/Packages/com.unity.render-pipelines.universal/Runtime/2D/Renderer2D.cs b/Packages/com.unity.render-pipelines.universal/Runtime/2D/Renderer2D.cs index 9c1be2aecda..46b2c7ab0cf 100644 --- a/Packages/com.unity.render-pipelines.universal/Runtime/2D/Renderer2D.cs +++ b/Packages/com.unity.render-pipelines.universal/Runtime/2D/Renderer2D.cs @@ -361,13 +361,6 @@ public override void Setup(ScriptableRenderContext context, ref RenderingData re var cmd = universalRenderingData.commandBuffer; -#if UNITY_EDITOR - if(m_DefaultWhiteTextureHandle == null) - m_DefaultWhiteTextureHandle = RTHandles.Alloc(Texture2D.whiteTexture, "_DefaultWhiteTex"); - - cmd.SetGlobalTexture(m_DefaultWhiteTextureHandle.name, m_DefaultWhiteTextureHandle.nameID); -#endif - using (new ProfilingScope(cmd, m_ProfilingSampler)) { CreateRenderTextures(ref renderPassInputs, cmd, cameraData, ppcUsesOffscreenRT, colorTextureFilterMode, diff --git a/Packages/com.unity.render-pipelines.universal/Runtime/2D/Rendergraph/DrawLight2DPass.cs b/Packages/com.unity.render-pipelines.universal/Runtime/2D/Rendergraph/DrawLight2DPass.cs index 1b45af8e9fc..db5324f1d66 100644 --- a/Packages/com.unity.render-pipelines.universal/Runtime/2D/Rendergraph/DrawLight2DPass.cs +++ b/Packages/com.unity.render-pipelines.universal/Runtime/2D/Rendergraph/DrawLight2DPass.cs @@ -85,7 +85,8 @@ private static void Execute(RasterCommandBuffer cmd, PassData passData, ref Laye layerBatch.endLayerValue != light.GetTopMostLitLayer())) continue; - var lightMaterial = passData.rendererData.GetLightMaterial(light, passData.isVolumetric); + var useShadows = passData.layerBatch.lightStats.useShadows && layerBatch.shadowIndices.Contains(j); + var lightMaterial = passData.rendererData.GetLightMaterial(light, passData.isVolumetric, useShadows); var lightMesh = light.lightMesh; // For Batching. @@ -100,7 +101,6 @@ private static void Execute(RasterCommandBuffer cmd, PassData passData, ref Laye if (passData.layerBatch.lightStats.useNormalMap) s_PropertyBlock.SetTexture(k_NormalMapID, passData.normalMap); - var useShadows = passData.layerBatch.lightStats.useShadows && layerBatch.shadowIndices.Contains(j); if (useShadows && TryGetShadowIndex(ref layerBatch, j, out var shadowIndex)) s_PropertyBlock.SetTexture(k_ShadowMapID, passData.shadowTextures[shadowIndex]); @@ -163,7 +163,8 @@ internal static void ExecuteUnsafe(UnsafeCommandBuffer cmd, PassData passData, r layerBatch.endLayerValue != light.GetTopMostLitLayer())) continue; - var lightMaterial = passData.rendererData.GetLightMaterial(light, passData.isVolumetric); + var useShadows = passData.layerBatch.lightStats.useShadows && layerBatch.shadowIndices.Contains(j); + var lightMaterial = passData.rendererData.GetLightMaterial(light, passData.isVolumetric, useShadows); var lightMesh = light.lightMesh; // For Batching. @@ -178,7 +179,6 @@ internal static void ExecuteUnsafe(UnsafeCommandBuffer cmd, PassData passData, r if (passData.layerBatch.lightStats.useNormalMap) s_PropertyBlock.SetTexture(k_NormalMapID, passData.normalMap); - var useShadows = passData.layerBatch.lightStats.useShadows && layerBatch.shadowIndices.Contains(j); if (useShadows && TryGetShadowIndex(ref layerBatch, j, out var shadowIndex)) s_PropertyBlock.SetTexture(k_ShadowMapID, passData.shadowTextures[shadowIndex]); diff --git a/Packages/com.unity.render-pipelines.universal/Runtime/2D/Rendergraph/GlobalPropertiesPass.cs b/Packages/com.unity.render-pipelines.universal/Runtime/2D/Rendergraph/GlobalPropertiesPass.cs index 2eafb72663d..34d70f20a4e 100644 --- a/Packages/com.unity.render-pipelines.universal/Runtime/2D/Rendergraph/GlobalPropertiesPass.cs +++ b/Packages/com.unity.render-pipelines.universal/Runtime/2D/Rendergraph/GlobalPropertiesPass.cs @@ -7,16 +7,12 @@ internal class GlobalPropertiesPass : ScriptableRenderPass static readonly string k_SetGlobalProperties = "SetGlobalProperties"; private static readonly ProfilingSampler m_SetGlobalPropertiesProfilingSampler = new ProfilingSampler(k_SetGlobalProperties); -#if UNITY_EDITOR - private static readonly int k_DefaultWhiteTextureID = Shader.PropertyToID("_DefaultWhiteTex"); -#endif - class PassData { internal Vector2Int screenParams; } - internal static void Setup(RenderGraph graph, ContextContainer frameData, Renderer2DData rendererData, UniversalCameraData cameraData) + internal static void Setup(RenderGraph graph, ContextContainer frameData, Renderer2DData rendererData, UniversalCameraData cameraData, bool useLights) { Universal2DResourceData universal2DResourceData = frameData.Get(); @@ -28,15 +24,15 @@ internal static void Setup(RenderGraph graph, ContextContainer frameData, Render if (pixelPerfectCamera != null && pixelPerfectCamera.enabled && pixelPerfectCamera.offscreenRTSize != Vector2Int.zero) passData.screenParams = pixelPerfectCamera.offscreenRTSize; - // Set light lookup and fall off textures as global - var lightLookupTexture = graph.ImportTexture(Light2DLookupTexture.GetLightLookupTexture_Rendergraph()); - var fallOffTexture = graph.ImportTexture(Light2DLookupTexture.GetFallOffLookupTexture_Rendergraph()); + if (useLights) + { + // Set light lookup and fall off textures as global + var lightLookupTexture = graph.ImportTexture(Light2DLookupTexture.GetLightLookupTexture_Rendergraph()); + var fallOffTexture = graph.ImportTexture(Light2DLookupTexture.GetFallOffLookupTexture_Rendergraph()); - builder.SetGlobalTextureAfterPass(lightLookupTexture, Light2DLookupTexture.k_LightLookupID); - builder.SetGlobalTextureAfterPass(fallOffTexture, Light2DLookupTexture.k_FalloffLookupID); -#if UNITY_EDITOR - builder.SetGlobalTextureAfterPass(graph.defaultResources.whiteTexture, k_DefaultWhiteTextureID); -#endif + builder.SetGlobalTextureAfterPass(lightLookupTexture, Light2DLookupTexture.k_LightLookupID); + builder.SetGlobalTextureAfterPass(fallOffTexture, Light2DLookupTexture.k_FalloffLookupID); + } if (rendererData.useCameraSortingLayerTexture) builder.SetGlobalTextureAfterPass(universal2DResourceData.cameraSortingLayerTexture, CopyCameraSortingLayerPass.k_CameraSortingLayerTextureId); diff --git a/Packages/com.unity.render-pipelines.universal/Runtime/2D/Rendergraph/Renderer2DRendergraph.cs b/Packages/com.unity.render-pipelines.universal/Runtime/2D/Rendergraph/Renderer2DRendergraph.cs index 6c1d7239102..6a006244ec0 100644 --- a/Packages/com.unity.render-pipelines.universal/Runtime/2D/Rendergraph/Renderer2DRendergraph.cs +++ b/Packages/com.unity.render-pipelines.universal/Runtime/2D/Rendergraph/Renderer2DRendergraph.cs @@ -611,8 +611,12 @@ private void OnMainRendering(RenderGraph renderGraph) var cameraSortingLayerBoundsIndex = Render2DLightingPass.GetCameraSortingLayerBoundsIndex(m_Renderer2DData); + bool useLights = false; + for (int i = 0; i < m_BatchCount; ++i) + useLights |= m_LayerBatches[i].lightStats.useLights; + // Set Global Properties and Textures - GlobalPropertiesPass.Setup(renderGraph, frameData, m_Renderer2DData, cameraData); + GlobalPropertiesPass.Setup(renderGraph, frameData, m_Renderer2DData, cameraData, useLights); // Main render passes diff --git a/Packages/com.unity.render-pipelines.universal/Shaders/2D/Include/ShapeLightVariables.hlsl b/Packages/com.unity.render-pipelines.universal/Shaders/2D/Include/ShapeLightVariables.hlsl index f0b4ef1a3d6..47993aef946 100644 --- a/Packages/com.unity.render-pipelines.universal/Shaders/2D/Include/ShapeLightVariables.hlsl +++ b/Packages/com.unity.render-pipelines.universal/Shaders/2D/Include/ShapeLightVariables.hlsl @@ -1,10 +1,6 @@ #ifndef SHAPE_LIGHT_VARIABLES #define SHAPE_LIGHT_VARIABLES -TEXTURE2D(_DefaultWhiteTex); -SAMPLER(sampler_DefaultWhiteTex); -float4 _DefaultWhiteTex_TexelSize; - half _HDREmulationScale; #endif diff --git a/Packages/com.unity.render-pipelines.universal/Shaders/2D/Light2D.shader b/Packages/com.unity.render-pipelines.universal/Shaders/2D/Light2D.shader index 1dacff8dafe..da01448ca75 100644 --- a/Packages/com.unity.render-pipelines.universal/Shaders/2D/Light2D.shader +++ b/Packages/com.unity.render-pipelines.universal/Shaders/2D/Light2D.shader @@ -21,9 +21,11 @@ Shader "Hidden/Light2D" #pragma vertex vert #pragma fragment frag #pragma multi_compile_local USE_NORMAL_MAP __ + #pragma multi_compile_local USE_SHADOW_MAP __ #pragma multi_compile_local USE_ADDITIVE_BLENDING __ #pragma multi_compile_local USE_VOLUMETRIC __ #pragma multi_compile_local USE_POINT_LIGHT_COOKIES __ + #pragma multi_compile_local USE_SPRITE_LIGHT __ #pragma multi_compile_local LIGHT_QUALITY_FAST __ #include_with_pragmas "Packages/com.unity.render-pipelines.universal/Shaders/2D/Include/ShapeLightShared.hlsl" @@ -49,8 +51,10 @@ Shader "Hidden/Light2D" LIGHT_OFFSET(TEXCOORD5) }; +#if USE_SPRITE_LIGHT TEXTURE2D(_CookieTex); // This can either be a sprite texture uv or a falloff texture SAMPLER(sampler_CookieTex); +#endif TEXTURE2D(_FalloffLookup); SAMPLER(sampler_FalloffLookup); @@ -149,30 +153,36 @@ Shader "Hidden/Light2D" FragmentOutput frag_shape(Varyings i, PerLight2D light) { half4 lightColor = i.color; - if (_L2D_LIGHT_TYPE == 2) - { - half4 cookie = SAMPLE_TEXTURE2D(_CookieTex, sampler_CookieTex, i.uv); -#if USE_ADDITIVE_BLENDING - lightColor *= cookie * cookie.a; -#else - lightColor *= cookie; -#endif - } - else - { -#if USE_ADDITIVE_BLENDING - lightColor *= SAMPLE_TEXTURE2D(_FalloffLookup, sampler_FalloffLookup, i.uv).r; -#elif USE_VOLUMETRIC - lightColor.a = i.color.a * SAMPLE_TEXTURE2D(_FalloffLookup, sampler_FalloffLookup, i.uv).r; + +#if USE_SPRITE_LIGHT + half4 cookie = SAMPLE_TEXTURE2D(_CookieTex, sampler_CookieTex, i.uv); + + #if USE_ADDITIVE_BLENDING + lightColor *= cookie * cookie.a; + #else + lightColor *= cookie; + #endif + #else - lightColor.a = SAMPLE_TEXTURE2D(_FalloffLookup, sampler_FalloffLookup, i.uv).r; -#endif - } + + #if USE_ADDITIVE_BLENDING + lightColor *= SAMPLE_TEXTURE2D(_FalloffLookup, sampler_FalloffLookup, i.uv).r; + #elif USE_VOLUMETRIC + lightColor.a = i.color.a * SAMPLE_TEXTURE2D(_FalloffLookup, sampler_FalloffLookup, i.uv).r; + #else + lightColor.a = SAMPLE_TEXTURE2D(_FalloffLookup, sampler_FalloffLookup, i.uv).r; + #endif + +#endif // USE_SPRITE_LIGHT #if !USE_VOLUMETRIC APPLY_NORMALS_LIGHTING(i, lightColor, _L2D_POSITION.xyz, _L2D_POSITION.w); #endif + +#if USE_SHADOW_MAP APPLY_SHADOWS(i, lightColor, _L2D_SHADOW_INTENSITY); +#endif + return ToFragmentOutput(lightColor); } @@ -208,7 +218,10 @@ Shader "Hidden/Light2D" #if !USE_VOLUMETRIC APPLY_NORMALS_LIGHTING(i, lightColor, _L2D_POSITION.xyz, _L2D_POSITION.w); #endif + +#if USE_SHADOW_MAP APPLY_SHADOWS(i, lightColor, _L2D_SHADOW_INTENSITY); +#endif #if USE_VOLUMETRIC lightColor *= _L2D_VOLUME_OPACITY; From 86e043cde7060ca1f547719870ce7f9ccc6a9aa4 Mon Sep 17 00:00:00 2001 From: Reach Platform Support Date: Tue, 2 Sep 2025 21:44:53 +0000 Subject: [PATCH 16/36] [Port] [6000.2] [UUM-101919][6000.3][2D] Fix Light Batching Debugger UI constantly refreshing --- .../2D/LightBatchingDebugger/LightBatchingDebugger.cs | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/Packages/com.unity.render-pipelines.universal/Editor/2D/LightBatchingDebugger/LightBatchingDebugger.cs b/Packages/com.unity.render-pipelines.universal/Editor/2D/LightBatchingDebugger/LightBatchingDebugger.cs index 67b44df185c..f98c64c2e4a 100644 --- a/Packages/com.unity.render-pipelines.universal/Editor/2D/LightBatchingDebugger/LightBatchingDebugger.cs +++ b/Packages/com.unity.render-pipelines.universal/Editor/2D/LightBatchingDebugger/LightBatchingDebugger.cs @@ -457,18 +457,17 @@ private void Update() private bool IsDirty() { + if (lightCullResult == null) + return false; + bool isDirty = false; // Refresh if layers are added or removed isDirty |= Light2DManager.GetCachedSortingLayer().Count() != batchList.Sum(x => x.LayerNames.Count()); isDirty |= cachedSceneHandle != SceneManager.GetActiveScene().handle; isDirty |= cachedCamPos != Camera.main?.transform.position; - - if (lightCullResult != null) - { - isDirty |= totalLightCount != lightCullResult.visibleLights.Count(); - isDirty |= totalShadowCount != lightCullResult.visibleShadows.Count(); - } + isDirty |= totalLightCount != lightCullResult.visibleLights.Count(); + isDirty |= totalShadowCount != lightCullResult.visibleShadows.Count(); return isDirty; } From 35685ea353db920820e825383bbd624e22b065c4 Mon Sep 17 00:00:00 2001 From: Reach Platform Support Date: Tue, 2 Sep 2025 21:44:53 +0000 Subject: [PATCH 17/36] [Port] [6000.2] DOCG-7369 Improve Object node docs --- .../Documentation~/Object-Node.md | 33 ++++++++++--------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/Packages/com.unity.shadergraph/Documentation~/Object-Node.md b/Packages/com.unity.shadergraph/Documentation~/Object-Node.md index fdad51f00db..c01fb9d4348 100644 --- a/Packages/com.unity.shadergraph/Documentation~/Object-Node.md +++ b/Packages/com.unity.shadergraph/Documentation~/Object-Node.md @@ -1,32 +1,33 @@ -# Object Node +# Object node -## Description +The Object node outputs the position, scale, or bounds of the overall GameObject that Unity is currently rendering. -Provides access to various parameters of the currently rendering **Object**. +## Render pipeline compatibility -Note: The behaviour of the Position [Port](Port.md) can be defined per Render Pipeline. Different Render Pipelines may produce different results. If you're building a shader in one Render Pipeline that you want to use in both, try checking it in both pipelines before production. +The Object node is compatible with the following render pipelines: -#### Unity Render Pipelines Support -- Universal Render Pipeline -- High Definition Render Pipeline +- Universal Render Pipeline (URP) +- High Definition Render Pipeline (HDRP) + +**Note:** The output of the **Position** port might depend on the render pipeline you use. If you use your shader in both URP and HDRP, check the results in both pipelines before you use the shader in production. ## Ports -| Name | Direction | Type | Binding | Description | +| **Name** | **Direction** | **Type** | **Binding** | **Description** | |:------------ |:-------------|:-----|:---|:---| -| Position | Output | Vector 3 | None | Object position in world space | -| Scale | Output | Vector 3 | None | Object scale in world space | -| World Bounds Min | Output | Vector 3 | None | Minimum value of the renderer bounds in world space | -| World Bounds Max | Output | Vector 3 | None | Maximum value of the renderer bounds in world space | -| Bounds Size | Output | Vector 3 | None | Size of the renderer bounds | +| **Position** | Output | Vector 3 | None | The position of the overall GameObject in world space. | +| **Scale** | Output | Vector 3 | None | The scale of the overall GameObject in world space | +| **World Bounds Min** | Output | Vector 3 | None | The minimum position of the axis-aligned bounding box that fully encloses the GameObject in world space. | +| **World Bounds Max** | Output | Vector 3 | None | The maximum position of the bounding box. | +| **Bounds Size** | Output | Vector 3 | None | The total size of the bounding box. | -Note: the bounds values are the equivalent of [the bounds in the renderer component](https://docs.unity3d.com/ScriptReference/Renderer-bounds.html). This means that vertex deformation done in ShaderGraph doesn't affect these values. +**Note:** The bounds values are equivalent to the [bounds in the Renderer component](https://docs.unity3d.com/ScriptReference/Renderer-bounds.html) of the GameObject. If you deform the vertices in the shader graph, the bounds in the Renderer component don't change. -## Generated Code Example +## Generated code example The following example code represents one possible outcome of this node. -``` +```hlsl float3 _Object_Position = SHADERGRAPH_OBJECT_POSITION; float3 _Object_Scale = float3(length(float3(UNITY_MATRIX_M[0].x, UNITY_MATRIX_M[1].x, UNITY_MATRIX_M[2].x)), length(float3(UNITY_MATRIX_M[0].y, UNITY_MATRIX_M[1].y, UNITY_MATRIX_M[2].y)), From 4867644b8b01970697ea20c0ad0d47f40c01c0d3 Mon Sep 17 00:00:00 2001 From: Christian Sasseville Date: Tue, 2 Sep 2025 21:44:54 +0000 Subject: [PATCH 18/36] [UUM-115756] [UUM-115757] Disabling 2 tests on PS4 --- .../Assets/Tests/HDRP_Runtime_Graphics_Tests.cs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/Tests/SRPTests/Projects/HDRP_RuntimeTests/Assets/Tests/HDRP_Runtime_Graphics_Tests.cs b/Tests/SRPTests/Projects/HDRP_RuntimeTests/Assets/Tests/HDRP_Runtime_Graphics_Tests.cs index 28892deb807..8416f3519c6 100644 --- a/Tests/SRPTests/Projects/HDRP_RuntimeTests/Assets/Tests/HDRP_Runtime_Graphics_Tests.cs +++ b/Tests/SRPTests/Projects/HDRP_RuntimeTests/Assets/Tests/HDRP_Runtime_Graphics_Tests.cs @@ -63,6 +63,16 @@ public class HDRP_Runtime_Graphics_Tests "003-VirtualTexturing-Forward$", "Artifacts appear at random on objects within the scene, see UUM-113462.", graphicsDeviceTypes: new GraphicsDeviceType[] { GraphicsDeviceType.GameCoreXboxSeries } + )] + [IgnoreGraphicsTest( + "003-VirtualTexturing$", + "PS4 https://jira.unity3d.com/browse/UUM-115757", + runtimePlatforms: new RuntimePlatform[] { RuntimePlatform.PS4 } + )] + [IgnoreGraphicsTest( + "003-VirtualTexturing-Forward$", + "PS4 https://jira.unity3d.com/browse/UUM-115756", + runtimePlatforms: new RuntimePlatform[] { RuntimePlatform.PS4 } )] [IgnoreGraphicsTest( "004-CloudsFlaresDecals$", From d7f5a4f6b56ad68f8d37c1fd61ad7fb0282ac5a4 Mon Sep 17 00:00:00 2001 From: Reach Platform Support Date: Tue, 2 Sep 2025 21:44:54 +0000 Subject: [PATCH 19/36] [Port] [6000.2] docg-7338: Fix Parallax Mapping image --- Packages/com.unity.shadergraph/Documentation~/UV-Nodes.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Packages/com.unity.shadergraph/Documentation~/UV-Nodes.md b/Packages/com.unity.shadergraph/Documentation~/UV-Nodes.md index e5076f9438b..4256df6f3fa 100644 --- a/Packages/com.unity.shadergraph/Documentation~/UV-Nodes.md +++ b/Packages/com.unity.shadergraph/Documentation~/UV-Nodes.md @@ -14,5 +14,5 @@ | ![Example of the Triplanar Node](images/TriplanarNodeThumb.png) | ![Example of the Twirl Node](images/TwirlNodeThumb.png) | | A method of generating UVs and sampling a texture by projecting in world space. | Applies a twirl warping effect similar to a black hole to the value of input UV. | | [**Parallax Mapping**](Parallax-Mapping-Node.md) | [**Parallax Occlusion Mapping**](Parallax-Occlusion-Mapping-Node.md) | -| ![Example of the Parallax Mapping Node](images/ParallaxOcclusionMappingThumb.png) | ![Example of the Parallax Occlusion Mapping Node](images/ParallaxOcclusionMappingNodeThumb.PNG) | +| ![Example of the Parallax Mapping Node](images/ParallaxMappingNodeThumb.PNG) | ![Example of the Parallax Occlusion Mapping Node](images/ParallaxOcclusionMappingNodeThumb.PNG) | | Creates a parallax effect that displaces a material's UVs. | Creates a parallax effect that displaces a material's UVs and depth. | From 295918bdb497dafe31bdabce212614d2165a9388 Mon Sep 17 00:00:00 2001 From: Reach Platform Support Date: Tue, 2 Sep 2025 21:44:54 +0000 Subject: [PATCH 20/36] [Port] [6000.2] docg-7367: Add section about https://unity.com/blog/engine-platform/new-shader-graph-node-reference-samples --- .../Documentation~/Node-Library.md | 5 +++++ .../Documentation~/ShaderGraph-Samples.md | 10 ++++++---- .../Documentation~/images/PatternSamples_01.png | Bin 86753 -> 0 bytes .../Documentation~/images/PatternSamples_02.png | Bin 14474 -> 0 bytes 4 files changed, 11 insertions(+), 4 deletions(-) delete mode 100644 Packages/com.unity.shadergraph/Documentation~/images/PatternSamples_01.png delete mode 100644 Packages/com.unity.shadergraph/Documentation~/images/PatternSamples_02.png diff --git a/Packages/com.unity.shadergraph/Documentation~/Node-Library.md b/Packages/com.unity.shadergraph/Documentation~/Node-Library.md index 4ef5902536d..1702a8697e9 100644 --- a/Packages/com.unity.shadergraph/Documentation~/Node-Library.md +++ b/Packages/com.unity.shadergraph/Documentation~/Node-Library.md @@ -20,3 +20,8 @@ The **Node Library** contains documentation for all the individual [Nodes](Node. |:-|:-| | [Built In](Built-In-Blocks.md) | | | Universal | High Definition | + + +## Shader graph node reference samples + +To learn node functions or get deeper insights and ideas for custom shaders, browse the [Shader Graph Node Reference Samples](ShaderGraph-Samples.md). diff --git a/Packages/com.unity.shadergraph/Documentation~/ShaderGraph-Samples.md b/Packages/com.unity.shadergraph/Documentation~/ShaderGraph-Samples.md index b86d6b88a2a..0f4571d108d 100644 --- a/Packages/com.unity.shadergraph/Documentation~/ShaderGraph-Samples.md +++ b/Packages/com.unity.shadergraph/Documentation~/ShaderGraph-Samples.md @@ -6,13 +6,15 @@ The Shader Graph package offers sample Assets, which you can download through ** ## Add samples -To add samples to your Project, go to **Window** > **Package Manager**. Locate **Shader Graph** in the list of available packages, and select it. Under the package description, there is list of available samples. Click the **Import into Project** button next to the sample you wish to add. +To add samples to your project: -![](images/PatternSamples_01.png) +1. In the main menu, go to **Window** > **Package Management** > **Package Manager**. -Unity places imported samples in your Project's Asset folder under **Assets** > **Samples** > **Shader Graph** > **[version number]** > **[sample name]**. The example below shows the samples for **Procedural Patterns**. +1. Select **Shader Graph** from the list of packages. -![](images/PatternSamples_02.png) +1. In the **Samples** section, select **Import** next to a sample. + +1. Open the sample assets from the `Assets/Samples/Shader Graph//` folder. ## Available samples diff --git a/Packages/com.unity.shadergraph/Documentation~/images/PatternSamples_01.png b/Packages/com.unity.shadergraph/Documentation~/images/PatternSamples_01.png deleted file mode 100644 index 6ab8b28d224a233b484907073607260118998fe7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 86753 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 O*C|yk{4*7E!v6y!t$_pp diff --git a/Packages/com.unity.shadergraph/Documentation~/images/PatternSamples_02.png b/Packages/com.unity.shadergraph/Documentation~/images/PatternSamples_02.png deleted file mode 100644 index 56bebecf8840819510340e5a8d9b86019459df95..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 14474 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 Date: Tue, 2 Sep 2025 21:44:54 +0000 Subject: [PATCH 21/36] [Port] [6000.2] docg-7320: Unexposed properties revert to default values --- Packages/com.unity.shadergraph/Documentation~/Blackboard.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Packages/com.unity.shadergraph/Documentation~/Blackboard.md b/Packages/com.unity.shadergraph/Documentation~/Blackboard.md index 9a302e382ac..6e66c3d15d3 100644 --- a/Packages/com.unity.shadergraph/Documentation~/Blackboard.md +++ b/Packages/com.unity.shadergraph/Documentation~/Blackboard.md @@ -75,6 +75,8 @@ To modify a material you have created with a Shader Graph, you can adjust specif ## Exposing properties and keywords Unity exposes properties and keywords by default. This enables write access from scripts, so that you can edit them via the C# API, in addition to the graph. Exposed items have a green dot in their label. Enable or disable this feature in the **Node Settings** menu. +If you disable the **Exposed** setting of a property, the property reverts to the default value and no longer uses the custom value you set. + ## Creating nodes Drag a property or keyword from the Blackboard into the graph to create a node of that kind. Settings for a node in the graph are identical to those for the related property or keyword in the Blackboard. Expand these nodes to use a sub-member of the property value. From ba52e78f1b364f0f5a12cde0e8e344c5fda3f6c3 Mon Sep 17 00:00:00 2001 From: Reach Platform Support Date: Tue, 2 Sep 2025 21:44:54 +0000 Subject: [PATCH 22/36] [Port] [6000.2] docs/graphics/docg-7326: Improve explanation of Unpack normal --- .../com.unity.shadergraph/Documentation~/Normal-Unpack-Node.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Packages/com.unity.shadergraph/Documentation~/Normal-Unpack-Node.md b/Packages/com.unity.shadergraph/Documentation~/Normal-Unpack-Node.md index 336b72e9f0b..986a96dca3a 100644 --- a/Packages/com.unity.shadergraph/Documentation~/Normal-Unpack-Node.md +++ b/Packages/com.unity.shadergraph/Documentation~/Normal-Unpack-Node.md @@ -4,6 +4,8 @@ Unpacks a normal map defined by input **In**. This node is used to unpack a texture that is defined as a **Normal Map** in its Texture Import Settings when it is sampled as if it were a default texture. +Data is stored in textures from 0 to 1. But vectors need to be from -1 to 1. Unpacking the normal means to expand its range from the original range to a range of -1 to 1, so you can use it as a vector. + Note that in most cases this node is unnecessary as the normal map should be sampled as such by setting its **Type** parameter to **Normal** when it is sampled using a [Sample Texture 2D](Sample-Texture-2D-Node.md) or [Triplanar](Triplanar-Node.md) node. ## Ports From 469b6148402fa88098d2ef2a15992aaab31b769e Mon Sep 17 00:00:00 2001 From: Reach Platform Support Date: Tue, 2 Sep 2025 21:44:54 +0000 Subject: [PATCH 23/36] [Port] [6000.2] DOCG-6643: Improve quality of Blackboard page in VFX Graph --- .../Documentation~/Attributes.md | 24 ++- .../Documentation~/Blackboard.md | 137 +----------------- .../Images/blackboard-subtitle.png | Bin 18644 -> 0 bytes .../Documentation~/Properties.md | 58 +++++++- .../Documentation~/Subgraph.md | 52 +++++-- 5 files changed, 118 insertions(+), 153 deletions(-) delete mode 100644 Packages/com.unity.visualeffectgraph/Documentation~/Images/blackboard-subtitle.png diff --git a/Packages/com.unity.visualeffectgraph/Documentation~/Attributes.md b/Packages/com.unity.visualeffectgraph/Documentation~/Attributes.md index 1ad1607841c..34f8801f23e 100644 --- a/Packages/com.unity.visualeffectgraph/Documentation~/Attributes.md +++ b/Packages/com.unity.visualeffectgraph/Documentation~/Attributes.md @@ -4,11 +4,27 @@ An Attribute is a piece of data attached to elements in a System. For example, t Systems can read from, or write to, Attributes in order to perform custom behavior and differentiate between elements. +![An attribute in the Custom Attributes list with a yellow three-axes icon that represents a Vector3.](Images/blackboard-attribute.png) + A System only stores Attributes when it needs them. This means that the System does not store any unnecessary data and thus saves memory. -## Using Attributes +## Manage Attributes + +You can manage Attributes as follows: + +- To duplicate a custom attribute, use the shortcut **Ctrl+D** (macOS: **Cmd+D**) or the context menu. + +- To select several custom attributes, hold **Shift+Click** or **Ctrl+Click** (macOS: **Cmd+Click**), then drag and drop them into the graph as needed. + +- To copy custom attributes and paste them across different VFX Graphs, use **Ctrl+C** and **Ctrl+V**. -### Writing Attributes +- To highlight all nodes using a custom or a built-in attribute, hover over the attribute in the Blackboard panel. Similarly, hover over a node in the graph to highlight its corresponding attribute in the Blackboard panel. + +- To identify unused custom attributes, right-click on categories or at the top of the Blackboard panel and select the appropriate option from the context menu. This is useful for cleaning up your VFX Graph. + +- To quickly create a custom attribute, duplicate a built-in attribute using **Ctrl+D** (macOS: **Cmd+D**). This creates a new custom attribute with a name like `originalname_1` and the same type. + +### Write Attributes To write to an Attribute, use a [Block](Blocks.md). Blocks are the only graph elements that can write Attributes to the System. @@ -17,7 +33,7 @@ The Visual Effect Graph only stores an Attribute that you write to in simulation * When you write to an Attribute in Initialize or Update Contexts, the Visual Effect Graph only stores the Attribute in simulation data if a later Update or Output Context reads from the Attribute. * When you write to an Attribute in Output Contexts, the Visual Effect Graph does not store the Attribute in simulation data and only uses the Attribute for rendering. -### Reading Attributes +### Read Attributes To read from an Attribute, use an Operator or Block: @@ -28,6 +44,7 @@ To read from an Attribute, use an Operator or Block: * If you read from an Attribute that the Visual Effect Graph has not stored in the simulation data, the Attribute passes its default, constant value. * Currently, you can only read from Attributes in Particle and ParticleStrip Systems. To read from Attributes in Spawn Systems, use [Spawner Callbacks](SpawnerCallbacks.md). +* To avoid typos when writing [custom HLSL](CustomHLSL-Common.md) code, drag and drop an attribute directly into the HLSL code editor in Unity. ## Attribute Locations @@ -58,3 +75,4 @@ When you read from a variadic Attribute, it reads from all other implicit compon For example, you can express the **scale** of a Quad particle as a **Vector2** (as the width, and length of the quad), whereas, to express the **scale** of a Box particle, you can use a **Vector3** (as the width, length, and depth of the cube). When you set variadic attributes, a drop-down of all channel combinations allows you to write only to the necessary channels. Another example is for the rotation of a sprite around its normal. You only need the **Z** component of the angle Attribute (**angleZ**), so it is unnecessary to store **angleX**, and **angleY**. + diff --git a/Packages/com.unity.visualeffectgraph/Documentation~/Blackboard.md b/Packages/com.unity.visualeffectgraph/Documentation~/Blackboard.md index f881cdb17e9..f3157aa78b1 100644 --- a/Packages/com.unity.visualeffectgraph/Documentation~/Blackboard.md +++ b/Packages/com.unity.visualeffectgraph/Documentation~/Blackboard.md @@ -1,135 +1,12 @@ -# Blackboard +# Blackboard panel -The Blackboard is a utility panel in the [Visual Effect Graph window](VisualEffectGraphWindow.md) that allows you to manage: -- [Properties](Properties.md) -- [Custom Attributes](#attributes) -- Built-in particle [attributes](Attributes.md) - -To toggle the Blackboard visibility, you can either use the `SHIFT + 1` shortcut or click on the **Blackboard** button in the Visual Effect Graph [Toolbar](VisualEffectGraphWindow.md#Toolbar). -Drag window's edge to resize and drag the window's header to move it. - -## Properties -You can create/delete, order and categorize properties. -For each property the following options are available: - -| **Setting** | **Description** | -|-------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| **Exposed** | Specifies whether the property is exposed or not. When enabled, you can see and edit the property on the [Visual Effect Component](VisualEffectComponent.md) as well as via the [C# API](ComponentAPI.md).
When the property is exposed, a green dot is displayed (bright green if the property is used and dimmed out if not used). | -| **Value** | Specifies the default value of the property. The Visual Effect Graph uses this value if you do not expose the property or if you expose the property, but do not override it. | -| **Tooltip** | Specifies text that appears when you hover the property in the graph or in the Visual Effect component inspector. | -| **Mode** | For numerical types you can set a **Range** mode (with minimum and maximum values) which turns the value control into a slider.
And for UInt type you can also choose **Enum** which turns the control into a dropdown | - - -To use a property in the graph you can either drag and drop it in the graph, or find it by name in the node search. -You can use the same property as many times as you want in the graph (even in different systems) - -### Add a property -To add a property, click the plus `+` button in the top-left corner of the Blackboard. -A menu will open offering two options: **Property** and [**Attribute**](#attributes). Choose the **Property** option and then select the desired type. - -You can also convert an inline [Operator](Operators.md) to a property. To do this, either use the shortcut `SHIFT + X` or right-click on the Node in the graph and select either: -- **Convert to Property** if you want to create a constant. -- **Convert to Exposed Property** if you want to create an exposed property -Regardless of the option you choose, you can enable or disable the **Exposed** setting later. - -### Arranging properties -1. To rename a property you can: - - Select property and press F2 - - Double-click the property name - - Right-click the property name and select **Rename** from the context menu. - - In the inspector change the **Exposed Name** value -2. To reorder a property, drag&drop it somewhere above or below. -If you drop it over a category or inside a category the property will move to that category -3. To delete a property: - - Right-click the property then select **Delete** from the context menu. - - Select the property then press the **Delete** key (for macOS, **Cmd** + **Delete** key). - -### Property categories -Categories allow you to sort properties into groups so you can manage them more easily. You can **rename** and **delete** categories in the same way as you can for properties. -Category creation works the same way as for Properties, just pick the **Category** type at the top of the menu. -You can drag&drop properties from one category to another. If you don't want a property to be part of a category, drop it at the top of the properties. - -### Property Nodes -Property Nodes look slightly different to standard [operators](Operators.md). They display the property name and a green dot if the property is exposed. -The value is either the default value set in the blackboard or the overriden value set in the component inspector. - -You can expand them to use a sub-member of the property value. - -### Exposed Properties in the Inspector -When you enable the **Exposed** setting for a property, the property becomes visible in the **Properties** section of the Inspector for a [Visual Effect](VisualEffectComponent.md) component. -Properties appear in the same order and categories that you set in the Blackboard. - -#### Overriding property values per GameObject +You can use the Blackboard panel in the [Visual Effect Graph window](VisualEffectGraphWindow.md) to manage the following: -For each VFX component in the scene, you can override any exposed property value. -When the GameObject holding the Visual Effect is selected in the hierarchy, in the inspector you'll see all exposed properties listed. -Then if you change a property value, the override checkbox will be checked and the value overriden. -To revert your change, you can simply uncheck the override checkbox, then the default value for that property, set in the blackboard, will be used. - -## Attributes -An [attribute](Attributes.md) is a short name for **Particle Attribute** which are independent values carried by each particle. -The blackboard now lets you manage both built-in attributes and custom attributes. - -The icon on the left represents the type of the attribute. In the screenshot below, we can see that the attribute is a `Vector3` - -![An attribute in the Custom Attributes list with a yellow three-axes icon that represents a Vector3.](Images/blackboard-attribute.png) - -To use an attribute in the graph you can drag&drop it in the graph. -* If you drop it in a context, it will create a `Set Attribute` block. -* If you drop it in the void, it will create a `Get Attribute` operator. - -You can also find the attribute in the node search window. - -### Custom Attributes -For each custom attribute you can: -- **Rename**: all usage of the custom attribute will be updated automatically -- **Change type**: all usage of the custom attribute will be updated automatically -- **Add a description**: it will be displayed as a tooltip in the graph - -### Built-in Attributes -This section lists all available built-in attributes. The small locker icon on the right indicates that you cannot modify them. -For each built-in attribute you have the follwing information: -- Name -- Type -- Access (is it read-only or not) -- Description - -### Custom HLSL -To avoid typo when writing [custom HLSL](CustomHLSL-Common.md) code, you can drag&drop an attribute inside the HLSL code editor (in Unity). - -## Common Features - -- **Duplicate**: you can duplicate a property or a custom attribute with the shortcut `Ctrl + D` (macOS: `Cmd + D`) or with the context menu -- **Multi-Selection**: you can multi-select properties or custom attributes with `Shift + Click` or `Ctrl + Click`(macOS: `Cmd + Click`) and then drag&drop in the graph for instance -- **Copy/Paste**: you can copy/paste properties and custom attributes across different VFX Graphs using `Ctrl + C` and `Ctrl + V` -- **Hover Property**: if you hover a property, all corresponding nodes in the graph will get highlighted in orange -And same if you hover a node in the graph, corresponding property will be highlighted in the blackboard. -- **Hover Attribute**: if you hover an attribute, all nodes using it in the graph will get highlighted in orange -And same if you hover a node in the graph, corresponding attributes will be highlighted in the blackboard. -This applies for both custom and built-in attributes. -- **Select unused**: when right clicking on categories (or at the top of the blackboard) a context menu offers options to select unused properties or unused custom attributes. -This can be helpful when you want to cleanup your VFX. - -> [!TIP] -> A handy workflow for custom attribute is to duplicate a built-in attribute with `Ctrl + D` (macOS: `Cmd + D`). -This will create a new custom attribute with a name like `orignalname_1` and with same type. - -## Filter -Near the top of the blackboard, there are three tabs which let you filter which kind of elements to display: -- **All**: Properties and Attributes are displayed -- **Properties**: Only properties are displayed -- **Attributes**: Only attributes are displayed +- [Properties](Properties.md) +- [Attributes](Attributes.md) -## Subgraph Category -When dealing with a subgraph, the blackboard lets you specify a category that will be used in the node search. -To change the category, double-click the subtitle of the blackboard and enter the desired category name, then validate using the `Return` key. +To display or hide the Blackboard panel, press **Shift+1** or select the **Blackboard** button in the [Visual Effect Graph toolbar](VisualEffectGraphWindow.md#Toolbar). -To create multiple category levels, use the `/` character. For example, `MySubgraphs/Math`. -![Subtitle in the blackboard](Images/blackboard-subtitle.png) +## Additional resources -> [!TIP] -> You can also define visual separators to better organize your subgraphs within their category using the following syntax: -> `MySubgraphs/Math/#0Trigonometry` or `MySubgraphs/Math/#1Algebra`. -> The `#` character indicates a separator and the number indicates the sorting order. -> -> ![Separator in the blackboard](Images/nodesearch-separator.png) +[Subgraph](Subgraph.md) diff --git a/Packages/com.unity.visualeffectgraph/Documentation~/Images/blackboard-subtitle.png b/Packages/com.unity.visualeffectgraph/Documentation~/Images/blackboard-subtitle.png deleted file mode 100644 index 4ce70b3554defe0e85965d8d3ecc52e6d30ad0aa..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 18644 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 diff --git a/Packages/com.unity.visualeffectgraph/Documentation~/Properties.md b/Packages/com.unity.visualeffectgraph/Documentation~/Properties.md index a395f410e7b..873e21a49f4 100644 --- a/Packages/com.unity.visualeffectgraph/Documentation~/Properties.md +++ b/Packages/com.unity.visualeffectgraph/Documentation~/Properties.md @@ -1,10 +1,10 @@ -## Properties +# Properties Properties are editable fields that you can connect to graph elements using [Property workflow](GraphLogicAndPhilosophy.md). They can be found on graph elements such as [Contexts](Contexts.md), [Blocks](Blocks.md) and [Operators](Operators.md). ![Two examples of using properties in a VFX Graph. In the first example, a blue line indicates that a Get Attribute: velocity (Current) Operator has its y output property connected to the X input of a Absolute (float) Operator. In the second example, a Total Time Operator outputs into the X parameters of both a Sine (float) Operator and a Cosine (float) Operator, which in turn output into the X and Y input parameters of a Vector3 Operator.](Images/PropertyComponents.png) -## Using Properties +## Use Properties Properties appear on graph elements, and change their value according to their actual value in the graph. When you connect another property to a property port, the graph element displays the computed value of the connected property. @@ -22,11 +22,11 @@ Properties in Visual Effect Graph can be of any Type, including the following: * AnimationCurve * Gradient -### Accessing Property Components +### Access Property Components Properties that are made of multiple components (such as Vectors, or Colors) can display every component individually in order to connect these to other properties of compatible type. Use the arrow next to the property to unfold the components. -### Casting Properties +### Cast Properties Properties can connect between base types to perform a cast. Casts change the data type you are working on in order to inherit its properties. For example, if you cast a float to integer, the float can use integer division. @@ -60,7 +60,7 @@ Depending on the [System Simulation Space](Systems.md#system-spaces), the value ## Property Nodes -Property Nodes are [Operators](Operators.md) that give access to Graph-Wide Properties defined in the [Blackboard](Blackboard.md). These properties allow you to reuse the same value throughout the graph at different places. +Property Nodes are [Operators](Operators.md) that give access to Graph-Wide Properties defined in the [Blackboard](Blackboard.md). You can reuse the same property multiple times in the graph, even across different systems. * Property Nodes display a Green dot left to the Property name if the property is exposed. * To create a Property Node: @@ -68,3 +68,51 @@ Property Nodes are [Operators](Operators.md) that give access to Graph-Wide Prop * Open the Right Click context menu, open the **Create Node** menu and select the desired property from the Property category. * To convert a Property Node to an Inline Node of the same type, right-click the property Node and select **Convert to Inline** * When you delete a property from the Blackboard, Unity also deletes its property Node instances from the graph. + +## Create a property + +To create a new property, follow these steps: + +1. Select the **+** button in the top-left corner of the Blackboard panel. + +1. Select **Property** and choose a category. + +To display a property in the **Properties** section of the **Inspector** window for a [Visual Effect](VisualEffectComponent.md) component, enable the **Exposed** setting. + +## Manage a property + +You can manage properties as follows: + +- To duplicate a property, use the shortcut **Ctrl+D** (macOS: **Cmd+D**) or the context menu. + +- To select several properties, hold **Shift+Click** or **Ctrl+Click** (macOS: **Cmd+Click**), then drag and drop them into the graph as needed. + +- To copy properties and paste them across different VFX Graphs, use **Ctrl+C** and **Ctrl+V**. + +- To highlight all nodes corresponding to a property, hover over the property in the Blackboard panel. Similarly, hover over a node in the graph to highlight its corresponding property in the Blackboard panel. + +- To identify unused properties, right-click a category or the top of the Blackboard panel, then select **Select Unused Properties**. This is useful for cleaning up your VFX Graph. + +## Convert an inline operator into a property + +To convert an inline operator into a property, do one of the following: + +- Press **Shift+X** + +- Right-click the node in the graph and select **Convert to Property**. + +The properties are displayed in the same order and categories as defined in the Blackboard panel. + +## Override property values per GameObject + +To override an exposed property value for a specific Visual Effect component, follow these steps: + +1. Select the GameObject holding the Visual Effect in the hierarchy. + +1. In the **Inspector** window, locate the exposed properties list. + +1. Modify the value of a property. + + The corresponding checkbox is enabled. + + To revert to the default value set in the Blackboard panel, disable the checkbox. diff --git a/Packages/com.unity.visualeffectgraph/Documentation~/Subgraph.md b/Packages/com.unity.visualeffectgraph/Documentation~/Subgraph.md index c721287de9b..d56f55e1276 100644 --- a/Packages/com.unity.visualeffectgraph/Documentation~/Subgraph.md +++ b/Packages/com.unity.visualeffectgraph/Documentation~/Subgraph.md @@ -1,4 +1,4 @@ -## Subgraph +# Subgraphs A Visual Effect Subgraph is an Asset that contains a part of a Visual Effect Graph that can be used in another Visual Effect Graph or Subgraph. Subgraphs appear as a single Node. @@ -10,7 +10,7 @@ Subgraphs can be used in graphs as three main usages: Subgraphs allow you to factorize commonly used sets of Nodes in a graph into reusable Assets and adds them to the Library. -## System Subgraphs +# System Subgraphs System Subgraphs are Visual Effect Graphs that are **nested** inside other Visual Effect Graphs: @@ -21,7 +21,7 @@ Visual Effect Graphs used as Subgraphs appear as a [Context](Contexts.md) that p * **Exposed Properties** defined in the subgraph. * **Events** used in the subgraph. -### Creating System Subgraphs +## Create System Subgraphs To create a System Subgraph: @@ -32,7 +32,7 @@ To create a System Subgraph: Creating a subgraph using this method replaces all converted content with a System Subgraph Node. -### Editing System Subgraphs +## Edit System Subgraphs To edit a System Subgraph that is open in the Visual Effect Graph window: @@ -40,11 +40,11 @@ To edit a System Subgraph that is open in the Visual Effect Graph window: 2. Right-click the System Subgraph Context. 3. Select Enter Subgraph in the context menu. -### Using a System Subgraph in a Visual Effect Graph +## Use a System Subgraph in a Visual Effect Graph To add a System Subgraph Node to your Graph, drag a Visual Effect Graph from your Project View to the Visual Effect Graph window. -### Customizing System Subgraph Nodes +## Customize System Subgraph Nodes You can customize System Subgraph properties in the same way you customise Visual Effect Graph properties. You can also use Operators to create custom expressions in that extend the behavior of the systems contained in the subgraph. @@ -56,7 +56,7 @@ Block Subgraphs are specific Subgraphs that only contain Operators and Blocks. Y ![Example Block subgraph of a superpower.](Images/BlockSubgraph.png)
Example Block subgraph of a superpower. -### Creating Block Subgraphs +## Create Block Subgraphs To create a Block Subgraph: @@ -67,7 +67,7 @@ To create a Block Subgraph: When you create a subgraph using this method, Unity replaces all converted content with a Block Subgraph Node. -### Editing Block Subgraphs +## Edit Block Subgraphs You can edit a Block Subgraph in one of the following ways: @@ -84,7 +84,7 @@ You can add Blocks inside the non-removable Context named Block Subgraph. You can define the Menu Category the subgraph Block appears in the [Blackboard](Blackboard.md) -### Using Block Subgraphs +## Use Block Subgraphs To add a Block Subgraph Node to your Graph: @@ -94,17 +94,17 @@ Or: * Use the Create Block Menu by typing the Block Subgraph Asset name. -### Customizing Block Subgraphs +## Customize Block Subgraphs You can customize Block Subgraph properties in the same way as regular Block properties. You can also use Operators to create custom expressions in order to extend the behavior of the Block used as subgraph. -## Operator Subgraphs +# Operator Subgraphs Operator Subgraphs are specific Subgraphs Assets that only contain Operators and that can be used as Operators inside another Visual Effect Graph or Sub Graph. ![Example Operator subgraph of a random vector.](Images/OperatorSubgraph.png)
Example Operator subgraph of a random vector. -### Creating Operator Subgraphs +## Create Operator Subgraphs To create an Operator Subgraph: @@ -115,7 +115,7 @@ To create an Operator Subgraph: When you create a subgraph using this method, Unity replaces all converted content with an Operator Subgraph Node. -### Editing Operator Subgraphs +## Edit Operator Subgraphs To edit an Operator Subgraph by opening it in the Visual Effect Graph window: @@ -132,7 +132,7 @@ You can set up Input and Output Properties for the Operator in the Blackboard: Use the [Blackboard](Blackboard.md) to define the Menu Category that the subgraph Operator appears in. -### Using Operator Subgraphs +## Use Operator Subgraphs To add an Operator Subgraph Node to your Graph: @@ -142,6 +142,28 @@ Or: * Right-click in the workspace, select Create Node from the menu, go to Subgraph category, and pick your preferred subgraph operator. -### Customizing Operator Subgraphs +## Customize Operator Subgraphs You can customize Operator Subgraph properties in the same way as regular Block properties. You can also use Operators to create custom expressions in order to extend the behavior of the Block used as subgraph. + +## Specify a subgraph category + +To specify a category for a subgraph used in the node search, follow these steps: + +1. Double-click the subgraph. + +1. Double-click the subtitle of the Blackboard panel. + +1. Enter the desired category name. + + * To create multiple category levels, use the `/` character. + + For example, enter `MySubgraphs/Math` to create a hierarchical category. + + * To organize your subgraphs visually within their category, define separators using the following syntax: +`MySubgraphs/Math/#0Trigonometry` or `MySubgraphs/Math/#1Algebra`. + + The `#` character indicates a separator, and the number determines the sorting order. + +1. Press **Return**. + From 1a82bb3c13e0a0bcb17f237e16e4dd3165ff0c38 Mon Sep 17 00:00:00 2001 From: Reach Platform Support Date: Tue, 2 Sep 2025 21:44:55 +0000 Subject: [PATCH 24/36] [Port] [6000.2] docg-7339: Clarify Reoriented option for Normal Blend Node --- .../Documentation~/Normal-Blend-Node.md | 26 ++++++++++++------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/Packages/com.unity.shadergraph/Documentation~/Normal-Blend-Node.md b/Packages/com.unity.shadergraph/Documentation~/Normal-Blend-Node.md index 1bbac11346b..a835dd89f65 100644 --- a/Packages/com.unity.shadergraph/Documentation~/Normal-Blend-Node.md +++ b/Packages/com.unity.shadergraph/Documentation~/Normal-Blend-Node.md @@ -2,28 +2,31 @@ ## Description -Blends two normal maps defined by inputs **A** and **B** together, normalizing the result to create a valid normal map. +Blends two normal maps defined by inputs **A** and **B**, normalizing the result to produce a valid normal map representing the combined surface detail. ## Ports -| Name | Direction | Type | Binding | Description | -|:------------ |:-------------|:-----|:---|:---| -| A | Input | Vector 3 | None | First input value | -| B | Input | Vector 3 | None | Second input value | -| Out | Output | Vector 3 | None | Output value | +| Name | Direction | Type | Binding | Description | +|:-----|:----------|:---------|:--------|:------------------------| +| A | Input | Vector 3 | None | First input normal map | +| B | Input | Vector 3 | None | Second input normal map | +| Out | Output | Vector 3 | None | Blended normal map | ## Controls -| Name | Type | Options | Description | -|:------------ |:-------------|:-----|:---| -| Mode | Dropdown | Default, Reoriented | Selects the the method used for blending. | +| Name | Type | Options | Description | +|:-----|:---------|:-----------|:-------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| Mode | Dropdown | Default | Blends the two normal maps by adding their x and y components and multiplying their z components, then normalizes the result to ensure a valid normal direction. | +| Mode | Dropdown | Reoriented | Blends the two normal maps using a mathematically correct method, ensuring the resulting normal map represents a realistic combined surface. | ## Generated Code Example -The following example code represents one possible outcome of this node per **Mode**. +The following example code demonstrates how the node blends normals in each **Mode**: **Default** +Adds the x and y components (R and G channels) of the input normals, multiplies the z components (B channel), then normalizes the result. + ``` void Unity_NormalBlend_float(float3 A, float3 B, out float3 Out) { @@ -31,8 +34,11 @@ void Unity_NormalBlend_float(float3 A, float3 B, out float3 Out) } ``` + **Reoriented** +Blends the input normals using a reoriented method that makes the resulting surface normal look realistic. + ``` void Unity_NormalBlend_Reoriented_float(float3 A, float3 B, out float3 Out) { From 8407e9a2e5c90e2cf0623baf8f2d73b79b8aa20e Mon Sep 17 00:00:00 2001 From: Reach Platform Support Date: Tue, 2 Sep 2025 21:44:55 +0000 Subject: [PATCH 25/36] [Port] [6000.2] docg-7367: add Lerp formula and additional info --- Packages/com.unity.shadergraph/Documentation~/Lerp-Node.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Packages/com.unity.shadergraph/Documentation~/Lerp-Node.md b/Packages/com.unity.shadergraph/Documentation~/Lerp-Node.md index eba2d017de4..90009c2d2f8 100644 --- a/Packages/com.unity.shadergraph/Documentation~/Lerp-Node.md +++ b/Packages/com.unity.shadergraph/Documentation~/Lerp-Node.md @@ -4,7 +4,11 @@ Returns the result of linearly interpolating between input **A** and input **B** by input **T**. -For example, when the value of input **T** is 0 the return value is equal to the value of input **A**, when it is 1 the return value is equal to the value of input **B** and when it is 0.5 the return value is the midpoint of the two inputs **A** and **B**. +The output is calculated as `A + T * (B - A)`. The value of input **T** acts as a weight factor applied to the difference between **B** and **A**: + +- When **T** is `0`, the output equals **A**. +- When **T** is `1`, the output equals **B**. +- When **T** is `0.5`, the output is the midpoint between **A** and **B**. ## Ports From 24003ade54d59a9967f66f3c52b5d251159fe881 Mon Sep 17 00:00:00 2001 From: Reach Platform Support Date: Tue, 2 Sep 2025 21:44:55 +0000 Subject: [PATCH 26/36] [Port] [6000.2] docs/graphics/docg-7270: add comment to basic test code --- .../com.unity.shadergraph/Documentation~/Boolean-Node.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Packages/com.unity.shadergraph/Documentation~/Boolean-Node.md b/Packages/com.unity.shadergraph/Documentation~/Boolean-Node.md index e0785189acd..2ff09735709 100644 --- a/Packages/com.unity.shadergraph/Documentation~/Boolean-Node.md +++ b/Packages/com.unity.shadergraph/Documentation~/Boolean-Node.md @@ -18,8 +18,9 @@ Defines a constant **Boolean** value in the [Shader Graph](index.md), although i ## Generated Code Example -The following example code represents one possible outcome of this node. +The following basic test code represents one possible outcome of this node with the Boolean value set to 0: ``` -float _Boolean = 1; +float _Boolean = 0; ``` + From d5554818a23d5a65d2284d6468cec9db07c53b1b Mon Sep 17 00:00:00 2001 From: Reach Platform Support Date: Tue, 2 Sep 2025 21:44:55 +0000 Subject: [PATCH 27/36] [Port] [6000.2] docg-7769: Add Additional resources section --- .../Documentation~/Rendering-Layers.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Packages/com.unity.render-pipelines.high-definition/Documentation~/Rendering-Layers.md b/Packages/com.unity.render-pipelines.high-definition/Documentation~/Rendering-Layers.md index 22edb89fffd..0987714724c 100644 --- a/Packages/com.unity.render-pipelines.high-definition/Documentation~/Rendering-Layers.md +++ b/Packages/com.unity.render-pipelines.high-definition/Documentation~/Rendering-Layers.md @@ -72,6 +72,7 @@ Assigning the bulb’s Mesh Renderer to a specific Rendering Layer means that th ![To restore the transmission effect, create a Point Light and assign it to the same Rendering Layer as the bulb’s Mesh Renderer. Now this Point Light only affects the bulb’s Mesh Renderer and does not contribute to the rest of the Scene Lighting.](Images/LightLayers3.png)
To restore the transmission effect, create a Point Light and assign it to the same Rendering Layer as the bulb’s Mesh Renderer. Now this Point Light only affects the bulb’s Mesh Renderer and does not contribute to the rest of the Scene Lighting. +## Additional resources -For more information on this process, see Pierre Donzallaz’s [expert guide](https://pydonzallaz.files.wordpress.com/2019/02/create-high-quality-light-fixtures-in-unity.pdf) on creating high quality light fixtures in Unity. +- [Pierre Donzallaz - Expert guide: Create High-Quality  Light Fixtures in Unity](https://pydonzallaz.files.wordpress.com/2019/02/create-high-quality-light-fixtures-in-unity.pdf) From 242cdbeb3000b6591894dd7ac71ec28143ec8e60 Mon Sep 17 00:00:00 2001 From: Reach Platform Support Date: Tue, 2 Sep 2025 21:44:55 +0000 Subject: [PATCH 28/36] [Port] [6000.2] docg-7723: Change link --- .../Documentation~/rendering-debugger-window-reference.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Packages/com.unity.render-pipelines.high-definition/Documentation~/rendering-debugger-window-reference.md b/Packages/com.unity.render-pipelines.high-definition/Documentation~/rendering-debugger-window-reference.md index 2c3f2d1b6db..144ce923814 100644 --- a/Packages/com.unity.render-pipelines.high-definition/Documentation~/rendering-debugger-window-reference.md +++ b/Packages/com.unity.render-pipelines.high-definition/Documentation~/rendering-debugger-window-reference.md @@ -116,7 +116,7 @@ The **Material** panel has tools that you can use to visualize different Materia | **Attributes** | N/A | Use the drop-down to select a 3D GameObject attribute, like Texture Coordinates or Vertex Color, to visualize on screen. | | **Properties** | N/A | Use the drop-down to select a property that the debugger uses to highlight GameObjects on screen. The debugger highlights GameObjects that use a Material with the property that you select. | | **GBuffer** | N/A | Use the drop-down to select a property to visualize from the GBuffer for deferred Materials. | -| **Material Validator** | N/A | Use the drop-down to select properties to display validation colors for:
| +| **Material Validator** | N/A | Display validation colors for a selected material property:
  • Diffuse Color: Select this option to check if the diffuse colors in your scene adhere to an acceptable PBR range. If the material color is out of this range, the debugger displays it in the **Too High Color** color if it's above the range, or in the **Too Low Color** if it's below the range.
  • Metal or SpecularColor: Select this option to check if a pixel contains a metallic or specular color that adheres to an acceptable PBR range. If it doesn't, the debugger highlights it in the **Not A Pure Metal Color**. For information about the acceptable PBR ranges in Unity, refer to the [Material Charts](https://docs.unity3d.com/Manual/StandardShaderMaterialCharts.html) documentation.
| | **Material Validator** | **Too High Color** | Use the color picker to select the color that the debugger displays when a Material's diffuse color is above the acceptable PBR range. | | **Material Validator** | **Too Low Color** | Use the color picker to select the color that the debugger displays when a Material's diffuse color is below the acceptable PBR range.
  • This property only appears when you select Diffuse Color or Metal or SpecularColor from the Material Validator drop-down.
| | **Material Validator** | **Not A Pure Metal Color** | Use the color picker to select the color that the debugger displays if a pixel defined as metallic has a non-zero albedo value. The debugger only highlights these pixels if you enable the True Metals checkbox.
  • This property only appears when you select Diffuse Color or Metal or SpecularColor from the Material Validator drop-down.
| @@ -134,7 +134,7 @@ The **Lighting** panel has tools that you can use to visualize various component | **Shadow Debug Option** | **Sub-option** | **Description** | |------------------------------------|----------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| **Debug Mode** | N/A | Use the drop-down to select which shadow debug information to overlay on the screen:
  • None: Select this mode to remove the shadow debug information from the screen.
  • VisualizePunctualLightAtlas: Select this mode to overlay the shadow atlas for Punctual Lights in your Scene.
  • VisualizeDirectionalLightAtlas: Select this mode to overlay the shadow atlas for Directional Lights in your Scene.
  • VisualizeAreaLightAtlas: Select this mode to overlay the shadow atlas for Area Lights in your Scene.
  • VisualizeShadowMap: Select this mode to overlay a single shadow map for a Light in your Scene.
  • SingleShadow: Select this mode to replace the Scene's lighting with a single Light. To select which Light to isolate, see Use Selection or Shadow Map Index.
| +| **Debug Mode** | N/A | Select the shadow debug information to display on the screen:
  • None: Select this mode to remove the shadow debug information from the screen.
  • VisualizePunctualLightAtlas: Select this mode to overlay the shadow atlas for Punctual Lights in your scene.
  • VisualizeDirectionalLightAtlas: Select this mode to overlay the shadow atlas for Directional Lights in your scene.
  • VisualizeAreaLightAtlas: Select this mode to overlay the shadow atlas for Area Lights in your scene.
  • VisualizeShadowMap: Select this mode to overlay a single shadow map for a light in your scene.
  • SingleShadow: Select this mode to replace the scene's lighting with a single light. To select which light to isolate, refer to Use Selection or Shadow Map Index.
| | **Debug Mode** | **Use Selection** | Enable the checkbox to display the shadow map for the Light you select in the Scene.
  • This property only appears when you select VisualizeShadowMap or SingleShadow from the Shadow Debug Mode drop-down.
| | **Debug Mode** | **Shadow Map Index** | Use the slider to select the index of the shadow map to view. To use this property correctly, you must have at least one Light in your Scene that uses shadow maps. | | **Global Scale Factor** | N/A | Use the slider to set the global scale that HDRP applies to the shadow rendering resolution. | @@ -146,7 +146,7 @@ The **Lighting** panel has tools that you can use to visualize various component | **Lighting Debug Option** | **Description** | |---------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **Show Lights By Type** | Allows the user to enable or disable lights in the scene based on their type.
  • Directional Lights: Enable the checkbox to see Directional Lights in your Scene. Disable this checkbox to remove Directional Lights from your Scene's lighting.
  • Punctual Lights: Enable the checkbox to see Punctual Lights in your Scene. Disable this checkbox to remove Punctual Lights from your Scene's lighting.
  • Area Lights: Enable the checkbox to see Area Lights in your Scene. Disable this checkbox to remove Area Lights from your Scene's lighting.
  • Reflection Probes: Enable the checkbox to see Reflection Probes in your Scene. Disable this checkbox to remove Reflection Probes from your Scene's lighting.
| -| **Exposure** | Allows you to select an Exposure debug mode to use.
  • Debug Mode: Use the drop-down to select a debug mode. See Exposure documentation for more information.
  • Show Tonemap Curve: Enable the checkbox to overlay the tonemap curve to the histogram debug view. This property only appears when you select HistogramView from Debug Mode.
  • Center Around Exposure: Enable the checkbox to center the histogram around the current exposure value. This property only appears when you select HistogramView from Debug Mode.
  • Display RGB Histogram: Enable the checkbox to display the Final Image Histogram as an RGB histogram instead of just luminance. This property only appears when you select FinalImageHistogramView from Debug Mode.
  • Display Mask Only: Enable the checkbox to display only the metering mask in the picture-in-picture. When disabled, the mask displays after weighting the scene color instead. This property only appears when you select MeteringWeighted from Debug Mode.
  • Debug Exposure Compensation: Set an additional exposure compensation for debug purposes.
| +| **Exposure** | Select an Exposure debug mode to use.
  • Debug Mode: Select a debug mode from the available options. Refer to [Control exposure](Override-Exposure.md) for more information.
  • Show Tonemap Curve: Enable this to overlay the Tonemap Curve to the histogram debug view. This property only appears when you select HistogramView from Debug Mode.
  • Center Around Exposure: Enable this to center the histogram around the current exposure value. This property only appears when you select HistogramView from Debug Mode.
  • Display RGB Histogram: Enable this to display the Final Image Histogram as an RGB histogram instead of just luminance. This property only appears when you select FinalImageHistogramView from Debug Mode.
  • Display Mask Only: Enable this to display only the metering mask in the picture-in-picture. When disabled, the mask displays after weighting the scene color instead. This property only appears when you select MeteringWeighted from Debug Mode.
  • Debug Exposure Compensation: Set an additional exposure compensation for debug purposes.
| | **Debug Mode** | Use the drop-down to select a lighting mode to debug. For example, you can visualize diffuse lighting, specular lighting, direct diffuse lighting, direct specular lighting, indirect diffuse lighting, indirect specular lighting, emissive lighting and Directional Light shadow cascades. | | **Hierarchy Debug Mode** | Use the drop-down to select a light type to display the direct lighting for or a Reflection Probe type to display the indirect lighting for. | From 280aae305a40870f4eff437c3bc3f0ccb9d67640 Mon Sep 17 00:00:00 2001 From: Reach Platform Support Date: Wed, 3 Sep 2025 09:38:06 +0000 Subject: [PATCH 29/36] [Port] [6000.2] DOCG-7365 Shader Graph feedback improvements --- .../Documentation~/Normal-Vector-Node.md | 23 ++++++++++++------- .../Documentation~/Not-Node.md | 19 ++++++--------- 2 files changed, 22 insertions(+), 20 deletions(-) diff --git a/Packages/com.unity.shadergraph/Documentation~/Normal-Vector-Node.md b/Packages/com.unity.shadergraph/Documentation~/Normal-Vector-Node.md index d5cb972bacf..cf6c4c9dca8 100644 --- a/Packages/com.unity.shadergraph/Documentation~/Normal-Vector-Node.md +++ b/Packages/com.unity.shadergraph/Documentation~/Normal-Vector-Node.md @@ -1,15 +1,22 @@ -## Description +# Normal Vector node -Provides access to the mesh vertex or fragment's **Normal Vector**. The coordinate space of the output value can be selected with the **Space** dropdown parameter. +The Normal Vector node outputs the normal of a vertex or fragment of a mesh. + +For more information about normals, refer to [Normal maps](https://docs.unity3d.com/Manual/StandardShaderMaterialParameterNormalMapLanding.html). ## Ports -| Name | Direction | Type | Binding | Description | +| **Name** | **Direction** | **Type** | **Binding** | **Description** | |:------------ |:-------------|:-----|:---|:---| -| Out | Output | Vector 3 | None | Mesh's **Normal Vector**. | +| **Out** | Output | Vector 3 | None | The normal of the vertex or fragment of the mesh, depending on the [shader stage](Shader-Stage.md) of the graph section. | + +## Space -## Parameters +The **Space** dropdown determines the coordinate space of the normal vector. -| Name | Type | Options | Description | -|:------------ |:-------------|:-----|:---| -| Space | Dropdown | Object, View, World, Tangent | Selects coordinate space of **Normal Vector** to output. | +| **Option** | **Description** | +|-|-| +| **Object** | Returns the vertex or fragment normal in object space, where up is the up axis of local space. | +| **View** | Returns the vertex or fragment normal in view space, where up is the up direction of the camera. | +| **World** | Returns the vertex or fragment normal in world space, where up is the up direction of the scene. | +| **Tangent** | Returns the vertex or fragment normal in tangent space, where up is away from the surface of the mesh. | diff --git a/Packages/com.unity.shadergraph/Documentation~/Not-Node.md b/Packages/com.unity.shadergraph/Documentation~/Not-Node.md index 600c17a6837..bd098259e76 100644 --- a/Packages/com.unity.shadergraph/Documentation~/Not-Node.md +++ b/Packages/com.unity.shadergraph/Documentation~/Not-Node.md @@ -1,23 +1,18 @@ -# Not Node +# Not node -## Description - -Returns the opposite of input **In**. If **In** is true the output will be false, otherwise it will be true. This is useful for [Branching](Branch-Node.md). +The Not node outputs the opposite of an input. If the input is true the output is false, otherwise the output is true. This node is useful for [branching](Branch-Node.md). ## Ports -| Name | Direction | Type | Binding | Description | +| **Name** | **Direction** | **Type** | **Binding** | **Description** | |:------------ |:-------------|:-----|:---|:---| -| In | Input | Boolean | None | Input value | -| Out | Output | Boolean | None | Output value | +| **In** | Input | Boolean | None | The input value. | +| **Out** | Output | Boolean | None | The opposite of **In**. | -## Generated Code Example +## Generated code example The following example code represents one possible outcome of this node. ``` -void Unity_NormalUnpack_float(float In, out float Out) -{ - Out = !In; -} +Out = !In; ``` From e844777c3d1af051db4f8e96fd66dbe154bd6fe5 Mon Sep 17 00:00:00 2001 From: Reach Platform Support Date: Thu, 4 Sep 2025 05:36:53 +0000 Subject: [PATCH 30/36] [Port] [6000.2] [UUM-115779] Fix artifacts caused by tiled deferred lighting after disabling path tracing in HDRP. --- .../Runtime/RenderPipeline/HDRenderPipeline.RenderGraph.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/HDRenderPipeline.RenderGraph.cs b/Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/HDRenderPipeline.RenderGraph.cs index 8449d35fd11..5963d0b52ef 100644 --- a/Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/HDRenderPipeline.RenderGraph.cs +++ b/Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/HDRenderPipeline.RenderGraph.cs @@ -144,6 +144,8 @@ void RecordRenderGraph(RenderRequest renderRequest, } else if (hdCamera.frameSettings.IsEnabled(FrameSettingsField.RayTracing) && pathTracing.enable.value && hdCamera.camera.cameraType != CameraType.Preview && GetRayTracingState() && GetRayTracingClusterState()) { + m_TileAndClusterData.listsAreClear = false; + // We only request the light cluster if we are gonna use it for debug mode if (FullScreenDebugMode.LightCluster == m_CurrentDebugDisplaySettings.data.fullScreenDebugMode && GetRayTracingClusterState()) { From fc72ced24420ee129579eaee2e7fd591566a14b2 Mon Sep 17 00:00:00 2001 From: Reach Platform Support Date: Thu, 4 Sep 2025 05:36:53 +0000 Subject: [PATCH 31/36] [Port] [6000.2] UUM-115123 - Disallow GPU Driven for MeshRenderers which have a non default sorting keys --- .../Runtime/GPUDriven/Components/DisallowGPUDrivenRendering.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Packages/com.unity.render-pipelines.core/Runtime/GPUDriven/Components/DisallowGPUDrivenRendering.cs b/Packages/com.unity.render-pipelines.core/Runtime/GPUDriven/Components/DisallowGPUDrivenRendering.cs index 8c0b3d9abe3..af9a92dd03d 100644 --- a/Packages/com.unity.render-pipelines.core/Runtime/GPUDriven/Components/DisallowGPUDrivenRendering.cs +++ b/Packages/com.unity.render-pipelines.core/Runtime/GPUDriven/Components/DisallowGPUDrivenRendering.cs @@ -62,7 +62,8 @@ private static void AllowGPUDrivenRenderingRecursively(Transform transform, bool private void OnValidate() { OnDisable(); - OnEnable(); + if (enabled) + OnEnable(); } } } From 80dddd2e009953ea3aabd01fd286bb9a00b36d32 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Olivier=20Carr=C3=A8re?= Date: Thu, 4 Sep 2025 18:59:36 +0000 Subject: [PATCH 32/36] [Port] [6000.2] DOCG-7264: Remove screenshots from node landing page --- .../Documentation~/Artistic-Nodes.md | 75 +++--- .../Documentation~/Channel-Nodes.md | 20 +- .../Custom-Render-Texture-Nodes.md | 13 +- .../Documentation~/Input-Nodes.md | 176 +++++++------- .../Documentation~/Math-Nodes.md | 218 +++++++----------- .../Documentation~/Node-Library.md | 40 ++-- .../Documentation~/Procedural-Nodes.md | 40 ++-- .../Documentation~/TableOfContents.md | 2 +- .../Documentation~/UV-Nodes.md | 32 ++- .../Documentation~/Utility-Nodes.md | 40 ++-- 10 files changed, 288 insertions(+), 368 deletions(-) diff --git a/Packages/com.unity.shadergraph/Documentation~/Artistic-Nodes.md b/Packages/com.unity.shadergraph/Documentation~/Artistic-Nodes.md index 5ec28680436..fc089474b9f 100644 --- a/Packages/com.unity.shadergraph/Documentation~/Artistic-Nodes.md +++ b/Packages/com.unity.shadergraph/Documentation~/Artistic-Nodes.md @@ -1,69 +1,56 @@ -# Artistic Nodes - -## Adjustment +# Artistic nodes +Adjust colors, blend layers, filter images, mask regions, manipulate normal maps, and convert color spaces. -|[Channel Mixer](Channel-Mixer-Node.md)| [Contrast](Contrast-Node.md) | -|:---------:|:---------:| -|![A node-based visual interface with a Channel Mixer block connected to a 3-component vector input labeled X 0, Y 0, Z 0, where only the red (R) channel is fully enabled (set to 1) while green (G) and blue (B) are set to 0, resulting in an output that isolates the red channel.](images/ChannelMixerNodeThumb.png)|![A node-based setup featuring a Contrast block connected to two inputs: a 3-component vector input set to (0, 0, 0) and a single contrast value set to 1, resulting in an output where no visible contrast is applied due to the black input vector.](images/ContrastNodeThumb.png)| -|Controls the amount each of the channels of input In contribute to each of the output channels.|Adjusts the contrast of input In by the amount of input Contrast.| -|[**Hue**](Hue-Node.md)|[**Invert Colors**](Invert-Colors-Node.md)| -|![A Hue block. A (0,0,0) Vector3 is connected to the In(3) slot and the 0 scalar value is connected to the Offset(1) slot. No value is connected to the Out(3) slot. The Degrees option is selected in the Range area.](images/HueNodeThumb.png)|![An Invert Colors block. A 0 scalar is connected to the In(1) slot. No value is connected to the Out (1) slot. A Red checkbox is unselected. The Green, Blue, and Alpha checkboxes are grayed out.](images/InvertColorsNodeThumb.png)| -|Offsets the hue of input In by the amount of input Offset.|Inverts the colors of input In on a per channel basis.| -|[**Replace Color**](Replace-Color-Node.md)|[**Saturation**](Saturation-Node.md)| -|![A Replace Color block. A (0,0,0) Vector3 is connected to the In(3) slot and 0 scalar values are connected to the Range(1) and Fuzziness(1) slots. Empty values are connected to the From (3) and To(3) slots. No value is connected to the Out(3) slot.](images/ReplaceColorNodeThumb.png)|![A Saturation block. A (0,0,0) Vector3 is connected to the In(3) slot and a 0 scalar value is connected to the Saturation(1) slot. No value is connected to the Out(3) slot.](images/SaturationNodeThumb.png)| -|Replaces values in input In equal to input From to the value of input To.|Adjusts the saturation of input In by the amount of input Saturation.| -|[**White Balance**](White-Balance-Node.md)|| -|![A White Balance block. A (0,0,0) Vector3 is connected to the In(3) slot and 0 scalar values are connected to the Temperature(1) and Tint(1) slots. No value is connected to the Out(3) slot.](images/WhiteBalanceNodeThumb.png)|| -|Adjusts the temperature and tint of input In by the amount of inputs Temperature and Tint respectively.|| +## Adjustment +| **Topic** | **Description** | +|:---------------------------------------|---------------------------------------------------------------------------------------------------------| +| [Channel Mixer](Channel-Mixer-Node.md) | Controls the amount each of the channels of input In contribute to each of the output channels. | +| [Contrast](Contrast-Node.md) | Adjusts the contrast of input In by the amount of input Contrast. | +| [Hue](Hue-Node.md) | Offsets the hue of input In by the amount of input Offset. | +| [Invert Colors](Invert-Colors-Node.md) | Inverts the colors of input In on a per channel basis. | +| [Replace Color](Replace-Color-Node.md) | Replaces values in input In equal to input From to the value of input To. | +| [Saturation](Saturation-Node.md) | Adjusts the saturation of input In by the amount of input Saturation. | +| [White Balance](White-Balance-Node.md) | Adjusts the temperature and tint of input In by the amount of inputs Temperature and Tint respectively. | ## Blend -|[Blend](Blend-Node.md)| -|:---------:| -|![A Blend block. A 0 scalar value is connected to the Base(1), Blend(1), and Opacity(1) slots. No value is connected to the Out(1) slot. The Overlay option is selected in the Mode area.](images/BlendNodeThumb.png)| -|Blends the value of input Blend onto input Base using the blending mode defined by parameter Mode.| +| **Topic** | **Description** | +|:-----------------------|----------------------------------------------------------------------------------------------------| +| [Blend](Blend-Node.md) | Blends the value of input Blend onto input Base using the blending mode defined by parameter Mode. | ## Filter -|[Dither](Dither-Node.md)| -|:---------:| -|![](images/DitherNodeThumb.png)| -|Dither is an intentional form of noise used to randomize quantization error. It is used to prevent large-scale patterns such as color banding in images..| +| **Topic** | **Description** | +|:-------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------| +| [Dither](Dither-Node.md) | Dither is an intentional form of noise used to randomize quantization error. It is used to prevent large-scale patterns such as color banding in images.. | ## Mask - -|[Channel Mask](Channel-Mask-Node.md)| [Color Mask](Color-Mask-Node.md) | -|:---------:|:---------:| -|![](images/ChannelMaskNodeThumb.png)|![](images/ColorMaskNodeThumb.png)| -|Masks values of input In on channels selected in dropdown Channels.|Creates a mask from values in input In equal to input Mask Color.| - +| **Topic** | **Description** | +|--------------------------------------|---------------------------------------------------------------------| +| [Channel Mask](Channel-Mask-Node.md) | Masks values of input In on channels selected in dropdown Channels. | +| [Color Mask](Color-Mask-Node.md) | Creates a mask from values in input In equal to input Mask Color. | ## Normal - -|[Normal Blend](Normal-Blend-Node.md)| [Normal From Height](Normal-From-Height-Node.md) | -|:---------:|:---------:| -|![](images/NormalBlendNodeThumb.png)|![](images/NormalFromHeightNodeThumb.png)| -|Blends two normal maps defined by inputs A and B together.|Creates a normal map from a height map defined by input Texture.| -|[**Normal Strength**](Normal-Strength-Node.md)|[**Normal Unpack**](Normal-Unpack-Node.md)| -|![](images/NormalStrengthNodeThumb.png)|![](images/NormalUnpackNodeThumb.png)| -|Adjusts the strength of the normal map defined by input In by the amount of input Strength.|Unpacks a normal map defined by input In.| - +| **Topic** | **Description** | +|--------------------------------------------------|---------------------------------------------------------------------------------------------| +| [Normal Blend](Normal-Blend-Node.md) | Blends two normal maps defined by inputs A and B together. | +| [Normal From Height](Normal-From-Height-Node.md) | Creates a normal map from a height map defined by input Texture. | +| [Normal Strength](Normal-Strength-Node.md) | Adjusts the strength of the normal map defined by input In by the amount of input Strength. | +| [Normal Unpack](Normal-Unpack-Node.md) | Unpacks a normal map defined by input In. | ## Utility - -| [Colorspace Conversion](Colorspace-Conversion-Node.md) | -| :----------------------------------------------------------: | -| ![](images/ColorspaceConversionNodeThumb.png) | -| Returns the result of converting the value of input In from one colorspace space to another. | +| **Topic** | **Description** | +|--------------------------------------------------------|----------------------------------------------------------------------------------------------| +| [Colorspace Conversion](Colorspace-Conversion-Node.md) | Returns the result of converting the value of input In from one colorspace space to another. | diff --git a/Packages/com.unity.shadergraph/Documentation~/Channel-Nodes.md b/Packages/com.unity.shadergraph/Documentation~/Channel-Nodes.md index 565c7428b01..09365bf86ef 100644 --- a/Packages/com.unity.shadergraph/Documentation~/Channel-Nodes.md +++ b/Packages/com.unity.shadergraph/Documentation~/Channel-Nodes.md @@ -1,13 +1,11 @@ -# Channel Nodes +# Channel nodes +Combine, split, reorder, or flip vector and color channels. -|[Append](Append-Node.md)|[Combine](Combine-Node.md)| -|:---------:|:---------:| -|![image](images/AppendNodeThumb.png)|![Image](images/CombineNodeThumb.png)| -|Combine two float or vector inputs into a single new vector of variable dimensions.|Creates new vectors from the four inputs **R**, **G**, **B** and **A**.| -|[**Flip**](Flip-Node.md)|[**Split**](Split-Node.md)| -|![Image](images/FlipNodeThumb.png)|![Image](images/SplitNodeThumb.png)| -|Flips the individual channels of input **In** selected by the [Node](Node.md)'s parameters.|Splits the input vector **In** into four **Float** outputs **R**, **G**, **B** and **A**.| -|[**Swizzle**](Swizzle-Node.md)|| -|![Image](images/SwizzleNodeThumb.png)|| -|Creates a new [vector](https://docs.unity3d.com/Manual/VectorCookbook.html) from the reordered elements of the input vector.|| \ No newline at end of file +| **Topic** | **Description** | +|----------------------------|-------------------------------------------------------------------------------------| +| [Append](Append-Node.md) | Combine two float or vector inputs into a single new vector of variable dimensions. | +| [Combine](Combine-Node.md) | Creates new vectors from the four inputs R, G, B and A. | +| [Flip](Flip-Node.md) | Flips the individual channels of input In selected by the node's parameters. | +| [Split](Split-Node.md) | Splits the input vector In into four Float outputs R, G, B and A. | +| [Swizzle](Swizzle-Node.md) | Creates a new vector from the reordered elements of the input vector. | diff --git a/Packages/com.unity.shadergraph/Documentation~/Custom-Render-Texture-Nodes.md b/Packages/com.unity.shadergraph/Documentation~/Custom-Render-Texture-Nodes.md index 137819f9553..2ae0b3724bd 100644 --- a/Packages/com.unity.shadergraph/Documentation~/Custom-Render-Texture-Nodes.md +++ b/Packages/com.unity.shadergraph/Documentation~/Custom-Render-Texture-Nodes.md @@ -1,6 +1,9 @@ -# Custom Render Texture Nodes +# Custom Render Texture nodes -|[Custom Render Texture Slice](Custom-Texture-Slice.md) | [Custom Render Texture Size](Custom-Texture-Size.md) | [Custom Render Texture Self](Custom-Texture-Self.md) | -|:---------:|:---------:|:---------:| -|![Image](images/CustomRenderTextureSliceIndex.png)| ![Image](images/CustomRenderTextureSize.png)| ![Image](images/CustomRenderTextureSelf.png)| -|Access the custom render texture slice index and cubemap face. | Access the custom render texture size. | Access the custom render texture from the previous update. | +Access properties and data of custom render textures, including size, slice index, cubemap face, and previous update state. + +| **Topic** | **Description** | +|--------------------------------------------------------|----------------------------------------------------------------| +| [Custom Render Texture Slice](Custom-Texture-Slice.md) | Access the custom render texture slice index and cubemap face. | +| [Custom Render Texture Size](Custom-Texture-Size.md) | Access the custom render texture size. | +| [Custom Render Texture Self](Custom-Texture-Self.md) | Access the custom render texture from the previous update. | diff --git a/Packages/com.unity.shadergraph/Documentation~/Input-Nodes.md b/Packages/com.unity.shadergraph/Documentation~/Input-Nodes.md index 25c772f4d9f..5983f8dc84c 100644 --- a/Packages/com.unity.shadergraph/Documentation~/Input-Nodes.md +++ b/Packages/com.unity.shadergraph/Documentation~/Input-Nodes.md @@ -1,124 +1,102 @@ -# Input Nodes +# Input nodes + +Supply shaders with essential data such as constants, mesh attributes, gradients, matrices, deformation, PBR parameters, scene details, and texture sampling options. ## Basic -|[Boolean](Boolean-Node.md)|[Color](Color-Node.md)| -|:--------:|:------:| -|![A flow diagram with a labeled node titled "Boolean" and an output labeled "out(B)". The output is connected via an arrow pointing outward, indicating the result of a Boolean operation.](images/BooleanNodeThumb.png)|![A diagram featuring a single element labeled **"Boolean"** with an output connection marked **"out(B)"**. An arrow extends from this output, indicating the flow of a Boolean value from the node. The design implies a logic or data flow representation centered around Boolean values.](images/ColorNodeThumb.png)| -| Defines a constant Boolean value in the shader. | Defines a constant Vector 4 value in the shader using a Color field. | -|[**Constant**](Constant-Node.md)|[**Integer**](Integer-Node.md)| -|![A diagram with a node labeled "Constant" and an output labeled "Out(1)". Below it, the symbol "PI" is displayed, with a downward arrow pointing toward it. ](images/ConstantNodeThumb.png)|![A node labeled "Integer" with an output labeled "out(1)". Next to it is the number 0, indicating that the node outputs the integer value zero.](images/IntegerNodeThumb.png)| -|Defines a Float of a mathematical constant value in the shader.|Defines a constant Float value in the shader using an Integer field.| -|[**Slider**](Slider-Node.md)|[**Time**](Time-Node.md)| -|![A slider control with an output labeled "out(1)". Below the slider, there is a range indicated by Min 0 on the left and Max 1 on the right. The current slider value is shown as 0, suggesting it is set at the minimum end of the range.](images/SliderNodeThumb.png)|![A node labeled Time with multiple outputs, each named and connected as follows: Time(1), Sine Time(1), Cosine Time(1), Delta Time(1), Smooth Delta(1).](images/TimeNodeThumb.png)| -|Defines a constant Float value in the shader using a Slider field.|Provides access to various Time parameters in the shader.| -|[**Float**](Float.md)|[**Vector 2**](Vector-2-Node.md)| -|![A Vector node with a label for the X component set to 0. There is a connection marked X(1) leading to an output labeled out(1). An arrow extends from the output, indicating the flow of this vector’s X value through the system.](images/Vector1NodeThumb.png)|![a Vector 2 node with two components: X set to 0, connected via X(1) to an output labeled out(2), Y set to 0, connected via Y(1). Arrows indicate the flow of these two values from their respective outputs.](images/Vector2NodeThumb.png)| -|Defines a Float value in the shader.|Defines a Vector 2 value in the shader.| -|[**Vector 3**](Vector-3-Node.md)|[**Vector 4**](Vector-4-Node.md)| -|![A Vector 3 node with three components: X set to 0, connected via X(1) to an output labeled out(3), Y set to 0, connected via Y(1), Z set to 0, connected via Z(1); Each component has arrows indicating the flow of these values, representing a three-dimensional vector output.](images/Vector3NodeThumb.png)|![A Vector 4 node with four components: X set to 0, connected via X(1) to an output labeled Out(4), Y set to 0, connected via Y(1), Z set to 0, connected via Z(1), W set to 0, connected via W(1). Each component is linked with arrows, showing the flow of these four values representing a four-dimensional vector output.](images/Vector4NodeThumb.png)| -|Defines a Vector 3 value in the shader.|Defines a Vector 4 value in the shader.| +| **Topic** | **Description** | +|------------------------------|----------------------------------------------------------------------| +| [Boolean](Boolean-Node.md) | Defines a constant Boolean value in the shader. | +| [Color](Color-Node.md) | Defines a constant Vector 4 value in the shader using a Color field. | +| [Constant](Constant-Node.md) | Defines a Float of a mathematical constant value in the shader. | +| [Integer](Integer-Node.md) | Defines a constant Float value in the shader using an Integer field. | +| [Slider](Slider-Node.md) | Defines a constant Float value in the shader using a Slider field. | +| [Time](Time-Node.md) | Provides access to various Time parameters in the shader. | +| [Float](Float-Node.md) | Defines a Float value in the shader. | +| [Vector 2](Vector-2-Node.md) | Defines a Vector 2 value in the shader. | +| [Vector 3](Vector-3-Node.md) | Defines a Vector 3 value in the shader. | +| [Vector 4](Vector-4-Node.md) | Defines a Vector 4 value in the shader. | ## Geometry -|[Bitangent Vector](Bitangent-Vector-Node.md)|[Normal Vector](Normal-Vector-Node.md)| -|:--------:|:------:| -|[![A Bitangent Vector node with an output labeled out(3). Below the label, there are two options or modes indicated: Space and World, with an arrow pointing down toward World. This suggests the vector can be interpreted or output in different coordinate spaces, with the current selection being World space.](images/BitangentVectorNodeThumb.png)](Combine-Node.md)|![A Normal Vector node with an output labeled Out(3). Below it, there are two options: Space and World, with an arrow pointing downward toward World. This indicates the vector can be output in different coordinate spaces, currently set to World space.](images/NormalVectorNodeThumb.png)| -| Provides access to the mesh vertex or fragment's Bitangent Vector. | Provides access to the mesh vertex or fragment's Normal Vector. | -|[**Position**](Position-Node.md)|[**Screen Position**](Screen-Position-Node.md)| -|![A Position node with an output labeled Out(3). Below it, there are two options: Space and World, with a downward arrow pointing at World. This indicates the position value can be represented in different coordinate spaces, currently set to World space.](images/PositionNodeThumb.png)|![A Position node with an output labeled Out(3). Beneath it, there are two selectable options: Space and World, with an arrow indicating the selection is set to World space. This suggests the position value is provided relative to the world coordinate system.](images/ScreenPositionNodeThumb.png)| -|Provides access to the mesh vertex or fragment's Position.|Provides access to the mesh vertex or fragment's Screen Position.| -|[**Tangent Vector**](Tangent-Vector-Node.md)|[**UV**](UV-Node.md)| -|![A Tangent Vector node with an output labeled Out(3). Below it, two options are listed: Space and World, with an arrow pointing downward toward World. This indicates the vector can be output in different coordinate spaces, currently set to World space.](images/TangentVectorNodeThumb.png)|![A Tangent Vector node with an output labeled Out(3). Below it, two options are listed: Space and World, with an arrow pointing downward toward World. This indicates the vector can be output in different coordinate spaces, currently set to World space.](images/UVNodeThumb.png)| -|Provides access to the mesh vertex or fragment's Tangent Vector.|Provides access to the mesh vertex or fragment's UV coordinates.| -|[**Vertex Color**](Vertex-Color-Node.md)|[**View Direction**](View-Direction-Node.md)| -|![a Vertex Color node with an output labeled Out(4). An arrow extends from the output, indicating the flow of a four-component color value, typically representing RGBA data.](images/VertexColorNodeThumb.png)|![A View Direction node with an output labeled Out(3). Below it, two options are shown: Space and World, with a downward arrow pointing to World, indicating the current coordinate space for the view direction vector.](images/ViewDirectionNodeThumb.png)| -|Provides access to the mesh vertex or fragment's Vertex Color value.|Provides access to the mesh vertex or fragment's View Direction vector.| -|[**Vertex ID**](Vertex-ID-Node.md)| -|![A Vertex ID node with an output labeled out(1).](images/VertexIDNodeThumb.png)| -|Provides access to the mesh vertex or fragment's Vertex ID value.| - +| **Topic** | **Description** | +|----------------------------------------------|-------------------------------------------------------------------------| +| [Bitangent Vector](Bitangent-Vector-Node.md) | Provides access to the mesh vertex or fragment's Bitangent Vector. | +| [Normal Vector](Normal-Vector-Node.md) | Provides access to the mesh vertex or fragment's Normal Vector. | +| [Position](Position-Node.md) | Provides access to the mesh vertex or fragment's Position. | +| [Screen Position](Screen-Position-Node.md) | Provides access to the mesh vertex or fragment's Screen Position. | +| [Tangent Vector](Tangent-Vector-Node.md) | Provides access to the mesh vertex or fragment's Tangent Vector. | +| [UV](UV-Node.md) | Provides access to the mesh vertex or fragment's UV coordinates. | +| [Vertex Color](Vertex-Color-Node.md) | Provides access to the mesh vertex or fragment's Vertex Color value. | +| [View Direction](View-Direction-Node.md) | Provides access to the mesh vertex or fragment's View Direction vector. | +| [Vertex ID](Vertex-ID-Node.md) | Provides access to the mesh vertex or fragment's Vertex ID value. | ## Gradient -|[Blackbody](Blackbody-Node.md)|[Gradient](Gradient-Node.md)| -|:--------:|:------:| -|![A node labeled Tempnat with an output labeled out(3). An arrow points outward from the output.](images/BlackbodyNodeThumb.png)|![a Gradient node with an output labeled out(G). An arrow extends from the output.](images/GradientNodeThumb.png)| -| Samples a radiation based gradient from temperature input (in Kelvin). | Defines a constant Gradient in the shader. | -|[Sample Gradient](Sample-Gradient-Node.md)| -|![A Sample Gradient node with two main elements: An input labeled Gradient, an output labeled out(4). There is also an input labeled X set to 0, connected via Time(1).](images/SampleGradientNodeThumb.png)| -| Samples a Gradient given the input of Time. | +| **Topic** | **Description** | +|--------------------------------------------|------------------------------------------------------------------------| +| [Blackbody](Blackbody-Node.md) | Samples a radiation based gradient from temperature input (in Kelvin). | +| [Gradient](Gradient-Node.md) | Defines a constant Gradient in the shader. | +| [Sample Gradient](Sample-Gradient-Node.md) | Samples a Gradient given the input of Time. | ## Matrix -|[Matrix 2x2](Matrix-2x2-Node.md)|[Matrix 3x3](Matrix-3x3-Node.md)| -|:--------:|:------:| -|![A Matrix 2x2 node with an output labeled Out(2x2). The matrix elements are all set to 0, arranged in a 2-by-2 grid.](images/Matrix2x2NodeThumb.png)|![A Matrix 3x3 node with an output labeled Out(3x3). The matrix is displayed as a 3-by-3 grid with all elements set to 0.](images/Matrix3x3NodeThumb.png)| -| Defines a constant Matrix 2x2 value in the shader. | Defines a constant Matrix 3x3 value in the shader. | -|[**Matrix 4x4**](Matrix-4x4-Node.md)|[**Transformation Matrix**](Transformation-Matrix-Node.md)| -|![A Matrix 4x4 node with an output labeled Out(4x4). The matrix is displayed as a 4-by-4 grid with all elements set to 0.](images/Matrix4x4NodeThumb.png)|![ A Transformation Matrix node with an output labeled Out(4x4). Below it, there is a dropdown or selection labeled Model with a downward arrow.](images/TransformationMatrixNodeThumb.png)| -|Defines a constant Matrix 4x4 value in the shader.|Defines a constant Matrix 4x4 value for a default Unity Transformation Matrix in the shader.| +| **Topic** | **Description** | +|--------------------------------------------------------|----------------------------------------------------------------------------------------------| +| [Matrix 2x2](Matrix-2x2-Node.md) | Defines a constant Matrix 2x2 value in the shader. | +| [Matrix 3x3](Matrix-3x3-Node.md) | Defines a constant Matrix 3x3 value in the shader. | +| [Matrix 4x4](Matrix-4x4-Node.md) | Defines a constant Matrix 4x4 value in the shader. | +| [Transformation Matrix](Transformation-Matrix-Node.md) | Defines a constant Matrix 4x4 value for a default Unity Transformation Matrix in the shader. | ## Mesh Deformation -| [Compute Deformation Node](Compute-Deformation-Node.md) | [Linear Blend Skinning Node](Linear-Blend-Skinning-Node.md) | -| :----------------------------------------------------------- | :----------------------------------------------------------- | -| ![A Compute Deformation node with three outputs: Deformed Position, Deformed Normal, Deformed Tangent.](images/ComputeDeformationNodeThumb.png) | ![A Linear Blend Skinning node with three pairs of inputs and outputs: Vertex Position(3) input connected to Skinned Position(3) output, Vertex Normal(3) input connected to Skinned Normal(3) output, Vertex Tangent(3) input connected to Skinned Tangent(3) output.](images/LinearBlendSkinningNodeThumb.png) | -| Passes compute deformed vertex data to a vertex shader. Only works with the [Entities Graphics package](https://docs.unity3d.com/Packages/com.unity.entities.graphics@latest/). | Applies Linear Blend Vertex Skinning. Only works with the [Entities Graphics package](https://docs.unity3d.com/Packages/com.unity.entities.graphics@latest/). | + +| **Topic** | **Description** | +|-------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| [Compute Deformation Node](Compute-Deformation-Node.md) | Passes compute deformed vertex data to a vertex shader. Only works with the [Entities Graphics package](https://docs.unity3d.com/Packages/com.unity.entities.graphics@latest/). | +| [Linear Blend Skinning Node](Linear-Blend-Skinning-Node.md) | Applies Linear Blend Vertex Skinning. Only works with the [Entities Graphics package](https://docs.unity3d.com/Packages/com.unity.entities.graphics@latest/). | ## Sprite Deformation -| [Sprite Skinning Node](Sprite-Skinning-Node.md) | -| :----------------------------------------------------------- | -| ![A Linear Blend Skinning node with three pairs of inputs and outputs, each handling 3-component vectors: Vertex Position(3) connected to Skinned Position(3) output, Vertex Normal(3) connected to Skinned Normal(3) output, Vertex Tangent(3) connected to Skinned Tangent(3) output.](images/SpriteSkinningNodeThumb.png) | -| Applies Vertex Skinning on Sprites. Only works with the [2D Animation](https://docs.unity3d.com/Packages/com.unity.2d.animation@latest/). | -## PBR +| **Topic** | **Description** | +|-------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------| +| [Sprite Skinning Node](Sprite-Skinning-Node.md) | Applies Vertex Skinning on Sprites. Only works with the [2D Animation](https://docs.unity3d.com/Packages/com.unity.2d.animation@latest/). | -| [**Dielectric Specular**](Dielectric-Specular-Node.md) | [**Metal Reflectance**](Metal-Reflectance-Node.md) | -| :----------------------------------------------------------: | :----------------------------------------------------------: | -| ![A Dielectric Specular node with an output labeled Out(1). Below it, there are settings including: Material with an option labeled Common and a dropdown arrow, Range set to LJ 0.5, IOR (Index of Refraction) set to 1.](images/DielectricSpecularNodeThumb.png) | ![A Metal Reflectance node with an output labeled out(3). Below it, there is a Material option set to Iron with a dropdown arrow.](images/MetalReflectanceNodeThumb.png) | -| Returns a Dielectric Specular F0 value for a physically based material. | Returns a Metal Reflectance value for a physically based material. | +## PBR +| **Topic** | **Description** | +|----------------------------------------------------|-------------------------------------------------------------------------| +| [Dielectric Specular](Dielectric-Specular-Node.md) | Returns a Dielectric Specular F0 value for a physically based material. | +| [Metal Reflectance](Metal-Reflectance-Node.md) | Returns a Metal Reflectance value for a physically based material. | ## Scene -|[Ambient](Ambient-Node.md)|[Camera](Camera-Node.md)| -|:--------:|:------:| -|![An Ambient node with three outputs: Color/Sky(3), Equator(3), Ground(3).](images/AmbientNodeThumb.png)|![A Camera node with multiple outputs: Position(3), Direction(3), Orthographic(1), Near Plane(1), Far Plane(1), Z Buffer Sign(1), Width(1), Height(1).](images/CameraNodeThumb.png)| -| Provides access to the Scene's Ambient color values. | Provides access to various parameters of the current Camera. | -|[**Fog**](Fog-Node.md)|[**Baked GI**](Baked-GI-Node.md)| -|![A Fog node with: An input labeled Object Space Position(3), outputs labeled Color(4) and Density(1).](images/FogNodeThumb.png)|| -|Provides access to the Scene's Fog parameters.|Provides access to the Baked GI values at the vertex or fragment's position.| -|[**Object**](Object-Node.md)|[**Reflection Probe**](Reflection-Probe-Node.md)| -|![An Object node with two outputs: Position(3), Scale(3).](images/ObjectNodeThumb.png)|![A Reflection Probe node with several elements: An input labeled Object Space View Dir(3) connected to an output labeled Out(3), an input labeled Object Space Normal(3), an input labeled X set to 0, connected via LOD(1)](images/ReflectionProbeNodeThumb.png).| -|Provides access to various parameters of the Object.|Provides access to the nearest Reflection Probe to the object.| -|[**Scene Color**](Scene-Color-Node.md)|[**Scene Depth**](Scene-Depth-Node.md)| -|![A Scene Color node with: An input labeled Default, an output labeled Out(4).](images/SceneColorNodeThumb.png)|![A Scene Depth node with: An input labeled Default UV(4), an output labeled out(1), a setting or option labeled Sampling Linear 01.](images/SceneDepthNodeThumb.png)| -|Provides access to the current Camera's color buffer.|Provides access to the current Camera's depth buffer.| -|[**Screen**](Screen-Node.md)|[**Eye Index**](Eye-Index-Node.md)| -|![A Screen node with two outputs: Width(1), Height(1).](images/ScreenNodeThumb.png)|![An Eye Index node with an output labeled Out(1).](images/EyeIndexNodeThumb.png)| -|Provides access to parameters of the screen.|Provides access to the Eye Index when stereo rendering.| +| **Topic** | **Description** | +|----------------------------------------------|------------------------------------------------------------------------------| +| [Ambient](Ambient-Node.md) | Provides access to the Scene's Ambient color values. | +| [Camera](Camera-Node.md) | Provides access to various parameters of the current Camera. | +| [Fog](Fog-Node.md) | Provides access to the Scene's Fog parameters. | +| [Baked GI](Baked-GI-Node.md) | Provides access to the Baked GI values at the vertex or fragment's position. | +| [Object](Object-Node.md) | Provides access to various parameters of the Object. | +| [Reflection Probe](Reflection-Probe-Node.md) | Provides access to the nearest Reflection Probe to the object. | +| [Scene Color](Scene-Color-Node.md) | Provides access to the current Camera's color buffer. | +| [Scene Depth](Scene-Depth-Node.md) | Provides access to the current Camera's depth buffer. | +| [Screen](Screen-Node.md) | Provides access to parameters of the screen. | +| [Eye Index](Eye-Index-Node.md) | Provides access to the Eye Index when stereo rendering. | ## Texture -|[**Cubemap Asset**](Cubemap-Asset-Node.md)|[**Sample Cubemap**](Sample-Cubemap-Node.md)| -|:--------:|:------:| -|[![A Cubemap Asset node with an output labeled out(C). Below it, there is a dropdown or selector displaying None (Cubemap).](images/CubemapAssetNodeThumb.png)](Combine-Node.md)|![A Sample Cubemap node with: An input labeled None (Cubemap), an input labeled World Space connected to pijr(3), an input labeled x set to 0, connected to LoD(1), an output labeled Out(4).](images/SampleCubemapNodeThumb.png)| -| Defines a constant Cubemap Asset for use in the shader. | Samples a Cubemap and returns a Vector 4 color value for use in the shader. | -|[**Sample Reflected Cubemap Node**](Sample-Reflected-Cubemap-Node.md)|[**Sample Texture 2D**](Sample-Texture-2D-Node.md)| -|![A Sample Cubemap node with several inputs and an output: An input labeled None (Cubemap) connected to Cube(C), inputs labeled Object Space ViewDir(3) and Object Space Normal(3), an input labeled Sampler(SS), an input labeled X set to 0, connected to LOD(1), an output labeled Out(4).](images/SampleReflectedCubemapThumb.png)|![A Sample Texture 2D node with: An input labeled None (Texture) connected to Texture(T2), an input labeled UV(2), an input labeled Sampler(SS), multiple outputs labeled RGBA(4), R(1), G(1), B(1), and A(1), two dropdown options: Type set to Default, and Space set to Tangent.](images/SampleTexture2DNodeThumb.png)| -|Samples a Cubemap with reflected vector and returns a Vector 4 color value for use in the shader.|Samples a Texture 2D and returns a color value for use in the shader.| -|[**Sample Texture 2D Array**](Sample-Texture-2D-Array-Node.md)|[**Sample Texture 2D LOD**](Sample-Texture-2D-LOD-Node.md)| -|![A Sample Texture 2D Array node with: An input labeled None (Texture) connected to Texture Array (T2A), an input labeled X set to 0, connected to Index(1), an input labeled UV connected to UV(2), an input labeled Sampler(SS), multiple outputs labeled RGBA(4), R(1), G(1), B(1), and A(1).](images/SampleTexture2DArrayNodeThumb.png)|![A Sample Texture 2D LOD node with: An input labeled None (Texture) connected to Texture(T2), an input labeled UV(2), an input labeled Sampler(SS), an input labeled X set to 0, connected to LOD(1), multiple outputs labeled RGBA(4), R(1), G(1), B(1), and A(1), two dropdown options: Type set to Default, and Space set to Tangent.](images/SampleTexture2DLODNodeThumb.png)| -|Samples a Texture 2D Array at an Index and returns a color value for use in the shader.|Samples a Texture 2D at a specific LOD and returns a color value for use in the shader.| -|[**Sample Texture 3D**](Sample-Texture-3D-Node.md)| [**Sample Virtual Texture**](Sample-Virtual-Texture-Node.md) | -|![A Sample Texture 3D node with: An input labeled None (Texture) connected to Texture(T3), inputs labeled X 0, Y 0, Z 0 combined as UV(3), an input labeled Sampler(SS), an output labeled Out(4).](images/SampleTexture3DNodeThumb.png)| ![A Sample Virtual Texture node with: An input labeled UV(2), an input labeled VT(VT) connected to Virtual Texture (VT), four outputs labeled Out(4), Out2(4), Out3(4), and Out4(4).](images/SampleVirtualTextureNodeThumb.png) | -|Samples a Texture 3D and returns a color value for use in the shader.| Samples a Virtual Texture and returns color values for use in the shader.| -|[**Sampler State**](Sampler-State-Node.md)|[**Texture Size**](Texture-Size-Node.md)| -|![A Sampler State node with an output labeled Out(SS). Below it are settings including: Filter set to Linear, Wrap set to Repeat.](images/SamplerStateNodeThumb.png)|![A Texture Size node with: An input labeled None (Texture) connected to Texture(T2), outputs labeled Width(1), Height(1), Texel Width(1), and Texel Height(1).](images/TexelSizeNodeThumb.png) | -|Defines a Sampler State for sampling textures.|Returns the Width and Height of the texel size of Texture 2D input.| -|[**Texture 2D Array Asset**](Texture-2D-Array-Asset-Node.md)|[**Texture 2D Asset**](Texture-2D-Asset-Node.md)| -|![A Texture 2D Array Asset node with an output labeled Out(T2A). Below it, there is a dropdown or selector displaying None (Texture 2D Array).](images/Texture2DArrayAssetNodeThumb.png)|![A Texture 2D Asset node with an output labeled Out(T2). Below it, there is a dropdown or selector displaying None (Texture).](images/Texture2DAssetNodeThumb.png)| -|Defines a constant Texture 2D Array Asset for use in the shader.|Defines a constant Texture 2D Asset for use in the shader.| -|[**Texture 3D Asset**](Texture-3D-Asset-Node.md)| | -|![A Texture 3D Asset node with an output labeled Out(T3). Below it, there is a dropdown or selector displaying None (Texture 3D).](images/Texture3DAssetNodeThumb.png)| | -|Defines a constant Texture 3D Asset for use in the shader.| | +| **Topic** | **Description** | +|-------------------------------------------------------------------|---------------------------------------------------------------------------------------------------| +| [Cubemap Asset](Cubemap-Asset-Node.md) | Defines a constant Cubemap Asset for use in the shader. | +| [Sample Cubemap](Sample-Cubemap-Node.md) | Samples a Cubemap and returns a Vector 4 color value for use in the shader. | +| [Sample Reflected Cubemap Node](Sample-Reflected-Cubemap-Node.md) | Samples a Cubemap with reflected vector and returns a Vector 4 color value for use in the shader. | +| [Sample Texture 2D](Sample-Texture-2D-Node.md) | Samples a Texture 2D and returns a color value for use in the shader. | +| [Sample Texture 2D Array](Sample-Texture-2D-Array-Node.md) | Samples a Texture 2D Array at an Index and returns a color value for use in the shader. | +| [Sample Texture 2D LOD](Sample-Texture-2D-LOD-Node.md) | Samples a Texture 2D at a specific LOD and returns a color value for use in the shader. | +| [Sample Texture 3D](Sample-Texture-3D-Node.md) | Samples a Texture 3D and returns a color value for use in the shader. | +| [Sample Virtual Texture](Sample-Virtual-Texture-Node.md) | Samples a Virtual Texture and returns color values for use in the shader. | +| [Sampler State](Sampler-State-Node.md) | Defines a Sampler State for sampling textures. | +| [Texture Size](Texture-Size-Node.md) | Returns the Width and Height of the texel size of Texture 2D input. | +| [Texture 2D Array Asset](Texture-2D-Array-Asset-Node.md) | Defines a constant Texture 2D Array Asset for use in the shader. | +| [Texture 2D Asset](Texture-2D-Asset-Node.md) | Defines a constant Texture 2D Asset for use in the shader. | +| [Texture 3D Asset](Texture-3D-Asset-Node.md) | Defines a constant Texture 3D Asset for use in the shader. | diff --git a/Packages/com.unity.shadergraph/Documentation~/Math-Nodes.md b/Packages/com.unity.shadergraph/Documentation~/Math-Nodes.md index 3a4dd3ecf86..e49584d7529 100644 --- a/Packages/com.unity.shadergraph/Documentation~/Math-Nodes.md +++ b/Packages/com.unity.shadergraph/Documentation~/Math-Nodes.md @@ -1,159 +1,119 @@ -# Math Nodes +# Math nodes -## Advanced +Perform a mathematical operations, from basic arithmetic to advanced functions like trigonometry, vectors, matrices, interpolation, and waves. -| [Absolute](Absolute-Node.md) | [Exponential](Exponential-Node.md) | -| :------- | :------ | -| ![Image](images/AbsoluteNodeThumb.png) | ![Image](images/ExponentialNodeThumb.png) | -| Returns the absolute value of input In. | Returns the exponential value of input In. | -| [**Length**](Length-Node.md) | [**Log**](Log-Node.md) | -| ![Image](images/LengthNodeThumb.png) | ![Image](images/LogNodeThumb.png) | -| Returns the length of input In. | Returns the logarithm of input In. | -| [**Modulo**](Modulo-Node.md) | [**Negate**](Negate-Node.md) | -| ![Image](images/ModuloNodeThumb.png) | ![Image](images/NegateNodeThumb.png) | -| Returns the remainder of input A divided by input B. | Returns the inverse value of input In. | -| [**Normalize**](Normalize-Node.md) | [**Posterize**](Posterize-Node.md) | -| ![Image](images/NormalizeNodeThumb.png) | ![Image](images/PosterizeNodeThumb.png) | -| Returns the normalized vector of input In. | Returns the input In converted into a number of values defined by input Steps. | -| [**Reciprocal**](Reciprocal-Node.md) | [**Reciprocal Square Root**](Reciprocal-Square-Root-Node.md) | -| ![Image](images/ReciprocalNodeThumb.png) | ![Image](images/ReciprocalSquareRootNodeThumb.png) | -| Returns the result of 1 divided by input In. | Returns the result of 1 divided by the square root of input In. | +## Advanced +| **Topic** | **Description** | +|----------------------------------------------------------|--------------------------------------------------------------------------------| +| [Absolute](Absolute-Node.md) | Returns the absolute value of input In. | +| [Exponential](Exponential-Node.md) | Returns the exponential value of input In. | +| [Length](Length-Node.md) | Returns the length of input In. | +| [Log](Log-Node.md) | Returns the logarithm of input In. | +| [Modulo](Modulo-Node.md) | Returns the remainder of input A divided by input B. | +| [Negate](Negate-Node.md) | Returns the inverse value of input In. | +| [Normalize](Normalize-Node.md) | Returns the normalized vector of input In. | +| [Posterize](Posterize-Node.md) | Returns the input In converted into a number of values defined by input Steps. | +| [Reciprocal](Reciprocal-Node.md) | Returns the result of 1 divided by input In. | +| [Reciprocal Square Root](Reciprocal-Square-Root-Node.md) | Returns the result of 1 divided by the square root of input In. | ## Basic -| [Add](Add-Node.md) | [Divide](Divide-Node.md) | -| :------- | :------ | -| ![Image](images/AddNodeThumb.png) | ![Image](images/DivideNodeThumb.png) | -| Returns the sum of the two input values. | Returns the result of input A divided by input B. | -| [**Multiply**](Multiply-Node.md) | [**Power**](Power-Node.md) | -| ![Image](images/MultiplyNodeThumb.png) | ![Image](images/PowerNodeThumb.png) | -| Returns the result of input A multiplied by input B. | Returns the result of input A to the power of input B. | -| [**Square Root**](Square-Root-Node.md) | [**Subtract**](Subtract-Node.md) | -| ![Image](images/SquareRootNodeThumb.png) | ![Image](images/SubtractNodeThumb.png) | -| Returns the square root of input In. | Returns the result of input A minus input B. | - - +| **Topic** | **Description** | +|------------------------------------|--------------------------------------------------------| +| [Add](Add-Node.md) | Returns the sum of the two input values. | +| [Divide](Divide-Node.md) | Returns the result of input A divided by input B. | +| [Multiply](Multiply-Node.md) | Returns the result of input A multiplied by input B. | +| [Power](Power-Node.md) | Returns the result of input A to the power of input B. | +| [Square Root](Square-Root-Node.md) | Returns the square root of input In. | +| [Subtract](Subtract-Node.md) | Returns the result of input A minus input B. | ## Derivative -| [DDX](DDX-Node.md) | [DDXY](DDXY-Node.md) | -| :------- | :------ | -| ![Image](images/DDXNodeThumb.png) | ![Image](images/DDXYNodeThumb.png) | -| Returns the partial derivative with respect to the screen-space x-coordinate. | Returns the sum of both partial derivatives. | -| [**DDY**](DDY-Node.md) || -| ![Image](images/DDYNodeThumb.png) || -| Returns the partial derivative with respect to the screen-space y-coordinate. || - - +| **Topic** | **Description** | +|----------------------|-------------------------------------------------------------------------------| +| [DDX](DDX-Node.md) | Returns the partial derivative with respect to the screen-space x-coordinate. | +| [DDXY](DDXY-Node.md) | Returns the sum of both partial derivatives. | +| [DDY](DDY-Node.md) | Returns the partial derivative with respect to the screen-space y-coordinate. | ## Interpolation -| [Inverse Lerp](Inverse-Lerp-Node.md) | [Lerp](Lerp-Node.md) | -| :------- | :------ | -| ![Image](images/InverseLerpNodeThumb.png) | ![Image](images/LerpNodeThumb.png) | -| Returns the parameter that produces the interpolant specified by input T within the range of input A to input B. | Returns the result of linearly interpolating between input A and input B by input T. | -| [**Smoothstep**](Smoothstep-Node.md) || -| ![Image](images/SmoothstepNodeThumb.png) || -| Returns the result of a smooth Hermite interpolation between 0 and 1, if input In is between inputs Edge1 and Edge2. || - - +| **Topic** | **Description** | +|--------------------------------------|----------------------------------------------------------------------------------------------------------------------| +| [Inverse Lerp](Inverse-Lerp-Node.md) | Returns the parameter that produces the interpolant specified by input T within the range of input A to input B. | +| [Lerp](Lerp-Node.md) | Returns the result of linearly interpolating between input A and input B by input T. | +| [Smoothstep](Smoothstep-Node.md) | Returns the result of a smooth Hermite interpolation between 0 and 1, if input In is between inputs Edge1 and Edge2. | ## Matrix -| [Matrix Construction](Matrix-Construction-Node.md) | [Matrix Determinant](Matrix-Determinant-Node.md) | -| :----------------------------------------------------------- | :----------------------------------------------------------- | -| ![Image](images/MatrixConstructionNodeThumb.png) | ![Image](images/MatrixDeterminantNodeThumb.png) | -| Constructs square matrices from the four input vectors M0, M1, M2 and M3. | Returns the determinant of the matrix defined by input In. | -| [**Matrix Split**](Matrix-Split-Node.md) | [**Matrix Transpose**](Matrix-Transpose-Node.md) | -| ![Image](images/MatrixSplitNodeThumb.png) | ![Image](images/MatrixTransposeNodeThumb.png) | -| Splits a square matrix defined by input In into vectors. | Returns the transposed value of the matrix defined by input In. | - - +| **Topic** | **Description** | +|----------------------------------------------------|---------------------------------------------------------------------------| +| [Matrix Construction](Matrix-Construction-Node.md) | Constructs square matrices from the four input vectors M0, M1, M2 and M3. | +| [Matrix Determinant](Matrix-Determinant-Node.md) | Returns the determinant of the matrix defined by input In. | +| [Matrix Split](Matrix-Split-Node.md) | Splits a square matrix defined by input In into vectors. | +| [Matrix Transpose](Matrix-Transpose-Node.md) | Returns the transposed value of the matrix defined by input In. | ## Range -| [Clamp](Clamp-Node.md) | [Fraction](Fraction-Node.md) | -| :------- | :------ | -| ![Image](images/ClampNodeThumb.png) | ![Image](images/FractionNodeThumb.png) | -| Returns the input In clamped between the minimum and maximum values defined by inputs Min and Max respectively. | Returns the fractional (or decimal) part of input In; which is greater than or equal to 0 and less than 1. | -| [**Maximum**](Maximum-Node.md) | [**Minimum**](Minimum-Node.md) | -| ![Image](images/MaximumNodeThumb.png) | ![Image](images/MinimumNodeThumb.png) | -| Returns the largest of the two inputs values A and B. | Returns the smallest of the two inputs values A and B. | -| [**One Minus**](One-Minus-Node.md) | [**Random Range**](Random-Range-Node.md) | -| ![Image](images/OneMinusNodeThumb.png) | ![Image](images/RandomRangeNodeThumb.png) | -| Returns the result of input In subtracted from 1. | Returns a pseudo-random number that is between the minimum and maximum values defined by inputs Min and Max. | -| [**Remap**](Remap-Node.md) | [**Saturate**](Saturate-Node.md) | -| ![Image](images/RemapNodeThumb.png) | ![Image](images/SaturateNodeThumb.png) | -| Remaps the value of input In from between the values of input Out Min Max to between the values of input In Min Max. | Returns the value of input In clamped between 0 and 1. | - - +| **Topic** | **Description** | +|--------------------------------------|----------------------------------------------------------------------------------------------------------------------| +| [Clamp](Clamp-Node.md) | Returns the input In clamped between the minimum and maximum values defined by inputs Min and Max respectively. | +| [Fraction](Fraction-Node.md) | Returns the fractional (or decimal) part of input In; which is greater than or equal to 0 and less than 1. | +| [Maximum](Maximum-Node.md) | Returns the largest of the two inputs values A and B. | +| [Minimum](Minimum-Node.md) | Returns the smallest of the two inputs values A and B. | +| [One Minus](One-Minus-Node.md) | Returns the result of input In subtracted from 1. | +| [Random Range](Random-Range-Node.md) | Returns a pseudo-random number that is between the minimum and maximum values defined by inputs Min and Max. | +| [Remap](Remap-Node.md) | Remaps the value of input In from between the values of input Out Min Max to between the values of input In Min Max. | +| [Saturate](Saturate-Node.md) | Returns the value of input In clamped between 0 and 1. | ## Round -| [Ceiling](Ceiling-Node.md) | [Floor](Floor-Node.md) | -| :------- | :------ | -| ![Image](images/CeilingNodeThumb.png) | ![Image](images/FloorNodeThumb.png) | -| Returns the smallest integer value, or whole number, that is greater than or equal to the value of input In. | Returns the largest integer value, or whole number, that is less than or equal to the value of input In. | -| [**Round**](Round-Node.md) | [**Sign**](Sign-Node.md) | -| ![Image](images/RoundNodeThumb.png) | ![Image](images/SignNodeThumb.png) | -| Returns the value of input In rounded to the nearest integer, or whole number. | Returns -1 if the value of input In is less than zero, 0 if equal to zero and 1 if greater than zero. | -| [**Step**](Step-Node.md) | [**Truncate**](Truncate-Node.md) | -| ![Image](images/StepNodeThumb.png) | ![Image](images/TruncateNodeThumb.png) | -| Returns 1 if the value of input In is greater than or equal to the value of input Edge, otherwise returns 0. | Returns the integer, or whole number, component of the value of input In. | +| **Topic** | **Description** | +|------------------------------|--------------------------------------------------------------------------------------------------------------| +| [Ceiling](Ceiling-Node.md) | Returns the smallest integer value, or whole number, that is greater than or equal to the value of input In. | +| [Floor](Floor-Node.md) | Returns the largest integer value, or whole number, that is less than or equal to the value of input In. | +| [Round](Round-Node.md) | Returns the value of input In rounded to the nearest integer, or whole number. | +| [Sign](Sign-Node.md) | Returns -1 if the value of input In is less than zero, 0 if equal to zero and 1 if greater than zero. | +| [Step](Step-Node.md) | Returns 1 if the value of input In is greater than or equal to the value of input Edge, otherwise returns 0. | +| [Truncate](Truncate-Node.md) | Returns the integer, or whole number, component of the value of input In. | ## Trigonometry -| [Arccosine](Arccosine-Node.md) | [Arcsine](Arcsine-Node.md) | -| :------- | :------ | -| ![Image](images/ArccosineNodeThumb.png) | ![Image](images/ArcsineNodeThumb.png) | -| Returns the arccosine of each component the input In as a vector of equal length. | Returns the arcsine of each component the input In as a vector of equal length. | -| [**Arctangent**](Arctangent-Node.md) | [**Arctangent2**](Arctangent2-Node.md) | -| ![Image](images/ArctangentNodeThumb.png) | ![Image](images/Arctangent2NodeThumb.png) | -| Returns the arctangent of the value of input In. Each component should be within the range of -Pi/2 to Pi/2. | Returns the arctangent of the values of both input A and input B. | -| [**Cosine**](Cosine-Node.md) | [**Degrees to Radians**](Degrees-To-Radians-Node.md) | -| ![Image](images/CosineNodeThumb.png) | ![Image](images/DegreesToRadiansNodeThumb.png) | -| Returns the cosine of the value of input In. | Returns the value of input In converted from degrees to radians. | -| [**Hyperbolic Cosine**](Hyperbolic-Cosine-Node.md) | [**Hyperbolic Sine**](Hyperbolic-Sine-Node.md) | -| ![Image](images/HyperbolicCosineNodeThumb.png) | ![Image](images/HyperbolicSineNodeThumb.png) | -| Returns the hyperbolic cosine of input In. | Returns the hyperbolic sine of input In. | -| [**Hyperbolic Tangent**](Hyperbolic-Tangent-Node.md) | [**Radians to Degrees**](Radians-To-Degrees-Node.md) | -| ![Image](images/HyperbolicTangentNodeThumb.png) | ![Image](images/RadiansToDegreesNodeThumb.png) | -| Returns the hyperbolic tangent of input In. | Returns the value of input In converted from radians to degrees. | -| [**Sine**](Sine-Node.md) | [**Tangent**](Tangent-Node.md) | -| ![Image](images/SineNodeThumb.png) | ![Image](images/TangentNodeThumb.png) | -| Returns the sine of the value of input In. | Returns the tangent of the value of input In. | - - +| **Topic** | **Description** | +|--------------------------------------------------|--------------------------------------------------------------------------------------------------------------| +| [Arccosine](Arccosine-Node.md) | Returns the arccosine of each component the input In as a vector of equal length. | +| [Arcsine](Arcsine-Node.md) | Returns the arcsine of each component the input In as a vector of equal length. | +| [Arctangent](Arctangent-Node.md) | Returns the arctangent of the value of input In. Each component should be within the range of -Pi/2 to Pi/2. | +| [Arctangent2](Arctangent2-Node.md) | Returns the arctangent of the values of both input A and input B. | +| [Cosine](Cosine-Node.md) | Returns the cosine of the value of input In. | +| [Degrees to Radians](Degrees-To-Radians-Node.md) | Returns the value of input In converted from degrees to radians. | +| [Hyperbolic Cosine](Hyperbolic-Cosine-Node.md) | Returns the hyperbolic cosine of input In. | +| [Hyperbolic Sine](Hyperbolic-Sine-Node.md) | Returns the hyperbolic sine of input In. | +| [Hyperbolic Tangent](Hyperbolic-Tangent-Node.md) | Returns the hyperbolic tangent of input In. | +| [Radians to Degrees](Radians-To-Degrees-Node.md) | Returns the value of input In converted from radians to degrees. | +| [Sine](Sine-Node.md) | Returns the sine of the value of input In. | +| [Tangent](Tangent-Node.md) | Returns the tangent of the value of input In. | ## Vector -| [Cross Product](Cross-Product-Node.md) | [Distance](Distance-Node.md) | -| :------- | :------ | -| ![Image](images/CrossProductNodeThumb.png) | ![Image](images/DistanceNodeThumb.png) | -| Returns the cross product of the values of the inputs A and B. | Returns the Euclidean distance between the values of the inputs A and B. | -| [**Dot Product**](Dot-Product-Node.md) | [**Fresnel Effect**](Fresnel-Effect-Node.md) | -| ![Image](images/DotProductNodeThumb.png) | ![Image](images/FresnelEffectNodeThumb.png) | -| Returns the dot product, or scalar product, of the values of the inputs A and B. | Fresnel Effect is the effect of differing reflectance on a surface depending on viewing angle, where as you approach the grazing angle more light is reflected. | -| [**Projection**](Projection-Node.md) | [**Reflection**](Reflection-Node.md) | -| ![Image](images/ProjectionNodeThumb.png) | ![Image](images/ReflectionNodeThumb.png) | -| Returns the result of projecting the value of input A onto a straight line parallel to the value of input B. | Returns a reflection vector using input In and a surface normal Normal. | -| [**Rejection**](Rejection-Node.md) | [**Rotate About Axis**](Rotate-About-Axis-Node.md) | -| ![Image](images/RejectionNodeThumb.png) | ![Image](images/RotateAboutAxisNodeThumb.png) | -| Returns the result of the projection of the value of input A onto the plane orthogonal, or perpendicular, to the value of input B. | Rotates the input vector In around the axis Axis by the value of Rotation. | -| [**Projection**](Projection-Node.md) | [**Rejection**](Rejection-Node.md) | -| ![Image](images/ProjectionNodeThumb.png) | ![Image](images/RejectionNodeThumb.png) | -| Returns the result of projecting the value of input A onto a straight line parallel to the value of input B. | Returns the result of the projection of the value of input A onto the plane orthogonal, or perpendicular, to the value of input B. | -| [**Sphere Mask**](Sphere-Mask-Node.md) | [**Transform**](Transform-Node.md) | -| ![Image](images/SphereMaskNodeThumb.png)| ![Image](images/TransformNodeThumb.png) | -| Creates a sphere mask originating from input Center. | Returns the result of transforming the value of input In from one coordinate space to another. | +| **Topic** | **Description** | +|------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------| +| [Cross Product](Cross-Product-Node.md) | Returns the cross product of the values of the inputs A and B. | +| [Distance](Distance-Node.md) | Returns the Euclidean distance between the values of the inputs A and B. | +| [Dot Product](Dot-Product-Node.md) | Returns the dot product, or scalar product, of the values of the inputs A and B. | +| [Fresnel Effect](Fresnel-Effect-Node.md) | Fresnel Effect is the effect of differing reflectance on a surface depending on viewing angle, where as you approach the grazing angle more light is reflected. | +| [Projection](Projection-Node.md) | Returns the result of projecting the value of input A onto a straight line parallel to the value of input B. | +| [Reflection](Reflection-Node.md) | Returns a reflection vector using input In and a surface normal Normal. | +| [Rejection](Rejection-Node.md) | Returns the result of the projection of the value of input A onto the plane orthogonal, or perpendicular, to the value of input B. | +| [Rotate About Axis](Rotate-About-Axis-Node.md) | Rotates the input vector In around the axis Axis by the value of Rotation. | +| [Sphere Mask](Sphere-Mask-Node.md) | Creates a sphere mask originating from input Center. | +| [Transform](Transform-Node.md) | Returns the result of transforming the value of input In from one coordinate space to another. | ## Wave -| [Noise Sine Wave](Noise-Sine-Wave-Node.md) | [Sawtooth Wave](Sawtooth-Wave-Node.md) | -| :----------------------------------------------------------- | :----------------------------------------------------------- | -| ![Image](images/NoiseSineWaveNodeThumb.png) | ![Image](images/SawtoothWaveNodeThumb.png) | -| Returns the sine of the value of input In. For variance, random noise is added to the amplitude of the sine wave. | Returns a sawtooth wave from the value of input In. | -| [**Matrix Split**](Matrix-Split-Node.md) | [**Matrix Transpose**](Matrix-Transpose-Node.md) | -| ![Image](images/MatrixSplitNodeThumb.png) | ![Image](images/MatrixTransposeNodeThumb.png) | -| Splits a square matrix defined by input In into vectors. | Returns the transposed value of the matrix defined by input In. | +| **Topic** | **Description** | +|----------------------------------------------|-------------------------------------------------------------------------------------------------------------------| +| [Noise Sine Wave](Noise-Sine-Wave-Node.md) | Returns the sine of the value of input In. For variance, random noise is added to the amplitude of the sine wave. | +| [Sawtooth Wave](Sawtooth-Wave-Node.md) | Returns a sawtooth wave from the value of input In. | +| [Matrix Split](Matrix-Split-Node.md) | Splits a square matrix defined by input In into vectors. | +| [Matrix Transpose](Matrix-Transpose-Node.md) | Returns the transposed value of the matrix defined by input In. | diff --git a/Packages/com.unity.shadergraph/Documentation~/Node-Library.md b/Packages/com.unity.shadergraph/Documentation~/Node-Library.md index 1702a8697e9..9d773bda455 100644 --- a/Packages/com.unity.shadergraph/Documentation~/Node-Library.md +++ b/Packages/com.unity.shadergraph/Documentation~/Node-Library.md @@ -1,27 +1,29 @@ -# Node Library +# Node library -## Description +Explore nodes that enable color and channel manipulation, mathematical and procedural generation, input data handling, custom texture management, UV mapping, utility logic, and shader data representation. -The **Node Library** contains documentation for all the individual [Nodes](Node.md) in Shader Graph; including descriptions, ports, parameters, shader code and example images. The [Nodes](Node.md) are organised in the same categories as found in the [Create Node Menu](Create-Node-Menu.md) for convenience. +## Graph nodes -## Graph Nodes +| **Topic** | **Description** | +|:--------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------| +| [Artistic](Artistic-Nodes.md) | Learn about color adjustment, blending, filtering, masking, normal map manipulation, and color space conversion. | +| [Channel](Channel-Nodes.md) | Learn about combining, splitting, reordering, or flipping vector and color channels. | +| [Custom Render Texture nodes](Custom-Render-Texture-Nodes.md) | Learn about properties and data of custom render textures. | +| [Input](Input-Nodes.md) | Learn about values, mesh attributes, gradients, matrices, deformation data, PBR parameters, scene information, and texture sampling options. | +| [Math](Math-Nodes.md) | Learn about mathematical operations. | +| [Procedural](Procedural-Nodes.md) | Learn about creating patterns, noise textures, and geometric shapes. | +| [Utility](Utility-Nodes.md) | Learn about basic preview, sub-graph referencing, and essential logic operations. | +| [UV](UV-Nodes.md) | Learn about manipulation and mapping effects, enabling advanced texture animations, coordinate transformations, and warping techniques. | -| | | -|:--|:--| -| [Artistic](Artistic-Nodes.md)| [Channel](Channel-Nodes.md)| -| [Input](Input-Nodes.md) | [Math](Math-Nodes.md) | -| [Procedural](Procedural-Nodes.md) | [Utility](Utility-Nodes.md)| -| [UV](UV-Nodes.md) | | +## Block nodes +| **Topic** | **Description** | +|:-------------------------------|-------------------------------------------------------------------------------------------| +| [Block](Block-Node.md) | You can find these nodes in the **Vertex** and **Fragment** contexts of the Master Stack. | -## Block Nodes +## Additional resources -| | | -|:-|:-| -| [Built In](Built-In-Blocks.md) | | -| Universal | High Definition | +* [Node](Node.md) +* [Create Node Menu](Create-Node-Menu.md) +* [Shader Graph Node Reference Samples](ShaderGraph-Samples.md) - -## Shader graph node reference samples - -To learn node functions or get deeper insights and ideas for custom shaders, browse the [Shader Graph Node Reference Samples](ShaderGraph-Samples.md). diff --git a/Packages/com.unity.shadergraph/Documentation~/Procedural-Nodes.md b/Packages/com.unity.shadergraph/Documentation~/Procedural-Nodes.md index 71eeb84666c..ff915cbf021 100644 --- a/Packages/com.unity.shadergraph/Documentation~/Procedural-Nodes.md +++ b/Packages/com.unity.shadergraph/Documentation~/Procedural-Nodes.md @@ -1,29 +1,25 @@ -# Procedural Nodes +# Procedural nodes -| [Checkerboard](Checkerboard-Node.md) | -| :-----------| -| ![A Checkerboard node. A UV0 value is connected to the UV(2) slot. A dark-gray value is connected to the Color A(3) slot. A light gray value is connected to the Color B(3) slot. A (1,1) Vector 2 is connected to the Frequency(2) slot. No value is connected to the Out(3) slot. A 2 by 2 checkerboard is displayed in the lower part of the node.](images/CheckerboardNodeThumb.png) | -| Generates a checkerboard of alternating colors between inputs Color A and Color B based on input UV. | +Generate patterns, noise textures, and customizable geometric shapes procedurally using UV input. + +| **Topic** | **Description** | +|--------------------------------------|------------------------------------------------------------------------------------------------------| +| [Checkerboard](Checkerboard-Node.md) | Generates a checkerboard of alternating colors between inputs Color A and Color B based on input UV. | ## Noise -| [Gradient Noise](Gradient-Noise-Node.md) | [Simple Noise](Simple-Noise-Node.md) | -| :------------------------ | :---------------------------- | -| ![A Gradient Noise node. A UV0 value is connected to the UV(2) slot. A 10 scalar is attached to the Scale(1) slot. No value is connected to the Out(1) slot. A textured, abstract grayscale pattern that resembles soft, cloudy noise is displayed in the lower part of the node.](images/GradientNoiseNodeThumb.png) | ![A Simple Noise node. A UV0 value is connected to the UV(2) slot. A 500 scalar is attached to the Scale(1) slot. No value is connected to the Out(1) slot. A TV static pattern is displayed in the lower part of the node.](images/SimpleNoiseNodeThumb.png) | -| Generates a gradient, or Perlin, noise based on input UV. | Generates a simple, or Value, noise based on input UV. | -| [**Voronoi**](Voronoi-Node.md) | | -| ![A Voronoi node. A UV0 value is connected to the UV(2) slot. A 2 scalar is attached to the Angle Offset(1) slot. A 5 scalar is attached to the Cell Density(1) slot. No value is connected to the Out(1) slot or the Cells(1) slot. A pattern of cells is displayed in the lower part of the node.](images/VoronoiNodeThumb.png) || -|Generates a Voronoi, or Worley, noise based on input UV. || +| **Topic** | **Description** | +|------------------------------------------|-----------------------------------------------------------| +| [Gradient Noise](Gradient-Noise-Node.md) | Generates a gradient, or Perlin, noise based on input UV. | +| [Simple Noise](Simple-Noise-Node.md) | Generates a simple, or Value, noise based on input UV. | +| [Voronoi](Voronoi-Node.md) | Generates a Voronoi, or Worley, noise based on input UV. | ## Shape -| [Ellipse](Ellipse-Node.md) | [Polygon](Polygon-Node.md) | -| :----------------------------------------------------------- | :----------------------------------------------------------- | -| ![An Ellipse node. A UV0 value is connected to the UV(2) slot. 0.5 scalars are atttached to the Width(1) and Height(1) slots. No value is connected to the Out(1) slot. A solid white disk is displayed in the lower part of the node.](images/EllipseNodeThumb.png) | ![A Polygon node. A UV0 value is connected to the UV(2) slot. A 6 scalar is attached to the Sides(1) slot. 0.5 scalars are atttached to the Width(1) and Height(1) slots. No value is connected to the Out(1) slot. A solid white hexagon is displayed in the lower part of the node.](images/PolygonNodeThumb.png) | -| Generates an ellipse shape based on input UV at the size specified by inputs Width and Height. | Generates a regular polygon shape based on input UV at the size specified by inputs Width and Height. The polygon's amount of sides is determined by input Sides. | -| [**Rectangle**](Rectangle-Node.md) | [**Rounded Rectangle**](Rounded-Rectangle-Node.md) | -| ![A Rectangle node. A UV0 value is connected to the UV(2) slot. A 0.5 scalar is attached to the Width(1) slot. A 0.5 scalar is attached to the Height(1) slot. No value is connected to the Out(1) slot. The Fastest option is selected in a drop-down. A solid white square is displayed in the lower part of the node.](images/RectangleNodeThumb.png) | ![A Rounded Rectangle node. A UV0 value is connected to the UV(2) slot. 0.5 scalars are attached to the Width(1), Height(1), and Radius(1) slots. No value is connected to the Out(1) slot. A solid white rounded square is displayed in the lower part of the node.](images/RoundedRectangleNodeThumb.png) | -| Generates a rectangle shape based on input UV at the size specified by inputs Width and Height. | Generates a rounded rectangle shape based on input UV at the size specified by inputs Width and Height. The input Radius defines the radius of each corner. | -| [](Rounded-Polygon-Node.md) || -|![A Rounded Polygon node. A UV0 value is connected to the UV(2) slot. 0.5 scalars are atttached to the Width(1) and Height(1) slots. A 5 scalar is attached to the Sides(1) slot. A 0.3 scalar is attached to the Roudness(1) slot. No value is connected to the Out(1) slot. A solid white rounded pentagon is displayed in the lower part of the node.](images/RoundedPolygonNodeThumb.png) || -| Generates a rounded polygon shape based on input UV at the size specified by inputs Width and Height. The input Sides specifies the number of sides, and the input Roundness defines the roundness of each corner. || +| **Topic** | **Description** | +|------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| [Ellipse](Ellipse-Node.md) | Generates an ellipse shape based on input UV at the size specified by inputs Width and Height. | +| [Polygon](Polygon-Node.md) | Generates a regular polygon shape based on input UV at the size specified by inputs Width and Height. The polygon's amount of sides is determined by input Sides. | +| [Rectangle](Rectangle-Node.md) | Generates a rectangle shape based on input UV at the size specified by inputs Width and Height. | +| [Rounded Polygon](Rounded-Polygon-Node.md) | Generates a rounded polygon shape based on input UV at the size specified by inputs Width and Height. The input Sides specifies the number of sides, and the input Roundness defines the roundness of each corner. | +| [Rounded Rectangle](Rounded-Rectangle-Node.md) | Generates a rounded rectangle shape based on input UV at the size specified by inputs Width and Height. The input Radius defines the radius of each corner. | diff --git a/Packages/com.unity.shadergraph/Documentation~/TableOfContents.md b/Packages/com.unity.shadergraph/Documentation~/TableOfContents.md index 77741b179a8..8a72fca1afc 100644 --- a/Packages/com.unity.shadergraph/Documentation~/TableOfContents.md +++ b/Packages/com.unity.shadergraph/Documentation~/TableOfContents.md @@ -76,7 +76,7 @@ * [Flip](Flip-Node.md) * [Split](Split-Node.md) * [Swizzle](Swizzle-Node.md) - * [Custom Render Texture Nodes](Custom-Render-Texture.md) + * [Custom Render Texture Nodes](Custom-Render-Texture-Nodes.md) * [Self](Custom-Texture-Self.md) * [Size](Custom-Texture-Size.md) * [Slice](Custom-Texture-Slice.md) diff --git a/Packages/com.unity.shadergraph/Documentation~/UV-Nodes.md b/Packages/com.unity.shadergraph/Documentation~/UV-Nodes.md index 4256df6f3fa..400d924bea3 100644 --- a/Packages/com.unity.shadergraph/Documentation~/UV-Nodes.md +++ b/Packages/com.unity.shadergraph/Documentation~/UV-Nodes.md @@ -1,18 +1,16 @@ -# UV Nodes +# UV nodes -| [Flipbook](Flipbook-Node.md) | [Polar Coordinates](Polar-Coordinates-Node.md) | -| :--------------- | :-------- | -| ![Example of the Flipbook Node](images/FlipbookNodeThumb.png) | ![Example of the Polar Coordinates Node](images/PolarCoordinatesNodeThumb.png) | -| Creates a flipbook, or texture sheet animation, of the UVs supplied to input In. | Converts the value of input UV to polar coordinates. | -| [**Radial Shear**](Radial-Shear-Node.md) | [**Rotate**](Rotate-Node.md) | -| ![Example of the Radial Shear Node](images/RadialShearNodeThumb.png) | ![Example of the Rotate Node](images/RotateNodeThumb.png) | -| Applies a radial shear warping effect similar to a wave to the value of input UV. | Rotates the value of input UV around a reference point defined by input Center by the amount of input Rotation. | -| [**Spherize**](Spherize-Node.md) | [**Tiling and Offset**](Tiling-And-Offset-Node.md) | -| ![Example of the Spherize Node](images/SpherizeNodeThumb.png) | ![Example of the Tiling and Offset Node](images/TilingAndOffsetNodeThumb.png) | -| Applies a spherical warping effect similar to a fisheye camera lens to the value of input UV. | Tiles and offsets the value of input UV by the inputs Tiling and Offset respectively. | -| [**Triplanar**](Triplanar-Node.md) | [**Twirl**](Twirl-Node.md) | -| ![Example of the Triplanar Node](images/TriplanarNodeThumb.png) | ![Example of the Twirl Node](images/TwirlNodeThumb.png) | -| A method of generating UVs and sampling a texture by projecting in world space. | Applies a twirl warping effect similar to a black hole to the value of input UV. | -| [**Parallax Mapping**](Parallax-Mapping-Node.md) | [**Parallax Occlusion Mapping**](Parallax-Occlusion-Mapping-Node.md) | -| ![Example of the Parallax Mapping Node](images/ParallaxMappingNodeThumb.PNG) | ![Example of the Parallax Occlusion Mapping Node](images/ParallaxOcclusionMappingNodeThumb.PNG) | -| Creates a parallax effect that displaces a material's UVs. | Creates a parallax effect that displaces a material's UVs and depth. | +Create texture animations, coordinate transformations, and warping through UV manipulation and mapping effects. + +| **Topic** | **Description** | +|------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------| +| [Flipbook](Flipbook-Node.md) | Creates a flipbook, or texture sheet animation, of the UVs supplied to input In. | +| [Radial Shear](Radial-Shear-Node.md) | Applies a radial shear warping effect similar to a wave to the value of input UV. | +| [Spherize](Spherize-Node.md) | Applies a spherical warping effect similar to a fisheye camera lens to the value of input UV. | +| [Triplanar](Triplanar-Node.md) | A method of generating UVs and sampling a texture by projecting in world space. | +| [Parallax Mapping](Parallax-Mapping-Node.md) | Creates a parallax effect that displaces a material's UVs. | +| [Polar Coordinates](Polar-Coordinates-Node.md) | Converts the value of input UV to polar coordinates. | +| [Rotate](Rotate-Node.md) | Rotates the value of input UV around a reference point defined by input Center by the amount of input Rotation. | +| [Tiling and Offset](Tiling-And-Offset-Node.md) | Tiles and offsets the value of input UV by the inputs Tiling and Offset respectively. | +| [Twirl](Twirl-Node.md) | Applies a twirl warping effect similar to a black hole to the value of input UV. | +| [Parallax Occlusion Mapping](Parallax-Occlusion-Mapping-Node.md) | Creates a parallax effect that displaces a material's UVs and depth. | diff --git a/Packages/com.unity.shadergraph/Documentation~/Utility-Nodes.md b/Packages/com.unity.shadergraph/Documentation~/Utility-Nodes.md index f278b98a0c0..fdf7276670c 100644 --- a/Packages/com.unity.shadergraph/Documentation~/Utility-Nodes.md +++ b/Packages/com.unity.shadergraph/Documentation~/Utility-Nodes.md @@ -1,25 +1,23 @@ -# Utility Nodes +# Utility nodes -| [Preview](Preview-Node.md) | [Sub-Graph](Sub-graph-Node.md) | -|:-------------|:------| -| ![Image](images/PreviewNodeThumb.png) | ![Image](images/SubgraphNodeThumb.png) | -| Provides a preview window and passes the input value through without modification. | Provides a reference to a Sub-graph asset. | +Enable essential logic operations, previews, and sub-graph referencing. + +| **Topic** | **Description** | +|--------------------------------|------------------------------------------------------------------------------------| +| [Preview](Preview-Node.md) | Provides a preview window and passes the input value through without modification. | +| [Sub-Graph](Sub-graph-Node.md) | Provides a reference to a Sub-graph asset. | ## Logic -| [All](All-Node.md) | [And](And-Node.md) | -|:-------------|:------| -| ![Image](images/AllNodeThumb.png) | ![Image](images/AndNodeThumb.png) | -| Returns true if all components of the input In are non-zero. | Returns true if both the inputs A and B are true. | -|[**Any**](Any-Node.md)|[**Branch**](Branch-Node.md)| -|![Image](images/AnyNodeThumb.png)|![Image](images/BranchNodeThumb.png)| -|Returns true if any of the components of the input In are non-zero.|Provides a dynamic branch to the shader.| -|[**Comparison**](Comparison-Node.md)|[**Is Infinite**](Is-Infinite-Node.md)| -|![Image](images/ComparisonNodeThumb.png)|![Image](images/IsInfiniteNodeThumb.png)| -|Compares the two input values A and B based on the condition selected on the dropdown.|Returns true if any of the components of the input In is an infinite value.| -|[**Is NaN**](Is-NaN-Node.md)|[**Nand**](Nand-Node.md)| -|![Image](images/IsNaNNodeThumb.png)|![Image](images/NandNodeThumb.png)| -|Returns true if any of the components of the input In is not a number (NaN).|Returns true if both the inputs A and B are false.| -|[**Not**](Not-Node.md)|[**Or**](Or-Node.md)| -|![Image](images/NotNodeThumb.png)|![Image](images/OrNodeThumb.png)| -|Returns the opposite of input In. If In is true, the output is false. Otherwise, it returns true.|Returns true if either input A or input B is true.| +| **Topic** | **Description** | +|------------------------------------|---------------------------------------------------------------------------------------------------| +| [All](All-Node.md) | Returns true if all components of the input In are non-zero. | +| [And](And-Node.md) | Returns true if both the inputs A and B are true. | +| [Any](Any-Node.md) | Returns true if any of the components of the input In are non-zero. | +| [Branch](Branch-Node.md) | Provides a dynamic branch to the shader. | +| [Comparison](Comparison-Node.md) | Compares the two input values A and B based on the condition selected on the dropdown. | +| [Is Infinite](Is-Infinite-Node.md) | Returns true if any of the components of the input In is an infinite value. | +| [Is NaN](Is-NaN-Node.md) | Returns true if any of the components of the input In is not a number (NaN). | +| [Nand](Nand-Node.md) | Returns true if both the inputs A and B are false. | +| [Not](Not-Node.md) | Returns the opposite of input In. If In is true, the output is false. Otherwise, it returns true. | +| [Or](Or-Node.md) | Returns true if either input A or input B is true. | From 649da10bff4c7be0731eb691df73986ecab98f4a Mon Sep 17 00:00:00 2001 From: Reach Platform Support Date: Thu, 4 Sep 2025 18:59:36 +0000 Subject: [PATCH 33/36] [Port] [6000.2] docg-7781: Fix typo --- .../Documentation~/CustomHLSL-Common.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Packages/com.unity.visualeffectgraph/Documentation~/CustomHLSL-Common.md b/Packages/com.unity.visualeffectgraph/Documentation~/CustomHLSL-Common.md index 83c163c74c6..b87c3f017cb 100644 --- a/Packages/com.unity.visualeffectgraph/Documentation~/CustomHLSL-Common.md +++ b/Packages/com.unity.visualeffectgraph/Documentation~/CustomHLSL-Common.md @@ -187,6 +187,6 @@ The HLSL Code Editor supports the following shortcuts: - `Ctrl + S` to save the current HLSL code - `Ctrl + Mouse Wheel` to change the font size ->If you need to write down the name of a particle attribute, you can drag&drop drop the attribute from the blackboard to the code editor. This helps avoid any typo. +>If you need to write down the name of a particle attribute, you can drag and drop the attribute from the blackboard to the code editor. This helps avoid any typo. ![Custom HLSL Editor](Images/custom-hlsl-editor.png) From 6119bd8700ef4ea33a7fa497e9b9bf609fdeb73d Mon Sep 17 00:00:00 2001 From: Reach Platform Support Date: Mon, 8 Sep 2025 09:51:12 +0000 Subject: [PATCH 34/36] [Port] [6000.2] [UUM-70734] Fix for Size of ShadowCaster2D with Casting Source set to a Collider increases when RigidBody2D is attached to the GameObject --- .../ShadowProvider/Providers/ShadowShape2DProvider_Collider.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Packages/com.unity.render-pipelines.universal/Runtime/2D/Shadows/ShadowProvider/Providers/ShadowShape2DProvider_Collider.cs b/Packages/com.unity.render-pipelines.universal/Runtime/2D/Shadows/ShadowProvider/Providers/ShadowShape2DProvider_Collider.cs index aee0fdefc1e..2565b080a5e 100644 --- a/Packages/com.unity.render-pipelines.universal/Runtime/2D/Shadows/ShadowProvider/Providers/ShadowShape2DProvider_Collider.cs +++ b/Packages/com.unity.render-pipelines.universal/Runtime/2D/Shadows/ShadowProvider/Providers/ShadowShape2DProvider_Collider.cs @@ -91,7 +91,7 @@ private void CalculateShadows(Collider2D collider, ShadowShape2D persistantShape // Fetch collider space. var attachedBody = collider.attachedRigidbody; - var colliderSpace = attachedBody ? attachedBody.transform.localToWorldMatrix : Matrix4x4.identity; + var colliderSpace = attachedBody ? attachedBody.localToWorldMatrix : Matrix4x4.identity; // If the shape hash has changed, grab a new potential visible geometry group. var shapeHash = collider.GetShapeHash(); From 94f291fe0abb03f6c4a9aa5b19dfe7af979a6a25 Mon Sep 17 00:00:00 2001 From: Evergreen Date: Mon, 8 Sep 2025 09:51:13 +0000 Subject: [PATCH 35/36] [6000.2] Fix Multiple errors occur when setting the Render Object Event to AfterRenderingPostProcessing while using STP for Upscaling --- .../UniversalRenderPipelineAssetUI.Drawers.cs | 5 +++++ .../Runtime/Passes/RenderObjectsPass.cs | 3 ++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/Packages/com.unity.render-pipelines.universal/Editor/UniversalRenderPipelineAsset/UniversalRenderPipelineAssetUI.Drawers.cs b/Packages/com.unity.render-pipelines.universal/Editor/UniversalRenderPipelineAsset/UniversalRenderPipelineAssetUI.Drawers.cs index 7b174ecd580..1fadc778749 100644 --- a/Packages/com.unity.render-pipelines.universal/Editor/UniversalRenderPipelineAsset/UniversalRenderPipelineAssetUI.Drawers.cs +++ b/Packages/com.unity.render-pipelines.universal/Editor/UniversalRenderPipelineAsset/UniversalRenderPipelineAssetUI.Drawers.cs @@ -217,6 +217,11 @@ static void DrawQuality(SerializedUniversalRenderPipelineAsset serialized, Edito } } + if (serialized.renderScale.floatValue < 1.0f || serialized.asset.upscalingFilter == UpscalingFilterSelection.STP || serialized.asset.upscalingFilter == UpscalingFilterSelection.FSR) + { + EditorGUILayout.HelpBox("Camera depth isn't supported when Upscaling is turned on in the game view. We will automatically fall back to not doing depth-testing for this pass.", MessageType.Warning, true); + } + EditorGUILayout.PropertyField(serialized.enableLODCrossFadeProp, Styles.enableLODCrossFadeText); EditorGUI.BeginDisabledGroup(!serialized.enableLODCrossFadeProp.boolValue); EditorGUILayout.PropertyField(serialized.lodCrossFadeDitheringTypeProp, Styles.lodCrossFadeDitheringTypeText); diff --git a/Packages/com.unity.render-pipelines.universal/Runtime/Passes/RenderObjectsPass.cs b/Packages/com.unity.render-pipelines.universal/Runtime/Passes/RenderObjectsPass.cs index 285ceb0ed67..94ddaabd550 100644 --- a/Packages/com.unity.render-pipelines.universal/Runtime/Passes/RenderObjectsPass.cs +++ b/Packages/com.unity.render-pipelines.universal/Runtime/Passes/RenderObjectsPass.cs @@ -279,7 +279,8 @@ public override void RecordRenderGraph(RenderGraph renderGraph, ContextContainer passData.color = resourceData.activeColorTexture; builder.SetRenderAttachment(resourceData.activeColorTexture, 0, AccessFlags.Write); - builder.SetRenderAttachmentDepth(resourceData.activeDepthTexture, AccessFlags.Write); + if (cameraData.imageScalingMode != ImageScalingMode.Upscaling || passData.renderPassEvent != RenderPassEvent.AfterRenderingPostProcessing) + builder.SetRenderAttachmentDepth(resourceData.activeDepthTexture, AccessFlags.Write); TextureHandle mainShadowsTexture = resourceData.mainShadowsTexture; TextureHandle additionalShadowsTexture = resourceData.additionalShadowsTexture; From c2e8eb91b725bf119142c6dc3e69798c742c91f8 Mon Sep 17 00:00:00 2001 From: Reach Platform Support Date: Tue, 9 Sep 2025 07:21:12 +0000 Subject: [PATCH 36/36] [Port] [6000.2] UUM-116018 : Fix GRDLightMaps test --- .../BRGGameObjects/GRDLightMaps.unity | 3 +- .../Runtime/GraphicsTestSettingsCustom.cs | 1 + .../Assets/Tests/Runtime/GraphicsTests.cs | 8 ++++ .../Assets/Tests/Runtime/SwitchScene.cs | 39 +++++++++++++++++++ .../Assets/Tests/Runtime/SwitchScene.cs.meta | 2 + 5 files changed, 52 insertions(+), 1 deletion(-) create mode 100644 Tests/SRPTests/Projects/BatchRendererGroup_URP/Assets/Tests/Runtime/SwitchScene.cs create mode 100644 Tests/SRPTests/Projects/BatchRendererGroup_URP/Assets/Tests/Runtime/SwitchScene.cs.meta diff --git a/Tests/SRPTests/Projects/BatchRendererGroup_URP/Assets/SampleScenes/BRGGameObjects/GRDLightMaps.unity b/Tests/SRPTests/Projects/BatchRendererGroup_URP/Assets/SampleScenes/BRGGameObjects/GRDLightMaps.unity index ff31981362d..e4b71bbc3be 100644 --- a/Tests/SRPTests/Projects/BatchRendererGroup_URP/Assets/SampleScenes/BRGGameObjects/GRDLightMaps.unity +++ b/Tests/SRPTests/Projects/BatchRendererGroup_URP/Assets/SampleScenes/BRGGameObjects/GRDLightMaps.unity @@ -320,7 +320,8 @@ MonoBehaviour: ImageResolution: 0 ActiveImageTests: 1 ActivePixelTests: 7 - WaitFrames: 30 + Wait: 1 + WaitFrames: 2 --- !u!1660057539 &9223372036854775807 SceneRoots: m_ObjectHideFlags: 0 diff --git a/Tests/SRPTests/Projects/BatchRendererGroup_URP/Assets/Tests/Runtime/GraphicsTestSettingsCustom.cs b/Tests/SRPTests/Projects/BatchRendererGroup_URP/Assets/Tests/Runtime/GraphicsTestSettingsCustom.cs index 9e2064c842a..c44a672e847 100644 --- a/Tests/SRPTests/Projects/BatchRendererGroup_URP/Assets/Tests/Runtime/GraphicsTestSettingsCustom.cs +++ b/Tests/SRPTests/Projects/BatchRendererGroup_URP/Assets/Tests/Runtime/GraphicsTestSettingsCustom.cs @@ -5,6 +5,7 @@ public class GraphicsTestSettingsCustom : GraphicsTestSettings { + public bool Wait = false; public int WaitFrames = 2; public GraphicsTestSettingsCustom() diff --git a/Tests/SRPTests/Projects/BatchRendererGroup_URP/Assets/Tests/Runtime/GraphicsTests.cs b/Tests/SRPTests/Projects/BatchRendererGroup_URP/Assets/Tests/Runtime/GraphicsTests.cs index 2b00eadb751..33896f97395 100644 --- a/Tests/SRPTests/Projects/BatchRendererGroup_URP/Assets/Tests/Runtime/GraphicsTests.cs +++ b/Tests/SRPTests/Projects/BatchRendererGroup_URP/Assets/Tests/Runtime/GraphicsTests.cs @@ -59,6 +59,14 @@ public IEnumerator Run(GraphicsTestCase testCase) yield return null; + // Add a maximum amount of wait frames to avoid infinite loop + int maxWaitFrames = 300; + while (settings.Wait && maxWaitFrames > 0) + { + maxWaitFrames--; + yield return new WaitForEndOfFrame(); + } + int waitFrames = settings.WaitFrames; if (settings.ImageComparisonSettings.UseBackBuffer && settings.WaitFrames < 1) diff --git a/Tests/SRPTests/Projects/BatchRendererGroup_URP/Assets/Tests/Runtime/SwitchScene.cs b/Tests/SRPTests/Projects/BatchRendererGroup_URP/Assets/Tests/Runtime/SwitchScene.cs new file mode 100644 index 00000000000..3d0dcf2f12a --- /dev/null +++ b/Tests/SRPTests/Projects/BatchRendererGroup_URP/Assets/Tests/Runtime/SwitchScene.cs @@ -0,0 +1,39 @@ +using UnityEngine; +using UnityEngine.SceneManagement; + +public class SwitchScene : MonoBehaviour +{ + public float delayInSeconds = 1.0f; + public string sceneToLoad; + public string sceneToUnload; + + private float m_StartTime; + private bool m_SceneSwitched = false; + + void Start() + { + m_StartTime = Time.time; + m_SceneSwitched = false; + } + + // Update is called once per frame + void Update() + { + if ((Time.time - m_StartTime) > delayInSeconds && !m_SceneSwitched) + { + m_SceneSwitched = true; + + var loadHandle = SceneManager.LoadSceneAsync(sceneToLoad, LoadSceneMode.Additive); + loadHandle.completed += operation => + { + var unloadHandle = SceneManager.UnloadSceneAsync(SceneManager.GetSceneByName(sceneToUnload), UnloadSceneOptions.UnloadAllEmbeddedSceneObjects); + unloadHandle.completed += operation => { + // Unblock the waiting so we can take a screenshot + var settings = Object.FindObjectOfType(); + if (settings) + settings.Wait = false; + }; + }; + } + } +} diff --git a/Tests/SRPTests/Projects/BatchRendererGroup_URP/Assets/Tests/Runtime/SwitchScene.cs.meta b/Tests/SRPTests/Projects/BatchRendererGroup_URP/Assets/Tests/Runtime/SwitchScene.cs.meta new file mode 100644 index 00000000000..b9adfb10c2e --- /dev/null +++ b/Tests/SRPTests/Projects/BatchRendererGroup_URP/Assets/Tests/Runtime/SwitchScene.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 15ee8d80d4dd91a43be091df04916480 \ No newline at end of file