Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 12 Next capture
2021 2022 2023
1 capture
12 Jun 22 - 12 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
0
Question by ChristmasEve · Dec 09, 2017 at 07:32 PM · shadermaterialoutlineuma

Adding to SkinnedMeshRenderer Materials array

Hey everyone, I'm facing a huge problem that many days of googling has not answered. I am using a library for Unity called UMA that generates humans for me. Their have skinned mesh renderers that have two materials -- the 1st seems to be for their body and the 2nd for their hair. I'm trying to add a red outline material (with an outline shader) to them so I can show the character as selected. If I simply replace the array of two with my outline material, I see only the outline. If I leave the two as-is and I add a 3rd material, it seems to apply to the hair only. So, somehow UMA created a set of meshes that is dependent on material INDEX. ONLY index 0 applies to the body but I cannot replace it, nor do I know enough about shaders to make a shader that will show the body AND the outline. Is there a simple way for me to add my outline material but apply it to all meshes in the renderer? I don't care about draw calls. Only a single object will ever be selected in the scene at any given time anyway.

One more thing to note... I want my technique to work for all other creatures in my game, besides UMA humans, so the materials could vary. A water elemental, for example, will have a completely different material/shader so I would like my solution to be something along the lines of adding an additional material for the outline and apply it to those same meshes rather than trying to make a whole new set of shaders to parallel all of my existing shaders.

Thanks in advance! :)

Comment
Add comment
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

2 Replies

· Add your reply
  • Sort: 
avatar image
2
Best Answer

Answer by Bunny83 · Dec 09, 2017 at 10:10 PM

Unfortunately that is not possible. The way submeshes works is like this:


  • For every submesh in the mesh you have to have one material in the materials / sharedMaterials array.

  • Each submesh is paired with the material from the materials / sharedMaterials array with the same index. So submesh 0 uses material 0 and submesh 1 uses material 1.

  • However if you add more materials than there are submeshes, only the last submesh will be re-rendered again for every additional material. So the submesh index is basically clamped.


It would be great if Unity would simply wrap the index around and keep going but unfortunately it doesn't. That means when you have two submeshes but specify 4 materials Unity will render this:


  • submesh 0 with material 0

  • submesh 1 with material 1

  • submesh 1 with material 2

  • submesh 1 with material 3


That means a single skinned mesh renderer with submeshes can only render the mesh once with one set of materials. If you want to render the whole mesh again with different materials you would have to duplicate the object. Another way could be to actually create a "selected shader" that is a combination of your two shaders. So you can either switch the selection on / off by using a shader parameter or by replacing the materials with the selection material variant.

edit
Another way if merging of the shaders is too complicated would be to "manually" render the objects again using a replacement shader inside OnPostRender. This requires your objects to have a specific tag. When rendering the camera with a replacement shader and using a tag value only the object with that tag will be rendered again with the replacement shader. So you could dynamically assign the tag "selected" to the desired objects and they should get their outline.

Comment
Add comment · Show 4 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image ChristmasEve · Dec 09, 2017 at 11:46 PM 0
Share

I replied to this but it wouldn't let me post it as a reply to your comment. $$anonymous$$aybe it was too long. I added it as an answer.
Thank you for your help :)

avatar image ChristmasEve · Dec 10, 2017 at 01:49 AM 0
Share

Thanks for telling me about OnPostRender and SetReplacementShader... two concepts I didn't know about. I did try your suggestion but I didn't get it right.
I added this tag to my subshader: Tags { "Queue" = "Transparent" "RenderType" = "selected" }

I created this script and added it to my camera:

 using UnityEngine;
 
 public class PostRender : $$anonymous$$onoBehaviour
 {
 
     Shader shader;
     void Start() {
         shader=Shader.Find("Outlined/Silhouette Only");
     }
 
     public void OnPostRender() {
         Camera.main.SetReplacementShader(shader,"selected");
     }
 }

Then, when I ran my game, the camera wouldn't render anything. Furthermore, in the editor, I set an object's tag to "selected" and even that one object's outline didn't render. Nothing did. I'm sorry if I'm missing something simple here. I assumed this would only be an additional pass after my scene was rendered.

avatar image ChristmasEve ChristmasEve · Dec 10, 2017 at 02:42 AM 0
Share

