UNPKG

marching

Version:

Marching.js is a JavaScript library that compiles GLSL ray marchers.

146 lines (120 loc) 3.61 kB
module.exports = `/* __--__--__--__--__--__--__--____ Live Coding There are a couple of techniques that can make live coding a bit easier in marching.js. First, if you're doing any audio-reactive visuals, be sure to check out the audio / FFT tutorial. You'll notice that many demos and tutorials use a pattern where we name objects in our graph for subsequent manipulations. This is an important step to get used to when you're setting up your graph. __--__--__--__--__--__--__--____ */ march( rpt = Repeat( Sphere(.125), Vec3(.5) ) ).render( 3, true ) // now we can change the distance later... rpt.distance.x = 1 /* __--__--__--__--__--__--__--____ Easy enough. However, a problem occurs if you then re-execute your calls to march / render... the repeat distance is reset to the the value in its constructor. During live coding performances you often want to maintain state (as much as possible) while making changes to the graph, so that abrupt changes don't occur. If you run the line: Marching.useProxies = true ...a new behavior is enabled. When you create an object in the global namespace, a 'proxy' is created. IF you reassign a new object to this proxy, the proxy will copy all the properties of the previous object to the new one. This enables you to re-execute the graph while maintaining state, and makes it much easier to acheive continuity when live coding. Try running the code below: __--__--__--__--__--__--__--____ */ // run this line by itself before // executing other code Marching.useProxies = true march( rpt2 = Repeat( Sphere(.125), Vec3(.5) ) ).render( 3, true ) rpt2.distance.x = 1 // if you re-execute the graph // now, you'll notice the distance.x // value is maintained. This only // works because we enabled proxies // and assigned our Repeat object // to the same global variable. /* __--__--__--__--__--__--__--____ Another useful technique, that relies on assigning names to objects, is to "fade", or transition gradually, to a new state in objects. __--__--__--__--__--__--__--____ */ march( s = Sphere(0) ).render( 3, true ) fade( 's','radius', 2, 10 ) /* __--__--__--__--__--__--__--____ In the example above, we give the name of the object we want to manipulate, the name of the property, the value we want to transition to, and the length in seconds of the transition. There is quadratic easing on the fade. By using dot notation in the property string, we can fade individual vector members. __--__--__--__--__--__--__--____ */ march( b = Box() ).render( 3, true ) fade( 'b','size.x', 2, 10 ) /* __--__--__--__--__--__--__--____ it's also worth noting we can fade a whole vector by simply leaving out the dot notation. The example below fades the size on the x,y,and z axis in one line of code. Note we have to use a new name to avoid the proxy effect! __--__--__--__--__--__--__--____ */ march( b2 = Box() ).render( 3, true ) fade( 'b2','size', 1.5, 10 ) /* __--__--__--__--__--__--__--____ We can use the same vector shortcut when manipulate animation at the frame level. __--__--__--__--__--__--__--____ */ march( rpt2 = Repeat( b3 = Box(), Vec3(1) ) ) .fog( .25, Vec3(0) ) .render( 3, true ) onframe = t => { // manipulate one vector member rpt2.distance.x = .5 + Math.sin( t/3 ) * .125 // manipulate entire vector at once b3.size = .1 + Math.cos( t/2 ) * .075 } /* __--__--__--__--__--__--__--____ Hopefully this is enough to get you started live coding. Between the use of onframe, fade, the fft, and proxies, there's a number of tools to get started. __--__--__--__--__--__--__--____ */`