[solved] glViewport glScissor & gluOrtho2D

Hi,

I’m still working on a 2D curve editor using jogl (like Cubase for example),
and I think I misunderstood the difference between glViewport & glScissor.

I’ve got a canvas and I want to split it in different tracks (each track beeing a vector of curves), I can not afford having multiple canvas in this case, because I have other windows using other canvas and I can have up to 32 tracks.
I thought I could use glScissor to do that but I’m not able to draw correctly in the different parts of this canvas.

My idea was to draw like this for each track (in a “for” loop) :

// define the portion representing the track in windows coordinates
glViewport(X,Y,W,H);
glScissor(X,Y,W,H);
// define the opengl coordinate of this portion
gluOrtho2D(minX,maxX,minY,maxY);

where Y, H are different (each track can have a different height)
and X,W,minX,maxX,minY,maxY are the same for all tracks (the space representing the track is the same whatever the eight of the track)
the X axis is Time, Y the value of the curve at that time.

Not sure it’s clear, but is this the right way to go ?

Thanks

Léo

Pretty close. glViewport and glScissor act in screen space - pixels. glOrtho works in world coordinates and maps the extents of the world space to the pixel space of the screen. You can set up your ortho camera to have a left/right of -3,+3 and then regardless of your pixel space that the scissor test defines, everything in that world space will always be mapped to that specified section of pixel space on screen.

Thanks for your answer but this doesn’t seem to work,
If you could check this portion of code :


import javax.media.opengl.GL;
import javax.media.opengl.GLAutoDrawable;
import javax.media.opengl.GLEventListener;
import javax.media.opengl.GLJPanel;
import javax.media.opengl.glu.GLU;
import javax.swing.JFrame;

public class ScissorTest extends JFrame implements GLEventListener
{
	private final int H_TIME_SCALE = 20;
	private final int H_TIME_SCROLL = 10;
	private final int W_TRACK_SCROLL = 10;
	private final int W_TRACK_HEADER = 100;
	private final int TK_NUMBER = 10;
	private float[] bgColor = {1,1,1,1};
	private int width;
	private int height;
	private GLJPanel glp;
	private GL gl;
	private GLU glu;
	private float minY = 0;
	private float maxY = 20;
	private float minX = 0;
	private float maxX = 2000;
	
	public ScissorTest()
	{
		super("ScissorTest");
		setSize(400,400);
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		
		glp = new GLJPanel();
		glp.addGLEventListener(this);

		add(glp);	
		setVisible(true);
	}
	
	public void init(GLAutoDrawable drawable)
	{
		gl = drawable.getGL();
		glu = new GLU();
		gl.glShadeModel(GL.GL_SMOOTH); // Enable Smooth Shading
		gl.glClearColor(bgColor[0],bgColor[1],bgColor[2],bgColor[3]); // White Background
		gl.glViewport(0, 0, width, height);
		gl.glEnable(GL.GL_POINT_SMOOTH);
		gl.glEnable(GL.GL_LINE_SMOOTH);
		gl.glEnable(GL.GL_POLYGON_SMOOTH);
		gl.glPolygonMode(GL.GL_FRONT, GL.GL_LINE);
		gl.glEnable(GL.GL_BLEND);
		gl.glBlendFunc(GL.GL_SRC_ALPHA, GL.GL_ONE_MINUS_SRC_ALPHA);
		gl.glMatrixMode(GL.GL_PROJECTION);
		gl.glEnable(GL.GL_SCISSOR_TEST);
	}

