@@ -262,6 +262,54 @@ public static RawTextureBuffer GenerateConcrete(int width,
262262 return buffer ;
263263 }
264264
265+ /// <summary>
266+ /// Generates realistic architectural concrete with fine grit, aggregate pores, and no topographic worm-rings.
267+ /// </summary>
268+ /// <param name="width">The width.</param>
269+ /// <param name="height">The height.</param>
270+ /// <param name="noiseGenInstance">The noise gen instance.</param>
271+ /// <param name="baseTone">The base tone.</param>
272+ /// <param name="gritSpread">The grit spread.</param>
273+ /// <returns>A raw texture buffer containing the generated porous concrete texture.</returns>
274+ [ MethodImpl ( MethodImplOptions . AggressiveOptimization ) ]
275+ public static RawTextureBuffer GenerateConcretePorous (
276+ int width ,
277+ int height ,
278+ object noiseGenInstance ,
279+ byte baseTone = 140 ,
280+ byte gritSpread = 22 )
281+ {
282+ var buffer = new RawTextureBuffer ( width , height ) ;
283+ var span = buffer . AsSpan ( ) ;
284+ dynamic noiseGen = noiseGenInstance ;
285+
286+ var idx = 0 ;
287+ for ( var y = 0 ; y < height ; y ++ )
288+ {
289+ for ( var x = 0 ; x < width ; x ++ )
290+ {
291+ // 1. Broad smooth macro patches
292+ var macro = ( double ) noiseGen . SmoothNoise ( x / 48.0 , y / 48.0 ) ;
293+
294+ // 2. Medium concrete aggregate speckles
295+ var mid = ( double ) noiseGen . SmoothNoise ( x / 12.0 , y / 12.0 ) * 0.4 ;
296+
297+ // 3. Fine surface pores (high frequency)
298+ var micro = ( ( double ) noiseGen . GetNoise ( x , y ) - 0.5 ) * 0.35 ;
299+
300+ var val = Math . Clamp ( macro * 0.6 + mid + micro , 0.0 , 1.0 ) ;
301+ var colorVal = ( byte ) Math . Clamp ( baseTone - gritSpread + ( int ) ( gritSpread * 2.0 * val ) , 0 , 255 ) ;
302+
303+ span [ idx ++ ] = colorVal ; // B
304+ span [ idx ++ ] = colorVal ; // G
305+ span [ idx ++ ] = colorVal ; // R
306+ span [ idx ++ ] = 255 ; // A
307+ }
308+ }
309+
310+ return buffer ;
311+ }
312+
265313 /// <summary>
266314 /// Generates interlocking woven canvas fabric textures with deterministic line cutoffs.
267315 /// </summary>
@@ -620,6 +668,99 @@ public static RawTextureBuffer GenerateCellular(int width,
620668 return buffer ;
621669 }
622670
671+ /// <summary>
672+ /// Generates realistic flat-top cobblestones with defined grout lines instead of spherical bubbles.
673+ /// </summary>
674+ /// <param name="width">The width.</param>
675+ /// <param name="height">The height.</param>
676+ /// <param name="cellSize">Size of the cell.</param>
677+ /// <param name="stoneR">The stone r.</param>
678+ /// <param name="stoneG">The stone g.</param>
679+ /// <param name="stoneB">The stone b.</param>
680+ /// <param name="groutR">The grout r.</param>
681+ /// <param name="groutG">The grout g.</param>
682+ /// <param name="groutB">The grout b.</param>
683+ /// <returns>The generated raw texture buffer.</returns>
684+ [ MethodImpl ( MethodImplOptions . AggressiveOptimization ) ]
685+ public static RawTextureBuffer GenerateCobblestoneBeveled (
686+ int width ,
687+ int height ,
688+ int cellSize = 28 ,
689+ byte stoneR = 128 , byte stoneG = 132 , byte stoneB = 138 ,
690+ byte groutR = 45 , byte groutG = 48 , byte groutB = 52 )
691+ {
692+ var buffer = new RawTextureBuffer ( width , height ) ;
693+ var span = buffer . AsSpan ( ) ;
694+ var rand = new Random ( 4242 ) ;
695+
696+ var gridCols = ( width / cellSize ) + 2 ;
697+ var gridRows = ( height / cellSize ) + 2 ;
698+ var pointsX = new int [ gridCols , gridRows ] ;
699+ var pointsY = new int [ gridCols , gridRows ] ;
700+
701+ for ( var y = 0 ; y < gridRows ; y ++ )
702+ {
703+ for ( var x = 0 ; x < gridCols ; x ++ )
704+ {
705+ pointsX [ x , y ] = ( x * cellSize ) + rand . Next ( 2 , cellSize - 2 ) ;
706+ pointsY [ x , y ] = ( y * cellSize ) + rand . Next ( 2 , cellSize - 2 ) ;
707+ }
708+ }
709+
710+ var idx = 0 ;
711+
712+ for ( var y = 0 ; y < height ; y ++ )
713+ {
714+ for ( var x = 0 ; x < width ; x ++ )
715+ {
716+ var cellX = x / cellSize ;
717+ var cellY = y / cellSize ;
718+
719+ var d1 = double . MaxValue ;
720+ var d2 = double . MaxValue ;
721+
722+ var startX = Math . Max ( 0 , cellX - 1 ) ;
723+ var endX = Math . Min ( gridCols - 1 , cellX + 1 ) ;
724+ var startY = Math . Max ( 0 , cellY - 1 ) ;
725+ var endY = Math . Min ( gridRows - 1 , cellY + 1 ) ;
726+
727+ for ( var cy = startY ; cy <= endY ; cy ++ )
728+ {
729+ for ( var cx = startX ; cx <= endX ; cx ++ )
730+ {
731+ var dx = x - pointsX [ cx , cy ] ;
732+ var dy = y - pointsY [ cx , cy ] ;
733+ var dist = Math . Sqrt ( dx * dx + dy * dy ) ;
734+
735+ if ( dist < d1 )
736+ {
737+ d2 = d1 ;
738+ d1 = dist ;
739+ }
740+ else if ( dist < d2 )
741+ {
742+ d2 = dist ;
743+ }
744+ }
745+ }
746+
747+ // F2 - F1 is 0 at the grout border, and large inside the stone
748+ var borderDist = d2 - d1 ;
749+
750+ // Sharp bevel: Stones stay completely flat until 2.5 pixels to the seam
751+ var stoneFactor = Math . Clamp ( borderDist / 3.0 , 0.0 , 1.0 ) ;
752+ stoneFactor = Math . Pow ( stoneFactor , 0.35 ) ; // Rapid curve to flat plateau
753+
754+ span [ idx ++ ] = ( byte ) ( groutB + ( stoneB - groutB ) * stoneFactor ) ;
755+ span [ idx ++ ] = ( byte ) ( groutG + ( stoneG - groutG ) * stoneFactor ) ;
756+ span [ idx ++ ] = ( byte ) ( groutR + ( stoneR - groutR ) * stoneFactor ) ;
757+ span [ idx ++ ] = 255 ;
758+ }
759+ }
760+
761+ return buffer ;
762+ }
763+
623764 /// <summary>
624765 /// Generates a texture by mapping turbulence noise to a predefined array of colors (Color Ramp).
625766 /// Ideal for lava, magic auras, and water.
@@ -1051,6 +1192,143 @@ internal static RawTextureBuffer GenerateFoliage(int width,
10511192 return buffer ;
10521193 }
10531194
1195+ /// <summary>
1196+ /// Generates clean, stylized leaf clumps suitable for low-poly tree meshes and terrain overlays.
1197+ /// Leaves lighting to the 3D engine while providing rich organic micro-shapes and clean alpha silhouettes.
1198+ /// </summary>
1199+ /// <param name="width">The width.</param>
1200+ /// <param name="height">The height.</param>
1201+ /// <param name="noiseGenInstance">The noise gen instance.</param>
1202+ /// <param name="clusterSize">Size of the cluster.</param>
1203+ /// <param name="transparentGaps">if set to <c>true</c> [transparent gaps].</param>
1204+ /// <param name="baseR">The base r.</param>
1205+ /// <param name="baseG">The base g.</param>
1206+ /// <param name="baseB">The base b.</param>
1207+ /// <param name="highlightR">The highlight r.</param>
1208+ /// <param name="highlightG">The highlight g.</param>
1209+ /// <param name="highlightB">The highlight b.</param>
1210+ /// <param name="shadowR">The shadow r.</param>
1211+ /// <param name="shadowG">The shadow g.</param>
1212+ /// <param name="shadowB">The shadow b.</param>
1213+ /// <returns>The generated raw texture buffer.</returns>
1214+ [ MethodImpl ( MethodImplOptions . AggressiveOptimization ) ]
1215+ public static RawTextureBuffer GenerateStylizedFoliage (
1216+ int width ,
1217+ int height ,
1218+ object noiseGenInstance ,
1219+ int clusterSize = 32 ,
1220+ bool transparentGaps = true ,
1221+ byte baseR = 52 , byte baseG = 125 , byte baseB = 38 , // Mid foliage green
1222+ byte highlightR = 108 , byte highlightG = 175 , byte highlightB = 45 , // Sunlit tint
1223+ byte shadowR = 28 , byte shadowG = 75 , byte shadowB = 26 ) // Ambient crevice green
1224+ {
1225+ var buffer = new RawTextureBuffer ( width , height ) ;
1226+ var span = buffer . AsSpan ( ) ;
1227+ dynamic noiseGen = noiseGenInstance ;
1228+
1229+ var rand = new Random ( 1337 ) ;
1230+ var gridCols = ( width / clusterSize ) + 2 ;
1231+ var gridRows = ( height / clusterSize ) + 2 ;
1232+ var pointsX = new int [ gridCols , gridRows ] ;
1233+ var pointsY = new int [ gridCols , gridRows ] ;
1234+
1235+ for ( var y = 0 ; y < gridRows ; y ++ )
1236+ {
1237+ for ( var x = 0 ; x < gridCols ; x ++ )
1238+ {
1239+ pointsX [ x , y ] = ( x * clusterSize ) + rand . Next ( 2 , clusterSize - 2 ) ;
1240+ pointsY [ x , y ] = ( y * clusterSize ) + rand . Next ( 2 , clusterSize - 2 ) ;
1241+ }
1242+ }
1243+
1244+ var idx = 0 ;
1245+ var maxRadius = clusterSize * 0.75 ;
1246+
1247+ for ( var y = 0 ; y < height ; y ++ )
1248+ {
1249+ for ( var x = 0 ; x < width ; x ++ )
1250+ {
1251+ // 1. Organic domain-warp for jagged leaf edges instead of smooth spheres
1252+ var warpX = ( ( double ) noiseGen . SmoothNoise ( x / 12.0 , y / 12.0 ) - 0.5 ) * 8.0 ;
1253+ var warpY = ( ( double ) noiseGen . SmoothNoise ( ( x + 64 ) / 12.0 , ( y + 64 ) / 12.0 ) - 0.5 ) * 8.0 ;
1254+
1255+ var px = x + warpX ;
1256+ var py = y + warpY ;
1257+
1258+ var cellX = ( int ) px / clusterSize ;
1259+ var cellY = ( int ) py / clusterSize ;
1260+
1261+ var d1 = double . MaxValue ;
1262+ var d2 = double . MaxValue ;
1263+
1264+ var startX = Math . Max ( 0 , cellX - 1 ) ;
1265+ var endX = Math . Min ( gridCols - 1 , cellX + 1 ) ;
1266+ var startY = Math . Max ( 0 , cellY - 1 ) ;
1267+ var endY = Math . Min ( gridRows - 1 , cellY + 1 ) ;
1268+
1269+ for ( var cy = startY ; cy <= endY ; cy ++ )
1270+ {
1271+ for ( var cx = startX ; cx <= endX ; cx ++ )
1272+ {
1273+ var dx = px - pointsX [ cx , cy ] ;
1274+ var dy = py - pointsY [ cx , cy ] ;
1275+ var dist = Math . Sqrt ( dx * dx + dy * dy ) ;
1276+
1277+ if ( dist < d1 )
1278+ {
1279+ d2 = d1 ;
1280+ d1 = dist ;
1281+ }
1282+ else if ( dist < d2 )
1283+ {
1284+ d2 = dist ;
1285+ }
1286+ }
1287+ }
1288+
1289+ // Clump core factor: flat plateau in the center, dropping sharply at edges
1290+ var edgeDistance = ( d2 - d1 ) / ( clusterSize * 0.45 ) ;
1291+ var leafCoverage = Math . Clamp ( edgeDistance , 0.0 , 1.0 ) ;
1292+
1293+ // Large macro noise for subtle tone variations across the canopy
1294+ var canopyGradient = ( double ) noiseGen . SmoothNoise ( x / 48.0 , y / 48.0 ) ;
1295+
1296+ if ( transparentGaps && leafCoverage < 0.25 )
1297+ {
1298+ span [ idx ++ ] = 0 ;
1299+ span [ idx ++ ] = 0 ;
1300+ span [ idx ++ ] = 0 ;
1301+ span [ idx ++ ] = 0 ; // Transparent cutout for low-poly tree card meshes
1302+ continue ;
1303+ }
1304+
1305+ // Soft color blend (No harsh black crevices!)
1306+ byte r , g , b ;
1307+ if ( canopyGradient > 0.5 )
1308+ {
1309+ var t = ( canopyGradient - 0.5 ) * 2.0 ;
1310+ r = ( byte ) ( baseR + ( highlightR - baseR ) * t ) ;
1311+ g = ( byte ) ( baseG + ( highlightG - baseG ) * t ) ;
1312+ b = ( byte ) ( baseB + ( highlightB - baseB ) * t ) ;
1313+ }
1314+ else
1315+ {
1316+ var t = ( 0.5 - canopyGradient ) * 2.0 ;
1317+ r = ( byte ) ( baseR + ( shadowR - baseR ) * t ) ;
1318+ g = ( byte ) ( baseG + ( shadowG - baseG ) * t ) ;
1319+ b = ( byte ) ( baseB + ( shadowB - baseB ) * t ) ;
1320+ }
1321+
1322+ span [ idx ++ ] = b ;
1323+ span [ idx ++ ] = g ;
1324+ span [ idx ++ ] = r ;
1325+ span [ idx ++ ] = 255 ;
1326+ }
1327+ }
1328+
1329+ return buffer ;
1330+ }
1331+
10541332 /// <summary>
10551333 /// Generates a rough, furrowed tree bark texture using anisotropic domain-warped noise.
10561334 /// </summary>
0 commit comments