Game Development Community

Rendering to texture problem, part 2

by Justin Tolchin · in Torque Game Engine Advanced · 08/04/2005 (2:28 pm) · 7 replies

Hi all,

I am trying to replicate (in TSE) the Minimap rendering from the RTS kit. After a little hunting around I was able to figure out how to render to a texture and got the terrain to show up. Unfortunately, I was only able to get part of it to draw.

The way the RTS minimap rendering code works is that it takes the mission area and divides it up into "chunks" based on the size of the texture. In my case I'm using a 200x200 texture, so the minimap rendering chops the terrain up into 4 equal rectangles, positions the camera in the center of those 4 chunks, and then renders a chunk to a 100x100 pixel section of the backbuffer. Then the code copies that 100x100 pixel section into the appropriate part of the rendered texture, and then does the next chunk. At least that's my understanding.

What I'm seeing is that the last chunk to get rendered gets stretched over the entire bitmap. Actually it seems like it's only a portion of the last chunk but it's kind of hard to tell. In any case, it's wiping out the rest of the bitmap (assuming they were ever copied in properly). I was just hoping somebody could look at the original RTS code and my TSE-converted version and tell me if I made an obvious mistake. I'm really clueless about the GFX library, so in some cases I was just taking my best guess. In particular I'm wondering if the GFX->drawBitmapSR function is the right one to use (and that I called it correctly).

So here's the rendering portion of the original RTS kit code:

Con::printf("Map generation beginning...");
   for (S32 v = 0; v < subDivs; v++)
   {
      sCurrRenderPos.y = start.y + v * renderSquareSize;
      for (S32 u = 0; u < subDivs; u++)
      {
         sCurrRenderPos.x = start.x + u * renderSquareSize;

         glClear(GL_DEPTH_BUFFER_BIT);
         Parent::onRender(mBounds.point, mBounds);

         glFinish();
         glBindTexture(GL_TEXTURE_2D, mRenderTexture.getGLName());
         glCopyTexSubImage2D(GL_TEXTURE_2D, 0,
            texelSquareSize*u, texelSquareSize*v, 0, 0, texelSquareSize, texelSquareSize);
      }
   }

And here's my version in TSE:

Con::printf("Map generation beginning...");
	
	GFX->startActiveRenderSurface(mRenderTexture);
	GFX->setZEnable( true );
	GFX->clear( GFXClearZBuffer | GFXClearStencil | GFXClearTarget, ColorI( 255, 0, 0 ), 1.0f, 0 );

	for (S32 v = 0; v < subDivs; v++)
	{
		sCurrRenderPos.y = start.y + v * renderSquareSize;
		for (S32 u = 0; u < subDivs; u++)
		{
			sCurrRenderPos.x = start.x + u * renderSquareSize;

			GFX->clear(GFXClearZBuffer | GFXClearStencil, ColorI( 255, 0, 0 ), 1.0f, 0);
			
			Parent::onRender(mBounds.point, mBounds);
			
			GFX->drawBitmapSR(mRenderTexture, Point2I(texelSquareSize*u, texelSquareSize*v),
				RectI(0, 0, texelSquareSize, texelSquareSize));
				 
		}
	}

	GFX->endActiveRenderSurface();

Thanks!

#1
08/04/2005 (4:18 pm)
I *think* what you want to do is set your viewport up before calling Parent::onRender. So it renders to the correct chunk of the texture. Then get rid of the drawBitmapSR call, because mRenderTexture will already have the data rendered into it.

Hopethat helps.
#2
08/04/2005 (4:29 pm)
Just want to make sure I understand: it sounds like you're saying I can render directly to the texture instead of the backbuffer; is that correct? And when you say "set your viewport" do you mean literally calling GFX->setViewport before each chunk? Would I construct the viewport rect as:

RectI(texelSquareSize*u, texelSquareSize*v, texelSquareSize, texelSquareSize)

or some other way?

Thanks!
#3
08/04/2005 (4:40 pm)
You can render directly to a texture if you want. Why go to all the trouble of breaking it up though, just use a 400x400 or 800x800 texture. A power-of-2 texture size would be best FYI, ie. 256x256 or 512x512.
#4
08/04/2005 (4:46 pm)
Hi Brian. I was thinking of doing that, actually. I just assumed the RTS kit broke it up into chunks for a reason (maybe positioning the camera far enough away to render the whole terrain at once caused too much blurriness?).

BTW, I tried removing the drawBitmapSR call and I actually get basically identical behavior (I just see the last rendered chunk of terrain). So I'm guessing when GFX->endActiveRenderSurface() is called, it just flips whatever's been drawn to the backbuffer into the texture? Or am I just totally not understanding these calls? :-)
#5
05/24/2008 (5:17 pm)
What happened with GFX->startActiveRenderSurface() and GFX->endActiveRenderSurface() ?

Ive read some other thread where those are renamed to pushActiveRenderSurface() and popActiveRenderSurface().

However, I either cant find references to those in TGEA 1.7. What would be the correct way now to implement the Justin's code of the first comment?

Edit: and sorry for raising this old thread.
#6
05/25/2008 (9:52 pm)
Now to render in a surface, you need to setup a render target (see here ). However, as I highlight in this thread, there is an issue with the DRL render code when setting up the chain textures. I have currently solved half of the issue, but I still need some help / hints to know how to solve it all.

By the way for the Z buffer issue, one important things is to not forget to link a stencil and define a ZRender texture too.
#7
05/26/2008 (8:50 am)
Thanks Frank, later tonight I'll be looking at this.