Search Unity

Simple Multi Pass Rendering?

Discussion in 'Shaders' started by EncodedNybble_Legacy, Apr 3, 2012.

  1. EncodedNybble_Legacy

    EncodedNybble_Legacy

    Joined:
    Apr 3, 2012
    Posts:
    31
    I asked a question over in Unity answers last week and no one is responding, so I'm trying here on the forums to see if it is more active.

    I have a VERY good knowledge of OpenGL and GLSL. I am trying to do something very simple (for now) that would be very easy (almost trivial) to do using native code and OpenGL but I'm wanting to learn Unity and get similar behavior using the engine, so I need some enlightenment. None of the docs I've read have really answered my questions, so I'm here.

    My set up is pretty simple. I have a "ground plane" and another piece of geometry (some mesh I'll download or what not, it's not there yet). I have 2 cameras. The first camera is to render the scene (the other two pieces of geometry) and write to a render target (in this case a texture). The second camera is then supposed to write to the color buffer the straight contents of the texture.

    THIS IS NOT A USEFUL EXAMPLE FOR ANYTHING. I'm just wanting to use it as a proof of concept so I can do some shadow mapping later on iOS devices by encoding the object depth from the first camera into an RGB texture.

    I know how to get one camera to write to a render texture. My problem is that the material that exists on the 2 game objects uses the same shader even though the behavior is pretty different in the 2 rendering "passes." I've read the "Replacement Shader" docs and the "Pass Tag" type doc but none of them are very clear.

    How are the "tags" to be used in replacement shader specified by the game objects? How are the "queues" specified in rendering passes? All of the docs say "just use a tag of 'RenderTarget'='Opaque'" or "just set the queue to be 'Transparent+1'" and stuff like that but nothing every mentions HOW ARE OPAQUE, TRANSPARENT, etc. specified anywhere? I'm very confused.

    This should be a really simple set up. I just want the same geometry to use different shaders.

    :confused::confused::confused:
     
  2. Martin-Kraus

    Martin-Kraus

    Joined:
    Feb 18, 2011
    Posts:
    617
    Last edited: Apr 3, 2012
  3. EncodedNybble_Legacy

    EncodedNybble_Legacy

    Joined:
    Apr 3, 2012
    Posts:
    31
    Perhaps I was unclear. I know this documentation and I've read it plenty of times. It still does not tell me how to specify the value of the "RenderType" in that example for the given material/piece of geometry. I believe these "tags" are different than the "tags" used to group game objects right?

    Is all I can do is reference Background, Geometry, Transparent and Overlay with just +- numbers? Can I specify my own like "Depth Pass" or whatever

    Am I just misunderstanding something?
     
    Last edited: Apr 4, 2012
  4. Martin-Kraus

    Martin-Kraus

    Joined:
    Feb 18, 2011
    Posts:
    617
    I shouldn't answer because I've never used shader replacement. But the documentation appars to be quite clear. You set subshader tags in shaders. Thus, each shader has a couple of tags, each tag with a value. You can use any string for a tag as far as I know. "RenderType" and "Queue" are just two special strings that are used by Unity's rendering engine but you can use other strings (which then have no meaning to the rendering engine but they can be used for replacement shaders). There is no need for a central definition of them; just use them. I think this is the point that you are struggling with: a tag is just a string.

    Shader replacement is explained here:
    http://unity3d.com/support/documentation/Components/SL-ShaderReplacement.html

    * If replacementTag is empty, then all objects in the scene are rendered with the given replacement shader.
    * If replacementTag is not empty, then for each object that would be rendered:
    o The real object's shader is queried for the tag value.
    o If it does not have that tag, object is not rendered.
    o A subshader is found in the replacement shader that has a given tag with the found value. If no such subshader is found, object is not rendered.
    o Now that subshader is used to render the object.

    The "replacementTag" is just a string. If you don't specify one, all shaders are replaced with the replacement shader.
    If you specify a "replacementTag" string, only those shaders that specify that tag are taken into consideration. E.g. if you use "RenderType" then all built-in shaders will be taken into consideration because they all use that tag. The shaders are then replaced by the subshader of the replacement shader that uses the same value(!) of the replacementTag, e.g. all shaders that use "RenderType"="Opaque" are replaced by the subshader in the replacement shader that also uses "RenderType"="Opaque" (assuming that you used "RenderType" as "replacementTag"), etc.

    But I'm probably missing your problem. ;)
     
  5. EncodedNybble_Legacy

    EncodedNybble_Legacy

    Joined:
    Apr 3, 2012
    Posts:
    31
    I understand that the "replacementTag" is just a string. So, in my script I can set the camera to use a replacement shader and say to use subshaders based on the value of the "replacementTag." In the example they give they use "RenderType". I get that, totally clear.

    What is unclear however is how the value of the "RenderType" (being "Opaque", "Transparent") are ever set for the geometry. For instance if I have a subshader with tags { "MyRandomTag" = "DepthPass" }, I understand that I can write a script to set the replacement tag as "MyRandomTag". This means that, during the time where the replacement shader is active, the shader will only run subshaders with a tag value for "MyRandomTag" is equal to the tag of the geometry. My question is, given this example, how in the world would I set the value of "MyRandomTag" to be "DepthPass" for all of my geometry and then how would I set it back to something else after this "rendering pass."
     
  6. EncodedNybble_Legacy

    EncodedNybble_Legacy

    Joined:
    Apr 3, 2012
    Posts:
    31
    Alright, I think maybe I'm starting to understand more but my question remains.

    So for my simple example (2 cameras.....one camera I want to render all geometry to a texture, second camera renders that texture to screen) I seem to have 2 options.

    1) Write two shaders, one which renders to texture and one which reads from texture. I can then use the replacement shader functionality in a script to completely replace the shader used wholly.

    2) Write two shaders one which has a subshader of with a tag of "MyRandomTag"="Bla" (or whatever value I want.) The second shader has a subshader with the same tag key/value pair "MyRandomTag"="Bla".

    I guess I now have 2 questions because I don't want to write 2 shaders if there is "sub shader" functionality

    1) (My original question) if I have a shader that has multiple sub-shaders which tags of "MyRandomTag"="Value1" and another sub shader with "MyRandomTag"="Value2", how do I ever specify "Value1" and "Value2" to dictate which sub shader to use.

    2) Is there a way to have what I want using 1 shader with 2 sub shaders? If I can figure out how to do #1 above then I think this should be trivial but I can't seem to find any documentation to do what I want.
     
  7. Martin-Kraus

    Martin-Kraus

    Joined:
    Feb 18, 2011
    Posts:
    617
    In my understanding the different subshaders of a replacement shader are used to apply different shaders to different materials in the same pass (based on the tag/value pairs of the original shaders and of the subshaders of the replacement shader). Thus, the primary purpose of subshaders of replacement shaders is to do different things for different materials. They are not(!) designed such that you can use different subshaders for the same material in different passes.

    Maybe there is a way to do it but as far as I understand it, it wouldn't be the way replacement shaders are supposed to work. As far as I understand replacement shaders and your problem, you should use two different replacement shaders for the two passes (possibly with different subshaders for different materials).

    Why don't you want to use two replacement shaders for the two passes?
     
  8. EncodedNybble_Legacy

    EncodedNybble_Legacy

    Joined:
    Apr 3, 2012
    Posts:
    31
    It's not that I don't want to, just call it a lack of understanding. In my native code/openGL world that exists in my head, I would do what I want to do with 2 "rendering passes" and 2 shaders. Reading some of the unity docs/forum posts I was under the impression that using SubShaders was the way I wanted to go and I somehow got it into my head that I could do what I wanted with 1 shader and 2 sub shaders. *Shrug*

    So, after reading over your comments, I believe you're right. I'll have to write 2 shaders (which is fine). I'm still brand new to unity and the docs don't really specify what the intended use of features like this is, just how to use it. So, thanks for the clarification. I'll try to hook this up later today and see if it works.
     
  9. aubergine

    aubergine

    Joined:
    Sep 12, 2009
    Posts:
    2,602
    I didnt read the whole post, but here is how to use replacement shaders:

    your original shaders tag = "some custom tag or some builtin tag"
    your other original shaders tag = "some different custom tag or some other builtin tag"

    your replacement shader:
    subshader (
    "some custom tag or some builtin tag" (the original shaders tag) and every object in scene which has this tag will be rendered with this subshader
    )
    another subshader (
    "some different custom tag or some other builtin tag" (your other original shaders tag) and every object in scene which has this other tag will be rendered with this other subshader
    .
    .
    .etc.

    If you must, i have a glow per object item in the assetstore which heavily uses replacement shaders. And it is a good learning resource as well.

    Hope it helps.
     
  10. EncodedNybble_Legacy

    EncodedNybble_Legacy

    Joined:
    Apr 3, 2012
    Posts:
    31
    I believe I understand your post, I may check our your object in the asset store.

    I guess the bolded part is my ultimate question. You say "every object in scene which has that tag." Do you mean the tag *value* i.e. "Opaque", "Transparent" (using values for a RenderType tag) or the tag like "RenderType"? Also, how is that tag specified? Are these the same tags that are in Edit -> Project Settings -> Tags? They sound like a different concept than that.
     
  11. aubergine

    aubergine

    Joined:
    Sep 12, 2009
    Posts:
    2,602
    RenderType value, if you make a replacement shader with 1 subshader with rendertype="Opaque", then all objects WHICH has opaque shader in scene will be rendered with your replacement. Nothing else will be rendered.

    If you have 1 subshader with rendertype="opaque" and 1 more subshader with rendertype="some custom tag", then all objects WHICH has opaque will use the 1st subshader, and all objects which has "some custom tag" will use 2nd subshader, and nothing else will be rendered.
    ...etc
    goes on like this.
     
  12. Martin-Kraus

    Martin-Kraus

    Joined:
    Feb 18, 2011
    Posts:
    617
    I didn't. @Aubergine: I think it would be very helpful if you would use the same terminology as the Unity documentation. They make a clear distinction between a subshader "tag" (the string on the left-hand-side of the "=") and its "value" (the string on the right-hand-side of the "=").

    They are different concepts.
     
  13. aubergine

    aubergine

    Joined:
    Sep 12, 2009
    Posts:
    2,602
    Sorry english is not my main language.
    Replacement shaders replace the original scene shaders depending on the original scene Shader's Subshader's RenderType's Value
    When using replacement shaders, the only tag and its value matters is RenderType.
    You prepare a replacement shader as i previously explained, and call the function from a script like:
    camera.RenderWithShader(replacementShader, "RenderType");
    [Advertisement]
    Besides the glow per object item in the assetstore, i also have a replacement shaders package for unity free/pro which is another good learning item.
    [/Advertisement]
     
  14. EncodedNybble_Legacy

    EncodedNybble_Legacy

    Joined:
    Apr 3, 2012
    Posts:
    31
    Still not quite answering my question. I understand that if you have 2 subshaders, one with "RenderType" = "Opaque" and one with "RenderType" = "Some custom tag" that all objects which are opaque will use the first sub shader and all objects which has "some custom tag" will use the second shader. This is clear to me; I understand.

    My question is, you state "all objects which are opaque" and "all objects which has 'some custom shader'" but HOW are the objects specified to be "opaque" and "some custom shader"?
     
  15. Martin-Kraus

    Martin-Kraus

    Joined:
    Feb 18, 2011
    Posts:
    617
    I think with being "opaque" Aubergine just meant: using a (original) shader that includes the line Tags {"RenderType" = "Opaque" }. And all objects which have "some custom value" are just all objects that use a (original) shader with the line Tags {"RenderType" ="some custom value"} .
     
  16. EncodedNybble_Legacy

    EncodedNybble_Legacy

    Joined:
    Apr 3, 2012
    Posts:
    31
    If that's the case, that's fine, but does anyone know the answer to my question? How are the values of the tags ever set? Via scripts? So confused
     
  17. Martin-Kraus

    Martin-Kraus

    Joined:
    Feb 18, 2011
    Posts:
    617
    I think I still don't get that question. My idea about setting the subshader tag "bob" to the value "bib" is just to type the line

    Tags {"bob"" = "bib"}

    in the definition of a subshader as described in http://unity3d.com/support/documentation/Components/SL-SubshaderTags.html

    Hmm, you are aware how to edit the code of a shader and how to create new shaders in the ShaderLab syntax?
     
  18. EncodedNybble_Legacy

    EncodedNybble_Legacy

    Joined:
    Apr 3, 2012
    Posts:
    31
    I am aware how to create new shaders and how to make sub shaders. That is not my question.

    My question is such:

    In your example, you have a shader that has a sub shader with Tags {"bob" = "bib"}. This sub shader is used when rendering any game object that has a value of "bib" for the sub shader tag "bob" correct? I believe that is my understanding.

    So my question is, where does the user specify the value of "bib" anywhere for the tag "bob" for a game object? I can't seem to find that anywhere.

    I can understand that some of the default tags like "RenderType" might have some hidden functionality that has values set to be "Opaque" and "Transparent" but if the sub shader tags have the ability to be any arbitrary set of keys and values then there MUST be a way to set the values for a tag. So how does one do that? I can't seem to find that documented or in the UI anywhere.

    Or does unity just keep a list of all tags and their values and uses every single one at some point? If that is the case in what order does it iterate over the tags and in what order does it iterate over the values?
     
    Last edited: Apr 5, 2012
  19. aubergine

    aubergine

    Joined:
    Sep 12, 2009
    Posts:
    2,602
    This is not just too complicated.
    You set a tag like;
    {"RenderType" = "Bob" } or {"RenderType" = "Bib" }
    Thats it.
    "RenderType" is a Keyword that unity internally uses to identify things which doesnt concern us.
     
  20. Martin-Kraus

    Martin-Kraus

    Joined:
    Feb 18, 2011
    Posts:
    617
    No! Unless you are using rendering with replaced shaders, the line Tags {"bob" = "bib"} has no effect at all. (It's only meaningful if you use rendering with replaced shaders and specify "bob" as the replacement tag.)

    Normally (i.e. without replaced shaders) the shader of an object is determined by the material that is set in the MeshRenderer component. The material specifies a shader, and the shader might include sub shaders. Unity then uses the first sub shader that can be used on the specific hardware. (For example, most sub shaders require programmable shading, but in case that the hardware doesn't offer programmable shading, it is good practice to include another sub shader which doesn't require programmable shading.) I.e. normally the subshader tags are not relevant for the decision which of the subshaders is used by Unity. (They are only relevant for the decision which subshader is used when using replaced shaders.)

    When someone writes a object "has" a subshader tag "bob"="bib", what this means is that the object specifies a material, which specifies a shader, which includes a subshader that includes a tag definition "bob"="bib". There is no other way an object can specify subshader tags.

    Hmm, are we talking about rendering with replaced shaders?
     
  21. aubergine

    aubergine

    Joined:
    Sep 12, 2009
    Posts:
    2,602
    There is no Tags {"bob" = "bib"} !!!

    Damn, how can you misunderstand such a simple thing. Please check the replacement shaders pack from unity samples. What you are looking for is the custom depth buffer shader.
     
  22. EncodedNybble_Legacy

    EncodedNybble_Legacy

    Joined:
    Apr 3, 2012
    Posts:
    31
    Ok, great. I believe this was a massive misunderstanding on my part. It didn't help that the Unity documentation kept mentioning the "Queue" tag as a way of specifying rendering order. I was thoroughly confused.

    So, subshaders are just used to get different behavior based on rendering parameters and DO NOT dictate any sense of rendering order? The actual subshader used is just the first subshader that fits the right criteria and the subshaders are considered in order?

    I guess now I'm confused on the "Queue" and "RenderType" tags though. I will try to reread them.
     
  23. EncodedNybble_Legacy

    EncodedNybble_Legacy

    Joined:
    Apr 3, 2012
    Posts:
    31
    Dude, relax. I did not misunderstand the use on replacement shaders, I misunderstood how sub shaders were used in general as the documentation mentions using the special "Queue" shader tag to dictate render order. Thus, I misunderstood and thought that all sub shader tags were somehow used to dictate render order.

    I checked the replacement shader pack long before I posted here. Due to my fundamental confusion and misunderstanding, the replacement shader packs didn't answer the one question I had which is why I came here.

    I'm pretty sure there are probably many things I understand that are "simple" to me that you don't and I'm also pretty sure there are many things which you misunderstood the first time you saw them. So please don't think you're better than anyone else and don't put people down.
     
  24. Martin-Kraus

    Martin-Kraus

    Joined:
    Feb 18, 2011
    Posts:
    617
    Usually, only one subshader of each shader is used for rendering based on the hardware and also shader LOD setting: http://unity3d.com/support/documentation/Components/SL-ShaderLOD.html

    The value of the subshader tag "Queue" is used to determine rendering order between different objects but other subshader tags have nothing to do with rendering order.

    Well, I'm glad we were able to solve this one. :)
     
  25. aubergine

    aubergine

    Joined:
    Sep 12, 2009
    Posts:
    2,602
    So, thats what you think i do? Putting you down??
    I was trying to help here, but good luck to you then.
     
  26. EncodedNybble_Legacy

    EncodedNybble_Legacy

    Joined:
    Apr 3, 2012
    Posts:
    31
    If that's not what you were doing, I apologize. It is hard to get tone across with just typing.

    I don't understand how else you could have meant "How can you misunderstand such a simple thing?" To me that statement means you believe something is simple and I lack the knowledge, understanding, or intelligence to comprehend something that is so easy for you to comprehend. Perhaps it is a language barrier issue that I read the sentence different than you.

    Thank you for all of your help. I know it is often hard (I used to tutor kids so I know) and frustrating when people don't understand something that you understand in a way that you understand. It is much better and constructive to try to explain in a different manner like Martin Kraus did than to say "how can you not understand." The second statement there does not help the person understand anything and it probably makes them feel bad.
     
  27. EncodedNybble_Legacy

    EncodedNybble_Legacy

    Joined:
    Apr 3, 2012
    Posts:
    31
    Ok good, that is as I suspected after your other post. The "Queue" tag is just a very special tag in unity than can dictate rendering order then (between objects obviously)?

    Thank you for all of your help.
     
    Last edited: Apr 5, 2012
  28. Martin-Kraus

    Martin-Kraus

    Joined:
    Feb 18, 2011
    Posts:
    617
    Yes.

    In fact, after this discussion, I wonder what the "RenderType" tag is good for (apart from identifying different kinds of built-in subshaders such that they can be more easily used with replacement shaders). Probably nothing. (At least that was the answer given in Unity answers and it would be consistent with the documentation.)