Jump to content

  • Log In with Google      Sign In   
  • Create Account

derrace

Member Since 27 Sep 2012
Offline Last Active Dec 06 2012 12:20 AM

Topics I've Started

HLSL Pixel Shader that does palette swap

21 November 2012 - 09:40 PM

Hi there,

I have implemented a simple pixel shader which can replace a particular colour in a sprite with another colour.

It looks something like this:


sampler input : register(s0);
float4 PixelShaderFunction(float2 coords: TEXCOORD0) : COLOR0 
{  
    float4 colour = tex2D(input, coords); 
    if(colour.r == sourceColours[0].r &&
    colour.g == sourceColours[0].g &&
    colour.b == sourceColours[0].b) return targetColours[0];

    return colour; 
} 

What I would like to do is have the function take in 2 textures, a default table, and a lookup table (both same dimensions).
Grab the current pixel, and find the location XY (coords) of the matching RGB in the default table, and then substitute it with the colour found in the lookup table at XY.

I have figured how to pass the Textures from C# into the function, but I am not sure how to find the coords in the default table by matching the colour.

Could someone kindly assist?

Thanks in advance.

2D Camera, limiting bounds and zoom

27 September 2012 - 11:21 PM

Hi all,

I have been following this tutorial (http://www.david-gou...rolling-in-xna/) and I have build a 2D camera, but I am struggling to understand a particular behaviour of the camera when I am applying a zoom.

For the sake of simplicity, I will be using 1x and 2x zooms to describe my query,
my map size is 512x448 and at 1x, I am setting the res to 256x224, and 512x448 at 2x. I want to keep the amount of "objects" I can see consistent. I am using the zoom function instead of changing the scale in the draw method because I don't want to muck around with handling the scaling for the physics of the game.

graphics.PreferredBackBufferWidth = 256;
graphics.PreferredBackBufferHeight = 224;

public void LookAt(Vector2 position)
		{
			Position = position - ScreenCenter;
		}
In my update method, I have called LookAt and passed in the center position of my player object
Is the above code meant to move the camera, only if the the player is not in the center of the screen?

If I used the class without specifying a Limit object
cam = new Camera2d(GraphicsDevice.Viewport, ZoomScale);

Attached File  as1.png   24.57KB   31 downloads

From my understanding, David has implemented a Rectangle Limit object which I have used to specify my maximum map area along the lines:

cam = new Camera2d(GraphicsDevice.Viewport, ZoomScale) { Limits = new Rectangle(0, 0, (int)level.MapSize.X, (int)level.MapSize.Y) };

While I have managed to get it to work for 1x (+ panning)
Attached File  as2.png   22.02KB   34 downloads



Now, when I change it to 2X, I need to set the hard min limit for the Rect to (-128,-112) to ensure my camera displays exactly what the 1x displayed, only 2 times bigger.

else if (Zoom == 2.0f) //xxx hardcoded values for testing
					{
						pos.X = MathHelper.Clamp(pos.X, -128, Limits.Value.X + Limits.Value.Width - viewport.Width / Zoom);
						pos.Y = MathHelper.Clamp(pos.Y, -112, Limits.Value.Y + Limits.Value.Height - viewport.Height / Zoom);
					}

Attached File  as3.png   48.81KB   28 downloads

I have obtained the values by visually calculating the offset. My question is, why can't I set the limit's origin to (0,0)? Is the implementation in the tutorial wrong, or am I failing to understand how it works?



The code is as follows:

class Camera2d
	{
		public Vector2 ScreenCenter;
		public float Zoom = 1; //default
		private readonly Viewport viewport;
		private Vector2 pos;
		private Rectangle? limits;
		public Vector2 Position
		{
			get
			{
				return pos;
			}
			set
			{
				pos = value;
				if (Limits != null)
				{
					if (Zoom == 1.0f)
					{
						pos.X = MathHelper.Clamp(pos.X, Limits.Value.X, Limits.Value.X + Limits.Value.Width - viewport.Width);
						pos.Y = MathHelper.Clamp(pos.Y, Limits.Value.Y, Limits.Value.Y + Limits.Value.Height - viewport.Height);
					}
					else if (Zoom == 2.0f) //xxx hardcoded values for testing
					{
						pos.X = MathHelper.Clamp(pos.X, -128, Limits.Value.X + Limits.Value.Width - viewport.Width / Zoom);
						pos.Y = MathHelper.Clamp(pos.Y, -112, Limits.Value.Y + Limits.Value.Height - viewport.Height / Zoom);
					}
				}
			}
		}

		public Rectangle? Limits
		{
			get
			{
				return limits;
			}
			set
			{
				if (value != null)
				{
					// Assign limit but make sure it's always bigger than the viewport
					limits = new Rectangle
					{
						X = value.Value.X,
						Y = value.Value.Y,
						Width = System.Math.Max(viewport.Width, value.Value.Width),
						Height = System.Math.Max(viewport.Height, value.Value.Height)
					};
					// Validate camera position with new limit
					Position = Position;
				}
				else
				{
					limits = null;
				}
			}
		}
		public Camera2d(Viewport viewport, float zoom)
		{
			Zoom = zoom;
			this.viewport = viewport;
			ScreenCenter = new Vector2(viewport.Width / 2.0f, viewport.Height / 2.0f);					
		}
		public Matrix GetViewMatrix(Vector2 parallax)
		{
			return Matrix.CreateTranslation(new Vector3(-Position * parallax, 0.0f)) *
				   Matrix.CreateTranslation(new Vector3(-ScreenCenter, 0.0f)) *
				   Matrix.CreateScale(Zoom, Zoom, 1.0f) *
				   Matrix.CreateTranslation(new Vector3(ScreenCenter, 0.0f));
		}
		public void LookAt(Vector2 position)
		{
			Position = position - ScreenCenter;
		}
		public void Move(Vector2 displacement)
		{
			 Position += displacement;
		}
	}

Any inputs is much appreciated.

Thank you for your time.

ric

PARTNERS