Render To Texture gets suboptimal results

Started by CodeBunny, May 08, 2011, 16:19:34

Previous topic - Next topic

CodeBunny

To render a large amount of static text, I first draw the font onto a texture, and then render the quad. This is great for performance, but for high-detail fonts, I get bad-looking results.

Example:

Text without render-to-texture (the desired quality):

Same text, rendered to texture:

Zoomed in, to highlight the disparity:
Normal:

Rendered:

As you can see, the lower-transparency pixels (the red edging and the edges of the white text) are drawn far less strongly. What's causing this? Is RTT just lower quality? I'm using the same render call between the two, the only difference is that I use a framebuffer on one and normal rendering on the other.

Fool Running

Just a guess, but is it possible the render-to-texture is resized to a power-of-2? This, I think, would cause what you are seeing (some of the pixels in the texture are not showing because there are more textels available then the number of pixels to show it in).
You can verify this by blowing up the rendered quad so only a small portion is shown at a bigger size (like 1024x1024 or something). (I assume that is not what you did in the zoomed screen shot.)
If possible, try render the text in a power-of-2 square and see if that helps.
Programmers will, one day, rule the world... and the world won't notice until its too late.Just testing the marquee option ;D

CodeBunny

From looking at my code, I don't see the discrepancy you said, but I might be wrong.

Here's how I initialize the FBO and set the viewport and Ortho:

if(renderToTextureEnabled())
{
	IntBuffer buffer = ByteBuffer.allocateDirect(4).order(
			ByteOrder.nativeOrder()).asIntBuffer();
	
	EXTFramebufferObject.glGenFramebuffersEXT(buffer);
	
	frameBuffersActive.push(buffer.get());
	
	EXTFramebufferObject.glBindFramebufferEXT(EXTFramebufferObject.GL_FRAMEBUFFER_EXT,
			frameBuffersActive.peek());
	EXTFramebufferObject.glFramebufferTexture2DEXT(EXTFramebufferObject.GL_FRAMEBUFFER_EXT,
			EXTFramebufferObject.GL_COLOR_ATTACHMENT0_EXT, GL11.GL_TEXTURE_2D, 
			texture.getTextureID(), 0);

	checkFBO(frameBuffersActive.peek());

	GL11.glPushAttrib(GL11.GL_VIEWPORT_BIT);
	GL11.glViewport(0, 0, width, height);
	
	GL11.glMatrixMode(GL11.GL_PROJECTION);
	GL11.glPushMatrix();
	GL11.glLoadIdentity();
	GL11.glOrtho(0, width, height, 0, -1, 1);
	
	GL11.glMatrixMode(GL11.GL_MODELVIEW);
	GL11.glPushMatrix();
	GL11.glLoadIdentity();
	return true;
}


Would doing this cause what you said?

Fool Running

Sorry, I guess I wasn't being clear.
What I mean is that, although you're viewport might be 800x600 (I don't know what values you are actually using), the texture that you made might be bigger (or smaller) since it has to be a power-of-two (say 1024x1024 in this case). If you then shrink the texture to 800x600 to fit on your quad, there are more textels then there are pixels (1024 instead of 800) which might cause what you are seeing.

To test this theory, you need to make the quad you draw on to be the power-of-two size that you used to create your texture and see if it looks right (but you may not be able to see it all in your viewport).

I'm just guessing since I'm not sure what doing a render-to-texture on the framebuffer does to the texture. I would have thought if you created a 1024x1024 texture, but just drew to 800x600 of it, then a lot of the texture would be blank and I assume you would notice that. Also, if your texture was too small, I would assume that the text would be cut off and you would notice that as well.

Hope that helps. ;D
Programmers will, one day, rule the world... and the world won't notice until its too late.Just testing the marquee option ;D

CodeBunny

I don't believe that's happening - I use Slick's Internal Texture Loader to create the texture, and that takes desired dimensions and ceilings them to the
lowest POT >= desired size. I've run some tests, and the texture desired is always at least the size you desire.

And, I forgot to mention one thing: When I render the text to the texture multiple times (say, 3x instead of 1) I get the result I'm looking for (or close enough that I can't tell the difference). Since this is the case, I'm convinced the texture is of the right dimensions. However, for some reason, the transparent pixels are getting drawn at less transparency than they should.

spasi

Some stuff you can check:

- Are blending and alpha test states exactly the same with both FBO rendering and non-FBO rendering?
- Does the texture attached to the FBO have an alpha channel?
- Are all channels enabled when rendering to the FBO? (all params true in glColorMask)

CodeBunny

Thanks, Spasi.

After doing some additional googling, it seems like this is actually not an uncommon problem, and most people are pointing to the way glBlendFunc is working when operating on a FBO.

CodeBunny

RESOLVED. For anyone who gets this problem in the future:

Using this blend function:

GL11.glBlendFunc(GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA);


when you are rendering to texture fixes the problem. If you think about how the blending functions work you'll see why this is.

spasi

Ah, additive blending ftw. Read this for the best explanation on the issue.