	public void display(GLAutoDrawable drawable)
	{
		gl = drawable.getGL();
		gl.glClear(GL.GL_COLOR_BUFFER_BIT);
		gl.glLoadIdentity();
		
		gl.glPolygonMode(GL.GL_FRONT, GL.GL_FILL);

		// TIME SCALE
		gl.glViewport(W_TRACK_HEADER,height-H_TIME_SCALE,width-W_TRACK_HEADER-W_TRACK_SCROLL,H_TIME_SCALE);
		gl.glScissor(W_TRACK_HEADER,height-H_TIME_SCALE,width-W_TRACK_HEADER-W_TRACK_SCROLL,H_TIME_SCALE);
		glu.gluOrtho2D(0,1,0,1);
		gl.glColor3f(1,0,0);
		gl.glRectf(0,0,1,1);
		
		// TRACK HEADER
		gl.glViewport(0,H_TIME_SCROLL,W_TRACK_HEADER,height-H_TIME_SCROLL-H_TIME_SCALE);
		gl.glScissor(0,H_TIME_SCROLL,W_TRACK_HEADER,height-H_TIME_SCROLL-H_TIME_SCALE);
		glu.gluOrtho2D(0,1,0,1);
		gl.glColor3f(0,1,0);
		gl.glRectf(0,0,1,1);
		
		// TRACK SCROLL
		gl.glViewport(width-W_TRACK_SCROLL,H_TIME_SCROLL,W_TRACK_SCROLL,height-H_TIME_SCROLL-H_TIME_SCALE);
		gl.glScissor(width-W_TRACK_SCROLL,H_TIME_SCROLL,W_TRACK_SCROLL,height-H_TIME_SCROLL-H_TIME_SCALE);
		glu.gluOrtho2D(0,1,0,1);
		gl.glColor3f(0,0,1);
		gl.glRectf(0,0,1,1);
		
		// TIME SCROLL
		gl.glViewport(W_TRACK_HEADER,0,width-W_TRACK_HEADER-W_TRACK_SCROLL,H_TIME_SCROLL);
		gl.glScissor(W_TRACK_HEADER,0,width-W_TRACK_HEADER-W_TRACK_SCROLL,H_TIME_SCROLL);
		glu.gluOrtho2D(0,1,0,1);
		gl.glColor3f(0.5f,0.5f,0);
		gl.glRectf(0,0,1,1);
		
		// TRACK DISPLAY
		int trackHeight = (height-H_TIME_SCALE-H_TIME_SCROLL)/TK_NUMBER;
		gl.glColor3f(0,0,0);

		int currentHeight = 0;
		for(int i = TK_NUMBER ; i >= 0 ; i--)
		{
			gl.glViewport(W_TRACK_HEADER,H_TIME_SCROLL+currentHeight,width-W_TRACK_HEADER-W_TRACK_SCROLL,trackHeight);
			gl.glScissor(W_TRACK_HEADER,H_TIME_SCROLL+currentHeight,width-W_TRACK_HEADER-W_TRACK_SCROLL,trackHeight);
			glu.gluOrtho2D(minX,maxX,minY,maxY);
		
			gl.glBegin(GL.GL_LINES);
				gl.glVertex2f(minX,minY);
				gl.glVertex2f(maxX,maxY);
			gl.glEnd();
			currentHeight += trackHeight;
		}	
	}
	
	public void reshape(GLAutoDrawable drawable, int x, int y, int w, int h)
	{
		width = w;
		height = h;
	}

	public void displayChanged(GLAutoDrawable drawable, boolean modeChanged, boolean deviceChanged){}
	
	public static void main(String args[])
	{
		new ScissorTest();
	}
}

In this code I define different areas, the colored ones are for time scale, scrollbar…
the center is for curve drawing :
what I draw is pretty simple, a simple line going from the left/bottom corner to the right/upper corner of the gluOrtho2D view.

As you can see in the picture attached, on my computer (mac os x) each line is drawn in the same area.

Can you reproduce this ? What am I doing wrong here ?

Thanks for your time.

Léo

Ok, since noone answers, I think the example wasn’t clear,
I simplified it, but the problem still remains.
So, can someone take a look at that code please ?


import javax.media.opengl.GL;
import javax.media.opengl.GLAutoDrawable;
import javax.media.opengl.GLEventListener;
import javax.media.opengl.GLJPanel;
import javax.media.opengl.glu.GLU;
import javax.swing.JFrame;

public class ScissorTest extends JFrame implements GLEventListener
{
	private final int TK_NUMBER = 3;
	private float[] bgColor = { 1, 1, 1, 1 };
	private int width;
	private int height;
	private GLJPanel glp;
	private GL gl;
	private GLU glu;
	private float minY = 0;
	private float maxY = 20;
	private float minX = 0;
	private float maxX = 2000;

	public ScissorTest()
	{
		super("ScissorTest");
		setSize(400, 400);
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		glp = new GLJPanel();
		glp.addGLEventListener(this);
		add(glp);
		setVisible(true);
	}