Also, I just noticed I was getting this warning repeatedly: Attempting to render from a camera that is currently rendering. Create a copy of the camera (Camera.CopyFrom) if you wish to do this.

avatar image Bunny83 ChristmasEve · Dec 12, 2017 at 05:23 AM 0
Share

You should use RenderWithShader not SetReplacementShader. "SetReplacementShader" does permanentally set the given replacement shader for the camera which you do not want. "RenderWithShader" does render the camera immediately. That's why this method can only be called during rendering.


You may need to use a second camera as the warning tells you to do the replacement shader rendering.

avatar image
0

Answer by ChristmasEve · Dec 09, 2017 at 11:38 PM

Thank you for clarifying this for me Bunny! That's so unfortunate though. You know what? My experience was that it worked like this:

 submesh 0 with material 0
 submesh **1** with material 1
 submesh **1** with material 2
 submesh **1** with material 3

Body was 0 and hair was 1. When I started adding more materials, it was only affecting the hair. Yeah, it's funny that you mentioned you wished Unity "wrapped the indexes" because that's exactly what I hoped for. I tried adding materials, hoping that would happen but :( no... I thought about duplicating the object but I have to handle animating both at exactly the same time. All my code has to be changed to loop through both. The combination of the two shaders sounds like my best bet but I've been shying away from that since I use different shaders throughout my players/mobs in the game. I don't know a lot about shaders but, let's say you were using the standard "built-in" shader.... how hard would it be to add this shader script and make it switchable (on/off):

 // Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'
 
 Shader "Outlined/Silhouette Only" {
     Properties {
         _OutlineColor ("Outline Color", Color) = (0,0,0,1)
         _Outline ("Outline width", Range (0.0, 0.03)) = .005
     }
  
 CGINCLUDE
 #include "UnityCG.cginc"
  
 struct appdata {
     float4 vertex : POSITION;
     float3 normal : NORMAL;
 };
  
 struct v2f {
     float4 pos : POSITION;
     float4 color : COLOR;
 };
  
 uniform float _Outline;
 uniform float4 _OutlineColor;
  
 v2f vert(appdata v) {
     // just make a copy of incoming vertex data but scaled according to normal direction
     v2f o;
     o.pos = UnityObjectToClipPos(v.vertex);
  
     float3 norm   = normalize(mul ((float3x3)UNITY_MATRIX_IT_MV, v.normal));
     float2 offset = TransformViewToProjection(norm.xy);
  
     o.pos.xy += offset * o.pos.z * _Outline;
     o.color = _OutlineColor;
     return o;
 }
 ENDCG
  
     SubShader {
         Tags { "Queue" = "Transparent" }
  
         Pass {
             Name "BASE"
             Cull Back
             Blend Zero One
  
             // uncomment this to hide inner details:
             //Offset -8, -8
  
             SetTexture [_OutlineColor] {
                 ConstantColor (0,0,0,0)
                 Combine constant
             }
         }
  
         // note that a vertex shader is specified here but its using the one above
         Pass {
             Name "OUTLINE"
             Tags { "LightMode" = "Always" }
             Cull Front
  
             // you can choose what kind of blending mode you want for the outline
             //Blend SrcAlpha OneMinusSrcAlpha // Normal
             //Blend One One // Additive
             Blend One OneMinusDstColor // Soft Additive
             //Blend DstColor Zero // Multiplicative
             //Blend DstColor SrcColor // 2x Multiplicative
  
 CGPROGRAM
 #pragma vertex vert
 #pragma fragment frag
  
 half4 frag(v2f i) :COLOR {
     return i.color;
 }
 ENDCG
         }
  
  
     }
  
     Fallback "Diffuse"
 }

Comment
Add comment · Show 1 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Bunny83 · Dec 10, 2017 at 12:00 AM 0
Share

Yes, my bad i fixed my answer. I also added another alternative which might fit your situation better.

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

126 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

QuickOutline: how can I change the shader to work with objects with two materials? 3 Answers

Outline diffuse shader (toon) : no results? 1 Answer

Shader Edit Help: 2D Outline Coloring 2 Answers

Object outline component 0 Answers

Outline Shader HELP 0 Answers


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges