xrModder Posted November 24, 2020 Share Posted November 24, 2020 (edited) 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; } } } To install, copy xy2xyz.dll to the Effects folder. xy2xyz.dll Edited November 19, 2021 by xrModder Putting things in order 3 1 1 Quote Link to comment Share on other sites More sharing options...
ReMake Posted November 24, 2020 Share Posted November 24, 2020 Show us the result of the plugin (the original image, the image with Normal Map and image after applying your effect). Quote Link to comment Share on other sites More sharing options...
xrModder Posted November 24, 2020 Author Share Posted November 24, 2020 (edited) 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 November 24, 2020 by xrModder Quote Link to comment Share on other sites More sharing options...
Ego Eram Reputo Posted November 25, 2020 Share Posted November 25, 2020 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. Quote 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 Link to comment Share on other sites More sharing options...
xrModder Posted November 25, 2020 Author Share Posted November 25, 2020 (edited) [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 November 26, 2020 by xrModder + English text Quote Link to comment Share on other sites More sharing options...
Ego Eram Reputo Posted November 26, 2020 Share Posted November 26, 2020 In English please @xrModder. It is acceptable to post a Google Translation Quote 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 Link to comment Share on other sites More sharing options...
xrModder Posted November 26, 2020 Author Share Posted November 26, 2020 1 hour ago, Ego Eram Reputo said: In English please @xrModder. It is acceptable to post a Google Translation Added. 1 Quote Link to comment Share on other sites More sharing options...
xrModder Posted November 19, 2021 Author Share Posted November 19, 2021 (edited) 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 November 23, 2021 by xrModder Putting things in order Quote Link to comment Share on other sites More sharing options...
xrModder Posted November 23, 2021 Author Share Posted November 23, 2021 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 Quote Link to comment Share on other sites More sharing options...
xrModder Posted March 22 Author Share Posted March 22 (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 March 22 by xrModder 2 2 1 Quote Link to comment Share on other sites More sharing options...
Kokonut Posted March 29 Share Posted March 29 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. Quote Link to comment Share on other sites More sharing options...
xrModder Posted April 1 Author Share Posted April 1 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 Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.