- Home /
Why does the downloaded Standard shader behave differently than the built-in?
I've recently had to download the built-in shaders and remap all of our models and materials to use them to fix the duplicate shader issue with asset bundles and reduce our ShaderLab memory usage. However, I've found that the downloaded Standard (Specular setup) and Standard shaders are behaving differently than the built-in shaders. The downloaded shaders are rendering opaque when they should be transparent, they are causing other artifacts with overlapping objects (this is mainly when used as a water surface), or they are sorting incorrectly and/or simply disappearing at certain angles. I have not figured out the exact situation that causes the issues, but it appears to be related to transparency and specular highlights. When I changed the shader in the materials from built-in to downloaded in script, Unity also removed the Transparency setting and queue order from the material. When I reset those settings and make sure that the only difference in the material file is the shader reference, they still behave differently. The fun thing is that everything renders properly in the editor, so I have to build our bundles to test this. Anyway, I've reverted the handful of materials that we've found through testing, and I'm about to run a script to crawl the project and alert us to other potential problems so that we can test those as well. Are the downloadable shaders for 2018.2.15f1 correct? If so, why are they behaving differently than the built-in shaders when the materials don't have any other differences? And why do they render correctly in the editor?
I built the assets into bundles and now the downloaded shaders are opaque. If I run the scene in the editor without the bundles, it works correctly. Is this possibly some issue with the required shader variants not being built and bundled correctly? What happens when the exact shader variant isn't available? Does Unity use the closest that it can find?
Answer by Eno-Khaon · Apr 17, 2019 at 01:37 AM
Unity's Standard Shader is essentially an all-in-one shader. Because of that, they enable and disable features for the shader on demand in order to accommodate some of those variations using a custom shader editor.
For direct references on how it does that in full, take a look at StandardShaderGUI.cs.
The part that most directly (and most likely) affects the Transparency factors you're looking for should be under the SetupMaterialWithBlendMode(Material, BlendMode) function). To borrow an excerpt from it:
case BlendMode.Transparent:
material.SetOverrideTag("RenderType", "Transparent");
material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One);
material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha);
material.SetInt("_ZWrite", 0);
material.DisableKeyword("_ALPHATEST_ON");
material.DisableKeyword("_ALPHABLEND_ON");
material.EnableKeyword("_ALPHAPREMULTIPLY_ON");
material.renderQueue = (int)UnityEngine.Rendering.RenderQueue.Transparent;
break;
When you change between modes in the selection box, it immediately makes 8 changes to the instance of the shader used by that material to switch from an opaque- to a transparent-intended variation of the same shader.
Ooh, that's good to know. I'll take a look at that file. Though it doesn't necessarily explain why the settings were being removed when my script reassigned the shader from the built-in Standard shader to the downloaded Standard shader. $$anonymous$$y script didn't change any other settings, but the transparency and render queue were cleared. I created a test project to try and repro this issue with $$anonymous$$imal assets, but am not seeing the same artifacts. I'm going to continue working on it today. I'll make sure the graphics and quality settings are identical, and then I'll also build the assets into bundles to see if I can narrow down where things are going wrong. Thanks for the info.
Answer by PW_Dave · Apr 17, 2019 at 08:33 PM
I opened my test scene in the editor and created a ShaderVariantCollection from the Graphics settings. I added that ShaderVariantCollection to the shader bundle, and it works now. So, apparently when building to bundles, you can't count on the correct variants being included without a ShaderVariantCollection. Does that sound right?
That's not wrong, but it's also not the whole story, nor the only option.
To borrow a quote from the writeup on $$anonymous$$ultiple Shader Variants:
shader_feature is very similar to multi_compile. The only difference is that Unity does not include unused variants of shader_feature shaders in the final build. For this reason, you should use shader_feature for keywords that are set from the $$anonymous$$aterials, while multi_compile is better for keywords that are set from code globally.
Specifically, this "shader_feature" feature was added in order to adequately support Unity's Standard shader. By having so many different combinations, it would likely add thousands of unused shader variants in order to support what few versions you might need to build with.
Along with that, however, it means that Unity can only make an educated guess regarding which variations you intend to use. These come from active implementations, such as a ShaderVariantCollection or simply having a $$anonymous$$aterial/Shader combination active in a scene (to ensure it's "found" when you build the game).
I don't personally know all of the means by which a shader variant can be validated in this way, but that's the key to utilizing "shader_feature" in your shader.
Your answer
Follow this Question
Related Questions
What license has built-in shaders? 1 Answer
Fog Mode Off Functionality 1 Answer
up the contrast (0-1) in shader code 0 Answers
ShaderLab CG question 0 Answers
Make a complex object semi transparent without changing it 2 Answers