How to smooth scroll text?

Hello,

I am new to JOGL, so forgive me if this should have been posted in the newbie section or I am missing something very dumb. However, I have been stuck on this for several days now.

I am trying to develop an application that provides ultra-smooth text scrolling in Java. In order to achieve this I have been trying to use JOGL from examples I have found on the internet, but with only minimal luck. The canvas continually flickers, and moves my GL_QUADS (or texture, idk) even when I am not calling the redraw method of my GLCanvas. I don’t know how to describe it well, but image is very jerky. When I had a similar problem with Graphics2D, using a frame buffer helped. I have found some sites that say (atleast on windows, but I am using linux) that you have to disable the awt erasing:
System.setProperty(“sun.awt.noerasebackground”, “true”);
but that does not work for me. I have also tried setting the noddraw, and that doesn’t work. What is worse is that not all the lines of text in the same texture seem to move at the same rate (even though they are being rendered from the same tile). This was the problem with simply using a TextRenderer, making that option infeasable.

Basically, I break up the text I want to scroll, and create a TextRenderer for each section (I call them a “Tile”) and use its graphics2D to draw the pieces of text. Then when each tile comes into view, I want to draw the textures with jogl. That way I don’t have to draw the whole document at once. My GLCanvas then draws each of the tiles using the following method:

		GL2 gl = canvas.getGL().getGL2();
		texture.setTexParameteri(gl,GL.GL_TEXTURE_WRAP_S, GL.GL_REPEAT);
		texture.setTexParameteri(gl,GL.GL_TEXTURE_WRAP_T, GL.GL_REPEAT);
		texture.setTexParameteri(gl,GL.GL_TEXTURE_MAG_FILTER, GL.GL_LINEAR);
		texture.setTexParameteri(gl,GL.GL_TEXTURE_MIN_FILTER, GL.GL_LINEAR);

		float startY = ...;
		float endY = ...;
		
		texture.bind(gl);
		//gl.glTexEnvi(GL2.GL_TEXTURE_ENV, GL2.GL_TEXTURE_ENV_MODE, GL2.GL_REPLACE); 
		gl.glClear(GL2.GL_COLOR_BUFFER_BIT); //use the clear color we set
	
/*		I can't make this code work, but I doubt it would be any better.
		renderer.beginOrthoRendering(,);
		renderer.drawOrthoRect(,);
		renderer.endOrthoRendering();*/
		
		gl.glBegin(GL2.GL_QUADS);
		{
			gl.glTexCoord2d(0.0, 0.0);
			gl.glVertex2d(0.0f, startY);
			gl.glTexCoord2d(1.0, 0.0);
			gl.glVertex2d(1.0f, startY);
			gl.glTexCoord2d(1.0, 1.0);
			gl.glVertex2d(1.0f, endY);
			gl.glTexCoord2d(0.0, 1.0);
			gl.glVertex2d(0.0f, endY);
		}
		gl.glEnd();

After calling this for each of the Textures, I run:

		// glad is the GLAutoDrawable
		glad.getGL().getGL2().glFlush();
		glad.swapBuffers();

Those lines don’t seem to make any difference. My initialization code is as follows:

		GLCapabilities caps = new GLCapabilities(getGLProfile());
		caps.setDoubleBuffered(true);
		caps.setHardwareAccelerated(true);
		GL2 gl = glad.getGL().getGL2();
		// Clearing screen color
		gl.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
		gl.glMatrixMode(GL2.GL_PROJECTION);
		gl.glLoadIdentity();
		// this is where to flip the image, etc.
		gl.glOrtho(0, 1, 0, 1, -1, 1);

Is it possible to smooth scroll in jogl? Should I be using something aside from textures like bitmaps? Should I always use the same quad but scroll the texture over it? Would compiling help? Do you have any other tips/ideas? I guess part of the question is also just, “What tools would you use to develop the smoothest scrolling application you could?”

