Search Unity

Stereo - Anagylph Rendering HELP!!! ;)

Discussion in 'Shaders' started by TheLorax, Jul 6, 2008.

  1. TheLorax

    TheLorax

    Joined:
    Mar 25, 2007
    Posts:
    86
    OK, I'm at wits end. This is the first time I've messed with the Shader Lab coding and I think I've gone as far as I can.

    We're trying to do anagylphic rendering, and are close, but no cigar.

    I'm using renderTexture to get the basic Right/Left view and coloring them with a shader to get the following:


    Red Image


    Blue Image




    Here's what it looks like in Photoshop using a Screen Overlay. This image POPS out of the screen and looks great!!!


    And here's the two combined in Unity, very washed out and does not pop at all.




    Here's the shader code being used;




    Code (csharp):
    1. Shader "Tutorial/Basic" {
    2.     Properties {
    3.         _RColor ("Red Color", Color) = (1,0,0,0)
    4.         _LColor ("Blue Color", Color) = (0,1,1,0)
    5.         _TexR ("Right Eye (RGB)", 2D) = "white" {}
    6.         _TexL ("Left Eye (RGB)", 2D) = "white" {}
    7.     }
    8.     /*
    9.        SubShader
    10.    {
    11.       Pass
    12.       {
    13.          SetTexture [_TexL]   { combine texture }
    14.          SetTexture [_TexR]   { combine texture }
    15.       }
    16.    }
    17.    
    18. */
    19.  SubShader
    20.    {
    21.       //cull off
    22.       Lighting On
    23.      // ZTest Always
    24.       //ZWrite Off
    25.       Blend One One
    26.              
    27.              
    28.              Pass
    29.       {
    30.         Lighting off
    31.          SetTexture [_TexR]
    32.          {
    33.             constantColor [_RColor]
    34.             combine constant * texture
    35.          }
    36.       }
    37.        
    38.        
    39.       Pass
    40.       {
    41.         Lighting off
    42.          SetTexture [_TexL]
    43.          {
    44.             constantColor [_LColor]
    45.             combine constant * texture
    46.          }
    47.       }
    48.        
    49.  
    50.    }
    51. }

    Any help would be great!!!

    Thanks!

    TheLorax
     
  2. Joe ByDesign

    Joe ByDesign

    Joined:
    Oct 13, 2005
    Posts:
    841
    I've no experience implementing such an effect in Unity, and no idea what else you're doing to achieve on this effect, but the issue you are seeing might be due to the fact that you're shader blending is multiplying, when a Screen blend is desired.

    Typically a Screen blend is the result of 2 inverted / negative images being multiplied and then inverted back*

    Suggest trying to invert each "eye" texture, multiply the result (as the shader does currently via "Blend One One") then invert it back (perhaps on the "final" Camera?).

    If you can resolve such a blending, then you probably be closer to the desired effect (i'm no SL guru obviously).


    *You can verify this by inverting the red blue layers in Photoshop, setting one of their blend modes to Multiply, then copying the combined result into a new layer and inverting it. The result will look exactly as your Screen blend image.
     
  3. InfiniteAmmo

    InfiniteAmmo

    Joined:
    Aug 12, 2008
    Posts:
    45
    Any luck with this? It sounds really cool. :)
     
  4. antenna-tree

    antenna-tree

    Joined:
    Oct 30, 2005
    Posts:
    5,324
    I've been working on this over the last week in my spare time and I think I came up with a pretty solid solution. Big thanks to Daniel for setting me straight on the shader. Attach this script to your camera and you should be good to go. If you're using image effects then this script obviously needs to be tweaked a bit. I'd also love to see any improvements people come up with to make this script a truly general anaglyph rendering solution.

    Code (csharp):
    1. public var eyeDistance = 0.03;
    2. public var focalDistance = 10.0;
    3.  
    4. var anaglyphMat;
    5.  
    6. var leftEyeRT;    
    7. var rightEyeRT;  
    8.  
    9. var leftEye;
    10. var rightEye;
    11.  
    12.  
    13. function Start ()
    14. {
    15.     leftEye = new GameObject ("leftEye", Camera);
    16.     rightEye = new GameObject ("rightEye", Camera);
    17.    
    18.     leftEye.camera.CopyFrom (camera);
    19.     rightEye.camera.CopyFrom (camera);
    20.    
    21.     leftEyeRT = new RenderTexture (Screen.width, Screen.height, 24);
    22.     rightEyeRT = new RenderTexture (Screen.width, Screen.height, 24);
    23.    
    24.     anaglyphMat = new Material
    25.     (  
    26.         "Shader \"Hidden/Anaglyph\"" +
    27.         "{" +
    28.         "    Properties" +
    29.         "    {" +
    30.         "        _Color (\"Main Color, Alpha\", Color) = (1,1,1,1)" +
    31.         "        _LeftTex (\"Left (RGB)\", RECT) = \"white\" {}" +
    32.         "        _RightTex (\"Right (RGB)\", RECT) = \"white\" {}" +
    33.         "    }" +
    34.         "    Category" +
    35.         "    {" +
    36.         "        ZWrite Off" +
    37.         "        Lighting On" +
    38.         "        Tags {Queue=Transparent}" +
    39.         "        SubShader" +
    40.         "        {" +
    41.         "            Pass" +
    42.         "            {" +
    43.         "               ColorMask R" +
    44.         "               Cull Off" +
    45.         "               Material" +
    46.         "               {" +
    47.         "                   Emission [_Color]" +
    48.         "               }" +
    49.         "" +               
    50.         "               SetTexture [_LeftTex]" +
    51.         "               {" +
    52.         "                   Combine texture * primary, texture + primary" +
    53.         "               }" +
    54.         "           }" +
    55.         "" +           
    56.         "           Pass" +
    57.         "            {" +
    58.         "               ColorMask GB" +
    59.         "               Cull Off" +
    60.         "               Material" +
    61.         "               {" +
    62.         "                   Emission [_Color]" +
    63.         "               }" +
    64.         "" +          
    65.         "               SetTexture [_RightTex]" +
    66.         "               {" +
    67.         "                   Combine texture * primary, texture + primary" +
    68.         "               }" +
    69.         "           }" +
    70.         "       }" +
    71.         "   }" +
    72.         "}"
    73.     );
    74.    
    75.     leftEye.camera.targetTexture = leftEyeRT;
    76.     rightEye.camera.targetTexture = rightEyeRT;
    77.        
    78.     anaglyphMat.SetTexture ("_LeftTex", leftEyeRT);
    79.     anaglyphMat.SetTexture ("_RightTex", rightEyeRT);
    80.        
    81.     leftEye.camera.depth = camera.depth -2;
    82.     rightEye.camera.depth = camera.depth -1;
    83.    
    84.     leftEye.transform.position = transform.position + transform.TransformDirection(-eyeDistance, 0, 0);
    85.     rightEye.transform.position = transform.position + transform.TransformDirection(eyeDistance, 0, 0);
    86.    
    87.     leftEye.transform.rotation = transform.rotation;
    88.     rightEye.transform.rotation = transform.rotation;
    89.    
    90.     leftEye.transform.LookAt (transform.position + (transform.TransformDirection (Vector3.forward) * focalDistance));
    91.     rightEye.transform.LookAt (transform.position + (transform.TransformDirection (Vector3.forward) * focalDistance));
    92.    
    93.     leftEye.transform.parent = transform;
    94.     rightEye.transform.parent = transform;
    95.    
    96.     camera.cullingMask = 0;
    97.     camera.backgroundColor = Color (0,0,0,0);
    98.     camera.Render();
    99.     camera.clearFlags = CameraClearFlags.Nothing;  
    100. }
    101.  
    102. function OnPostRender ()
    103. {      
    104.     GL.PushMatrix ();
    105.     GL.LoadOrtho ();
    106.    
    107.     anaglyphMat.SetPass (0);
    108.    
    109.     GL.Begin (GL.QUADS);
    110.    
    111.     GL.TexCoord2 (0, 0); GL.Vertex3 (0, 0, 1);
    112.     GL.TexCoord2 (1, 0); GL.Vertex3 (1, 0, 1);
    113.     GL.TexCoord2 (1, 1); GL.Vertex3 (1, 1, 1);
    114.     GL.TexCoord2 (0, 1); GL.Vertex3 (0, 1, 1);
    115.    
    116.     GL.End ();
    117.     GL.PopMatrix ();
    118.    
    119.     GL.PushMatrix ();
    120.     GL.LoadOrtho ();
    121.    
    122.     anaglyphMat.SetPass (1);
    123.    
    124.     GL.Begin (GL.QUADS);
    125.    
    126.     GL.TexCoord2 (0, 0); GL.Vertex3 (0, 0, 1);
    127.     GL.TexCoord2 (1, 0); GL.Vertex3 (1, 0, 1);
    128.     GL.TexCoord2 (1, 1); GL.Vertex3 (1, 1, 1);
    129.     GL.TexCoord2 (0, 1); GL.Vertex3 (0, 1, 1);
    130.    
    131.     GL.End ();
    132.     GL.PopMatrix ();   
    133. }
     
  5. jareds

    jareds

    Joined:
    May 8, 2008
    Posts:
    207
    Hey folks,

    I thought this would be a neat thing to try out.

    I seem to have some problems creating the render textures.

    If I use the code above, nothing shows up in the Unity preview window or in the web player on the Mac. I looked at the "leftEye" and "rightEye" cameras in the inspector after they are created and they indicate that the target texture is missing.

    I then manually created some RenderTextures and used those instead of creating them with the code:

    leftEyeRT = new RenderTexture (Screen.width, Screen.height, 24);
    rightEyeRT = new RenderTexture (Screen.width, Screen.height, 24);

    This appeared to work correctly (worked in the Unity preview window and in the web player on the Mac). However, if I check it out on the web player on the PC, all I see is a black screen (if I use the code above, the web player on the PC shows the content without the anaglyphic effect).

    So, do I need to do something in order for the code that creates the RenderTextures to work properly? Is there an issue with the PC web player that might cause a problem? I tried it on multiple Macs and multiple PCs and the results were consistent..

    Thanks,
    Jared
     
  6. InfiniteAmmo

    InfiniteAmmo

    Joined:
    Aug 12, 2008
    Posts:
    45
    We used a version of this script for Paper Moon. I ran into problems with it on Windows. (probably the same ones?) I got some help from Shawn White of Flash Bang Studios and we came up with a solution.

    Here's an updated version! The script is a little disorganized right now - but it does contain the fix for the Windows problem.

    (also includes persistent distance values and input handling so that you can change the effect using the keyboard while the project is running)


    Code (csharp):
    1.  
    2. var anaglyphMat;
    3.  
    4. var leftEyeRT;  
    5. var rightEyeRT;
    6.  
    7. var leftEye;
    8. var rightEye;
    9.  
    10. var enableKeys              : boolean   = true;
    11.  
    12. var downEyeDistance         : KeyCode   = KeyCode.O;
    13. var upEyeDistance           : KeyCode   = KeyCode.P;
    14. var downFocalDistance       : KeyCode   = KeyCode.K;
    15. var upFocalDistance         : KeyCode   = KeyCode.L;
    16.  
    17. var zvalue                  : float     = 0.0; // original: 1.0
    18.  
    19. class S3DV extends System.Object {
    20.     static var eyeDistance = 0.035;
    21.     static var focalDistance = 6.5;
    22. };
    23.  
    24. function Start () {
    25.    leftEye = new GameObject ("leftEye", Camera);
    26.    rightEye = new GameObject ("rightEye", Camera);
    27.    
    28.    leftEye.camera.CopyFrom (camera);
    29.    rightEye.camera.CopyFrom (camera);
    30.    
    31.    leftEyeRT = new RenderTexture (Screen.width, Screen.height, 24);
    32.    rightEyeRT = new RenderTexture (Screen.width, Screen.height, 24);
    33.    
    34.    anaglyphMat = new Material
    35.    (  
    36.       "Shader \"Hidden/Anaglyph\"" +
    37.       "{" +
    38.       "    Properties" +
    39.       "    {" +
    40.       "        _Color (\"Main Color, Alpha\", Color) = (1,1,1,1)" +
    41.       "        _LeftTex (\"Left (RGB)\", RECT) = \"white\" {}" +
    42.       "        _RightTex (\"Right (RGB)\", RECT) = \"white\" {}" +
    43.       "    }" +
    44.       "    Category" +
    45.       "    {" +
    46.       "        ZWrite Off" +
    47.       "        ZTest Always" +
    48.       "        Lighting On" +
    49.       "        Tags {Queue=Transparent}" +
    50.       "        SubShader" +
    51.       "        {" +
    52.       "            Pass" +
    53.       "            {" +
    54.       "               ColorMask R" +
    55.       "               Cull Off" +
    56.       "               Material" +
    57.       "               {" +
    58.       "                   Emission [_Color]" +
    59.       "               }" +
    60.       "" +              
    61.       "              SetTexture [_LeftTex]" +
    62.       "               {" +
    63.       "                   Combine texture * primary, texture + primary" +
    64.       "               }" +
    65.       "           }" +
    66.       "" +          
    67.       "           Pass" +
    68.       "            {" +
    69.       "               ColorMask GB" +
    70.       "               Cull Off" +
    71.       "               Material" +
    72.       "               {" +
    73.       "                   Emission [_Color]" +
    74.       "               }" +
    75.       "" +          
    76.       "               SetTexture [_RightTex]" +
    77.       "               {" +
    78.       "                   Combine texture * primary, texture + primary" +
    79.       "               }" +
    80.       "           }" +
    81.       "       }" +
    82.       "    }" +
    83.       "}"
    84.    );
    85.    
    86.    leftEye.camera.targetTexture = leftEyeRT;
    87.    rightEye.camera.targetTexture = rightEyeRT;
    88.      
    89.    anaglyphMat.SetTexture ("_LeftTex", leftEyeRT);
    90.    anaglyphMat.SetTexture ("_RightTex", rightEyeRT);
    91.      
    92.    leftEye.camera.depth = camera.depth -2;
    93.    rightEye.camera.depth = camera.depth -1;
    94.    
    95.    leftEye.transform.position = transform.position + transform.TransformDirection(-S3DV.eyeDistance, 0, 0);
    96.    rightEye.transform.position = transform.position + transform.TransformDirection(S3DV.eyeDistance, 0, 0);
    97.    
    98.    leftEye.transform.rotation = transform.rotation;
    99.    rightEye.transform.rotation = transform.rotation;
    100.    
    101.    leftEye.transform.LookAt (transform.position + (transform.TransformDirection (Vector3.forward) * S3DV.focalDistance));
    102.    rightEye.transform.LookAt (transform.position + (transform.TransformDirection (Vector3.forward) * S3DV.focalDistance));
    103.    
    104.    leftEye.transform.parent = transform;
    105.    rightEye.transform.parent = transform;
    106.    
    107.    camera.cullingMask = 0;
    108.    camera.backgroundColor = Color (0,0,0,0);
    109.    //camera.Render();
    110.    camera.clearFlags = CameraClearFlags.Nothing;
    111.    //camera.enabled = false;
    112. }
    113.  
    114. function Stop () {
    115. }
    116.  
    117. function UpdateView() {
    118.    leftEye.camera.depth = camera.depth -2;
    119.    rightEye.camera.depth = camera.depth -1;
    120.    
    121.    leftEye.transform.position = transform.position + transform.TransformDirection(-S3DV.eyeDistance, 0, 0);
    122.    rightEye.transform.position = transform.position + transform.TransformDirection(S3DV.eyeDistance, 0, 0);
    123.    
    124.    leftEye.transform.rotation = transform.rotation;
    125.    rightEye.transform.rotation = transform.rotation;
    126.    
    127.    leftEye.transform.LookAt (transform.position + (transform.TransformDirection (Vector3.forward) * S3DV.focalDistance));
    128.    rightEye.transform.LookAt (transform.position + (transform.TransformDirection (Vector3.forward) * S3DV.focalDistance));
    129.    
    130.    leftEye.transform.parent = transform;
    131.    rightEye.transform.parent = transform;
    132. }
    133.  
    134. function LateUpdate() {
    135.     UpdateView();
    136.    
    137.     if (enableKeys) {
    138.         // o and p
    139.         var eyeDistanceAdjust : float = 0.01;
    140.         if (Input.GetKeyDown(upEyeDistance)) {
    141.             S3DV.eyeDistance += eyeDistanceAdjust;
    142.         } else if (Input.GetKeyDown(downEyeDistance)) {
    143.             S3DV.eyeDistance -= eyeDistanceAdjust;
    144.         }
    145.        
    146.         // k and l
    147.         var focalDistanceAdjust : float = 0.5;
    148.         if (Input.GetKeyDown(upFocalDistance)) {
    149.             //Debug.Log("focal up");
    150.             S3DV.focalDistance += focalDistanceAdjust;
    151.         } else if (Input.GetKeyDown(downFocalDistance)) {
    152.             S3DV.focalDistance -= focalDistanceAdjust;
    153.         }
    154.     }
    155. }
    156.  
    157. function OnRenderImage (source:RenderTexture, destination:RenderTexture) {
    158.     RenderTexture.active = destination;
    159.     GL.PushMatrix();
    160.     GL.LoadOrtho();
    161.     for(var i:int = 0; i < anaglyphMat.passCount; i++) {
    162.         anaglyphMat.SetPass(i);
    163.         DrawQuad();
    164.     }
    165.     GL.PopMatrix();
    166. }
    167.  
    168. private function DrawQuad() {
    169.     GL.Begin (GL.QUADS);       
    170.         GL.TexCoord2( 0.0, 0.0 ); GL.Vertex3( 0.0, 0.0, zvalue );
    171.         GL.TexCoord2( 1.0, 0.0 ); GL.Vertex3( 1.0, 0.0, zvalue );
    172.         GL.TexCoord2( 1.0, 1.0 ); GL.Vertex3( 1.0, 1.0, zvalue );
    173.         GL.TexCoord2( 0.0, 1.0 ); GL.Vertex3( 0.0, 1.0, zvalue );
    174.     GL.End();
    175. }
    176.  
     
  7. antenna-tree

    antenna-tree

    Joined:
    Oct 30, 2005
    Posts:
    5,324
    Cool man, thanks for sharing your tweaks and fixes!

    A few of us here at UT were checking out Paper Moon last night with the anaglyph glasses on. It looks great :D

    Ethan
     
  8. Marc

    Marc

    Joined:
    Oct 4, 2007
    Posts:
    499
    This is cool. Nice Job.
     
  9. jareds

    jareds

    Joined:
    May 8, 2008
    Posts:
    207
    Thanks a bunch.

    Using a few lines of InfiniteAlec's updated code I was able to tweak the original code to work correctly in Windows.

    * I commented out "camera.Render();" in the Start function.
    * I added "ZTest Always" to the shader declaration.
    * I changed the z value in the DrawQuad calls to 0.0 (from 1).

    Out of curiosity, does anyone know why I still can't seem to get it to work if I create the RenderTextures with the code:

    leftEyeRT = new RenderTexture (Screen.width, Screen.height, 24);
    rightEyeRT = new RenderTexture (Screen.width, Screen.height, 24);

    Basically what I've done is comment this code out and use some RenderTextures from my library, which seems to work.. just curious why it doesn't work both ways.

    Thanks,
    Jared
     
  10. Joe ByDesign

    Joe ByDesign

    Joined:
    Oct 13, 2005
    Posts:
    841
    Definitely cool beans. And Stereo - Anagylph Paper Moon looks particularly cool! :)

    Any objections to throwing this up on the Unity Wiki?
     
  11. Frieza

    Frieza

    Joined:
    Aug 29, 2008
    Posts:
    68
    Very cool stuff! I've been doing similar stuff in a totally different way on one of my many projects (this one's for work!) we have a stereoscopic screen that works by using polarising filters on two projectors laid ontop of each other.

    The solution was really simple in Unity, just two viewports, two cameras. Job done. Only tricky thing is calculating the optimum eye seperation distance for viewing near/far objects :)
     
  12. Jonathan Czeck

    Jonathan Czeck

    Joined:
    Mar 17, 2005
    Posts:
    1,713
    The method in this thread actually is the incorrect way to do stereo and results in "vertical parallax distortions" in the rendered image. Check out chapter 14 in this free book if anyone is interested in doing it the accurate way:
    http://www.pangeasoft.net/book/buy.html

    Cheers,
    -Jon
     
  13. UnityExplorer

    UnityExplorer

    Joined:
    Jun 15, 2009
    Posts:
    12
    Hi, I tried to apply the above code to the Islands Demo project, it works fine within the Editor. However, when I build it to standalone application, it shows only the original contents without anaglyph. Any suggestion what I have missed? Or is there any extra build settings? I'm with Unity 2.5.

    Thanks.
     
  14. Juan

    Juan

    Joined:
    May 21, 2009
    Posts:
    142
    Can this be used in the indie version?

    Cheers.
     
  15. antenna-tree

    antenna-tree

    Joined:
    Oct 30, 2005
    Posts:
    5,324
    No, this is Unity Pro only.
     
  16. Juan

    Juan

    Joined:
    May 21, 2009
    Posts:
    142
    can someone post a demo of this?

    This is really interesting.

    Cheers.
     
  17. DerWoDaSo

    DerWoDaSo

    Joined:
    May 25, 2009
    Posts:
    131
    With the new nVidia beta divers you can create anaglyph renderings in almost any 3D application... but didn't check if it works with unity.

    But my eyes start to hurt anyway after a few minutes because of the retinal rivalry... did some tests with anaglyph rendering in XNA last year.
     
  18. monark

    monark

    Joined:
    May 2, 2008
    Posts:
    1,598
    I've been playing around with this a bit today here are some screen grabs, using red/green rather than red/cyan. It works even better when it's moving around and on windows where the gamma makes the red stronger. Might depend on your glasses too I suppose.
     

    Attached Files:

  19. monark

    monark

    Joined:
    May 2, 2008
    Posts:
    1,598
    Thanks for this link!

    I've implemented the skewed projection matrix method and it does seem easier on the eyes.

    It's quite simple to do if anyone else wants to try the code for skewing the matrix is in the Unity help, the code below can just be bolted into the original script.

    Code (csharp):
    1.  
    2. function PerspectiveOffCenter(
    3.     left : float, right : float,
    4.     bottom : float, top : float,
    5.     near : float, far : float ) : Matrix4x4
    6. {        
    7.     var x =  (2.0 * near) / (right - left);
    8.     var y =  (2.0 * near) / (top - bottom);
    9.     var a =  (right + left) / (right - left);
    10.     var b =  (top + bottom) / (top - bottom);
    11.     var c = -(far + near) / (far - near);
    12.     var d = -(2.0 * far * near) / (far - near);
    13.     var e = -1.0;
    14.  
    15.     var m : Matrix4x4;
    16.     m[0,0] = x;  m[0,1] = 0;  m[0,2] = a;  m[0,3] = 0;
    17.     m[1,0] = 0;  m[1,1] = y;  m[1,2] = b;  m[1,3] = 0;
    18.     m[2,0] = 0;  m[2,1] = 0;  m[2,2] = c;  m[2,3] = d;
    19.     m[3,0] = 0;  m[3,1] = 0;  m[3,2] = e;  m[3,3] = 0;
    20.     return m;
    21. }
    22.  
    23. function projectionMatrix(isLeftEye : boolean) : Matrix4x4 {
    24.     var left : float;
    25.     var right : float;
    26.     var a : float;
    27.     var b : float;
    28.     var fov : float;
    29.    
    30.     fov = camera.fieldOfView / 180.0 * Mathf.PI;  // convert FOV to radians
    31.  
    32.     var aspect : float = camera.aspect;
    33.  
    34.     a = camera.nearClipPlane * Mathf.Tan(fov * 0.5);
    35.     b = camera.nearClipPlane / S3DV.focalDistance;
    36.    
    37.     if (isLeftEye)      // left camera
    38.     {
    39.         left  = - aspect * a + (S3DV.eyeDistance) * b;
    40.         right =   aspect * a + (S3DV.eyeDistance) * b;
    41.     }
    42.     else         // right camera
    43.     {
    44.         left  = - aspect * a - (S3DV.eyeDistance) * b;
    45.         right =   aspect * a - (S3DV.eyeDistance) * b;
    46.     }
    47.  
    48.     return PerspectiveOffCenter(left, right, -a, a, camera.nearClipPlane, camera.farClipPlane);
    49.    
    50. }
    51.  
    Then just modify the part of the original script that rotates the left and right eye cameras so instead of doing that they just copy the rotation from the original camera and then get their projection matrices modified thus

    Code (csharp):
    1.  
    2.  if (useOffsetMatrix) {
    3.         leftEye.transform.rotation = transform.rotation;
    4.         rightEye.transform.rotation = transform.rotation;
    5.        
    6.         leftEye.camera.projectionMatrix = projectionMatrix(true);
    7.         rightEye.camera.projectionMatrix = projectionMatrix(false);
    8.     }
    9.  
     
  20. monark

    monark

    Joined:
    May 2, 2008
    Posts:
    1,598
    I've also been playing with the colour balancing method also found in the link posted above.

    So instead of just using the anaglyph shader embedded in the script use this one instead

    Code (csharp):
    1.  
    2. Shader "Hidden/Colour Balance Anaglyph" {
    3. Properties {
    4.     _LeftTex ("Left (RGB)", RECT) = "white" {}
    5.     _RightTex ("Right (RGB)", RECT) = "white" {}
    6. }
    7.  
    8. SubShader {
    9.     Pass {
    10.         ZTest Always Cull Off ZWrite Off
    11.         Fog { Mode off }
    12.  
    13.         CGPROGRAM
    14.         #pragma vertex vert
    15.         #pragma fragment frag
    16.         #pragma fragmentoption ARB_precision_hint_fastest
    17.         #include "UnityCG.cginc"
    18.        
    19.         #define RED_RATIO_ADJ  .6f
    20.         #define GREEN_RATIO_ADJ  .4f
    21.         #define BLUE_RATIO_ADJ  .8f
    22.        
    23.         uniform samplerRECT _LeftTex;
    24.         uniform samplerRECT _RightTex;
    25.        
    26.         struct v2f {
    27.             float4 pos : POSITION;
    28.             float2 uv : TEXCOORD0;
    29.         };
    30.        
    31.         v2f vert( appdata_img v )
    32.         {
    33.             v2f o;
    34.             o.pos = mul (glstate.matrix.mvp, v.vertex);
    35.             float2 uv = MultiplyUV( glstate.matrix.texture[0], v.texcoord );
    36.             o.uv = uv;
    37.             return o;
    38.         }
    39.        
    40.         half4 frag (v2f i) : COLOR
    41.         {
    42.             float r, g, b;
    43.             float4 texR = texRECT(_LeftTex, i.uv);
    44.             float4 texGB = texRECT(_RightTex, i.uv);
    45.             float4 texRGB;
    46.            
    47.             r=texR.r;
    48.             g=texGB.g;
    49.             b=texGB.b;
    50.            
    51.             float lumR = texR.r * 0.299f;
    52.             float lumGB = texR.g * 0.587f + texR.b * 0.114f;
    53.            
    54.             // Balance red
    55.             float ratio = lumGB / lumR;
    56.             float d = texR.r * ratio * RED_RATIO_ADJ;
    57.             if (d > texR.r) {
    58.                 r = d;
    59.                 if (r > 0xff) r = 0xff;
    60.             }
    61.            
    62.             lumR = texGB.r * 0.299f;
    63.             lumGB = texGB.g * 0.587f + texGB.b * 0.114f;
    64.            
    65.             //Balance green
    66.             ratio = lumR / lumGB;
    67.             d = texGB.g * ratio * GREEN_RATIO_ADJ;
    68.             if (d > texGB.g) {
    69.                 g = d;
    70.                 if (g > 0xff) g = 0xff;
    71.             }
    72.            
    73.             //Balance blue
    74.             d = texGB.b * ratio * BLUE_RATIO_ADJ;
    75.             if (d > texGB.b) {
    76.                 b = d;
    77.                 if (b > 0xff) b = 0xff;
    78.             }
    79.            
    80.             texRGB = float4(r,g,b,1);
    81.             return texRGB;
    82.         }
    83.         ENDCG
    84.     }
    85. }  
    86.     Fallback off
    87. }
    88.  

    However I'm ussure as to whether this is supported on all hardware, can anyone who knows shaderLab better confirm if this would work always?
     
  21. rahuxx

    rahuxx

    Joined:
    May 8, 2009
    Posts:
    537
    hi there,

    first of all great software and nice work.
    More i got the idea how anaglyph works in unity, but i am quiet confused on how passive stereoscopy and active stereoscopy works.
    if some one can provide a tutorial or script on which i can try and work to improve my knowledge will be great help for me.

    Thanks for all
    hope for the comming days
    rahuxx
     
  22. wimwouters

    wimwouters

    Joined:
    Jan 7, 2009
    Posts:
    20
    We're also using Anaglyph rendering... but using a much more "low-tech" way to do it...

    We just put a plane in front of each camera (red/cyaan) then combined the 2 camera views...

    DEMO: (we should avoid red stoplights...)
    http://www.underdog.be/games/cruiserVR/

    Press G for anaglyph
     

    Attached Files:

  23. rahuxx

    rahuxx

    Joined:
    May 8, 2009
    Posts:
    537
    Nice work.

    But if you can provide some short of tutorial on it will help me more.

    Thanks in advance
     
  24. rahuxx

    rahuxx

    Joined:
    May 8, 2009
    Posts:
    537
    Hi there

    Thanks for the script.
    I loved to work on unity using this new script, but struck to this silly problem that when i am using rollover script on object and use this script, generated exe has no rollover effect on objects.

    Please some one help me on it, its hardly needed.

    thanks
    rahu
     
  25. apple_motion

    apple_motion

    Joined:
    Jul 2, 2009
    Posts:
    169
    Thanks all, I learnt a lot from here. This help me to understand the correct way to use camera matrix.

    I follow the idea of "shear" and make these test too :)
    http://www.youtube.com/watch?v=jxK0FF0JTq4
    http://homepage.mac.com/antonioh/unity3d/build/Anaglyph_v007.html

    I create the matrix in this way...
    Code (csharp):
    1. var M:Matrix4x4 = Matrix4x4.zero;  
    2. M[1,1] = 1.0/tan(fov*0.5);
    3. M[0,0] = M[1,1]/aspect;
    4. M[2,2] = -(  far+near)/(far-near);
    5. M[2,3] = -(2*far*near)/(far-near);
    6. M[3,2] = -1.0;
    ... then change the value of "shear" for each child camera matrix.
    Code (csharp):
    1. M[0,2] = shear_x;
    In fact, I have a question about mixing the RED+CYAN view.
    Are there another way to do that without using "RenderTexture"??

    I tried to use "SetReplacementShader" and it is work (on unity free edition too), but it is not convenience, since, I need to replace every shaders within the view :p

    Many Thanks !
     
  26. yuriythebest

    yuriythebest

    Joined:
    Nov 21, 2009
    Posts:
    1,125
    hi! very newbiesh question here - I've tried placing the second (revised) code on the first page of this thread in a new shader file created in unity3d but it gives an error that there is a variable at line 1 - I tried other formats but that didn't work

    EDIT: nevermind figured it out just a javascript file! awesome script!



    EDIT2: hmm I just noticed - the GUI for my game (made of texture2D's) disappears if this script is enabled how do I fix this?
     
  27. yuriythebest

    yuriythebest

    Joined:
    Nov 21, 2009
    Posts:
    1,125
  28. yuriythebest

    yuriythebest

    Joined:
    Nov 21, 2009
    Posts:
    1,125
    please help - how to preserve my GUI with anaglyph turned on?
     
  29. Joe-Robins

    Joe-Robins

    Unity Technologies

    Joined:
    Apr 21, 2008
    Posts:
    430
    Hi,

    Can you confirm what exactly you are doing with the texture2d's?

    how are you building your GUI?

    using 3d objects with texture2d's on the material?

    using GUI Textures?

    or writing your UI using onGUI?

    beyond that, do you want your GUI to be affected by the anaglyph effect or not?
     
  30. dhaval992004

    dhaval992004

    Joined:
    Mar 3, 2010
    Posts:
    2
    Hey I am working on a project where i need to create phantograms using unity 3d.Above shader helped me but along with that I need to change the frustum of the camera for the lefteye camera and right camera.
    I am trying to change the projection matrix of both the cameras.Any help is appreciated regarding this.
     
  31. nooB

    nooB

    Joined:
    Oct 4, 2009
    Posts:
    20
    Anybody tried creating phantograms?
    I m having some issues with porting from MAC to Windows.
     
  32. lesfundi

    lesfundi

    Joined:
    Jan 10, 2009
    Posts:
    628
    does this work on the iPhone?
     
  33. lesfundi

    lesfundi

    Joined:
    Jan 10, 2009
    Posts:
    628
    i bring that in the scene on a emtpy game object?
    i get the error: line 27/12 'camera' is not a member of 'object'
     
  34. zhuangfengzi

    zhuangfengzi

    Joined:
    Feb 7, 2010
    Posts:
    11
    I used the following code:


    var anaglyphMat;

    var leftEyeRT;
    var rightEyeRT;

    var leftEye;
    var rightEye;

    var enableKeys : boolean = true;

    var downEyeDistance : KeyCode = KeyCode.O;
    var upEyeDistance : KeyCode = KeyCode.P;
    var downFocalDistance : KeyCode = KeyCode.K;
    var upFocalDistance : KeyCode = KeyCode.L;

    var zvalue : float = 0.001; // original: 1.0

    class S3DV extends System.Object {
    static var eyeDistance = 0.035;
    static var focalDistance = 6.5;
    };

    function Start () {
    leftEye = new GameObject ("leftEye", Camera);
    rightEye = new GameObject ("rightEye", Camera);

    leftEye.camera.CopyFrom (camera);
    rightEye.camera.CopyFrom (camera);

    leftEyeRT = new RenderTexture (Screen.width, Screen.height, 24);
    rightEyeRT = new RenderTexture (Screen.width, Screen.height, 24);

    anaglyphMat = new Material
    (
    "Shader \"Colour Balance Anaglyph \"" +
    "{ " +
    "Properties"+
    "{ " +
    "_LeftTex (\"Left (RGB)\", RECT) = \"white\" {}" +
    "_RightTex (\"Right (RGB)\", RECT) = \"white\" {}" +
    "} "+

    "SubShader "+
    "{ "+
    "Pass "+
    "{ "+
    "ZTest Always Cull Off ZWrite Off "+
    "Fog { Mode off }" +

    "CGPROGRAM "+
    " #pragma vertex vert "+
    "#pragma fragment frag "+
    " #pragma fragmentoption ARB_precision_hint_fastest "+
    " #include "UnityCG.cginc" "+

    " #define RED_RATIO_ADJ .6f "+
    " #define GREEN_RATIO_ADJ .4f "+
    " #define BLUE_RATIO_ADJ .8f"+

    "uniform samplerRECT _LeftTex"+
    "uniform samplerRECT _RightTex"+

    "struct v2f "+
    "{ "+
    " float4 pos : POSITION"+
    "float2 uv : TEXCOORD0"+
    "}; "+

    "v2f vert( appdata_img v ) "+
    " { "+
    " v2f o; "+
    "o.pos = mul (glstate.matrix.mvp, v.vertex)"+
    " float2 uv = MultiplyUV( glstate.matrix.texture[0], v.texcoord )"+
    " o.uv = uv"+
    "return o"+
    " } "+

    "half4 frag (v2f i) : COLOR "+
    "{ "+
    " float r, g, b "+
    " float4 texR = texRECT(_LeftTex, i.uv)"+
    " float4 texGB = texRECT(_RightTex, i.uv)"+
    "float4 texRGB"+

    "r=texR.r"+
    "g=texGB.g"+
    "b=texGB.b"+

    "float lumR = texR.r * 0.299f"+
    "float lumGB = texR.g * 0.587f + texR.b * 0.114f"+

    // Balance red
    "float ratio = lumGB / lumR"+
    "float d = texR.r * ratio * RED_RATIO_ADJ"+
    "if (d > texR.r)"+
    "{ "+
    " r = d"+
    " if (r > 0xff) r = 0xff "+
    "} "+

    "lumR = texGB.r * 0.299f"+
    "lumGB = texGB.g * 0.587f + texGB.b * 0.114f"+

    //Balance green
    "ratio = lumR / lumGB"+
    "d = texGB.g * ratio * GREEN_RATIO_ADJ"+
    "if (d > texGB.g) "+
    " { "+
    " g = d; "+
    " if (g > 0xff) g = 0xff"+
    "} "+

    //Balance blue
    "d = texGB.b * ratio * BLUE_RATIO_ADJ"+
    " if (d > texGB.b)"+
    "{ "+
    " b = d; "+
    " if (b > 0xff) b = 0xff"+
    "} "+

    "texRGB = float4(r,g,b,1)"+
    " return texRGB"+
    "} "+
    "ENDCG "+
    "} "+
    "} "+
    " Fallback off "+
    "} "
    );

    leftEye.camera.targetTexture = leftEyeRT;
    rightEye.camera.targetTexture = rightEyeRT;

    anaglyphMat.SetTexture ("_LeftTex", leftEyeRT);
    anaglyphMat.SetTexture ("_RightTex", rightEyeRT);

    leftEye.camera.depth = camera.depth -2;
    rightEye.camera.depth = camera.depth -1;

    leftEye.transform.position = transform.position + transform.TransformDirection(-S3DV.eyeDistance, 0, 0);
    rightEye.transform.position = transform.position + transform.TransformDirection(S3DV.eyeDistance, 0, 0);

    leftEye.transform.rotation = transform.rotation;
    rightEye.transform.rotation = transform.rotation;

    leftEye.transform.LookAt (transform.position + (transform.TransformDirection (Vector3.forward) * S3DV.focalDistance));
    rightEye.transform.LookAt (transform.position + (transform.TransformDirection (Vector3.forward) * S3DV.focalDistance));

    leftEye.transform.parent = transform;
    rightEye.transform.parent = transform;

    //camera.cullingMask = 0;
    //camera.backgroundColor = Color (0,0,0,0);
    //camera.Render();
    //camera.clearFlags = CameraClearFlags.Nothing;
    //camera.enabled = false;
    }

    function Stop () {
    }

    function UpdateView() {
    leftEye.camera.depth = camera.depth -2;
    rightEye.camera.depth = camera.depth -1;

    leftEye.transform.position = transform.position + transform.TransformDirection(-S3DV.eyeDistance, 0, 0);
    rightEye.transform.position = transform.position + transform.TransformDirection(S3DV.eyeDistance, 0, 0);

    leftEye.transform.rotation = transform.rotation;
    rightEye.transform.rotation = transform.rotation;

    leftEye.camera.projectionMatrix = projectionMatrix(true);
    rightEye.camera.projectionMatrix = projectionMatrix(false);

    leftEye.transform.LookAt (transform.position + (transform.TransformDirection (Vector3.forward) * S3DV.focalDistance));
    rightEye.transform.LookAt (transform.position + (transform.TransformDirection (Vector3.forward) * S3DV.focalDistance));

    leftEye.transform.parent = transform;
    rightEye.transform.parent = transform;

    }

    function LateUpdate() {
    UpdateView();

    if (enableKeys) {
    // o and p
    var eyeDistanceAdjust : float = 0.01;
    if (Input.GetKeyDown(upEyeDistance)) {
    S3DV.eyeDistance += eyeDistanceAdjust;
    } else if (Input.GetKeyDown(downEyeDistance)) {
    S3DV.eyeDistance -= eyeDistanceAdjust;
    }

    // k and l
    var focalDistanceAdjust : float = 0.5;
    if (Input.GetKeyDown(upFocalDistance)) {
    //Debug.Log("focal up");
    S3DV.focalDistance += focalDistanceAdjust;
    } else if (Input.GetKeyDown(downFocalDistance)) {
    S3DV.focalDistance -= focalDistanceAdjust;
    }
    }
    }

    function OnRenderImage (source:RenderTexture, destination:RenderTexture) {
    RenderTexture.active = destination;
    GL.PushMatrix();
    GL.LoadOrtho();
    for(var i:int = 0; i < anaglyphMat.passCount; i++) {
    anaglyphMat.SetPass(i);
    DrawQuad();
    }
    GL.PopMatrix();
    }

    private function DrawQuad() {
    GL.Begin (GL.QUADS);
    GL.TexCoord2( 0.0, 0.0 ); GL.Vertex3( 0.0, 0.0, zvalue );
    GL.TexCoord2( 1.0, 0.0 ); GL.Vertex3( 1.0, 0.0, zvalue );
    GL.TexCoord2( 1.0, 1.0 ); GL.Vertex3( 1.0, 1.0, zvalue );
    GL.TexCoord2( 0.0, 1.0 ); GL.Vertex3( 0.0, 1.0, zvalue );
    GL.End();
    }

    function PerspectiveOffCenter(
    left : float, right : float,
    bottom : float, top : float,
    near : float, far : float ) : Matrix4x4
    {
    var x = (2.0 * near) / (right - left);
    var y = (2.0 * near) / (top - bottom);
    var a = (right + left) / (right - left);
    var b = (top + bottom) / (top - bottom);
    var c = -(far + near) / (far - near);
    var d = -(2.0 * far * near) / (far - near);
    var e = -1.0;

    var m : Matrix4x4;
    m[0,0] = x; m[0,1] = 0; m[0,2] = a; m[0,3] = 0;
    m[1,0] = 0; m[1,1] = y; m[1,2] = b; m[1,3] = 0;
    m[2,0] = 0; m[2,1] = 0; m[2,2] = c; m[2,3] = d;
    m[3,0] = 0; m[3,1] = 0; m[3,2] = e; m[3,3] = 0;
    return m;
    }

    function projectionMatrix(isLeftEye : boolean) : Matrix4x4 {
    var left : float;
    var right : float;
    var a : float;
    var b : float;
    var fov : float;

    fov = camera.fieldOfView / 180.0 * Mathf.PI; // convert FOV to radians

    var aspect : float = camera.aspect;

    a = camera.nearClipPlane * Mathf.Tan(fov * 0.5);
    b = camera.nearClipPlane / S3DV.focalDistance;

    if (isLeftEye) // left camera
    {
    left = - aspect * a + (S3DV.eyeDistance) * b;
    right = aspect * a + (S3DV.eyeDistance) * b;
    }
    else // right camera
    {
    left = - aspect * a - (S3DV.eyeDistance) * b;
    right = aspect * a - (S3DV.eyeDistance) * b;
    }

    return PerspectiveOffCenter(left, right, -a, a, camera.nearClipPlane, camera.farClipPlane);

    }
    But the result isn't too good,it don't reach your effect. And appeared the flowing mistake .where is the question ?





    Waiting for your reply!
    Thank first!
     

    Attached Files:

  35. menneske

    menneske

    Joined:
    Jan 23, 2009
    Posts:
    44
    If anybody is interested I have worked out a way to get anaglyph rendering like this working without the pro license. It also works on the iPhone.

    Currently only does flat rendering (single texture materials, no lights), but for the right price most things are possible.

    Not for free, PM if interested.
     
  36. lesfundi

    lesfundi

    Joined:
    Jan 10, 2009
    Posts:
    628
    i noticed here all the different scripts for anaglyph and now that i have a pro version i am trying to put the different script together. Is somebody willing to a simple demo scene (even with just a sphere) and those script(s) correctly applied?


    thx,;
    lesfundi
     
  37. lesfundi

    lesfundi

    Joined:
    Jan 10, 2009
    Posts:
    628
    oh this work for the iphone nor not?
     
  38. Dreamora

    Dreamora

    Joined:
    Apr 5, 2008
    Posts:
    26,601
    no it won't
    the shader uses cgprograms (programmable pipeline) which are not available in unity iphone at all
     
  39. menneske

    menneske

    Joined:
    Jan 23, 2009
    Posts:
    44
    Yes, my solution works for the iPhone as well.

    iPhone Basic build (red/cyan):

    (web version here)
     
  40. lesfundi

    lesfundi

    Joined:
    Jan 10, 2009
    Posts:
    628
    i am talking here about the script posted here for the pro version.
     
  41. lesfundi

    lesfundi

    Joined:
    Jan 10, 2009
    Posts:
    628
    nobody got this script working in the unity iphone pro?
     
  42. antenna-tree

    antenna-tree

    Joined:
    Oct 30, 2005
    Posts:
    5,324
    The Pro version posted here requires render textures which are not supported in Unity iPhone atm.
     
  43. lesfundi

    lesfundi

    Joined:
    Jan 10, 2009
    Posts:
    628
    aha! Thx for the info.
    Is that support in Unity 3.0 iPhone Pro?
     
  44. lesfundi

    lesfundi

    Joined:
    Jan 10, 2009
    Posts:
    628
    i use this setup but it seems to only work in unity pro (no-iPhone) in the editor but when i build the project the screen becomes yellow? what am i doing?

    c
     
  45. Checco-Esimple

    Checco-Esimple

    Joined:
    Feb 14, 2008
    Posts:
    82
  46. phoberman

    phoberman

    Joined:
    Jan 16, 2008
    Posts:
    75
  47. rahuxx

    rahuxx

    Joined:
    May 8, 2009
    Posts:
    537
    where i can find similar tool for quad buffer stereo that works with quadro cards like nvidia quadro fx and ati firegl
     
  48. phoberman

    phoberman

    Joined:
    Jan 16, 2008
    Posts:
    75
    Turns out you don't need any special tools - we recently discovered that Unity builds will run in stereo 3D with nVidia 3D Vision (Windows 7 with Quadro FX, nVidia glasses Acer 120Hz monitor) - all you have to do is turn on "Enable Stereoscopic 3D" from the nVidia Control Panel run your game.

    Deferred lighting doesn't work (vertex lit and forward are ok), and shadows don't work at all. Other rendering stuff might not work, haven't checked everything. And the Unity editor crashes sometimes if you have 3D turned on.

    nVidia has keyboard shortcuts for controlling interaxial distance (Ctrl-F3 and Ctrl-F4) convergence (Ctrl-F5 and Ctrl-F6).

    Don't know about ATI.
     
  49. rahuxx

    rahuxx

    Joined:
    May 8, 2009
    Posts:
    537

    trust me it is not good solution, as you have to keep changing depth and eye separation continuously to get better results.
    Actually i wanted something like crytek, native stereo support.
     
  50. phoberman

    phoberman

    Joined:
    Jan 16, 2008
    Posts:
    75
    Well, obviously. But it's way better than nothing.