Forum Discussion

🚨 This forum is archived and read-only. To submit a forum post, please visit our new Developer Forum. 🚨
skooter500's avatar
skooter500
Explorer
11 years ago

GL.Lines only showing in one eye

Hi Guys

I am adding rift support to my Unity Game AI Framework (https://github.com/skooter500/UnitySteeringBehaviours) and I am having trouble with GL.Lines. I have a class for drawing lines that uses a shader and OnPostRender. It's attached to the camera. I have also attached an instance to CameraLeft and CameraRight of the OVRCameraController. The problem is that when the rift camera is enabled, the lines only get drawn in the left eye. The list of lines is static, so all the scripts are drawing the same list of lines. How do I get 3D lines to be drawing in both eyes?



Here is my script:

using UnityEngine;
using System.Collections;
using System;
using System.Collections.Generic;

// Must be attached to the camera so that OnPostRender gets called
namespace BGE
{
public class LineDrawer : MonoBehaviour
{
struct Line
{
public Vector3 start;
public Vector3 end;
public Color color;
public bool isDebug;
public Line(Vector3 start, Vector3 end, Color color, bool isDebug)
{
this.start = start;
this.end = end;
this.color = color;
this.isDebug = isDebug;
}
}

static List<Line> lines = new List<Line>();

Material lineMaterial;

// Use this for initialization
void Start()
{
}

void Awake()
{
DontDestroyOnLoad(this);
}

public static void DrawLine(Vector3 start, Vector3 end, Color colour)
{
lines.Add(new Line(start, end, colour, false));
}

public static void DrawTarget(Vector3 target, Color colour)
{
float dist = 1;
DrawLine(new Vector3(target.x - dist, target.y, target.z), new Vector3(target.x + dist, target.y, target.z), colour);
DrawLine(new Vector3(target.x, target.y - dist, target.z), new Vector3(target.x, target.y + dist, target.z), colour);
DrawLine(new Vector3(target.x, target.y, target.z - dist), new Vector3(target.x, target.y, target.z + dist), colour);
}

public static void DrawSquare(Vector3 min, Vector3 max, Color colour)
{
Vector3 tl = new Vector3(min.x, min.y, max.z);
Vector3 br = new Vector3(max.x, min.y, min.z);

LineDrawer.DrawLine(min, tl, colour);
LineDrawer.DrawLine(tl, max, colour);
LineDrawer.DrawLine(max, br, colour);
LineDrawer.DrawLine(br, min, colour);
}

public static void DrawCircle(Vector3 centre, float radius, int points, Color colour)
{
float thetaInc = (Mathf.PI * 2.0f) / (float)points;
Vector3 lastPoint = centre + new Vector3(0, 0, radius);
for (int i = 1; i <= points; i++)
{
float theta = thetaInc * i;
Vector3 point = centre +
(new Vector3((float) Math.Sin(theta), 0, (float) Math.Cos(theta)) * radius);
DrawLine(lastPoint, point, colour);
lastPoint = point;
}
}

public static void DrawVectors(Transform transform)
{
float length = 20.0f;

DrawArrowLine(transform.position, transform.position + transform.forward * length, Color.blue, transform.rotation);
DrawArrowLine(transform.position, transform.position + transform.right * length, Color.red, transform.rotation * Quaternion.AngleAxis(90, Vector3.up));
DrawArrowLine(transform.position, transform.position + transform.up * length, Color.green, transform.rotation * Quaternion.AngleAxis(-90, Vector3.right));
}

public static void DrawArrowLine(Vector3 start, Vector3 end, Color color, Quaternion rot)
{
lines.Add(new Line(start, end, color, false));

float side = 1;
float back = -5;
Vector3[] points = new Vector3[3];
points[0] = new Vector3(-side, 0, back);
points[1] = new Vector3(0, 0, 0);
points[2] = new Vector3(side, 0, back);

for (int i = 0 ; i < 3 ; i ++)
{
points[i] = (rot * points[i]) + end;
}

lines.Add(new Line(points[0], points[1], color, false));
lines.Add(new Line(points[2], points[1], color, false));
}

void CreateLineMaterial()
{
if (!lineMaterial)
{
lineMaterial = new Material("Shader \"Lines/Colored Blended\" {" +
"SubShader { Pass { " +
" Blend SrcAlpha OneMinusSrcAlpha " +
" ZWrite Off Cull Off Fog { Mode Off } " +
" BindChannels {" +
" Bind \"vertex\", vertex Bind \"color\", color }" +
"} } }");
lineMaterial.hideFlags = HideFlags.HideAndDontSave;
lineMaterial.shader.hideFlags = HideFlags.HideAndDontSave;
}
}

void OnGUI()
{
//Debug.Log("On post render called");
CreateLineMaterial();
// set the current material
lineMaterial.SetPass(0);
GL.Begin(GL.LINES);
foreach (Line line in lines)
{
GL.Color(line.color);
GL.Vertex3(line.start.x, line.start.y, line.start.z);
GL.Vertex3(line.end.x, line.end.y, line.end.z);
}
GL.End();
lines.Clear();
}
}
}

6 Replies

Replies have been turned off for this discussion
  • owenwp's avatar
    owenwp
    Expert Protege
    You probably need to call GL.Viewport, I don't think Unity preserves state for you to use like that.
  • Hey

    I am doing now and now the lines are getting drawn in each half of the screen. However the ones in the right eye are drawn in the wrong place. I suspect they are being drawn using the left eye camera.. Ive tried:

    if (Params.riftEnabled)
    {
    GameObject ovrCameraController = (GameObject)GameObject.FindGameObjectWithTag("ovrcamera");
    Camera[] cameras = (Camera[])ovrCameraController.GetComponentsInChildren<Camera>();
    SteeringManager.PrintVector("Cam " + i, cameras[i].transform.position);
    camera.transform.position = cameras[i].transform.position;
    }


    I can see the two camera's positions getting printed out with what looks like ok values for the left and right eye, but the last line:

    camera.transform.position = cameras.transform.position;

    Seems to just move the camera upwards?!

    Any ideas?
  • Also tried this:

     if (Params.riftEnabled)
    {
    GameObject ovrCameraController = (GameObject)GameObject.FindGameObjectWithTag("ovrcamera");
    Camera[] cameras = (Camera[])ovrCameraController.GetComponentsInChildren<Camera>();
    SteeringManager.PrintVector("Cam " + i, cameras[i].transform.position);
    GL.modelview = cameras[i].worldToCameraMatrix;
    }


    :cry:
  • Thanks for the reply. I am now and that has now moved the lines to the correct locations in both eyes!

    if (Params.riftEnabled)
    {
    GameObject ovrCameraController = (GameObject)GameObject.FindGameObjectWithTag("ovrcamera");
    Camera[] cameras = (Camera[])ovrCameraController.GetComponentsInChildren<Camera>();
    SteeringManager.PrintVector("Cam " + i, cameras[i].transform.position);
    GL.modelview = cameras[i].worldToCameraMatrix;
    GL.LoadProjectionMatrix(cameras[i].projectionMatrix);
    }


    But I still have a problem which I hope you can see from these screenshots. This is screen without the rift enabled:



    And this is the rift enabled screenshot:



    If you line up the two screens you will see that the lines in the stereo image are being occluded by the positions of the 3D objects in the non-stereo image. Also in the non-stereo version, if a line happens to penetrate a 3D object, then the 3D object is drawn on top of the line however in the stereo image, the lines are drawn on top of the 3D models.

    BTW I tried adding this line:

    GL.Clear(true, false, Color.black);

    And rather strangely, this partially fixes the problem for the left eye. The lines are no longer getting occluded, but are still getting drawn on top of the 3D models, but it doesn't affect the right eye image.

    I feel Im getting close!
  • owenwp's avatar
    owenwp
    Expert Protege
    This looks like it might be somewhat out of your control, like Unity is doing some cleanup before you have a chance to use the depth values.

    Perhaps it would work if you move your code to OnRenderImage so that it is handled like a post processing effect, the rendering state might be more usable then. Setting the viewport may also not be necessary then, but make sure to set the source texture as a render target and then blit it into the destination texture when finished. If that fails then you could set the cameras to render depth to a texture, and do manual culling in a shader.