Jump to content
How to Install Plugins ×

[NormalMap] Restore Z from X and Y


xrModder

Recommended Posts

Plugin to restore Z from X and Y.

 

Spoiler
// Name:		xy2xyz
// Submenu:		
// Author:		iOrange & xrModder
// Title:		xy2xyz
// Version:		0.1
// Desc:		Restore Z from X and Y
// Keywords:	
// URL:			
// Help:		

float Clamp(float v, float a, float b)
{
	return Math.Min(b, Math.Max(a, v));
}

void Render(Surface dst, Surface src, Rectangle rect)
{
	ColorBgra srcPixel, dstPixel = new ColorBgra();

	// Fill alpha channel with white
	dstPixel.A = 255;

	for (int y = rect.Top; y < rect.Bottom; ++y)
	{
		if (IsCancelRequested) return;

		for (int x = rect.Left; x < rect.Right; ++x)
		{
			srcPixel = src[x, y];

			// Convert R and G channel (0...255) to X and Y (-1...+1)
			float nx = (float)srcPixel.R / 127.5f - 1.0f;
			float ny = (float)srcPixel.G / 127.5f - 1.0f;

			// Calculate Z
			float nz = (float)Math.Sqrt(Clamp(1.0f - (nx * nx + ny * ny), 0.0f, 1.0f));

			// Keep R and G channel unchanged
			dstPixel.R = srcPixel.R;
			dstPixel.G = srcPixel.G;

			// Convert Z (0...1) to B channel (0...255)
			dstPixel.B = (byte)Clamp(nz * 127.5f + 127.5f, 0.0f, 255.0f);

			dst[x, y] = dstPixel;
		}
	}
}

 

xy2xyz.jpg

 

To install, copy xy2xyz.dll to the Effects folder.

xy2xyz.dll

 

Edited by xrModder
Putting things in order
  • Like 3
  • Upvote 1
  • You're a Smart Cookie! 1
Link to comment
Share on other sites

Hello @xrModder - congratulations on this plugin!

 

Can I suggest you change the location of it to Effects > Height Map? There are several tools which use this submenu, and I think yours will be a good fit.

Link to comment
Share on other sites

[RUS] Можно восстановить любой NormalMap, если в текстуре есть X и Y. К примеру X в NormalMap игры Survarium находится в альфа канале (так как при сжатии DXT5 (BC3) в зелёном канале практический нет потерь, а альфа канал остается без изменении).

 

[ENG] You can restore any NormalMap, if the texture contains X and Y. For example, X in the NormalMap of Survarium is in the alpha channel (since with DXT5 (BC3) compression in the green channel there is practically no loss, and the alpha channel remains unchanged).

 

Пример кода / Sample code:

 

			...

			float nx = (float)srcPixel.A / 127.5f - 1.0f;
			float ny = (float)srcPixel.G / 127.5f - 1.0f;

			float nz = (float)Math.Sqrt(Clamp(1.0f - (nx * nx + ny * ny), 0.0f, 1.0f));

			dstPixel.R = srcPixel.A;
			dstPixel.G = srcPixel.G;

			dstPixel.B = (byte)Clamp(nz * 127.5f + 127.5f, 0.0f, 255.0f);

			...

 

xy2xyz.jpg

Edited by xrModder
+ English text
Link to comment
Share on other sites

In English please @xrModder. It is acceptable to post a Google Translation :)

 

Link to comment
Share on other sites

Plugin update (v0.2):

  • added help;
  • ability to invert the X and Y axes.
Spoiler
// Name:		xy2xyz
// Submenu:		Advanced
// Author:		iOrange & xrModder
// Title:		xy2xyz
// Version:		0.2
// Desc:		Restore Z from X and Y (convert XY Normal Map to XYZ Normal Map)
// Keywords:	Normal Map
// URL:			https://forums.getpaint.net/profile/161661-xrmodder/
// Help:		The plugin restores the Z axis of the Normal Map from the existing X and Y axes. By default, in the original image, the X and Y axis are respectively in the R and G channels.

