Ego Eram Reputo Posted September 11, 2022 Share Posted September 11, 2022 Here's a plugin I've been tinkering with for years. It makes simple maps at the touch of a few buttons. If you want a specifically shaped map, you can use transparency to mask the land & sea. Once installed, find the plugin in the Effects >> Render submenu. Please note: The code is not all my own. I'll ask for permission to post it. Comments &/or critiques welcomed ReliefMapGenerator.dll 7 1 1 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...
Ego Eram Reputo Posted September 11, 2022 Author Share Posted September 11, 2022 I just remembered @John Stewien's plugins are open source. Yay, because I lifted the ToAngle code from him. Here's the source Spoiler // Name: Relief Map Generator // Submenu: Render // Author: Scott Stringer aka Ego Eram Reputo // Title: Relief Map Generator // Version: 1.3 // Desc: Renders topographical landscapes // Keywords: Map topographical topography land sea mountains // URL: // Help: #region UICode IntSliderControl Amount1 = 250; // [1,1000,5] Scale IntSliderControl Amount3 = 30; // [10,50,5] Detail IntSliderControl Amount4 = 50; // [1,200,2] Elevation IntSliderControl Amount5 = 30; // [1,100,2] Land Mass IntSliderControl Mountains = 40; // [1,80,5] Mountains IntSliderControl ToAngleStrength = 5; // [3,20,5] Smoothing IntSliderControl Amount6 = 0; // [-180,180,2] Hue Adjustment IntSliderControl Amount7 = 0; // [-100,100,3] Saturation Adjustment IntSliderControl Amount8 = 0; // [-100,100,5] Lightness Adjustment CheckboxControl grayScale = false; // Grayscale CheckboxControl respectAlpha = true; // R-E-S-P-E-C-T Alpha (find out what it means to me) ReseedButtonControl Amount9 = 0; // Reseed #endregion // Working surface Surface wrk = null; // Auxillary surface Surface aux = null; // Setup for Overlay blending op private BinaryPixelOp overlayOp = LayerBlendModeUtil.CreateCompositionOp(LayerBlendMode.Overlay); // Setup for Hue, Saturation & Lightness ops private UnaryPixelOps.HueSaturationLightness saturationOp; protected override void OnDispose(bool disposing) { if (disposing) { // Release any surfaces or effects you've created wrk?.Dispose(); wrk = null; aux?.Dispose(); aux = null; } base.OnDispose(disposing); } // This single-threaded function is called after the UI changes and before the Render function is called // The purpose is to prepare anything you'll need in the Render function // Don't render to the dst surface in PreRender (BoltBait 18 Sept 2021) void PreRender(Surface dst, Surface src) { Rectangle selection = EnvironmentParameters.SelectionBounds; EnvironmentParameters.GetSelectionAsPdnRegion(); saturationOp = new UnaryPixelOps.HueSaturationLightness(Amount6, Amount7+100, Amount8); try { r = new Random(Convert.ToInt32(Amount9)); r1 = r.Next(1000, 10000); r2 = r.Next(100000, 1000000); r3 = r.Next(1000000000, 2000000000); } catch { } if (wrk == null) { wrk = new Surface(src.Size); } if (aux == null) { aux = new Surface(src.Size); } // Fill the aux surface with desaturated value noise (i.e. grayscale) for (int y = aux.Bounds.Top; y < aux.Bounds.Bottom; y++) { if (IsCancelRequested) return; for (int x = aux.Bounds.Left; x < aux.Bounds.Right; x++) { int c = (int)fBm(x, y); // get noise value from fractal brownian motion (fBm) routine int d = (int)(c / 3.6); // normalize into range from 0 to 255 i.e 256 colors. //int d = (int)(278-(9* Math.Sqrt(900-c))); if (d < 0) d = 0; if (respectAlpha) { // use Alpha of source pixel to lower the height value. ColorBgra SrcPixel = src[x, y]; d *= SrcPixel.A; d /= 255; } aux[x, y] = ColorBgra.FromBgra((byte)(d), (byte)(d), (byte)(d), 0xff); } } // run ToAngle on the aux surface and store the result in wrk int radius = (int)(ToAngleStrength / (Amount3*0.09)); int[] xdx = new int[2]; int[] ydy = new int[2]; for (int y = aux.Bounds.Top; y < aux.Bounds.Bottom; y++) { for (int x = aux.Bounds.Left ; x < aux.Bounds.Right; x++) { ColorBgra CurrentPixel = aux[x, y]; if (CurrentPixel.B < 81-Mountains+40) // don't render mountains below this level (default = sea level). Could have used any of BGR as value is grayscale. { wrk[x, y] = ColorBgra.FromBgra(0,0,0,0); } else{ float xdiffR = 0f; float xdiffG = 0f; float xdiffB = 0f; float ydiffR = 0f; float ydiffG = 0f; float ydiffB = 0f; for (int dx = 0; dx <= radius; ++dx) { xdx[0] = x - dx; if (xdx[0] < aux.Bounds.Left) { xdx[0] = aux.Bounds.Left + aux.Bounds.Left - xdx[0]; } xdx[1] = x + dx; if (xdx[1] >= aux.Bounds.Right) { xdx[1] = aux.Bounds.Right - 2 - xdx[1] + aux.Bounds.Right; } for (int dy = 0; dy <= radius; ++dy) { ydy[0] = y - dy; if (ydy[0] < aux.Bounds.Top) { ydy[0] = aux.Bounds.Top + aux.Bounds.Top - ydy[0]; } ydy[1] = y + dy; if (ydy[1] >= aux.Bounds.Bottom) { ydy[1] = aux.Bounds.Bottom - 2 - ydy[1] + aux.Bounds.Bottom; } xdiffR += aux[xdx[0], ydy[0]].R; xdiffR -= aux[xdx[1], ydy[0]].R; xdiffG += aux[xdx[0], ydy[0]].G; xdiffG -= aux[xdx[1], ydy[0]].G; xdiffB += aux[xdx[0], ydy[0]].B; xdiffB -= aux[xdx[1], ydy[0]].B; if (dy != 0) { xdiffR += aux[xdx[0], ydy[1]].R; xdiffR -= aux[xdx[1], ydy[1]].R; xdiffG += aux[xdx[0], ydy[1]].G; xdiffG -= aux[xdx[1], ydy[1]].G; xdiffB += aux[xdx[0], ydy[1]].B; xdiffB -= aux[xdx[1], ydy[1]].B; } ydiffR += aux[xdx[0], ydy[0]].R; ydiffR -= aux[xdx[0], ydy[1]].R; ydiffG += aux[xdx[0], ydy[0]].G; ydiffG -= aux[xdx[0], ydy[1]].G; ydiffB += aux[xdx[0], ydy[0]].B; ydiffB -= aux[xdx[0], ydy[1]].B; if (dx != 0) { ydiffR += aux[xdx[1], ydy[0]].R; ydiffR -= aux[xdx[1], ydy[1]].R; ydiffG += aux[xdx[1], ydy[0]].G; ydiffG -= aux[xdx[1], ydy[1]].G; ydiffB += aux[xdx[1], ydy[0]].B; ydiffB -= aux[xdx[1], ydy[1]].B; } } } CurrentPixel.R = (byte)(255 * Math.Abs(Math.Atan2(ydiffR, xdiffR) / Math.PI)); CurrentPixel.G = (byte)(255 * Math.Abs(Math.Atan2(ydiffG, xdiffG) / Math.PI)); CurrentPixel.B = (byte)(255 * Math.Abs(Math.Atan2(ydiffB, xdiffB) / Math.PI)); CurrentPixel.A = (byte)(aux[x,y].G-(81-Mountains)*1.5); wrk[x, y] = CurrentPixel; } } } // Recolor the aux surface using the grayscale value as an index into the palette. if (!grayScale){ int d2=0; for (int y = aux.Bounds.Top; y < aux.Bounds.Bottom; y++) { if (IsCancelRequested) return; for (int x = aux.Bounds.Left; x < aux.Bounds.Right; x++) { ColorBgra CurrentPixel = aux[x,y]; d2 = CurrentPixel.R; d2 *= 3; // byte offset in palette array = ElevationPalette aux[x, y] = saturationOp.Apply(ColorBgra.FromBgra(ElevationPalette[d2], ElevationPalette[++d2], ElevationPalette[++d2], 0xff)); } } } } // Here is the main multi-threaded render function // The dst canvas is broken up into rectangles and // your job is to write to each pixel of that rectangle void Render(Surface dst, Surface src, Rectangle rect) { // wrk has the topography in grayscale & alpha // aux has coloured landscape // Overlay Blend the wrk surface and the aux surface to the dst surface overlayOp.Apply(dst, aux ,wrk, rect); // If you want to see the individual layers, uncomment the following //for (int y = rect.Top; y < rect.Bottom; y++) //{ // if (IsCancelRequested) return; // for (int x = rect.Left; x < rect.Right; x++) // { // ColorBgra SrcPixel = src[x, y]; // ColorBgra WrkPixel = wrk[x, y]; // ColorBgra AuxPixel = aux[x, y]; // ColorBgra DstPixel = dst[x, y]; // // dst[x, y] = CurrentPixel; // } //} } // fBm = Fractal Brownian motion - a triple Value Noise routine. double fBm(int x, int y) { int HeightScale = 900; // was 1024; double k = (PerlinNoise2d(x, y) * HeightScale) * 12 / 15; k += (PerlinNoise2d(x + Amount9, y + Amount9) * HeightScale) * 2 / 15; // adds a bit more Noise, with less weighting. k += (int)(PerlinNoise2d(x + Amount9 / 4, y + Amount9 / 4) * HeightScale) / 15; // adds a tiny bit more, with even less weighting. return k; } static Random r = new Random(); int r1 = r.Next(1000, 10000); int r2 = r.Next(100000, 1000000); int r3 = r.Next(1000000000, 2000000000); double PerlinNoise2d(int x, int y) { double total = 0.0; double frequency = 0.075f / Math.Sqrt(Amount1); // was .015 smaller values = larger landmass double persistence = (32 + Amount3 / 2) / 100.0; // was .65 aka smoothness smaller values = finer detail double octaves = 8; // was 8; // USER ADJUSTABLE double amplitude = Amount4 / 60.0; // was 1 use larger values to eliminate mountain 'rings' double cloudCoverage = -2.0 + (Math.Sqrt(Math.Sqrt(Amount5))); // was 0 aka amount of land vs sea double cloudDensity = 0.6666666; //(Amount5 / 30.0) - 1; // was 1 aka feature density for (int lcv = 0; lcv < octaves; lcv++) { total += Smooth(x * frequency, y * frequency) * amplitude; frequency *= 2; amplitude *= persistence; } total += cloudCoverage; total *= cloudDensity; if (total > 1) total = 1 - (total - 1); // creating a downward slope from highest points total = (total < 0) ? 0 : total; return total; } double Smooth(double x, double y) { double n1 = Noise((int)x, (int)y); double n2 = Noise((int)x + 1, (int)y); double n3 = Noise((int)x, (int)y + 1); double n4 = Noise((int)x + 1, (int)y + 1); double i1 = Interpolate(n1, n2, x - (int)x, 1); double i2 = Interpolate(n3, n4, x - (int)x, 1); return Interpolate(i1, i2, y - (int)y, 1); } double Noise(int x, int y) { int n = x + y * 57; //smoothfactor; n = (n << 13) ^ (n-3); // was ^ n return (1.0 - ((n * (n * n * r1 + r2) + r3) & 0x6fffffff) / 1073741824.0); // was 0x7fffffff } double Interpolate(double x, double y, double a, int iType) { double iVal, val; switch (iType) { case 0: // Linear_Interpolate iVal = x * (1 - a) + y * a; break; case 1: // Cosine_Interpolate val = (1 - Math.Cos(a * Math.PI)) * .5; iVal = x * (1 - val) + y * val; break; default: iVal = 0; break; } return iVal; } // Array for colorization = 32x BGR triplets byte[] ElevationPalette = { // Sub-tropical coloring // deep blue = sea // source: 2022 Elevation palette.pdn & 2022 Elevation palette.csv 214,089,049, 214,091,049, 214,096,051, 215,100,054, 215,103,056, 216,109,060, 217,113,061, 217,117,064, 218,123,066, 219,127,069, 219,131,071, 219,136,073, 219,140,074, 220,142,077, 220,147,080, 221,153,082, 222,157,085, 222,161,086, 222,166,089, 224,170,092, 224,174,095, 224,179,097, 225,182,099, 225,185,100, 226,189,102, 154,168,079, 020,079,026, 020,079,026, 020,079,026, 021,080,026, 021,080,026, 020,081,026, 020,081,026, 021,082,027, 021,082,027, 021,082,027, 021,083,027, 021,083,027, 021,085,027, 021,085,027, 021,086,027, 021,086,027, 021,086,027, 021,088,028, 022,089,028, 021,090,028, 021,090,028, 021,090,028, 021,090,028, 021,090,028, 022,092,028, 022,092,028, 022,094,029, 022,094,029, 022,094,029, 022,094,029, 022,094,029, 022,095,031, 022,095,031, 023,096,032, 023,096,032, 023,098,032, 022,100,033, 022,100,033, 022,100,033, 022,100,033, 023,101,034, 023,102,036, 023,102,036, 023,102,036, 023,102,038, 024,104,039, 024,104,039, 024,105,040, 024,106,041, 024,107,041, 024,109,043, 024,109,043, 024,109,043, 025,109,045, 024,110,046, 024,111,047, 024,111,047, 024,111,047, 025,112,047, 025,113,047, 025,113,047, 025,113,048, 025,113,048, 025,114,049, 025,114,050, 025,114,050, 025,114,050, 025,114,050, 025,114,050, 025,114,050, 025,114,050, 025,114,050, 026,116,051, 026,117,052, 026,118,053, 026,118,053, 026,118,053, 026,118,053, 026,118,053, 026,118,053, 026,118,053, 026,119,055, 026,120,056, 026,121,057, 026,121,057, 027,121,058, 026,121,060, 026,123,060, 026,123,060, 026,123,060, 027,123,063, 027,123,066, 028,126,068, 028,126,068, 027,125,070, 028,127,073, 028,128,074, 028,130,076, 028,130,076, 028,129,080, 028,130,084, 029,132,086, 029,132,088, 029,132,088, 029,132,090, 030,133,094, 030,135,097, 030,135,097, 030,135,099, 030,135,100, 031,137,104, 030,137,105, 030,137,105, 031,139,109, 032,140,113, 033,140,113, 033,140,114, 035,143,116, 042,149,122, 047,153,126, 050,155,129, 050,155,129, 055,159,132, 062,165,139, 065,167,140, 068,168,142, 068,168,142, 076,173,148, 084,178,153, 088,181,156, 088,181,156, 091,182,157, 100,187,164, 107,193,168, 110,194,170, 105,211,200, 113,214,209, 122,214,218, 126,213,221, 127,211,225, 124,209,224, 123,206,223, 121,205,223, 119,203,223, 117,201,224, 115,199,222, 114,197,223, 113,194,222, 112,192,222, 109,190,221, 107,188,220, 104,186,219, 105,186,220, 102,181,220, 100,180,219, 100,178,219, 098,177,220, 095,173,219, 094,173,219, 092,169,219, 091,167,219, 090,164,218, 089,162,215, 088,158,212, 089,155,212, 089,153,209, 088,152,206, 088,148,206, 089,144,204, 087,141,200, 087,139,198, 088,138,196, 086,133,194, 087,130,193, 086,126,192, 086,125,189, 086,121,189, 086,118,186, 086,117,186, 086,113,182, 086,111,180, 086,109,178, 086,106,177, 092,108,173, 099,112,170, 106,115,167, 113,116,166, 120,121,162, 129,126,158, 135,129,154, 141,131,153, 149,132,149, 153,135,145, 159,138,143, 163,142,148, 169,151,155, 173,155,159, 179,162,166, 184,168,172, 188,174,179, 192,179,185, 198,186,190, 202,192,194, 206,198,200, 212,205,206, 216,209,211, 221,216,217, 227,223,224, 231,230,230, 235,235,235, 237,237,237, 237,237,237, 237,237,237, 237,237,237, 237,237,237, 237,237,237, 237,237,237, 237,237,237, 237,237,237, 230,230,230, 219,219,219, 220,220,220, 224,224,224, 229,229,229, 233,233,233, 234,234,234, 234,234,234, 233,233,233, 233,233,233, 233,233,233, }; 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...
Red ochre Posted September 11, 2022 Share Posted September 11, 2022 Many thanks for sharing the well annotated code! - The comments make it much easier to see what's going on. Thanks to Aretha too.🙂 1 Quote Red ochre Plugin pack.............. Diabolical Drawings ................Real Paintings Link to comment Share on other sites More sharing options...
lynxster4 Posted September 11, 2022 Share Posted September 11, 2022 This is really cool @Ego Eram Reputo. Mine doesn't look quite like yours, but....welcome to Lynx Island. 😄 3 1 Quote My Art Gallery | My Shape Packs | ShapeMaker Mini Tut | Air Bubble Stained Glass Chrome Text with Reflections | Porcelain Text w/ Variegated Coloring | Realistic Knit PatternOpalescent Stained Glass | Frosted Snowman Cookie | Leather Texture | Plastic Text | Silk Embroidery Visit my Personal Website "Never, ever lose your sense of humor - you'll live longer" Link to comment Share on other sites More sharing options...
Ego Eram Reputo Posted September 11, 2022 Author Share Posted September 11, 2022 👍 To get a more organic coastline, use dents at a largish scale to distort the mask outline, then run Gaussian blur to smooth it out. 1 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...
lynxster4 Posted September 11, 2022 Share Posted September 11, 2022 @Ego Eram Reputo Don't mean to sound dumb here but I'm having a brunette moment. 😆 I haven't used an alpha mask in such a long time, I forget. Could you please outline some steps to achieve your beautiful coastline? Then I'll probably say 'aha'. Thank you! Quote My Art Gallery | My Shape Packs | ShapeMaker Mini Tut | Air Bubble Stained Glass Chrome Text with Reflections | Porcelain Text w/ Variegated Coloring | Realistic Knit PatternOpalescent Stained Glass | Frosted Snowman Cookie | Leather Texture | Plastic Text | Silk Embroidery Visit my Personal Website "Never, ever lose your sense of humor - you'll live longer" Link to comment Share on other sites More sharing options...
lynxster4 Posted September 12, 2022 Share Posted September 12, 2022 Okay EER, I 'aha'd' myself. I was making it way more difficult than it needed to be. I figured it out with your tips, from 19 hours ago, and have a nice organic coastline with a smoother transition from the light blue to the darker blue ocean. Thanks! 😂 Quote My Art Gallery | My Shape Packs | ShapeMaker Mini Tut | Air Bubble Stained Glass Chrome Text with Reflections | Porcelain Text w/ Variegated Coloring | Realistic Knit PatternOpalescent Stained Glass | Frosted Snowman Cookie | Leather Texture | Plastic Text | Silk Embroidery Visit my Personal Website "Never, ever lose your sense of humor - you'll live longer" Link to comment Share on other sites More sharing options...
Ego Eram Reputo Posted September 14, 2022 Author Share Posted September 14, 2022 For those wondering about this bit.... On 9/12/2022 at 10:02 AM, Ego Eram Reputo said: To get a more organic coastline, use dents at a largish scale to distort the mask outline, then run Gaussian blur to smooth it out. ....if you're using a shape as a map-mask, soften the edge to get a more organic coastline. Otherwise the falloff from land to sea will be too abrupt. In the images below, notice how the hard Eastern edge of the shape produces a cookie-cutter coast. The softened Western side of the shape produces a more meandering coastline with a much more believable slope from the highlands down to the sea (and also light blue shallows). >>> The deeper the alpha blurring is, the gentler the taper from land to sea. See? 3 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...
TrevorOutlaw Posted September 18, 2022 Share Posted September 18, 2022 This would be a fun plug-in to generate old world map like The Lord of the Rings or Avatar: The Last Airbender. 1 Quote Link to comment Share on other sites More sharing options...
Ego Eram Reputo Posted September 19, 2022 Author Share Posted September 19, 2022 16 hours ago, TrevorOutlaw said: This would be a fun plug-in to generate old world map like The Lord of the Rings or Avatar: The Last Airbender. Run the plugin with a Saturation of -75 and increase the Lightness to 15. Then run the Sepia Adjustment & you're half way there! With a little tweaking, https://postimg.cc/hXnL94F4 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...
Kronos Posted December 10, 2022 Share Posted December 10, 2022 I am not sure how you made the swoosh. I have been doing everything I could think of. I am making my own map (world) and need the shapes I made for land to look better. Quote Link to comment Share on other sites More sharing options...
Ego Eram Reputo Posted October 8, 2023 Author Share Posted October 8, 2023 Time for this plugin to be released! Yay!! 2 3 1 1 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...
BoltBait Posted October 8, 2023 Share Posted October 8, 2023 Waiting for a slow news day so you could dominate the coverage? Smart! 1 1 Quote Download: BoltBait's Plugin Pack | CodeLab | and a Free Computer Dominos Game Link to comment Share on other sites More sharing options...
AndrewDavid Posted October 13, 2023 Share Posted October 13, 2023 @Ego Eram Reputo I wish all the authors would post their source code. Thanks for the lesson. Will the real RMG please stand up? Quote Link to comment Share on other sites More sharing options...
Holibken Posted July 26 Share Posted July 26 Is there a way to make mountain ranges on set lines? Quote Link to comment Share on other sites More sharing options...
Ego Eram Reputo Posted July 27 Author Share Posted July 27 Not with any great accuracy, but you can use Alpha blurring (see post https://forums.getpaint.net/topic/120809-relief-map-generator/?do=findComment&comment=600506) Start with a layer filled with a semi-transparent color. Overlay an opaque blurred shape where you want the mountains. Run RMG and pump the reseed button until you get something you like. 1 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...
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.