Metal-based implementation of beautiful mesh gradient. Image worth thousands of words, so just let me show you.
Small notes before I show you the code. This mesh is generated from the constants you provide. To create mesh you have to provide grid with ControlPoint matrix that describe your gradient (just like with other gradients, huh?):
- You need to provide
colorsfor gradient - that is obvious, right? - You need to provide
locations of control points. Locations are in metal coordinate space - that one is a bit scarier. Relax, it is just values in -1...1 - You need to provide how turbulent your mesh is. This is
uTangentandvTangentexists for.
Again, don't be scared. You have all the randomizers out of the box and they are pretty easy to use.
Now, to the code:
typealiasMeshColor=SIMD3<Float>
// You can provide custom `locationRandomizer` and `turbulencyRandomizer` for advanced usage
varmeshRandomizer=MeshRandomizer(colorRandomizer:MeshRandomizer.arrayBasedColorRandomizer(availableColors: meshColors))privatevarmeshColors:[simd_float3]{return[MeshRandomizer.randomColor(),MeshRandomizer.randomColor(),MeshRandomizer.randomColor(),]}
// This methods prepares the grid model that will be sent to metal for rendering
func generatePlainGrid(size:Int=6)->Grid<ControlPoint>{letpreparationGrid=Grid<MeshColor>(repeating:.zero, width: size, height: size)
// At first we create grid without randomisation. This is smooth mesh gradient without // any turbulency and overlaps
varresult=MeshGenerator.generate(colorDistribution: preparationGrid)
// And here we shuffle the grid using randomizer that we created
forxinstride(from:0, to: result.width, by:1){foryinstride(from:0, to: result.height, by:1){
meshRandomizer.locationRandomizer(&result[x, y].location, x, y, result.width, result.height)
meshRandomizer.turbulencyRandomizer(&result[x, y].uTangent, x, y, result.width, result.height)
meshRandomizer.turbulencyRandomizer(&result[x, y].vTangent, x, y, result.width, result.height)
meshRandomizer.colorRandomizer(&result[x, y].color,result[x, y].color, x, y, result.width, result.height)}}return result
}// If you want just show static grid without any animations
structMyStaticGrid:View{varbody:someView{MeshGradient(grid:generatePlainGrid())}}structMyAnimatedGrid:View{
// MeshRandomizer is a plain struct with just the functions. So you can dynamically change it!
@StatevarmeshRandomizer=MeshRandomizer(colorRandomizer:MeshRandomizer.arrayBasedColorRandomizer(availableColors: meshColors))varbody:someView{MeshGradient(initialGrid:generatePlainGrid(), animatorConfiguration:.init(animationSpeedRange:2...4, meshRandomizer: meshRandomizer)))}}Use MTKView and MetalMeshRenderer. I hope you have minimal knowledge in metal rendering. Good luck ;)
Check source code of SwiftUI MeshGradient implementation that just wraps MTKView.