#region UICode
CheckboxControl InvertXAxis = false; // Invert X axis
CheckboxControl InvertYAxis = false; // Invert Y axis
#endregion

float Clamp(float v, float a, float b)
{
	return Math.Min(b, Math.Max(a, v));
}

void Render(Surface dst, Surface src, Rectangle rect)
{
	ColorBgra srcPixel, dstPixel = new ColorBgra();

	// Fill alpha channel with white
	dstPixel.A = 255;

	for (int y = rect.Top; y < rect.Bottom; ++y)
	{
		if (IsCancelRequested) return;

		for (int x = rect.Left; x < rect.Right; ++x)
		{
			srcPixel = src[x, y];

			// Invert X axis
			if (InvertXAxis)
			{
				srcPixel.R = (byte)(255 - srcPixel.R);
			}

			// Invert Y axis
			if (InvertYAxis)
			{
				srcPixel.G = (byte)(255 - srcPixel.G);
			}

			// Convert R and G channel (0...255) to X and Y (-1...+1)
			float nx = (float)srcPixel.R / 127.5f - 1.0f;
			float ny = (float)srcPixel.G / 127.5f - 1.0f;

			// Calculate Z
			float nz = (float)Math.Sqrt(Clamp(1.0f - (nx * nx + ny * ny), 0.0f, 1.0f));

			// Keep R and G channel unchanged
			dstPixel.R = srcPixel.R;
			dstPixel.G = srcPixel.G;

			// Convert Z (0...1) to B channel (0...255)
			dstPixel.B = (byte)Clamp(nz * 127.5f + 127.5f, 0.0f, 255.0f);

			dst[x, y] = dstPixel;
		}
	}
}

 

 

To install, copy xy2xyz.dll to the Effects folder.

xy2xyz.dll

Edited by xrModder
Putting things in order
Link to comment
Share on other sites

Plugin update (v0.3):

  • choice of channel X and Y.
Spoiler
// Name:		xy2xyz
// Submenu:		Advanced
// Author:		iOrange & xrModder
// Title:		xy2xyz
// Version:		0.3
// Desc:		Restore Z from X and Y (convert XY Normal Map to XYZ Normal Map)
// Keywords:	Normal Map
// URL:			https://forums.getpaint.net/profile/161661-xrmodder/
// Help:		The plugin restores the Z axis of the Normal Map from the existing X and Y axes. By default, in the original image, the X and Y axis are respectively in the R and G channels.

#region UICode
RadioButtonControl XAxisChannel = 0; // X axis channel|Red|Green|Blue|Alpha
RadioButtonControl YAxisChannel = 1; // Y axis channel|Red|Green|Blue|Alpha
CheckboxControl InvertXAxis = false; // Invert X axis
CheckboxControl InvertYAxis = false; // Invert Y axis
#endregion

float Clamp(float v, float a, float b)
{
	return Math.Min(b, Math.Max(a, v));
}

