Matrix Projection Camera - Aligning Spritebatch and GPU Instance

Hey,
i know there have been several posts about this already, and i really didn’t want to post, but i just cant get it to work. Tinkering around for days now.

I want to align a spritebatch draw like this:

spriteBatch.Begin(transformMatrix: camera.worldViewProjSpriteBatch);
spriteBatch.Draw(texture, position, null, Color.White, 0, new(texture.Width / 2f, texture.Height / 2f), scale, SpriteEffects.None, layer);
spriteBatch.End();

with a quad i’ve drawn with a vertexbuffer:

float4 position = float4(vertexInput.Position.xy * textureSize + instanceInput.Position.xy, 0.0, 1.0);
output.Position = mul(position, worldViewProjGPU);

and these are my matrices for the cameras:

// SpriteBatch
var transformMatrix = Matrix.CreateTranslation(-player.position.X, -player.position.Y, 0);
transformMatrix *= Matrix.CreateScale(distance, distance, 1); // Scale by zoom
transformMatrix *= Matrix.CreateTranslation(windowSize.X * 0.5f, windowSize.Y * 0.5f, 0);
worldViewProjSpriteBatch = transformMatrix;

// GPU Instance
Matrix viewMatrixGPU = Matrix.CreateLookAt(V(player.position, 10), V(player.position, 0), Vector3.Up);
Matrix projectionMatrixGPU = Matrix.CreateOrthographicOffCenter(0, windowSize.X, windowSize.Y, 0, nearPlane, farPlane);
projectionMatrixGPU *= Matrix.CreateScale(distance, distance, 1);
worldViewProjGPU = viewMatrixGPU * projectionMatrixGPU;

V = Vector, distance is the zoom. And this kinda works, but the sprite’s scale and position dont align with the quad ones. And i’m just not getting something fundamentally. Like one is in screenspace and one in worldspace or something. If somebody could make me understand this, i would be really appreciative!

Here is the shader code for the MG sprites, and here is how the transformation matrix gets calculated.
If you make your custom quad drawer behave the same way, you should be fine.

The sprite position is usually passed to the SpriteBatch.Draw call. If you do it like this in the general transform, you can’t draw multiple sprites at different positions in a single batch.

EDIT: and the code that builds the sprite vertices

1 Like

Thank you! Got it to work with your help. :smiley:

		public void UpdateProjectionMatrix()
		{
			// SpriteBatch
			var transformMatrix = Matrix.CreateTranslation(-player.position.X, -player.position.Y, 0);
			transformMatrix *= Matrix.CreateScale(distance, distance, 1); // Scale by zoom
			transformMatrix *= Matrix.CreateTranslation(viewPort.Width * 0.5f, viewPort.Height * 0.5f, 0);
			worldViewProjSpriteBatch = transformMatrix;

			// GPU Instance
			Matrix viewMatrixGPU = Matrix.CreateLookAt(V(0, 0, 1), V(0, 0, 0), Vector3.Up);
			Matrix projectionMatrixGPU = GetSpriteBatchMatrix();
			worldViewProjGPU = transformMatrix * viewMatrixGPU * projectionMatrixGPU;
		}

		private Matrix GetSpriteBatchMatrix()
		{
		    float nearPlane = 0f;
		    float farPlane = 10;
			Matrix.CreateOrthographicOffCenter(0, viewPort.Width / 1, viewPort.Height / 1, 0, nearPlane, farPlane, out Matrix projectionMatrixGPU);
			if (graphics.GraphicsDevice.UseHalfPixelOffset)
			{
				projectionMatrixGPU.M41 += -0.5f * projectionMatrixGPU.M11;
				projectionMatrixGPU.M42 += -0.5f * projectionMatrixGPU.M22;
			}

			return projectionMatrixGPU;
		}

I did the translationMatrix to follow my player and have him centered, forgot to mention that.

1 Like