Search Unity

Question Hybrid Renderer V2:Material property override not working in shader for custom render pass material

Discussion in 'Graphics for ECS' started by BenMM, Jun 15, 2021.

  1. BenMM

    BenMM

    Joined:
    Jan 28, 2019
    Posts:
    16
    Hi,
    i'm tinkering with an Outline shader for a material applied as a custom render pass override(Forward Renderer -> Render Features -> Render Objects (Experimental)).
    This shader uses instancing and material property override (simple outline color change).

    Using:
    -URP 10.2.2
    -Hybrid Renderer 0.11.0-preview.42

    The material property override does not work if the material is used as a custom render pass override.

    But if i apply the material directly to the object, thus using no custom render pass, the material property override works as expected.

    I have a seperate situation where the object shader and override shader both use the same material property override. Here the object shader is made in shader graph and override shader is code written.

    In this case it works like a charm on both shaders.
    But if i remove the exposed variable with override property from the the shader graph shader, both shaders, Object shader (no material property override) and override shader (still using material property override), stop overriding the color value.

    Is it the case that material property overrides only work in custom render pass override materials if the material being overridden uses the same material property override?

    Any help is appreciated!
    Cheers

    The outline shader im using for the override Material:
    Code (CSharp):
    1. Shader "Outline/DecoOutline"
    2. {
    3.     Properties
    4.     {
    5.         _OutlineColor ("Outline Color", Color) = (1,1,1,1)
    6.         _OutlineScale ("Outline Scale",range(0,3))=1.2
    7.     }
    8.     SubShader
    9.     {
    10.         Tags
    11.         {
    12.             "RenderType" = "Opaque" "RenderPipeline" = "UniversalPipeline"
    13.         }
    14.  
    15.         Pass
    16.         {
    17.             Cull Front
    18.  
    19.             HLSLPROGRAM
    20.             #pragma vertex vert
    21.             #pragma fragment frag
    22.             #pragma target 4.5
    23.             #pragma multi_compile_instancing
    24.             #pragma multi_compile _ DOTS_INSTANCING_ON
    25.  
    26.  
    27.             #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
    28.  
    29.  
    30.             struct appdata
    31.             {
    32.                 float4 positionOS : POSITION;
    33.                 half3 normalOS : NORMAL;
    34.                 #if UNITY_ANY_INSTANCING_ENABLED
    35.                 uint instanceID : INSTANCEID_SEMANTIC;
    36.                 #endif
    37.             };
    38.  
    39.             struct v2f
    40.             {
    41.                 float4 positionHCS : SV_POSITION;
    42.                 #if UNITY_ANY_INSTANCING_ENABLED
    43.                 uint instanceID : CUSTOM_INSTANCE_ID;
    44.                 #endif
    45.             };
    46.  
    47.             CBUFFER_START(UnityPerMaterial)
    48.             float4 _OutlineColor;
    49.             float _OutlineScale;
    50.             CBUFFER_END
    51.  
    52.             #if defined( UNITY_DOTS_INSTANCING_ENABLED)
    53.                 UNITY_DOTS_INSTANCING_START(MaterialPropertyMetadata)
    54.                     UNITY_DOTS_INSTANCED_PROP(float4, _OutlineColor)
    55.                 UNITY_DOTS_INSTANCING_END(MaterialPropertyMetadata)
    56.            
    57.             #define _OutlineColor  UNITY_ACCESS_DOTS_INSTANCED_PROP_FROM_MACRO(float4, Metadata__OutlineColor)
    58.             #endif
    59.  
    60.             v2f vert(appdata IN)
    61.             {
    62.                 v2f output = (v2f)0;
    63.  
    64.                 UNITY_SETUP_INSTANCE_ID(IN);
    65.                 UNITY_TRANSFER_INSTANCE_ID(IN, output);
    66.  
    67.                 float3 normalOS = IN.normalOS;
    68.                 float3 posOS = IN.positionOS.xyz + normalOS * _OutlineScale;
    69.  
    70.                 output.positionHCS = GetVertexPositionInputs(posOS).positionCS;
    71.  
    72.                 #if UNITY_ANY_INSTANCING_ENABLED
    73.                 output.instanceID = IN.instanceID;
    74.                 #endif
    75.                 return output;
    76.             }
    77.  
    78.             float4 frag(v2f i) : SV_Target
    79.             {
    80.                 UNITY_SETUP_INSTANCE_ID(i);
    81.                 return UNITY_ACCESS_INSTANCED_PROP(MaterialPropertyMetadata, _OutlineColor);
    82.             }
    83.             ENDHLSL
    84.         }
    85.     }
    86. }
     
  2. JussiKnuuttila

    JussiKnuuttila

    Unity Technologies

    Joined:
    Jun 7, 2019
    Posts:
    351
    If I understood your situation correctly, it sounds like you have hit a limitation in the current version of the Hybrid Renderer. Property overrides are resolved based on the Material that has been set for the entity.

    If the Material is changed unexpectedly such as using an override mechanism, the property overrides determined for the original Materials will still be used. If the two Materials are compatible (e.g. same properties defined in the same order in the shader, which would be the case e.g. if both shaders get them from the same #include), then the rendering should work. If the override Material is incompatible, then the results will be unexpected.

    So, to answer your question directly: yes, in the current version you need to have the same overrides in both Materials.
     
    BenMM likes this.
  3. BenMM

    BenMM

    Joined:
    Jan 28, 2019
    Posts:
    16
    Thank your for the quick respone!

    I have an aditional question.

    While testing i have realised that the property override in the object shader must be connected to the fragment node in shader graph for it to work in the custom render pass override shader.
    It seems it is not enough to just have the property override in the shadergraph property section, but not used/connected in the graph itself.

    Is ther a reason for this and are there plans to change this?
    Also will future Hybrid Renderer packages allow property overrides just applied to the override shader?(with no/or not the same property override on the object shader)

    Thank you!
     
  4. JussiKnuuttila

    JussiKnuuttila

    Unity Technologies

    Joined:
    Jun 7, 2019
    Posts:
    351
    The reason why it needs to be connected is because the Hybrid Renderer uses shader reflection from the compiled shader to detect the properties (it has no access to Shader Graph's internal configuration). If the property is not connected, the shader compiler is likely to optimize it out and completely remove it, making it invisible to the Hybrid Renderer. This is annoying, and we hope to improve this situation in the future, but in the current version there isn't a good way other than to make sure at least one shader variant actually uses the property.
     
    BenMM likes this.