void Render(Surface dst, Surface src, Rectangle rect)
{
	ColorBgra srcPixel, dstPixel = new ColorBgra();

	// Fill alpha channel with white
	dstPixel.A = 255;

	for (int y = rect.Top; y < rect.Bottom; ++y)
	{
		if (IsCancelRequested) return;

		for (int x = rect.Left; x < rect.Right; ++x)
		{
			srcPixel = src[x, y];

			// X axis channel switch
			switch(XAxisChannel)
			{
				case 0:
					srcPixel.R = srcPixel.R;
					break;
				case 1:
					srcPixel.R = srcPixel.G;
					break;
				case 2:
					srcPixel.R = srcPixel.B;
					break;
				case 3:
					srcPixel.R = srcPixel.A;
					break;
			}

			// Y axis channel switch
			switch(YAxisChannel)
			{
				case 0:
					srcPixel.G = srcPixel.R;
					break;
				case 1:
					srcPixel.G = srcPixel.G;
					break;
				case 2:
					srcPixel.G = srcPixel.B;
					break;
				case 3:
					srcPixel.G = srcPixel.A;
					break;
			}

			// Invert X axis
			if (InvertXAxis)
			{
				srcPixel.R = (byte)(255 - srcPixel.R);
			}

			// Invert Y axis
			if (InvertYAxis)
			{
				srcPixel.G = (byte)(255 - srcPixel.G);
			}

			// Convert R and G channel (0...255) to X and Y (-1...+1)
			float nx = (float)srcPixel.R / 127.5f - 1.0f;
			float ny = (float)srcPixel.G / 127.5f - 1.0f;

			// Calculate Z
			float nz = (float)Math.Sqrt(Clamp(1.0f - (nx * nx + ny * ny), 0.0f, 1.0f));

			// Keep R and G channel unchanged
			dstPixel.R = srcPixel.R;
			dstPixel.G = srcPixel.G;

			// Convert Z (0...1) to B channel (0...255)
			dstPixel.B = (byte)Clamp(nz * 127.5f + 127.5f, 0.0f, 255.0f);

			dst[x, y] = dstPixel;
		}
	}
}

 

To install, copy xy2xyz.dll to the Effects folder.

xy2xyz.dll

Link to comment
Share on other sites

  • 1 year later...
Posted (edited)

Plugin update (v0.4):

  • code fix.
Spoiler
// Name:		xy2xyz
// Submenu:		
// Author:		iOrange & xrModder
// Title:		xy2xyz
// Version:		0.4
// Desc:		Restore Z from X and Y (convert XY Normal Map to XYZ Normal Map)
// Keywords:	Normal Map
// URL:			https://forums.getpaint.net/profile/161661-xrmodder/
// Help:		The plugin restores the Z axis of the Normal Map from the existing X and Y axes.

#region UICode
ListBoxControl		XAxisChannel	= 0;		// X axis channel|Red|Green|Blue|Alpha
ListBoxControl		YAxisChannel	= 1;		// Y axis channel|Red|Green|Blue|Alpha
CheckboxControl		FlipXAxis		= false;	// Flip X axis
CheckboxControl		FlipYAxis		= false;	// Flip Y axis
#endregion

float Clamp(float v, float a, float b)
{
	return Math.Min(Math.Max(a, v), b);
}

void Render(Surface dst, Surface src, Rectangle rect)
{
	ColorBgra srcPixel, dstPixel = new ColorBgra();

	// Fill alpha channel with white
	dstPixel.A = 255;

	for (int y = rect.Top; y < rect.Bottom; y++)
	{
		if (IsCancelRequested) return;

		for (int x = rect.Left; x < rect.Right; x++)
		{
			srcPixel = src[x, y];

			// X axis channel switch
			switch (XAxisChannel)
			{
				case 0: srcPixel.R = srcPixel.R; break;
				case 1: srcPixel.R = srcPixel.G; break;
				case 2: srcPixel.R = srcPixel.B; break;
				case 3: srcPixel.R = srcPixel.A; break;
			}

			// Y axis channel switch
			switch (YAxisChannel)
			{
				case 0: srcPixel.G = srcPixel.R; break;
				case 1: srcPixel.G = srcPixel.G; break;
				case 2: srcPixel.G = srcPixel.B; break;
				case 3: srcPixel.G = srcPixel.A; break;
			}

			// Flip X axis
			if (FlipXAxis) srcPixel.R = (byte)(255 - srcPixel.R);

			// Flip Y axis
			if (FlipYAxis) srcPixel.G = (byte)(255 - srcPixel.G);

			// Convert R and G channel (0...255) to X and Y (-1...1)
			float nx = (float)srcPixel.R / 127.5f - 1.0f;
			float ny = (float)srcPixel.G / 127.5f - 1.0f;

			// Calculate Z
			float nz = (float)Math.Sqrt(Clamp(1.0f - (nx * nx + ny * ny), 0.0f, 1.0f));

			// Keep R and G channel unchanged
			dstPixel.R = srcPixel.R;
			dstPixel.G = srcPixel.G;

			// Convert Z (0...1) to B channel (0...255)
			dstPixel.B = (byte)Clamp(nz * 127.0f + 128.0f, 0.0f, 255.0f);

			dst[x, y] = dstPixel;
		}
	}
}

 