Thanks in advance!

I did mean to say that I create a TextureRenderer for each tile instead of TextRenderer. If it helps, my code for that is:


		renderer = new TextureRenderer(width,height,false);
		Graphics2D graphics = renderer.createGraphics();
		graphics.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
		
		Settings settings = Settings.getInstance();
		graphics.setColor(settings.getBackgroundColor());
		graphics.fillRect(0,0,width,height);
		graphics.setColor(settings.getForegroundColor());
		if(!isBlank) {
			ArrayList<RenderedItem> ris = getItems();
			
			float offset = ...;
			for(int i=0;i<size;i++) {
// this makes a call to draw on a TextLayout object
				ris.get(i).draw(graphics, offset);
				offset += ris.get(i).getHeight();
			}
		}
		graphics.dispose();
//		renderer.markDirty(0,0,width,height);
		return renderer.getTexture();

In the first section of code that you say “renders each tile”, I am assuming that it is called once per tile that you have to render. If this is the case, you are clearing the entire GLCanvas every time you render a tile. This could account for the strange flickering that you’re seeing, and for the strange moving of tiles when you think that they shouldn’t be.

Thanks for the response lhkbob!

Sorry, I was not being clear. (sometimes I develop my own terminology that conflicts with others!) I use a TextureRenderer to “render” each texture when it comes on the screen, and then I save the texture. From that time on (until the window resizes), I draw that same texture using the first code snippet.

Is that what I should do, or is there a way to “move” a texture without drawing it (using the GL_QUADS) over again? What that way be more smooth than what I am doing?

Thanks again!

I understood what you were doing. It is in your first snippet that you’re calling glClear(). However, you’re only drawing a single quad in that first snippet, so I must assume that that snippet is called once for each tile that must be rendered onto the screen. In which case, you’re calling glClear() every time you draw tile.

You can “move a texture” by changing the vertex coordinates of the quad that the texture is rendered onto. If all you’re doing is text translations and rotations, then translating and rotating the quad will be much faster than updating every texture.

Is there a reason why you didn’t render all characters into a texture sprite sheet, and then have a quad for each character that you’ll need to render? You will save a lot of texture memory that way instead of creating a texture per tile. You can still easily filter out quads that are off screen, either per character checking, or grouping the characters into tiles that are rendered together or excluded together.

At this point, I should also suggest that you try to get a simple demo working that has a smoothly scrolling quad with a texture, where you only draw 1 quad with a single texture, and the texture is not updated. If that works and renders properly without flickers, than slowly add more features to emulate the requirements needed of your text rendering. You will find your bugs, or the problems in your algorithm that don’t fit well with the library, or you will fix your bug without realizing it.

Thanks again!

That makes sense, as long as I understand properly.

