Search Unity

Question hdrp/lit material on exported gameObjects do not render correctly

Discussion in 'High Definition Render Pipeline' started by 3dimYannick, Apr 15, 2020.

  1. 3dimYannick

    3dimYannick

    Joined:
    Mar 26, 2013
    Posts:
    14
    Hello it's me again with some asset bundling issues!

    This time I'm trying to figure out why a material with hdrp/lit shader act differently when it's loaded via asset bundle (as part of a game object with mesh) compared to what you get in the editor.

    what I got: what I expected.
    wrong.png correct.png
    So I was testing a few things and for the heck of it just applied the hdrp/lit shader again in the editor UI

    what_i_did.png
    I did this on the material that was part of the gameobject assetbundle.
    After I did that I got the "what I expected" result.

    I felt it was somewhat related to a problem I had before: link
    And I tried to find a solution similar to that, but there wasn't any other namespaces I could add.

    To be sure I would have the same problem with an actual build I added the game object to the scene that is added when I build the game. The material worked correctly from the start. But again the material from the asset bundle did not.

    So I this is what I currently know:
    - a material via assetbundle does not display correctly but isn't totally broken
    - when I somehow reinitialize said material (see third image) it will work correctly again (so no settings are lost)
    - when I build it as a standalone game the material which is loaded from the assetbundle does not work but the one build with the game does.

    So what am I missing this time?
     
  2. chap-unity

    chap-unity

    Unity Technologies

    Joined:
    Nov 4, 2019
    Posts:
    766
    I think the problem may not be on your side but is closely related to an issue with shaders inside asset bundles here.

    The gist of it, is that when downloaded via an asset bundle, the textures are not set correctly.

    The quick workaround we have for now is indeed to "Re-apply" the shader in runtime after the bundle was loaded.

    Code (CSharp):
    1. obj.GetComponent<Renderer>().materials[0].shader = Shader.Find("Standard"); //Or whatever shader you are using
     
    3dimYannick likes this.
  3. 3dimYannick

    3dimYannick

    Joined:
    Mar 26, 2013
    Posts:
    14
    This indeed solves my problem, thanks a lot!
     
    chap-unity likes this.
  4. 3dimYannick

    3dimYannick

    Joined:
    Mar 26, 2013
    Posts:
    14
    I do have one more question regarding the the shader.

    I have made a glass material, which has it's "Surface Type" set to "Transparent"

    But when I reapply it (via code), its surface type displays Transparent (in the interface) but act like it's opaque.
    When I reapply it like I mentioned before it works correctly again

    Since the issue you linked only mentions textures can I assume this issue is new?

    I thought I had a fix, by reapplying every property I would eventually also reapply the surface type property but it seems that is not as easily said as done. because I have to figure out what kind of properties there are.

    furthermore I noticed that the property "__surfacetype" is both 0 for Transparent and Opaque, when I request its float value.

    simply doing this:
    Code (CSharp):
    1.  
    2. float val = material.GetFloat("__surfacetype");
    3. material.SetFloat("__surfacetype", val);
    4.  
    will result in the glass material turing opaque again after I set it transparant myself.
    So by simply applying it's own value it turns opaque.

    I hope you have some insights in how to fix this issue, because I suspect this would be a problem for other properties within this shader as well.
     
    Migmac likes this.
  5. 3dimYannick

    3dimYannick

    Joined:
    Mar 26, 2013
    Posts:
    14
    ok so the bit about setting the surfacetype to an other value not working seems to be wrong, not why it didn't work but it does now.

    so to get transparent materials working correctly you still need to re apply it's property.
    I made this bit of code which applies all properties it can find. Maybe it will be of use for someone else aswell.

    Code (CSharp):
    1.  
    2. private void ReapplyProperties(Material material)
    3. {
    4.     Shader shader = material.shader;
    5.     int shaderPropCount = shader.GetPropertyCount();
    6.  
    7.     for (int i = 0; i < shaderPropCount; i++)
    8.     {
    9.         string propName = shader.GetPropertyName(i);
    10.         ShaderPropertyType propType = shader.GetPropertyType(i);
    11.         switch (propType)
    12.         {
    13.             case ShaderPropertyType.Color:
    14.                 Color color = material.GetColor(propName);
    15.                 material.SetColor(propName, color);
    16.                 break;
    17.             case ShaderPropertyType.Float:
    18.             case ShaderPropertyType.Range:
    19.                 float floatVal = material.GetFloat(propName);
    20.                 material.SetFloat(propName, floatVal);
    21.                 break;
    22.             case ShaderPropertyType.Texture:
    23.                 //do nothing
    24.                 break;
    25.             case ShaderPropertyType.Vector:
    26.                 Vector4 vector = material.GetVector(propName);
    27.                 material.SetVector(propName, vector);
    28.                 break;
    29.  
    30.         }
    31.     }
    32. }
     
    Last edited: Apr 16, 2020
    Migmac likes this.
  6. Eric-Boise

    Eric-Boise

    Joined:
    Jul 22, 2014
    Posts:
    6
    Thanks for posting this @3dimYannick . We have the same issue. I hope this is resolved on Unity's end soon. How are developers supposed to iterate on bundles with this bug? Artists needing to create new bundles and run binaries is not a good workflow.
     
  7. 3dimYannick

    3dimYannick

    Joined:
    Mar 26, 2013
    Posts:
    14
    @Eric-Boise I think I celebrated too soon, after I used my code in a more complex enviroment (lights wise)I got some weird results.

    It seems that my solution didn't seem to fix it completely and that the reapplying via the editor still does some things differently. I made some different iterations of the code shown above with different outcomes.

    I hope I'm still missing something.

    I will make a post about it here asap, since I need this problem resolved.
     
  8. 3dimYannick

    3dimYannick

    Joined:
    Mar 26, 2013
    Posts:
    14
    This is the result I want to achieve
    expected_result.png

    the white square in the reflection is an Area light, with it's mode set to realtime/

    So here is my breakdown of different results:

    no 1. Basic version
    This is basically what was suggested by @chap-unity

    Code (CSharp):
    1.  
    2. private Material ReapplyProperties(Material material)
    3. {
    4.     Shader shader = material.shader;
    5.     material.shader = Shader.Find(shader.name);
    6.     return material;
    7. }
    8.  
    Result: no transparency for materials with surface type set to transparent
    basic.png

    when I set surface type to opaque and back to transparency it looks like the expected result

    no 2. Re applying shader properties
    This does not reapply the shader, but only the properties it has.

    Code (CSharp):
    1.  
    2.  private Material ReapplyProperties(Material material)
    3. {
    4.     Shader shader = material.shader;
    5.     int shaderPropCount = shader.GetPropertyCount();
    6.     for (int i = 0; i < shaderPropCount; i++)
    7.     {
    8.         string propName = shader.GetPropertyName(i);
    9.         ShaderPropertyType propType = shader.GetPropertyType(i);
    10.         switch (propType)
    11.         {
    12.             case ShaderPropertyType.Color:
    13.                 Color color = material.GetColor(propName);
    14.                 material.SetColor(propName, color);
    15.                 break;
    16.             case ShaderPropertyType.Float:
    17.             case ShaderPropertyType.Range:
    18.                 float floatVal = material.GetFloat(propName);
    19.                 material.SetFloat(propName, floatVal);
    20.                 break;
    21.             case ShaderPropertyType.Texture:
    22.                 //do nothing
    23.                 break;
    24.             case ShaderPropertyType.Vector:
    25.                 Vector4 vector = material.GetVector(propName);
    26.                 material.SetVector(propName, vector);
    27.                 break;
    28.         }
    29.     }
    30.     return material;
    31. }
    32.  
    result: we have transparency, but the reflection is not working as intended (see expected results for reference)
    only_apply_shader_props.png

    when I set surface type to opaque and back to transparency it stays broken

    no 3. New material with old material properties
    The idea was that if I create a new material from scratch and I apply all the properties I would get the expected result.

    Code (CSharp):
    1.  
    2. private Material ReapplyProperties(Material oldMat)
    3. {
    4.     Shader shader = oldMat.shader;
    5.     Material newMat = new Material(Shader.Find(shader.name));
    6.     int shaderPropCount = shader.GetPropertyCount();
    7.     for (int i = 0; i < shaderPropCount; i++)
    8.     {
    9.         string propName = shader.GetPropertyName(i);
    10.         ShaderPropertyType propType = shader.GetPropertyType(i);
    11.         switch (propType)
    12.         {
    13.             case ShaderPropertyType.Color:
    14.                 Color color = oldMat.GetColor(propName);
    15.                 newMat.SetColor(propName, color);
    16.                 break;
    17.             case ShaderPropertyType.Float:
    18.             case ShaderPropertyType.Range:
    19.                 float floatVal = oldMat.GetFloat(propName);
    20.                 newMat.SetFloat(propName, floatVal);
    21.                 break;
    22.             case ShaderPropertyType.Texture:
    23.                 //do nothing
    24.                 break;
    25.             case ShaderPropertyType.Vector:
    26.                 Vector4 vector = oldMat.GetVector(propName);
    27.                 newMat.SetVector(propName, vector);
    28.                 break;
    29.         }
    30.     }
    31.     return newMat;
    32. }
    33.  
    result: correct reflection and it got darker, still no transparency
    instance_mat_copy_shader_settings.png

    when I set surface type to opaque and back to transparency it looks like the expected result

    so in short:
    1 and 3 both give a correct reflection but no transparency but when surface type is toggled it does.
    2 has transparency from the start but the reflection stays broken even when toggled.

    I am fresh out of ideas from now and I hope maybe @chap-unity or anyone else can shine some light on the problems I'm facing
     
  9. chap-unity

    chap-unity

    Unity Technologies

    Joined:
    Nov 4, 2019
    Posts:
    766
    So I tried reproducing your issue and it does not repro on my side. (with latest editor and HDRP version). I just created a simple glass material in a bundle and loaded it on start. As you can see, it's still transparent and you can see the area light properly.

    Do you have a simple project in which it repro or at least the Unity Editor and HDRP version in which it happens ?
     
  10. 3dimYannick

    3dimYannick

    Joined:
    Mar 26, 2013
    Posts:
    14
    I do not have a simple project at this time. but the version I am using are:
    unity: 2019.3.3f1
    HDRP: 7.1.8
     
  11. chap-unity

    chap-unity

    Unity Technologies

    Joined:
    Nov 4, 2019
    Posts:
    766
    Hi @3dimYannick, I've been able to reproduce your issue in your version, however it appears to be fixed in later version.

    You can try latest and see it that fixes it. 2019.3.10f1 with HDRP 7.3.1
     
  12. 3dimYannick

    3dimYannick

    Joined:
    Mar 26, 2013
    Posts:
    14
    @chap-unity I updated the project to the latest version as you suggested, sadly there was no change in behavior at all.

    My colleague reminded me that my current issue with materials not working might not be the same problem as the original issue I had (not entirely at least), since the glass material I load is loaded from a material assets bundle so no mesh or anything else. I haven't specifically tested a glass material on a object I load.

    But since other materials acted the same way it might not be an issue.

    I might do some tests, like removing caching (such as the shader cache) if that doesn't work I'm going to build a test environment, but this will have to wait till later this week.
     
  13. chap-unity

    chap-unity

    Unity Technologies

    Joined:
    Nov 4, 2019
    Posts:
    766
    Okay, FYI, this is what I specifically tested :
    - Built an asset bundle of a glass pane (simple quad) with a transparent HDRP/Lit material with refraction and transmission color
    - Host it on a distant server
    - Load the mesh with the material it at runtime in Unity editor without re-applying the shader.
     
  14. 3dimYannick

    3dimYannick

    Joined:
    Mar 26, 2013
    Posts:
    14
    Thanks for the info.

    Since it's on a external server I assume you're loading the asset as a web request? (with UnityWebRequestAssetBundle)
    Because we keep our files locally so we use AssetBunlde.LoadFromFile(filePath).

    You also mentioned not re-applying the shader in the latest version, I am still re-applying so I'll first test it without doing that.
     
  15. 3dimYannick

    3dimYannick

    Joined:
    Mar 26, 2013
    Posts:
    14
    Well I made the test project and I didn't get any weird reflections while creating asset bundles and loading them.

    So I took a look at the way we create our asset bundles.
    We create shared dependencies bundles for materials with shared assets such as textures (and shaders!).
    But as far as I can see that shouldn't be any issue since we first load the shared dependency bundle before the actual material bundle.

    But as a test I've excluded .shader files from being put in a separate bundles and now it works.
    I also noticed a lot more shader variants being created.

    So that means that depending on the context of an item in the bundle (a separate shader vs shader that's part of an actual material). The amount of shader variants will vary (which makes sense).

    Before HDRP we didn't have that issue, but we were using standard shaders and some custom shaders, but maybe we were just lucky?
     
  16. J-Luna

    J-Luna

    Joined:
    Sep 10, 2013
    Posts:
    4
    I'm using Unity 2020.3.25f1 and I randomly face this very same issue: sometimes the object becomes completely blue, sometimes it's full transparent. I tried to find a pattern on how to repro this but no success so far. Any progress on this?