Advanced Patterns
These snippets showcase features that go beyond basic styling.
1. GPU-Driven Circle (no vertex upload)
js
import { MeshLine } from 'makio-meshline'
import { Fn, vec3, cos, sin, time } from 'three/tsl'
const circleNode = Fn(( [progress] ) => {
const angle = progress.mul( Math.PI * 2 ).add( time.negate() )
return vec3( cos(angle), sin(angle), 0 )
})
const segments = 256 // only length matters when gpuPositionNode is used
const line = new MeshLine()
.lines(new Float32Array( segments * 3 )) // placeholder
.gpuPositionNode(circleNode)
.lineWidth(0.3)
.gradientColor(0xffff00)
.build()
scene.add( line )
2. Multi-Line Batch
js
const rings = [ circlePositions(64,1), circlePositions(64,1.5), circlePositions(64,2) ]
const multi = new MeshLine()
.lines(rings)
.closed(true)
.color(0xffffff)
.sizeAttenuation(true)
.lineWidth(2)
.build()
One draw-call – three rings.
3. Live Trail (fast setPositions()
)
js
// allocate once
const pts = new Float32Array( 64 * 3 )
const trail = new MeshLine()
.lines(pts)
.lineWidth(0.1)
.build()
scene.add( trail )
function update() {
writeTrail( pts ) // mutate coordinates in place
trail.geometry.setPositions( pts )
}
No buffers recreated, only a sub-data upload.
4. Miter Clip for Sharp Corners
js
const sharp = new MeshLine()
.lines(myPolyline)
.lineWidth(0.8)
.join({ type: 'miter', limit: 5 })
.build()
5. Animated Dashes
js
const dashed = new MeshLine()
.lines(sineWavePositions())
.dash({ count: 20, ratio: 0.4 })
.lineWidth(0.4)
.build()
stage.onUpdate.add( dt => {
dashed.material.dashOffset.value += dt * 0.002
})
6. Instanced Lines
Render thousands of lines efficiently with instancing:
js
import { MeshLine } from 'makio-meshline'
import { Fn, vec3, cos, sin, attribute, instanceIndex } from 'three/tsl'
const instanceCount = 1000
const segments = 32
// Create instanced line
const instancedLine = new MeshLine()
.instances(instanceCount) // Enable instancing
.segments(segments) // Segments per line instance
.lineWidth(0.1)
.color(0xffffff)
.build()
// Add custom instance attributes
instancedLine.addInstanceAttribute( 'instanceOffset', 3 )
instancedLine.addInstanceAttribute( 'instanceScale', 1 )
// Set per-instance data
for ( let i = 0; i < instanceCount; i++ ) {
const x = ( Math.random() - 0.5 ) * 20
const y = ( Math.random() - 0.5 ) * 20
const z = ( Math.random() - 0.5 ) * 20
instancedLine.setInstanceValue( 'instanceOffset', i, [x, y, z] )
const scale = 0.5 + Math.random() * 1.5
instancedLine.setInstanceValue( 'instanceScale', i, scale )
}
scene.add( instancedLine )
7. GPU Instanced Circles
Combine GPU position nodes with instancing for animated effects:
js
import { Fn, vec3, cos, sin, time, attribute, instanceIndex } from 'three/tsl'
const gpuPositionNode = Fn( ( [progress] ) => {
const offset = attribute( 'instanceOffset', 'vec3' )
const radius = attribute( 'instanceRadius', 'float' )
const angle = progress.mul( Math.PI * 2 ).add( time.negate() )
return vec3( cos( angle ), sin( angle ), 0 ).mul( radius ).add( offset )
} )
const instancedCircles = new MeshLine()
.instances(100)
.segments(64)
.gpuPositionNode(gpuPositionNode)
.lineWidth(0.2)
.colorFn(Fn( ( [color, progress] ) => {
const col = float( instanceIndex ).mod( 10 )
const row = float( instanceIndex ).div( 10 )
return vec3( col.div( 9 ), row.div( 9 ), 0.8 )
} ))
.build()
// Setup instance attributes
instancedCircles.addInstanceAttribute( 'instanceOffset', 3 )
instancedCircles.addInstanceAttribute( 'instanceRadius', 1 )
// Position instances in a grid
for ( let i = 0; i < 100; i++ ) {
const col = i % 10
const row = Math.floor( i / 10 )
const x = ( col - 4.5 ) * 3
const y = ( row - 4.5 ) * 3
instancedCircles.setInstanceValue( 'instanceOffset', i, [x, y, 0] )
instancedCircles.setInstanceValue( 'instanceRadius', i, 0.5 + col * 0.1 )
}
8. Material Hooks for Custom Effects
Use material hooks to create custom shader effects:
Dynamic Width Variation
js
import { Fn, sin, time } from 'three/tsl'
const pulsatingLine = new MeshLine()
.lines(circlePositions( 64 ))
.lineWidth(0.3)
.widthFn(Fn( ( [width, progress] ) => {
return width.mul( sin( time.add( progress.mul( 10 ) ) ).mul( 0.5 ).add( 1 ) )
} ))
.build()
Custom Color Gradients
js
const rainbowLine = new MeshLine()
.lines(sineWavePositions())
.colorFn(Fn( ( [color, progress] ) => {
const hue = progress.mul( 6.28 ).add( time )
return vec3(
sin( hue ).mul( 0.5 ).add( 0.5 ),
sin( hue.add( 2.09 ) ).mul( 0.5 ).add( 0.5 ),
sin( hue.add( 4.18 ) ).mul( 0.5 ).add( 0.5 )
)
} ))
.build()
Opacity Fading
js
const fadingLine = new MeshLine()
.lines(straightLine( 100 ))
.transparent(true)
.opacityFn(Fn( ( [alpha, progress] ) => {
return alpha.mul( smoothstep( 0, 0.1, progress ) ).mul( smoothstep( 1, 0.9, progress ) )
} ))
.build()
Custom Dash Patterns
js
const customDashes = new MeshLine()
.lines(circlePositions( 128 ))
.dash({ count: 10, ratio: 0.3 })
.dashFn(Fn( ( [cyclePos, progress] ) => {
// Create variable dash lengths
const variation = sin( progress.mul( 20 ) ).mul( 0.2 ).add( 1 )
return mod( cyclePos.mul( variation ), float( 1 ) )
} ))
.build()