{"id":2383,"date":"2013-05-18T23:29:58","date_gmt":"2013-05-18T22:29:58","guid":{"rendered":"http:\/\/t-machine.org\/?p=2383"},"modified":"2013-10-29T11:37:24","modified_gmt":"2013-10-29T10:37:24","slug":"mirrors-in-unity-free-version-almost-works","status":"publish","type":"post","link":"http:\/\/new.t-machine.org\/index.php\/2013\/05\/18\/mirrors-in-unity-free-version-almost-works\/","title":{"rendered":"Mirrors in Unity Free version &#8211; almost works"},"content":{"rendered":"<p>UPDATE: see end of post for another idea&#8230;<\/p>\n<p>One of the ways they make you buy Unity Pro is gimping the non-Pro version by taking away Stencil Buffer and Render-to-Texture (needed for &#8230; many (most?) of the truly interesting effect you can think of). Except &#8230; it&#8217;s only needed by old-school OpenGL programmers, because everything RtT does can be mimicked in Shaders. Stencils &#8230; maybe also?<\/p>\n<p>Anyway, I&#8217;m working on a hobby project and don&#8217;t need or want the Pro version for now (I&#8217;d like to support Unity, but these days the jump in price is way too expensive, at $X000 (they price-gouge you if you&#8217;re purchasing from within EU) for a simple hobby project). If\/when we&#8217;re using it at work, and I have lots of cash, sure &#8211; but for now: can&#8217;t find that much money.<\/p>\n<p>For the most part, I&#8217;m happy to go without RtT for now &#8211; generally speaking, hobby projects don&#8217;t &#8220;need&#8221; those kind of effects (and if they do: maybe it&#8217;s not a hobby any more?). There&#8217;s just one exception: reflections.<br \/>\n<!--more--><\/p>\n<h2>Reflections<\/h2>\n<p>Reflections are one of 3D&#8217;s reasons to exist: they are simple, and powerful, and easy to use, and they entirely rely upon Render to Tex .. &#8211; oh, crap.<\/p>\n<p>But I&#8217;ve been using <a href=\"http:\/\/en.wikibooks.org\/wiki\/GLSL_Programming\/Unity\/Mirrors\">this awesome free online book about writing GLSL shaders in Unity<\/a> and one of the interesting sections is about demonstrating that a GLSL shader can simulate a combination of RtT and Stencils. The GLSL code is very simple, if you know GLSL already it&#8217;s just a bit odd getting your head around the &#8220;special&#8221; way that Unity requires you to write your code (and note: some of the variable names are &#8220;magic&#8221;: hard-coded into Unity with bonus features).<\/p>\n<p>They use the standard starting point of cloning each of your objects to make a &#8220;mirrored&#8221; object that you can render in the &#8220;mirror universe&#8221;. Then they do a neat trick with simulating a stencil buffer, and simulating RtT through some shader-render-order fun and games. Unfortunately, it doesn&#8217;t work: In Unity 3.x, the objects &#8220;inside the mirror&#8221; still appear outside it, if you walk around behind it: this is the point of what the mirror was supposed to prevent (and it so nearly works &#8211; Unity renders the &#8220;behind&#8221; objects with a strange alpha-effect that makes me wonder if it&#8217;s a built-in anti-Free-version hack, or if there&#8217;s something odd about the default cameras)<\/p>\n<p>The book&#8217;s sample code does this:<\/p>\n<ol>\n<li>Javascript that makes any &#8220;reflected&#8221; object track its peer object (so long as they both have meshRenderers)\n<li>Shader for the mirror itself to do cool and clever stuff\n<li>Shader (very simplistic) for the &#8220;reflected&#8221; objects to render them &#8220;inside the mirror but not outside&#8221; (which doesn&#8217;t quite work, as noted above)\n<\/ol>\n<p>I had to add a few things to use this in practice:<\/p>\n<ol>\n<li>Convert the script to C#, so I get auto-completion when referencing it\n<li>Write some recursive methods to add the script + its parameters to the cloned Player object when player comes near mirror\n<li>Write some recursive methods to DESTROY EVERY COMPONENT on the &#8220;cloned&#8221; player, except for: MeshFilter, MeshRenderer (otherwise your mouselook script, your physics RigidBody etc all exist on the clone, and weird and insane freaky sh*t goes down)\n<li>Modify the simple &#8220;reflected objects&#8221; shader to support standard texture map\n<li>Add a post-attach method that when you mirror a dynamic object (e.g. the player) it grabs the texture from the original and assigns it to the bonus paramter on the mirrored-object shader (the book sample just gave mirrored objects a single colour)\n<\/ol>\n<h2>Does it work?<\/h2>\n<p>Well, almost. Very nearly.<\/p>\n<p>All of which is great, except for two major bugs:<\/p>\n<ol>\n<li>the bizarre semi-transparent colour of objects if you walk behind the mirror (e.g. if another room in your building lies behind the mirror) &#8211; they shouldn&#8217;t be rendering at all, and I&#8217;ve double-checked the book&#8217;s approach, it all looks like it should work fine to me (or: not at all. Not &#8220;partly work&#8221;) :(\n<li>the render-order for items in the mirror is FUBAR. They occlude each other back-to-front based on some weird algorithm. The back-to-front occlusion is part of the magic, IIRC, but &#8230; it seems to go wrong in the final render :(\n<\/ol>\n<p>For now, since this is a hobby project, I&#8217;ve removed everything from the mirror-universe except the player. So these are mirrors that don&#8217;t show the room you&#8217;re in &#8211; they only show you! Looks a bit sucky, but is good enough for now.<\/p>\n<p>If I find a way to fix the bugs, it would be great. Nowhere near as neat (or as performant!) a solution as getting Unity Pro (which I&#8217;d certainly encourage you to buy instead of using this poor-man&#8217;s approach), but plenty good enough for me to continue my hobbying&#8230;<\/p>\n<h2>UPDATE: a new technique for Render to Texture<\/h2>\n<p>I kicked myself <a href=\"http:\/\/answers.unity3d.com\/questions\/421450\/how-can-i-render-a-scene-to-a-surface.html#answer-444650\">when I saw this, which is a pretty obvious way of simulating RtT<\/a>. I&#8217;m already doing various tricks with multiple, overlapping cameras &#8211; so why didn&#8217;t I think of this?<\/p>\n<p>Although I fully understand all the techniques above (and can easily write them from scratch), I *don&#8217;t* understand how the occlusion is being simulated\/dissimulated via the shaders &#8212; because if I did, I&#8217;d have tried this:<\/p>\n<ol>\n<li>Create a slave-cam in mirror-world (I&#8217;ve already written the script to create a slave-player in mirror-world &#8211; doing the same with camera is trivial)\n<ul>\n<li>&#8230;in Update(), slave-cam re-sets its absolute position to be the opposite side of the mirror to player-cam, taking into account player-cam&#8217;s current\/new position<\/ul>\n<li>Draw slave-cam AND player-cam, both full-screen, but depth-sorted (set the camera.depth) so slave-cam is beneath (lower depth number)\n<ul>\n<li>&#8230;yes, Unity has &#8220;depth&#8221; upside-down, the variable should be called &#8220;height&#8221;<\/ul>\n<li>On slave-cam, &#8220;dis-render&#8221; everything on slave-cam&#8217;s side of the mirror (disable occlusion entirely)\n<li>On slave-cam, &#8220;dis-render&#8221; the mirror itself (so you can see through it!)\n<li>On player-cam, cut-out (using the link above) the area where mirror appears on-screen, so that slave-cam&#8217;s view shows through\n<\/ol>\n<p>As a thought-experiment, that Just Works. Which probably means it&#8217;s fundamentally wrong somehow ;). Sadly, I&#8217;m out of time for working on this now (remember: hobby project), and I don&#8217;t want to spend more time faffing with mirrors, but to anyone else interested, I&#8217;d say this technique is definitely worth a try.<\/p>\n<h2>UPDATE 2: a new way<\/h2>\n<p>I&#8217;ve had partial success with <a href=\"http:\/\/t-machine.org\/index.php\/2013\/05\/24\/creating-real-time-mirrors-in-unity-free-attempt-2\/\">a modified version of the above technique<\/a>. See that post for details (it took fewer steps than I expected, in some ways)<\/p>\n","protected":false},"excerpt":{"rendered":"<p>UPDATE: see end of post for another idea&#8230; One of the ways they make you buy Unity Pro is gimping the non-Pro version by taking away Stencil Buffer and Render-to-Texture (needed for &#8230; many (most?) of the truly interesting effect you can think of). Except &#8230; it&#8217;s only needed by old-school OpenGL programmers, because everything [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[20,67],"tags":[],"_links":{"self":[{"href":"http:\/\/new.t-machine.org\/index.php\/wp-json\/wp\/v2\/posts\/2383"}],"collection":[{"href":"http:\/\/new.t-machine.org\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/new.t-machine.org\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/new.t-machine.org\/index.php\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"http:\/\/new.t-machine.org\/index.php\/wp-json\/wp\/v2\/comments?post=2383"}],"version-history":[{"count":7,"href":"http:\/\/new.t-machine.org\/index.php\/wp-json\/wp\/v2\/posts\/2383\/revisions"}],"predecessor-version":[{"id":2872,"href":"http:\/\/new.t-machine.org\/index.php\/wp-json\/wp\/v2\/posts\/2383\/revisions\/2872"}],"wp:attachment":[{"href":"http:\/\/new.t-machine.org\/index.php\/wp-json\/wp\/v2\/media?parent=2383"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/new.t-machine.org\/index.php\/wp-json\/wp\/v2\/categories?post=2383"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/new.t-machine.org\/index.php\/wp-json\/wp\/v2\/tags?post=2383"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}