This blog is no longer updated. Feel free to copy any useful information to other blogs or wikis. Thanks.


Split screen in SunBurn

November 25th, 2009 | 2 comments

This is a quick post since there’s not a terribly large amount to it. I wanted to play around with split screen rendering with SunBurn and found that, as expected, it’s pretty easy to set up.

We’re going to start right where the last basic project ended so go ahead and download that if you don’t have it already.

Next go ahead and add this file to your project: GraphicsDeviceExtensions.cs. It’s a basic extension method for setting a viewport on a GraphicsDevice. While you could do this by hand, I find it much nicer to just call a method like this:

GraphicsDevice.SetViewport(ViewportLocation.TopHalf);

When I want to change the current viewport.

So with that, let’s make some changes. First let’s rename our ‘view’ matrix to ‘view1′ and add a ‘view2′ matrix as well. Then in LoadContent we’ll create those and update our creation of the projection matrix. Since we’re going to be doing half screen viewports, we need to divide the height by two to match:

view1 = Matrix.CreateLookAt(new Vector3(-7f, 10f, 7f), Vector3.Zero, Vector3.Up);
view2 = Matrix.CreateLookAt(new Vector3(7f, 10f, -7f), Vector3.Zero, Vector3.Up);

projection = Matrix.CreatePerspectiveFieldOfView(
	MathHelper.PiOver2,
	GraphicsDevice.Viewport.Width / (GraphicsDevice.Viewport.Height / 2f),
	.1f,
	1000f);

Next we’ll add a new field for the tank’s world matrix:

private Matrix tankWorld = Matrix.Identity;

Next we add a method to our game called DrawScene which handles rendering all of our content. DrawScene also handles submitting any object with an ObjectLifeSpan.Frame lifespan since those are flushed with each call to RenderManager.Render.

private void DrawScene(GameTime gameTime, Matrix view, Matrix proj)
{
	// draw all frame objects here since frame objects are flushed
	// each time you call renderManager.Render()
	tank.Draw(
		tankWorld,
		renderManager,
		ObjectVisibility.CastShadows | ObjectVisibility.Rendered,
		ObjectLifeSpan.Frame);

	// draw the scene
	sceneState.BeginFrameRendering(view, proj, gameTime, environment);
	renderManager.BeginFrameRendering(sceneState);
	renderManager.Render();
	renderManager.EndFrameRendering();
	sceneState.EndFrameRendering();
}

As you can see we pass in a GameTime, view matrix, and projection matrix to the method so that our BeginFrameRendering call can use those. You can see we needed that tankWorld field now because while we need to use it multiple times a frame, there’s no point in calculating it multiple times.

Lastly we update our Draw method to utilize this new method along with our extension method to set our viewports and render the scene to each one.

protected override void Draw(GameTime gameTime)
{
	// Check to see if the splash screen is finished.
	if (!SplashScreenGameComponent.DisplayComplete)
	{
		base.Draw(gameTime);
		return;
	}

	// update all the rotations for the parts we want
	tank.TurretRotation += (float)gameTime.ElapsedGameTime.TotalSeconds;
	tank.WheelRotation += (float)gameTime.ElapsedGameTime.TotalSeconds;
	tank.SteerRotation = (float)Math.Sin(gameTime.TotalGameTime.TotalSeconds * 2f) * .5f;
	tank.HatchRotation =
		(float)Math.Sin(gameTime.TotalGameTime.TotalSeconds * 3f) * MathHelper.PiOver2;
	tank.CannonRotation =
		(float)Math.Min(Math.Sin(gameTime.TotalGameTime.TotalSeconds) * MathHelper.Pi / 3f, 0f);

	// figure out a world matrix for the tank
	tankWorld =
		Matrix.CreateRotationY(-(float)gameTime.TotalGameTime.TotalSeconds * .125f) *
		Matrix.CreateTranslation(0f, 0f, (float)Math.Sin(gameTime.TotalGameTime.TotalSeconds));

	// set a viewport and then render the scene
	GraphicsDevice.SetViewport(ViewportLocation.TopHalf);
	DrawScene(gameTime, view1, projection);

	// set a viewport and then render the scene
	GraphicsDevice.SetViewport(ViewportLocation.BottomHalf);
	DrawScene(gameTime, view2, projection);

	base.Draw(gameTime);
}

And that’s it. Give it a run and you’ll see a fun split screen view of your dancing tank.

SplitScreenSunBurn

Pretty simple, right? Keep in mind that each time you render requires a lot of GPU power since you wind up rendering all those polygons again, along with all the lighting and shadowing. On my laptop here I can do a 4-way split but it starts to lose some frame rate. I’d imagine I’d be fine on the Xbox 360 since that GPU is quite a bit more powerful.

Any other things you’d like to see done with SunBurn? Some ideas I have:

  • Rockets – shows off a light attached to a model along with particle effects and then a big fun explosion at the end. :)
  • Some sort of indoor scene with two or more point/directional lights that sway just to do some more complex lighting.

Any other ideas? Let me know and I’ll see what I can do.

Download: SplitScreenSunBurn.zip

  1. November 25th, 2009 at 10:12
    Quote | #1

    A test with explosions would be nice. Also an indoor scene with some vitrals would kickass

  2. November 25th, 2009 at 10:12
    Quote | #2

    A test with explosions would be nice. Also an indoor scene with some vitrals would kickass

Comments are closed.