Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Double Sided *Material*

Discussion in 'Shaders' started by p3x797, Apr 24, 2009.

  1. Daniel_Brauer

    Daniel_Brauer

    Unity Technologies

    Joined:
    Aug 11, 2006
    Posts:
    3,355
    As I understand it, Unity walks through Renderer.materials and renders each submesh with the corresponding Material. If you have more Materials than submeshes, it loops through the submeshes until it runs out of Materials.
     
  2. Giantbean

    Giantbean

    Joined:
    Dec 13, 2012
    Posts:
    144
    Have things changed in Unity 4?

    Looking at the tutorial by Tessa Lee The built in shader source files for 4.1.5 don't have passes at line 14. People say "just change Cull Off" but when cull is off I get black faces. When I use Animaleante's code everything is white and when I try to use rectalogic's two shaders I cant get both scripts to run on one mesh.

    I tried setting the Mesh Renderer Size to accept more materials but this is not working. I would try to write the two scripts into one shader with passes but I am unsure of shader coding and it has already been said that surface materials don't do passes.

    I need a shader that renders doublesided faces (Like the default in Maya) and I would like it to use a cubemap for specular, but none of these posted suggestions are working. So I ask, Have things changed in Unity 4? What am I missing?

    As this is a popular and often recycled question on the forums I'm surprised no one has added a robust double-sided shader to the Wiki
     
  3. SympaK

    SympaK

    Joined:
    Apr 14, 2010
    Posts:
    134
    1) This thread has been created 4 yars ago;
    2) here and there I continually read know-alls lamenting that this question has been made many times before (and also after, I see);
    3) there are still some unofficial workabouts put by users, each of whom with his/hers own kind of solutions, and no one taken as the best effective...
    As for logical consequence, now the question is: should it take some other 4 years, in order for Unity coders will understand to implement the commands to automatically achieve this effect directly with a button inside of Unity?
    All the best, sirs.
     
  4. aubergine

    aubergine

    Joined:
    Sep 12, 2009
    Posts:
    2,878
    For a planar object;
    1-Calculate which side your camera is depending on the plane equation from a script.
    2-Reverse the normals according to the sign and pass this value as view vector to your shader.
    3-Do lighting based on this normal.
    Thats it.
     
    Devilwhale likes this.
  5. Dolkar

    Dolkar

    Joined:
    Jun 8, 2013
    Posts:
    576
    Unity coders can't do much more than what has already been suggested in this case. The most computationally efficient way to do this is to open your modeling program, duplicate the vertices and invert their normals. It takes 10 minutes tops to set it up as well, so I can't see a reason for any other solution.
     
  6. TOES2

    TOES2

    Joined:
    May 20, 2013
    Posts:
    135
    My search just found your answer, do you think it is helpful?
     
  7. wccrawford

    wccrawford

    Joined:
    Sep 30, 2011
    Posts:
    2,039
    You should probably read the whole thread before posting a snarky answer.
     
  8. Hoeloe

    Hoeloe

    Joined:
    May 9, 2013
    Posts:
    31
    I have a cheap package on the Asset Store with some shaders that do exactly this (it comes with a few others as well, for streamlining Beast Lightmapping, etc.)

    Interactive Cloth and other vertex displacement shaders can break with two-sided meshes like this because the vertices on both faces can be moved independently. I developed the aforementioned shaders for use with cloth precisely because of this.
     
  9. cm

    cm

    Joined:
    Jul 31, 2012
    Posts:
    14
    I agree. It would be handy, and easier than scripting support.
     
  10. TOES2

    TOES2

    Joined:
    May 20, 2013
    Posts:
    135
    You do understand that a search also brings your "answer" up, right? This just happened to me now.

    Please do not pollute threads with useless comments like this, if there is another thread with the solution, just post the link, instead of discouraging others to provide useful insight.

    Having multiple threads with the solution to the same common problem is useful, this way we can see different variations of answers, as there is usually more than one approach to solve something.
     
    Batracien333, ericpug and Alverik like this.
  11. TOES2

    TOES2

    Joined:
    May 20, 2013
    Posts:
    135
    Please refrain from posting unhelpful answers. The "search online for an existing answer" reply is pointless, and you better learn how Internet works, because I was searching online and got here by searching for an answer.
     
    Batracien333, ericpug and Alverik like this.
  12. jc_lvngstn

    jc_lvngstn

    Joined:
    Jul 19, 2006
    Posts:
    1,508
    I know this post is kinda being drug in and out of the grave, but I feel that lowering vertex count can be a big reason in some cases.
    And for some reason (maybe I have the user preferences wonky), trying to paint vertexes in Blender (for wind shaders and such) is a PITA when you do this. It is almost impossible to get consistent painting, it's like blender gets confused as to which vertex/face you are painting on.

    Anyway...I have seen (thanks ShaderForge) shaders for forward rendering that do this. But I'm personally still looking for a deferred one.

    And I'm not sure if everyone agrees on the features, but what I -think- everyone is asking for is a transparent/cutout shader that handles lighting and shadows properly, for a single poly (double sided that is) in both forward and deferred mode.
    That about right?
     
  13. Gamersground

    Gamersground

    Joined:
    Sep 15, 2014
    Posts:
    3
    Hi everyone,

    I tried rectalogic's approach and it seems to be the best one so far; however, it's not perfect. I am using Unity 4.6.0b.17 (Pro). I am getting problems with shadows. It's almost as if I can see the shadows through objects (Please see attached screenshot). Am I missing a step?

    I am also wondering if there was ever an official technique developed on how to do this since 2012.

    Thanks,
    Sam
     

    Attached Files:

  14. Daniel_Brauer

    Daniel_Brauer

    Unity Technologies

    Joined:
    Aug 11, 2006
    Posts:
    3,355
    The best way to render both sides of something is to double your geometry and flip the duplicates using your modelling program. Is there a reason you can't do this?
     
  15. Gamersground

    Gamersground

    Joined:
    Sep 15, 2014
    Posts:
    3
    Yes, and we have done this in some situations (palm trees, some types of vegetation, barbed-wire fence, chain link fence).

    CryEngine and Unreal does this out of the box with a simple tick of a checkbox. 3D Studio Max and every other modeling program I have ever used can do this as well. Even my low-tech Dark Basic Pro. game engine can do this too. It's such a basic requirement that I almost expect it to be available. Hundreds of 3D models were created with this assumption in mind; many hours and a lot of care is devoted everyday to insure that we aren't being wasteful when we create our models.

    Our team has created a ton of models that worked fine in other game engines; we would like the ability to re-purpose them without the need for anyone to go back and temper with them. I feel like am ruining them every time I go in and double my geometry to achieve this. I am embarrassed to send something like this to production. I can hear my fellow co-workers laughing at me already.

    Sometimes you especially need it for things like vertex animated cloth where it might be a bit too heavy for the pipeline and bad for memory (twice as many animated vertices if you duplicate the faces).

    I talked to our shader guy about making a double-sided shader that works properly; however, he is backed-up for months. If anyone is an expert shader programmer that writes advanced shaders for a living and would like to make some money, please contact me. I already talked to my boss and he said it's okay to pay someone to do this properly. BIG PLUS if you can make it compatible with Marmoset Skyshop. If not, I guess, we'll just need to wait for our shade guy.

    Thanks,
    Sam
     

    Attached Files:

    • CE2.jpg
      CE2.jpg
      File size:
      179.3 KB
      Views:
      1,538
    Devilwhale and Alverik like this.
  16. Daniel_Brauer

    Daniel_Brauer

    Unity Technologies

    Joined:
    Aug 11, 2006
    Posts:
    3,355
    I'm curious how other engines implement this checkbox, but I'd honestly be embarrassed to ship a shader solution to what (due to the way graphics cards work) is a modelling issue. There is no simple way for a shader to flip vertex normals in order to light front and back faces properly at the same time, and this translates to extra GPU effort every single frame.
     
    Last edited: Sep 18, 2014
  17. windwolfx_23

    windwolfx_23

    Joined:
    Jan 15, 2015
    Posts:
    11
    hi guys, I'm new to unity3d, if the double sided shader require multiple passes to calculate both sides, does it mean I can directly use a model that have actual thickness, and have the equivalent prossessing speed? is it why the built-in shaders don't have the option "double sided"?
     
  18. windwolfx_23

    windwolfx_23

    Joined:
    Jan 15, 2015
    Posts:
    11
    what actually bugs me is why there is no check box for the purpose
    tested and worked, this answers the ultimate double sided material question.
     
  19. Souvik025

    Souvik025

    Joined:
    Jul 7, 2015
    Posts:
    1
    lol I am here via google search :3
     
    AnomalusUndrdog likes this.
  20. Archanor

    Archanor

    Joined:
    Dec 2, 2013
    Posts:
    575
    Last edited: Jun 7, 2022
  21. DogF

    DogF

    Joined:
    Dec 31, 2013
    Posts:
    29
    The two links is not work, sir.
     
  22. DogF

    DogF

    Joined:
    Dec 31, 2013
    Posts:
    29
    I learned a lot from your code, thank you very much.
     
  23. passghost

    passghost

    Joined:
    Jun 15, 2015
    Posts:
    1
    AFTER Googling, this was the first post I came across. Scrolling passed the moderator's comments, I thought to myself.... What a jerk. My last search on this topic several weeks back yielded a wrong answer of "Extrude to make it double sided." That's okay for some models, but some it simply yields sloppy surfaces with higher detailed models. I think there is a certain attitude of "I don't want to hold anyone's hand" that comes from 'those that know' that ends up discouraging people from ASKING questions in the first place. I think the attitude could ABSOLUTELY be misconstrued as being malicious, and is a huge problem among big egos in the field. If you haven't had any direction, AT ALL, running into responses like that can be highly discouraging after sorting through 15 posts that simply aren't YOUR answer. Also (moderator) you have to consider; not everyone terms searches the same. Something may be common sense to you, and not the next. Food for thought. Those that offered answers that actually had some anatomy, thank you.
     
  24. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    Try to understand that you're referring to a post that was made 6 years ago. Consider that the googlescape was very different back then, and a basic search did in fact immediately turn up several threads that discussed the issue in detail. Plus there's the fact that I wasn't even a moderator back then. If I had been, I would have linked to an existing topic and closed this one.

    --Eric
     
    Devilwhale likes this.
  25. FuzzyQuills

    FuzzyQuills

    Joined:
    Jun 8, 2013
    Posts:
    2,871
    and this makes me think, since you seem to post that same thing something like 6 times on this thread's pages: "Can't one of them mods just CLOSE this thread already?! :eek:"
    anyway... :D point's made, we have a bunch of junk comments (some of them funny... :D) here for everyone else to gawk at, how's about this thread be shut down finally? Just saying. I do understand that people keep glaring at you for something stupid, but ah well, that's internet trolls for you. ;)

    Well yes, but... just saying, you can actually use the lighting models in Vertex/Fragment shaders, and it is indeed possible to write your own passes for that. ;) all the lighting models are shader functions that return float4s anyway.
     
    Last edited: Aug 13, 2015
  26. zbalai

    zbalai

    Joined:
    May 28, 2012
    Posts:
    21
    Thanx, this works!

     
  27. username_unity_of_my

    username_unity_of_my

    Joined:
    Feb 24, 2015
    Posts:
    330
  28. Eideren

    Eideren

    Joined:
    Aug 20, 2013
    Posts:
    309
    This thread still doesn't give solutions which would fit most of the use cases. So yes, I'm keeping this thread alive but not because I want someone to answer it, no, this post will be the definite answer to this question, I'll provide every possible method you could use to render those two sides with correct normal direction, one of those solutions has never been mentioned before and is probably the one you are looking for.


    Shader based Methods
    Single Pass rendering with incorrect normals :
    Right after the line which starts the Pass you just have to add Cull Off
    Multiple Pass rendering :
    Duplicate your pass and add inside the second one Cull Front, then inverse the second pass's normals.​
    Single Pass rendering with correct normals :
    Right after the line which starts the Pass add Cull Off.
    Now to inverse the normals correctly, we'll have to know if the face is facing backwards or forwards and for that you'll have to add inside your Fragment Input / struct the line
    float faceDir: VFACE;
    VFACE will give -1 if the face is facing backwards and 1 if forwards, now you can multiply your normals in the fragment/pixel shader by i.faceDir, which results in inversed normals for the back faces (direction * -1 = inverse of that direction) and standard normals for the front(direction * 1 = direction).
    (FYI : if you get the error "undefined variable "i.faceDir"", change the i. by what's inside the brackets of your fragment shader, something like IN. or input.)

    If your shader is written in glsl, gl_FrontFacing is probably what you are looking for.
    Modeling based Methods
    Duplicate your model inside your favorite modeling program, flip the normals, merge the front and back objects together and you are done.
    (If your mesh is skinned, you might have to rebind or transfer the skeleton)

    Differences in performances
    The test I did was on an ocean shader, generating voronoi and perlin using hashes and octaves - > fragment and vertex intensive.
    On planar, non-transparent object the fastest one is the Single Pass rendering( + correct normals following right next to it) and it should be since the fragment shader computes only what is on screen so using only a single pass is far more lightweight than using two passes or doubling the vertices count with the modeling based one.
    If you add tesselation on top of that, you'll see the difference in performance skyrocket.

    For concave objects the results might be slightly different based on the situation but I think that it'll be better than the modeling method in most cases.​


    It would be nice of you to avoid answering in this thread since that'll hide my post from those skimming through the thread for an answer.
    If you have other questions send me a message or start a new thread and if you want to show your appreciation just press the like link to this post.

    Have a nice day !
     
    Last edited: Nov 25, 2015
  29. Stevepunk

    Stevepunk

    Joined:
    Oct 20, 2013
    Posts:
    205
    I added Cull Off to the standard shader which I'm using on a sprite.
    Saying to search is all well and good but does not give the answer.

    When the sprite is flipped horizontally the y value on the normals is incorrect.

    Some searching brought up this answer:

    1. float3 n =UnpackNormal(text2D(_Bump, IN.uv_Bump));
    2. o.Normal= dot(IN.viewDir, float3(0,0,1))>0? n :-n;
    But I have no idea where to add it in the Standard shader which seems to simply reference other shaders..

    Again, the person above me states:

    "Multiple Pass rendering :
    Duplicate your pass and add inside the second one Cull Front, then inverse the second pass's normals."

    The Standard shader has multiple passes, but again I have no idea which pass to duplicate..
     
  30. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,329
    If you're trying to directly modify the full standard shader you're going to need an advanced understanding of shaders and Unity's rendering system to accomplish anything. The above bit of code in your example is for use in a surface shader, which requires a little less knowledge, but still some understanding of shaders and surface shaders.

    I'm kind of against using the IN.viewDir option as it's more expensive than it needs to be and can have some false positives, but it's a popular option as many people with mid level shader experience know about it and roughly understand what it's doing.

    The VFACE option listed earlier by @Eideren 's excellent breakdown of the options is probably the most correct answer (though multipass has some advantages for transparency).

    Here's a basic surface shader example using VFACE (and also a toggle for using the metallic map or the sliders).
    Code (CSharp):
    1. Shader "Custom/Standard Two Sided AlphaTest" {
    2.     Properties {
    3.         _Color ("Color", Color) = (1,1,1,1)
    4.         [NoScaleOffset] _MainTex ("Albedo (RGB)", 2D) = "white" {}
    5.         [Toggle] _UseMetallicMap ("Use Metallic Map", Float) = 0.0
    6.         [NoScaleOffset] _MetallicGlossMap("Metallic", 2D) = "black" {}
    7.         [Gamma] _Metallic ("Metallic", Range(0,1)) = 0.0
    8.         _Glossiness ("Smoothness", Range(0,1)) = 0.5
    9.         _BumpScale("Scale", Float) = 1.0
    10.         [NoScaleOffset] _BumpMap("Normal Map", 2D) = "bump" {}
    11.         _Cutoff("Alpha Cutoff", Range(0.01,1)) = 0.5
    12.     }
    13.     SubShader {
    14.         Tags { "Queue"="AlphaTest" "IgnoreProjector"="True" "RenderType"="TransparentCutout" }
    15.         LOD 200
    16.         ZWrite On
    17.         Cull Off
    18.    
    19.         CGPROGRAM
    20.         #pragma surface surf Standard fullforwardshadows alpha:_Cutoff nolightmap addshadow
    21.         #pragma shader_feature _USEMETALLICMAP_ON
    22.         #pragma target 3.0
    23.         sampler2D _MainTex;
    24.         sampler2D _MetallicGlossMap;
    25.         sampler2D _BumpMap;
    26.         struct Input {
    27.             float2 uv_MainTex;
    28.             fixed facing : VFACE;
    29.         };
    30.         half _Glossiness;
    31.         half _Metallic;
    32.         fixed4 _Color;
    33.         half _BumpScale;
    34.         fixed _Cutoff;
    35.         void surf (Input IN, inout SurfaceOutputStandard o) {
    36.             // Albedo comes from a texture tinted by color
    37.             fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color;
    38.             o.Albedo = c.rgb;
    39.             o.Alpha = c.a;
    40.  
    41.             #ifdef _USEMETALLICMAP_ON
    42.             fixed4 mg = tex2D(_MetallicGlossMap, IN.uv_MainTex);
    43.             o.Metallic = mg.r;
    44.             o.Smoothness = mg.a;
    45.             #else
    46.             o.Metallic = _Metallic;
    47.             o.Smoothness = _Glossiness;
    48.             #endif
    49.  
    50.             o.Normal = UnpackScaleNormal(tex2D(_BumpMap, IN.uv_MainTex), _BumpScale);
    51.             o.Normal.z *= IN.facing; // flip Z based on facing
    52.         }
    53.         ENDCG
    54.     }
    55.     FallBack "Diffuse"
    56. }
    57.  
     
  31. Stevepunk

    Stevepunk

    Joined:
    Oct 20, 2013
    Posts:
    205
    Thanks for your help!
    This seems to be the key part which will flip the normals based upon the facing with only 1 line of code and multiple passes not required. Any idea where I can insert this into the standard shader so as not to lose shadows, order in layer and emission?

    Am I correct in thinking that a surface shader just writes information on top of everything?
    That certainly seems to be the case in other shaders which flip the normals, though I need some foreground objects in the same layer to appear in front of the character as they do currently with the standard shaders.
     
  32. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,329
    It's not exactly one line of code, it's also using the VFACE semantic in a surface shader which most people don't realize can be done. As for which pass of the standard shader needs it the answer is all of them, except shadow caster and meta. How you go about doing that is up to you to learn, or you can buy one of the assets off of the asset store that's done the work for you (though I can't say what method is being used by those shaders).

    And surface shaders should work exactly the same as the standard shader. Surface shaders aren't so named because they render on top, they're so named because you just have to pass along the object's surface values and Unity generates the rest of the shader for you behind the scenes. You can even see what that generated shader looks like by selecting the shader in unity and clicking on show generated code.


    Like I said in my previous post the standard shader is enormously complex and doing something as seemingly simple as adding support for double sided rendering can touch a surprising number of files.
     
  33. Stevepunk

    Stevepunk

    Joined:
    Oct 20, 2013
    Posts:
    205
    If I could find an asset which does this it would save a lot of time but the assets I've used this far I've ended up refunding due to no support.
    Thanks for the advice!
     
  34. caponeart

    caponeart

    Joined:
    Jul 9, 2013
    Posts:
    40
    Confused, complete shader noob here and am trying to get into my shader to add/delete CULL command but I get something different when opening it up. Am I opening it up using the wrong software or something?

     
  35. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    You edit shaders with a text editor, not a hex editor.

    --Eric
     
    caponeart likes this.
  36. caponeart

    caponeart

    Joined:
    Jul 9, 2013
    Posts:
    40
    tried opening it with notepad++ and get this, what am I doing wrong?

     
  37. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    You need the shader source, not a compiled shader.

    --Eric
     
    caponeart likes this.
  38. caponeart

    caponeart

    Joined:
    Jul 9, 2013
    Posts:
    40
    Got it.

    So I opened it up and couldn't find any use of the word 'Cull'. Added a 'Cull Off' and saved. Worked! Double sided polys. Thanks!
     
  39. MattRix

    MattRix

    Joined:
    Aug 23, 2011
    Posts:
    121
    Can I just point out how frustrating it is that to this day, when you search google for "Double Sided Material in Unity", this thread is the first thing that comes up... Including @Eric5h5's response of "This has been asked and answered many times...a search will easily find the solution."
     
    ericpug likes this.
  40. Kusras

    Kusras

    Joined:
    Jul 9, 2015
    Posts:
    134
    same feeling whenewer I ask something google cannot find any responses... I understand that shaders are quite higher level and only few guys can help us :D but I feel a little lost. Anyway I did double sided material... it was pretty hard, because it does not write properly into zbuffer...
     
    Last edited: Jul 1, 2017
  41. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    You do understand that was in 2009, I hope. ;) It was certainly true then, and this topic wasn't the first thing that came up. (It's not even the first thing now...this is: http://answers.unity3d.com/questions/922846/unity-5-and-two-sided-materials.html here. Remember that Google doesn't return the same responses for everyone.)

    --Eric
     
  42. GfK

    GfK

    Joined:
    Aug 15, 2014
    Posts:
    107
    I searched, and ended up here. Just sayin.
     
    ericpug likes this.
  43. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    That response was from 2009. Just sayin.

    --Eric
     
  44. noah_petro

    noah_petro

    Joined:
    Jun 20, 2017
    Posts:
    6
    I just duplicate my object in blender and have the duplicate object have filpped normals. Then I export the two objects as one fbx file and it can be viewed from both sides in VR.
     
  45. noah_petro

    noah_petro

    Joined:
    Jun 20, 2017
    Posts:
    6
    Probably a rather clunky process though.
     
  46. digitalmkt

    digitalmkt

    Joined:
    Dec 1, 2016
    Posts:
    7

    Thank you! Works perfectly for me
     
  47. MeehdrescherStudios

    MeehdrescherStudios

    Joined:
    Aug 29, 2021
    Posts:
    1
    This is the solution to my problem, thanks a lot!