	public void init(GLAutoDrawable drawable)
	{
		gl = drawable.getGL();
		glu = new GLU();
		gl.glShadeModel(GL.GL_SMOOTH); // Enable Smooth Shading
		gl.glClearColor(bgColor[0], bgColor[1], bgColor[2], bgColor[3]); // White Background
		gl.glEnable(GL.GL_POINT_SMOOTH);
		gl.glEnable(GL.GL_LINE_SMOOTH);
		gl.glEnable(GL.GL_POLYGON_SMOOTH);
		gl.glPolygonMode(GL.GL_FRONT, GL.GL_LINE);
		gl.glEnable(GL.GL_BLEND);
		gl.glBlendFunc(GL.GL_SRC_ALPHA, GL.GL_ONE_MINUS_SRC_ALPHA);
		gl.glMatrixMode(GL.GL_PROJECTION);
		gl.glEnable(GL.GL_SCISSOR_TEST);
	}

	public void display(GLAutoDrawable drawable)
	{
		gl = drawable.getGL();
		gl.glViewport(0, 0, width, height);
		gl.glClear(GL.GL_COLOR_BUFFER_BIT);
		gl.glLoadIdentity();
		// TRACK DISPLAY
		int trackHeight = (height) / TK_NUMBER;
		gl.glColor3f(0, 0, 0);
		System.out.println("---------------------------------");
		int currentHeight = 0;
		for (int i = TK_NUMBER - 1; i >= 0; i--)
		{
			System.out.println("TK " + i + " Y:" + currentHeight + " H:" + trackHeight);
			gl.glViewport(0, currentHeight, width, trackHeight);
			gl.glScissor(0, currentHeight, width, trackHeight);
			glu.gluOrtho2D(minX, maxX, minY, maxY);
			gl.glBegin(GL.GL_LINES);
			gl.glVertex2f(minX, minY);
			gl.glVertex2f(maxX, maxY);
			gl.glEnd();
			currentHeight += trackHeight;
		}
	}

	public void reshape(GLAutoDrawable drawable, int x, int y, int w, int h)
	{
		width = w;
		height = h;
	}

	public void displayChanged(GLAutoDrawable drawable, boolean modeChanged, boolean deviceChanged)
	{
	}

	public static void main(String args[])
	{
		new ScissorTest();
	}
}

I expect this to draw 3 lines in 3 box area
but I think here the 3 lines are drawn in the same area.
What’s wrong ?

Léo

Hi,

I solved it by myself.
It just needed a glLoadIdentity() in the loop like this :


	public void display(GLAutoDrawable drawable)
	{
		gl = drawable.getGL();
		gl.glClear(GL.GL_COLOR_BUFFER_BIT);
		gl.glLoadIdentity();

		gl.glColor3f(0, 0, 0);

		System.out.println("---------------------------------");
		int trackHeight = height / TK_NUMBER;
		int currentHeight = 0;

		for (int i = TK_NUMBER - 1; i >= 0; i--)
		{
			System.out.println("TK " + i + " Y:" + currentHeight + " H:" + trackHeight);
			gl.glViewport(0, currentHeight, width, trackHeight);
			gl.glScissor(0, currentHeight, width, trackHeight);
			glu.gluOrtho2D(minX, maxX, minY, maxY);

			gl.glBegin(GL.GL_LINES);
				gl.glVertex2f(minX, minY);
				gl.glVertex2f(maxX, maxY);
			gl.glEnd();

			currentHeight += trackHeight;
			/////////////////////////////////
			gl.glLoadIdentity();
			////////////////////////////////
		}

Thanks

Léo

It will work, but it would make more sense to do:

glLoadIdentity();
gluOrtho2d(…);

Further, it doesn’t make much sense to scissor the viewport with a rectangle that is exactly the same rectangle as the viewport.

The scissor will cull all pixels outside its rectangle
The viewport will cull all pixels outside its rectangle

So use either the viewport change or the scissor

They behave differently BTW, as a small viewport will scale down the gfx, while a scissor will just render the remaining pixels

Thanks,

That’s sure it’s not very clear for me why I need all this.
Actually I don’t need scissors.
Removing glScissors works as expected.

Léo

I’ve found that typically you need both viewport and scissor settings when doing work like this. Some platforms/drivers don’t automatically trim the rendering to just the viewport area if you don’t also include the scissor calls.