To install, copy xy2xyz.dll to the Effects folder.

xy2xyz.dll

Edited by xrModder
  • Like 2
  • Upvote 2
  • You're a Smart Cookie! 1
Link to comment
Share on other sites

This is awesome! I used to have to do these kind of things manually, and the option to pick what channels to use from the source image are very useful for nonstandard normalmap formats.

 

It'd be nice if there was also an option to copy an existing Z channel from a layer rather than generate it, this would make this also a useful tool for converting normalmaps between different engines (since they often have different/inverted channels) while keeping Z 1:1 the same, and options to pick which channels to use for the output, although that might be better suited as its own tool.

Link to comment
Share on other sites

Plugin update (v0.5):

  • code fix.
Spoiler
// Name:		xy2xyz
// Submenu:		
// Author:		iOrange & xrModder
// Title:		xy2xyz
// Version:		0.5
// Desc:		Restore Z from X and Y (convert XY Normal Map to XYZ Normal Map)
// Keywords:	Normal Map
// URL:			https://forums.getpaint.net/profile/161661-xrmodder/
// Help:		The plugin restores the Z axis of the Normal Map from the existing X and Y axes.

#region UICode
ListBoxControl		XAxisChannel	= 0;		// X axis channel|Red|Green|Blue|Alpha
ListBoxControl		YAxisChannel	= 1;		// Y axis channel|Red|Green|Blue|Alpha
CheckboxControl		FlipXAxis		= false;	// Flip X axis
CheckboxControl		FlipYAxis		= false;	// Flip Y axis
#endregion

float Clamp(float v, float a, float b)
{
	return Math.Min(Math.Max(a, v), b);
}

void Render(Surface dst, Surface src, Rectangle rect)
{
	ColorBgra srcPixel, dstPixel = new ColorBgra();

	// Fill alpha channel with white
	dstPixel.A = 255;

	for (int y = rect.Top; y < rect.Bottom; y++)
	{
		if (IsCancelRequested) return;

		for (int x = rect.Left; x < rect.Right; x++)
		{
			srcPixel = src[x, y];

			// X axis channel switch
			switch (XAxisChannel)
			{
				case 0: dstPixel.R = srcPixel.R; break;
				case 1: dstPixel.R = srcPixel.G; break;
				case 2: dstPixel.R = srcPixel.B; break;
				case 3: dstPixel.R = srcPixel.A; break;
			}

			// Y axis channel switch
			switch (YAxisChannel)
			{
				case 0: dstPixel.G = srcPixel.R; break;
				case 1: dstPixel.G = srcPixel.G; break;
				case 2: dstPixel.G = srcPixel.B; break;
				case 3: dstPixel.G = srcPixel.A; break;
			}

			// Flip X axis
			if (FlipXAxis) dstPixel.R = (byte)(255 - dstPixel.R);

			// Flip Y axis
			if (FlipYAxis) dstPixel.G = (byte)(255 - dstPixel.G);

			// Convert R and G channel (0...255) to X and Y (-1...1)
			float nx = (float)dstPixel.R / 127.5f - 1.0f;
			float ny = (float)dstPixel.G / 127.5f - 1.0f;

			// Calculate Z
			float nz = (float)Math.Sqrt(Clamp(1.0f - (nx * nx + ny * ny), 0.0f, 1.0f));

			// Convert Z (0...1) to B channel (0...255)
			dstPixel.B = (byte)Clamp(nz * 127.0f + 128.0f, 0.0f, 255.0f);

			dst[x, y] = dstPixel;
		}
	}
}

 

To install, copy xy2xyz.dll to the Effects folder.

xy2xyz.dll

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...