Yes, I was calling glClear for each tile. Absent-mindedly, I had thought I was only clearing the region the next vertex quad was going to take up. (That explains why I was only displaying one tile at a time!") I will have to figure out how to “remember” or “save” the quad that I draw so that I only have to call gl_translate each draw instead of drawing a whole new one. (My best guess is that this will be done for me if I just don’t clear the screen. Maybe all I have to do is call gl_translate! Back to google…) I hadn’t realized that I was updating the texture each time I was binding it to the gl.

No! There is no reason I wasn’t making a texture for each character, I had assumed it would be best to make the texture as big as possible so that as much work was being done “under the hood” as possible. (The first thing I did when I was in Graphics2D was to render the whole text document at once, and I only decided to break it up into tiles after it took to long to resize.) As soon as I figure out how to only translate the quad I will fix this too.

Yes, I have had several demos: first using Graphics2D and drawing each line, then drawing Tiles with BufferedImages, then JOGL with a TextRenderer, and the the TextureRenderer was my last attempt. I could see the text and everything, but it looked very clearly wrong.

Wow, thanks so much! I have no idea how many examples and javadoc pages I would have read through before tying to simply translate the quad. One of the examples I was building from was the one on Wikipedia (which calls gl.glBegin(GL2.GL_QUADS)/gl.glEnd every time draw is called).

Again I just can’t thank you enough: I feel like I have hope again!

First of all, I see JOGL has its own section in this forum, so I should have put this in there. Sorry.

I am pretty sure I do have to clear the screen every time a tile “moves”, but not calling clear before drawing the tile does help. It is still not smooth enough though, I guess the only thing I can thing of left is to create textures for each character instead of each tile, and to make display lists for the tiles.

I don’t understand what you mean by translating/rotating the quads instead of updating the texture. I will call translate and rotate to be in the right position to draw the quad containing the texture, but I sill have to bind the texture to the gl each time. If you mean my calls:


      texture.setTexParameteri(gl,GL.GL_TEXTURE_WRAP_S, GL.GL_REPEAT);
      texture.setTexParameteri(gl,GL.GL_TEXTURE_WRAP_T, GL.GL_REPEAT);
      texture.setTexParameteri(gl,GL.GL_TEXTURE_MAG_FILTER, GL.GL_LINEAR);
      texture.setTexParameteri(gl,GL.GL_TEXTURE_MIN_FILTER, GL.GL_LINEAR);

then yes, that was easy to just move into the section where I create the tile, so it is only called once.

Thanks for your patience!

glTranslate() will translate the quad. It applies a translation transform to the vertices of the quad so you are effectively moving the quad. It has no effect on the texture, except that the texture is rendered on the quad. If you move the quad you move the texture.

glClear() clears the entire window, so you should only do it once at the very beginning of each frame of rendering. If you only render a frame every time any tile moves, then this will be the same as clearing it when the tiles move. You should not render 1 frame per moved tile, you want to render 1 frame where it renders all visible tiles. OpenGL can handle it, so don’t try to do anything fancy to optimize.

From the things you’ve said in your posts, I can tell that you’re new to OpenGL programming. Jumping into textures for text rendering is a pretty advanced place to start and OpenGL requires a lot of knowledge to use effectively and understand all of its concepts. I strongly recommend starting somewhere simple with geometry and at least understand the different types of vertex attributes, and transform matrices available.

Yes, I am very to new to JOGL and graphics programming, and honestly hate asking questions out of line. Before I give up though, there is one thing I should know that is obvious to you and would greatly help my understanding.

My understanding of glTranstate() is that I have to call it so that I am in the proper position BEFORE I draw my quad (using gl.begin(GL2.GL_QUADS)). From your posts in almost seems like your saying I can translate a quad without using gl.begin/gl.end. That I only have to call my gl.begin(GL2.GL_QUADS)/gl.end once, and then by calling glTranslate() to translate my quad. If this is the case, then could you point me at a method in the javadoc/example of somebody doing this? ( GLUquadric would seem to be the only thing in the documentation that I can think that might be able to “remember” a quad, but it doesn’t seem quite what I am looking for.)

Otherwise, thanks for everything you’ve helped me with! In that case, will be stuck continually binding a texture to my gl, and then using the gl do draw a quad for each tile(/character eventually).

Again, thanks for your patience and helping a poor noob!

You need glBegin/glEnd to draw a quad (in immediate mode anyway) since it’s how you tell OpenGL you’re starting to draw something in the first place (and when you’re done). You call glTranslate before glBegin to translate your coordinate system before drawing the quad. Effectively, it adds the amount you translate by to all your glVertex calls. Think of it as moving your “brush”, not the objects, which stay put where you draw them, and only get moved later by the projection matrix.

You should definitely read some tutorials, then when you know what functions you have available, play around with them, move some squares and triangles around the screen, see what happens when you plug in different values.

GLUQuadric is just utility methods to draw various shapes like cubes, spheres, cylinders, etc (and not among them is a single quad). It’s fun to play with but it’s otherwise woefully obsolete.