# [NormalMap] Restore Z from X and Y

## Recommended Posts

Plugin to restore Z from X and Y.

Spoiler
```// Name:		xy2xyz
// 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;
}
}
}```

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

Edited by xrModder
Putting things in order
• 2
• 1
• 1
##### Share on other sites

18 minutes ago, ReMake said:

Show us the result of the plugin (the original image, the image with Normal Map and image after applying your effect). Edited by xrModder
##### 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. ebook: Mastering Paint.NET | resources: Plugin Index | Stereogram Tut | proud supporter of Codelab
plugins: EER's Plugin Pack | Planetoid | StickMan | WhichSymbol+ | Dr Scott's Markup Renderer | CSV Filetype | dwarf horde plugins: Plugin Browser | ShapeMaker

##### 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);

...```

Edited by xrModder
+ English text
##### Share on other sites

In English please @xrModder. It is acceptable to post a Google Translation  ebook: Mastering Paint.NET | resources: Plugin Index | Stereogram Tut | proud supporter of Codelab
plugins: EER's Plugin Pack | Planetoid | StickMan | WhichSymbol+ | Dr Scott's Markup Renderer | CSV Filetype | dwarf horde plugins: Plugin Browser | ShapeMaker

##### Share on other sites

1 hour ago, Ego Eram Reputo said:

In English please @xrModder. It is acceptable to post a Google Translation • 1
##### Share on other sites

Plugin update (v0.2):

• ability to invert the X and Y axes.
Spoiler
```// Name:		xy2xyz
// 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.

Edited by xrModder
Putting things in order
##### Share on other sites

Plugin update (v0.3):

• choice of channel X and Y.
Spoiler
```// Name:		xy2xyz
// 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.

## Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account. ×   Pasted as rich text.   Paste as plain text instead

Only 75 emoji are allowed.

×   Your previous content has been restored.   Clear editor

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

×
×