├── .gitignore ├── MouseControls.js ├── README.md ├── assets └── walker │ └── Walker.js ├── cells.html ├── colors.html ├── composer.js ├── glsl ├── bits │ ├── draw │ │ ├── ao.glsl │ │ ├── environment.glsl │ │ ├── fog.glsl │ │ ├── normal.glsl │ │ ├── raymarch.glsl │ │ ├── rim.glsl │ │ └── shadows.glsl │ ├── geom │ │ ├── box.glsl │ │ ├── cylinder.glsl │ │ ├── madelbulb.glsl │ │ ├── mandelBox.glsl │ │ ├── plane.glsl │ │ ├── platonic_solids_ref.glsl │ │ ├── sierpinski.glsl │ │ ├── sphere.glsl │ │ └── torus.glsl │ └── util │ │ ├── lookat.glsl │ │ ├── noise.glsl │ │ ├── operations.glsl │ │ ├── perlin.glsl │ │ ├── rotation.glsl │ │ └── squareFrame.glsl ├── cells.glsl ├── colors.glsl ├── fragment.glsl ├── halibut.glsl ├── hulkbuster.glsl ├── interactive.glsl ├── noise_bulb.glsl ├── tmp.glsl ├── toy.glsl └── walker.glsl ├── halibut.html ├── hulkbuster.html ├── img ├── colors.png ├── cover.jpg ├── cubemap │ ├── cube03_0.png │ ├── cube03_1.png │ ├── cube03_2.png │ ├── cube03_3.png │ ├── cube03_4.png │ └── cube03_5.png ├── env.png ├── halibut.jpg ├── hulkbuster.jpg ├── matcap.png ├── noise_bulb.jpg └── walker.jpg ├── index.html ├── interactive.html ├── noise_bulb.html ├── raymarcher.js ├── tmp.html ├── vendor ├── controls │ └── OrbitControls.js ├── postprocessing │ ├── EffectComposer.js │ ├── MaskPass.js │ ├── RenderPass.js │ └── ShaderPass.js ├── shaders │ ├── CopyShader.js │ └── FXAAShader.js └── three.min.js └── walker.html /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | /.idea 3 | /vendor/three.js 4 | /glsl/tmp.glsl 5 | -------------------------------------------------------------------------------- /MouseControls.js: -------------------------------------------------------------------------------- 1 | var MouseControls = function(){ 2 | 3 | function MouseControls( rayMarching ){ 4 | 5 | this.rm = rayMarching; 6 | this.mouseDown = false; 7 | 8 | rayMarching.renderer.domElement.addEventListener( "mousedown", this.onDown.bind( this ), false ); 9 | rayMarching.renderer.domElement.addEventListener( "mousemove", this.onMove.bind( this ), false ); 10 | rayMarching.renderer.domElement.addEventListener( "mouseup", this.onUp.bind( this ), false ); 11 | rayMarching.renderer.domElement.addEventListener( "mouseleave", this.onUp.bind( this ), false ); 12 | 13 | } 14 | 15 | function onDown(e){ 16 | 17 | var pos = this.getPosition(e); 18 | this.rm.mouse.x = pos[0]; 19 | this.rm.mouse.y = pos[1]; 20 | this.mouseDown = true; 21 | } 22 | 23 | function onMove(e){ 24 | 25 | if( this.mouseDown ){ 26 | var pos = this.getPosition(e); 27 | this.rm.mouse.x = pos[0]; 28 | this.rm.mouse.y = pos[1]; 29 | } 30 | } 31 | 32 | function onUp(e){ 33 | this.mouseDown = false; 34 | } 35 | 36 | function getPosition(e){ 37 | 38 | var pos = [0,0]; 39 | if( e == null )return [window.innerWidth/2, window.innerHeight/2]; 40 | 41 | if( 'ontouchstart' in window ) 42 | { 43 | var touch = e.targetTouches[0]; 44 | pos[0] = touch.clientX; 45 | pos[1] = touch.clientY; 46 | }else 47 | { 48 | if (!e) e = window.event; 49 | if (e.pageX || e.pageY){ 50 | pos[0] = e.pageX; 51 | pos[1] = e.pageY; 52 | } 53 | else if (e.clientX || e.clientY){ 54 | pos[0] = e.clientX + document.body.scrollLeft + document.documentElement.scrollLeft; 55 | pos[1] = e.clientY + document.body.scrollTop + document.documentElement.scrollTop; 56 | } 57 | } 58 | var r = e.target.getBoundingClientRect(); 59 | pos[0] -= r.left; 60 | pos[1] -= r.top; 61 | return pos; 62 | } 63 | 64 | var _p = MouseControls.prototype; 65 | 66 | _p.constructor = MouseControls; 67 | _p.onDown = onDown; 68 | _p.onMove = onMove; 69 | _p.onUp = onUp; 70 | _p.getPosition = getPosition; 71 | 72 | return MouseControls; 73 | 74 | }(); -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # raymarching-for-THREE 2 | ![screenshot](https://rawgit.com/nicoptere/raymarching-for-THREE/master/img/cover.jpg) 3 |
4 | a "helper" to work with raymarching in THREE.js. 5 | * [basic demo](https://rawgit.com/nicoptere/raymarching-for-THREE/master/index.html)
6 | * [interactive demo](https://rawgit.com/nicoptere/raymarching-for-THREE/master/interactive.html) (mouse controls)
7 | * [color segmentation](https://rawgit.com/nicoptere/raymarching-for-THREE/master/colors.html)
8 | * [halibut](https://rawgit.com/nicoptere/raymarching-for-THREE/master/halibut.html)
9 | * [hulkbuster](https://rawgit.com/nicoptere/raymarching-for-THREE/master/hulkbuster.html)
10 | * [2D cells (not raymarched)](https://rawgit.com/nicoptere/raymarching-for-THREE/master/cells.html)
11 | 12 | it is heavily based on http://stack.gl/ core modules & scripts
13 |
14 | [THREE.js](http://threejs.org/) is a popular WebGL library, Raymarching Distance Fields is trendy nowadays, this is a way to bring them together. most of (all!) the work is done by the fragment shader, do not expect anything even remotely complex on the javascript side :)
15 | THREE makes it easy to upload various data to the shader (cameras, lights, textures for instance), another benefit is to be able to use THREE's post-processing ecosystem ; in the example above, I used a FXAA Pass to smooth the result.
16 | I've just left a small subset of the post processing & shaders folder for the sake of testing but there 's a lot more on THREE's repo.
17 |
18 | I've left the links to the resources I used in the [fragment file](https://github.com/nicoptere/raymarching-for-THREE/blob/master/glsl/fragment.glsl), most of the changes should be done in the "field()" method after the [HAMMER TIME!](https://github.com/nicoptere/raymarching-for-THREE/blob/master/glsl/fragment.glsl#L126) 19 | 20 | # sample script 21 | 22 | 23 | 24 | 49 | 50 | should give you something like this: 51 | ![noise bulb](https://cdn.rawgit.com/nicoptere/raymarching-for-THREE/master/img/noise_bulb.jpg)
52 | [noise bulb demo](https://rawgit.com/nicoptere/raymarching-for-THREE/master/noise_bulb.html)
53 | 54 | the loadFragmentShader method, takes the url of the fragment shader (can be plain text), loads it and call the callback method if it was specified 55 | 56 | loadFragmentShader( url, callback ); 57 | 58 | passing the animate loop as a callback is a good idea but is not necessary. 59 | 60 | the 2 most important values for the raymarching are the maximum distance and the precision (the minimum step distance under which the raymarching loop bails out). 61 | by default, their values are 50 and 0.01 respectively. you can set them directly like: 62 | 63 | rm.distance = X 64 | rm.precision = Y 65 | 66 | //then call an update to update the uniforms 67 | rm.update(); 68 | 69 | a 'good' value for raymarchMaximumDistance is twice the length of the camera's position ; it gives enough depth to render most of the things 70 | 71 | rm.distance = this.camera.position.length() * 2; 72 | 73 | the default raymarchPrecision is 0.01 which is fairly high (= coarse): 74 | 75 | if you need more accurate renders, increase the rm.distance and lower the rm.precision 76 | 77 | also, the raymarching 'steps' count has to be set directly in the shader like [here](https://github.com/nicoptere/raymarching-for-THREE/blob/master/glsl/fragment.glsl#L130) 78 | increasing it will give much more precise results at the cost of more intensive computations. 79 | 80 | for the sake of exhibiting the beauty of Raymarching, the above shape is produced by [this distance estimator](https://github.com/nicoptere/raymarching-for-THREE/blob/master/glsl/noise_bulb.glsl#L171-L186): 81 | 82 | vec2 field( vec3 position ){ 83 | 84 | //create a 5 units radius sphere 85 | vec2 sph = sphere( position, 5. ); 86 | 87 | //create a 10 units high, 4 units radius cylinder and positions it at Y = -12.5 units 88 | vec2 cyl = cylinder( position, 10.,4., vec3( 0.,-12.5,0.) ); 89 | 90 | //stores a copy of the position being evaluated 91 | vec3 nPos = position * .45; 92 | 93 | //adds some delta 94 | nPos.y -= time * .05; 95 | 96 | //creates a transform (time-based rotation about the Y axis) 97 | vec4 quat = vec4( 0., 1., 0., -time * .1 ); 98 | 99 | //evaluates a noise field using the transform above (the noise field "rotates") 100 | vec2 noi = vec2( max( -.5, .5-abs( perlin( nPos, quat ) ) ), 0. ); 101 | 102 | //combines the shapes: 103 | // 1 - blend the sphere and the cylinder: smin( sph, cyl, .99 ) 104 | // 2 - return the intersection of the blended shapes with the noise field 105 | return intersectionAB( smin( sph, cyl, .99 ), noi ); 106 | 107 | } 108 | 109 | then some [colors are being computed](https://github.com/nicoptere/raymarching-for-THREE/blob/master/glsl/noise_bulb.glsl#L270-L286) with the result of this evaluation. 110 | 111 | 112 | # differents colors: 113 | ![colors](https://cdn.rawgit.com/nicoptere/raymarching-for-THREE/master/img/colors.png) 114 | to assign different colors to the different parts of the shape you can do somethign like:
115 | 116 | //shape composition 117 | float blend = .5 + sin( time * .5 ) * .5; 118 | vec2 _out = unionAB( sce, smin( to0, smin( to1, subtract( sre, box ), blend ), blend ) ); 119 | 120 | //color attribution 121 | 122 | //the Y value of the return value will be used to apply a different shading 123 | // _out.y = 1. is the default value, here, it will be attributed to blended areas 124 | 125 | //we can retrieve the elements by depth 126 | //we use the raymarch precision as a threshold 127 | float d = raymarchPrecision; 128 | 129 | //then an object is found like: 130 | 131 | if( _out.x > box.x - d )_out.y = 0.80; 132 | if( _out.x > to1.x - d )_out.y = 0.66; 133 | if( _out.x > to0.x - d )_out.y = 0.25; 134 | if( _out.x > sce.x - d )_out.y = 0.; 135 | 136 | return _out; 137 | 138 | an alternative to remove the conditional branching would be to write it as : 139 | 140 | _out.y = 1.; 141 | _out.y -= step( box.x - d, _out.x ) * .2 142 | + step( to0.x - d, _out.x ) * .35 143 | + step( to1.x - d, _out.x ) * .75 144 | + step( sce.x - d, _out.x ) * 1.0; 145 | 146 | this approach is supposed to be faster, the downside is that it is less legible. 147 | 148 | check out the [live demo for the color selection](https://rawgit.com/nicoptere/raymarching-for-THREE/master/colors.html)
149 | see [the source shader](https://github.com/nicoptere/raymarching-for-THREE/blob/master/glsl/colors.glsl#L161-L181) for the code.
150 | 151 | # using the effectComposer 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 193 | the composer contains whatever filters you can think of and is called after the RayMarcher' render
194 | 195 | 196 | 197 | # tips 198 | 199 | cheap depth (in the main() function) : 200 | 201 | float depth = ( 1./ log( collision.x ) ); 202 | 203 | repeat a shape at a given interval (described by a vec3 r ): 204 | 205 | vec3 repeat( vec3 p, vec3 r ) { return mod( p, r ) - .5 * r; } 206 | 207 | //& in the field() function 208 | vec3 p = repeat( position, r ); 209 | 210 | //p is a repeated position, use it to place evenly spaced objects 211 | 212 | spherical uvs: (Spherical Environment Mapping) 213 | 214 | texture2D( map, nor.xy / 2. + .5 ); 215 | 216 | you can [lookat](https://github.com/nicoptere/raymarching-for-THREE/blob/master/glsl/bits/util/lookat.glsl) the camera to always face it 217 | 218 | #examples 219 | ![halibut](https://cdn.rawgit.com/nicoptere/raymarching-for-THREE/master/img/halibut.jpg)
220 | [halibut demo](http://barradeau.com/dump/raymarching/halibut.html)
221 | ![hulkbuster](https://cdn.rawgit.com/nicoptere/raymarching-for-THREE/master/img/hulkbuster.jpg)
222 | [hulkbuster demo](http://barradeau.com/dump/raymarching/hulkbuster.html)
223 | ![walker](https://cdn.rawgit.com/nicoptere/raymarching-for-THREE/master/img/walker.jpg)
224 | [walker demo](http://barradeau.com/dump/raymarching/walker.html)
225 | 226 | #helpful links: 227 | 228 | 229 | WebGL [quick reference](http://www.shaderific.com/glsl/) for types, functions, statements etc. 230 | 231 | [Jaume Sanchez Elias](https://twitter.com/thespite)'s [Shader Editor chrome extension](https://chrome.google.com/webstore/detail/shader-editor/ggeaidddejpbakgafapihjbgdlbbbpob) mandatory tool to work with shaders 232 | 233 | [Íñgo Quílez](http://www.iquilezles.org/) [distance functions](http://iquilezles.org/www/articles/distfunctions/distfunctions.htm) and his live [example / refernce for basically everything](https://www.shadertoy.com/view/Xds3zN) 234 | 235 | [POUET's thread on primitives, noise, AO, SSS & more]( http://www.pouet.net/topic.php?which=7931&page=1) 236 | 237 | [Kevin Roast](https://twitter.com/kevinroast)'s [homepage](http://www.kevs3d.co.uk/dev/shaders/) is full of examples, rendering tricks, shapes and more 238 | 239 | very interesting series of articles about distance estimators & fractals: 240 | * [Distance Estimated 3D Fractals (Part I)](http://blog.hvidtfeldts.net/index.php/2011/06/distance-estimated-3d-fractals-part-i/) 241 | * [Distance Estimated 3D Fractals (II): Lighting and Coloring](http://blog.hvidtfeldts.net/index.php/2011/08/distance-estimated-3d-fractals-ii-lighting-and-coloring/) 242 | * [Distance Estimated 3D Fractals (III): Folding Space](http://blog.hvidtfeldts.net/index.php/2011/08/distance-estimated-3d-fractals-iii-folding-space/) 243 | * [Distance Estimated 3D Fractals (IV): The Holy Grail](http://blog.hvidtfeldts.net/index.php/2011/09/distance-estimated-3d-fractals-iv-the-holy-grail/) 244 | * [Distance Estimated 3D Fractals (V): The Mandelbulb & Different DE Approximations](http://blog.hvidtfeldts.net/index.php/2011/09/distance-estimated-3d-fractals-v-the-mandelbulb-different-de-approximations/) 245 | * [Distance Estimated 3D Fractals (VI): The Mandelbox](http://blog.hvidtfeldts.net/index.php/2011/11/distance-estimated-3d-fractals-vi-the-mandelbox/) 246 | * [Distance Estimated 3D Fractals (VII): Dual Numbers](http://blog.hvidtfeldts.net/index.php/2011/12/distance-estimated-3d-fractals-vii-dual-numbers/) 247 | * [Distance Estimated 3D Fractals (Part VIII): Epilogue](http://blog.hvidtfeldts.net/index.php/2012/05/distance-estimated-3d-fractals-part-viii-epilogue/) 248 | 249 | which incidentally reminded me of [subblue](https://twitter.com/subblue)'s [beautiful works](http://sub.blue/) 250 | 251 | a reminder of how [the blinn-phong shading](https://en.wikipedia.org/wiki/Blinn%E2%80%93Phong_shading_model) works 252 | 253 |
-------------------------------------------------------------------------------- /assets/walker/Walker.js: -------------------------------------------------------------------------------- 1 | var Walker = function() 2 | { 3 | var meanwalker = [-10.7519383725583, -3.72746649802272, -16.466685709658, -65.2177300475541, 44.661335747837, -16.466685709658, -65.2177300475541, 44.661335747837, 17.7610082741684, 15.8662806749498, 74.7273524036626, -52.4475178141205, 15.8662806749498, 74.7273524036626, -52.4475178141205, 0, 0, 183.820336741237, 220.478676488392, 251.013364295138, -183.820336741237, -220.478676488392, -251.013364295138, 0, 94.4979146895428, 72.7179566209974, 50.9485900809081, -94.4979146895428, -72.7179566209974, -50.9485900809081, 1640.61993723311, 1366.6742993586, 1402.32109635485, 1130.65231705128, 907.447654999956, 1402.32109635485, 1130.65231705128, 907.447654999956, 1015.0295481002, 909.516923870395, 524.108918400734, 162.337873145943, 909.516923870395, 524.108918400734, 162.337873145943, 126.030870377155, -6.93889390390723E-17, -7.63278329429795E-17, 6.01188539660724, 18.6532785884334, 35.168904918911, -6.01188539660724, -18.6532785884334, -35.168904918911, -9.71445146547012E-17, 0.85583935993545, -66.7599801603397, -0.00136779054226829, -0.855839359935451, 66.7599801603397, 0.00136779054226821, 16.7454749227664, 13.6539217228521, 14.4561843900628, 18.2079200377397, 12.2517881770354, 14.4561843900628, 18.2079200377397, 12.2517881770354, 11.0805683180636, 12.7013089491983, -11.6385045948174, -16.8400386203203, 12.7013089491983, -11.6385045948174, -16.8400386203203, -2.42861286636753E-17, -3.46944695195361E-17, -2.74690764163242, -4.12039184625044, 3.90729059644772, 2.74690764163242, 4.12039184625044, -3.90729059644772, -2.77555756156289E-17, 6.0560609647142, -1.14939409468544, -54.9132000272359, -6.0560609647142, 1.14939409468544, 54.9132000272359, 1, 0, 0, -10.5990547628726, -81.6328045581542, -188.021237194147, 10.5990547628726, 81.6328045581542, 188.021237194147, 0, 7.51975855144645, 147.708816974537, 322.46460362452, -7.51975855144645, -147.708816974537, -322.46460362452, 5.16274050080685, -0.398924078714644, 0.682139326943909, -22.724670410904, -2.67261175746871, 0.682139326943909, -22.724670410904, -2.67261175746871, -4.87628414766496, -0.384609053714416, -5.45192419278888, 3.10930244892261, -0.384609053714416, -5.45192419278888, 3.10930244892261, 0, 0, -5.02980895672233, 5.4082726923341, -48.3290365382949, 5.02980895672233, -5.4082726923341, 48.3290365382949, 0, 2.16443515803395, 21.0488520130996, -38.6505735454448, -2.16443515803395, -21.0488520130996, 38.6505735454448, 11.301384163533, 5.04640285684089, 9.71946135141663, 9.21520988370216, 4.20442453473104, 0.0864653905040408, 9.21520988370216, 4.20442453473104, 0.0864653905040406, 14.0190823730271, 14.2108772033409, 24.0899676140367, -51.2214686002918, 14.2108772033409, 24.0899676140367, -51.2214686002918, -2.94902990916057E-17, -2.08166817117217E-17, 0.409655146504848, -2.13770523265812, -0.166911902672378, -0.409655146504848, 2.13770523265812, 0.166911902672378, 0, 0.128126516280133, 3.41361458305222, 1.50135626982485, -0.128126516280133, -3.41361458305222, -1.50135626982485, -2.71924845380677, -3.00211552243835, -3.52015839198105, -5.41544778625127, -11.7893450407488, -3.52015839198105, -5.41544778625127, -11.7893450407488, -3.36532602257169, -4.21217395862763, -13.3552651024839, 29.5052192061985, -4.21217395862763, -13.3552651024839, 29.5052192061985, 0, -0.777824905615586, 0.182070540329546, -0.266938159883533, -1.44755932031152, -2.33835042367754, -0.266938159883533, -1.44755932031152, -2.33835042367754, 0.308319043161397, -0.64475549181795, -31.9081123051583, 10.0432538072851, -0.64475549181795, -31.9081123051583, 10.0432538072851, 0, 1.38777878078145E-17, -0.4651308638072, -1.01059316019605, -3.22047187794453, 0.4651308638072, 1.01059316019605, 3.22047187794453, 1.21430643318377E-17, -0.652057779184334, -5.39933599975214, -2.65932524348569, 0.652057779184334, 5.39933599975214, 2.65932524348569, -20.8947287998807, -20.8939662029067, -20.4660022882249, -13.9663497069928, 3.72651392566029, -20.4660022882249, -13.9663497069928, 3.72651392566029, -20.8148027436241, -19.3607066652156, -12.4747872187268, -12.1435006547985, -19.3607066652156, -12.4747872187268, -12.1435006547985, 0]; 4 | var genderaxis = [10.8622752381147, 3.87784584606416, 3.96644411626268, 3.85579242843092, 2.20245821571388, 3.96644411626268, 3.85579242843092, 2.20245821571388, -1.91706656439971, -2.88401118505139, -7.71017967887297, -5.23282986301825, -2.88401118505139, -7.71017967887297, -5.23282986301825, 0, 0, 2.33504968867266, 5.35207779836652, 0.896955890332611, -2.33504968867266, -5.35207779836652, -0.896955890332611, 0, -4.92072625597757, 6.13262704447186, 4.90290566512624, 4.92072625597757, -6.13262704447186, -4.90290566512624, 0.598322945574293, -0.820230066738596, 1.10163845162971, 2.74334260600583, -0.954369366369163, 1.10163845162971, 2.74334260600583, -0.954369366369163, -4.07022663674413, -4.5315810093439, -1.9174147757701, -2.68748748543046, -4.5315810093439, -1.9174147757701, -2.68748748543046, -0.890102321103325, -8.32667268468867E-17, -5.55111512312578E-17, 1.30515160463045, 0.697114232970961, -0.527484841356247, -1.30515160463045, -0.697114232970961, 0.527484841356248, -2.77555756156289E-17, 0.0485813554947454, 1.82721802473303, -0.00338294354078825, -0.0485813554947455, -1.82721802473303, 0.00338294354078825, 5.01816863098923, 3.20435623460813, 3.55019257928635, 1.80610030041737, -1.36322519248119, 3.55019257928635, 1.80610030041738, -1.36322519248119, -0.162180926939796, -1.59859605581916, -2.25377676330274, 0.169346972086787, -1.59859605581916, -2.25377676330274, 0.169346972086787, -6.93889390390723E-18, -3.46944695195361E-18, -1.43489570265418, -1.33939655573188, -2.94792693327534, 1.43489570265418, 1.33939655573188, 2.94792693327534, 0, -1.72218146089708, -2.56033660634584, -0.740142747399359, 1.72218146089708, 2.56033660634584, 0.740142747399359, 0.034207395201156, 0, 0, 0.50895749811239, 10.8092969078574, 17.5970954067276, -0.50895749811239, -10.8092969078574, -17.5970954067276, -2.77555756156289E-17, -0.768659543801708, -3.28343975390831, -4.10636698720229, 0.768659543801708, 3.28343975390831, 4.10636698720229, 3.00122757985203, 0.99540454173169, 1.05848994151511, -0.953610312585894, -2.2087593437931, 1.05848994151511, -0.953610312585894, -2.2087593437931, -0.665648010096331, -1.09272854820708, -0.356435265191952, -0.252999700189796, -1.09272854820708, -0.356435265191952, -0.252999700189796, 6.93889390390723E-18, 0, -1.62054857692189, -4.68841758693348, -1.34999678078504, 1.62054857692189, 4.68841758693348, 1.34999678078504, 3.46944695195361E-18, -0.24203076680066, -2.61872493398542, -1.3140922430098, 0.24203076680066, 2.61872493398542, 1.3140922430098, 0.348889753128268, 0.860562851303457, -0.458459262279532, -0.27592558441124, -0.320091182027612, -0.667765665467602, -0.27592558441124, -0.320091182027612, -0.667765665467603, -1.62704716356786, -1.49325355842263, 2.1374462006464, 1.37280884103637, -1.49325355842263, 2.1374462006464, 1.37280884103637, -2.77555756156289E-17, -1.38777878078145E-17, -0.00400167616055201, -0.0820685931886628, 0.33762561402375, 0.00400167616055198, 0.0820685931886629, -0.33762561402375, -1.38777878078145E-17, 0.00516524711570088, 1.30236325923525, 0.405743234314944, -0.00516524711570093, -1.30236325923525, -0.405743234314944, -0.186397660789509, -0.154535028531196, -0.336599188354126, -0.0999716867334504, 0.217840087631619, -0.336599188354126, -0.0999716867334503, 0.217840087631619, -0.161083943571017, -0.245518701880568, 1.95664779431894, 1.05702171892267, -0.245518701880568, 1.95664779431894, 1.05702171892267, 0, 0.759222556825001, 0.355377914840419, 0.353595133224375, -0.425647703311692, 1.05136089417181, 0.353595133224375, -0.425647703311692, 1.05136089417181, -0.248022688099012, -0.429277241010223, 1.17633656323907, -0.240189659908589, -0.429277241010223, 1.17633656323907, -0.240189659908589, -2.77555756156289E-17, -2.08166817117217E-17, 0.016422717738074, 1.33953448719773, 0.913474371405699, -0.0164227177380741, -1.33953448719773, -0.913474371405699, -1.38777878078145E-17, 0.00970342000951549, -0.279947291858412, 0.889223046696579, -0.00970342000951552, 0.279947291858412, -0.889223046696579, -0.766276468753209, -0.558612770425893, -0.631510924081967, -1.74294715459389, -3.04002900775738, -0.631510924081967, -1.74294715459389, -3.04002900775738, -0.802355169400983, -0.880726423552862, -1.56721947803708, -0.338692149454206, -0.880726423552862, -1.56721947803708, -0.338692149454206, 0]; 5 | var weightaxis = [-8.60322982096967, -4.39777268443819, -4.31654137593974, -1.02419968988667, -1.60591703899923, -4.31654137593974, -1.02419968988667, -1.60591703899923, -4.26099331081557, -2.32629930281409, 6.43969549700463, 10.0935693318593, -2.32629930281409, 6.43969549700463, 10.0935693318593, 0, 0, 3.71622029046712, 6.65597759326383, 9.69562192919174, -3.71622029046712, -6.65597759326383, -9.69562192919174, 0, 7.78736639282353, 0.0787433078343267, -1.26556630921202, -7.78736639282353, -0.0787433078343267, 1.26556630921202, 0.0596088709303616, 0.817695654477612, -3.95444231532143, -6.22768530651593, -12.9325434566197, -3.95444231532143, -6.22768530651593, -12.9325434566197, 11.2221263908486, 10.3804686577979, 7.29828647571261, 2.28212360340294, 10.3804686577979, 7.29828647571261, 2.28212360340294, 4.55185600891705, 6.23921190478346E-17, 9.61506336619311E-18, -1.03881331001095, 1.17656495856413, 5.02239268004826, 1.03881331001095, -1.17656495856413, -5.02239268004826, 4.80753168309656E-18, -0.552115811903587, -3.59626076398225, 0.0146124883231591, 0.552115811903588, 3.59626076398225, -0.014612488323159, -0.845208137045764, 0.225742151854656, -0.162288739590334, 0.768519833706678, 1.38266394169628, -0.162288739590334, 0.768519833706659, 1.38266394169628, 2.2338618526944, 2.37246823360433, -2.62595872751184, -0.160888799369168, 2.37246823360433, -2.62595872751184, -0.160888799369168, -3.47752600781346E-17, -4.13723920383398E-17, 0.84983102742614, 0.730621878292606, 3.31882760712525, -0.84983102742614, -0.730621878292606, -3.31882760712525, 0, 0.937032237142068, 1.66858338568437, 0.606406841881119, -0.937032237142068, -1.66858338568437, -0.606406841881119, 0, 0, 0, -2.91479968579839, 1.9908650545833, 14.8457174549164, 2.91479968579839, -1.9908650545833, -14.8457174549164, -4.31619923154484E-17, -1.49629823768662, -4.65169274010743, -3.5699595564498, 1.49629823768662, 4.65169274010743, 3.5699595564498, -0.389314859668211, -0.722941359031102, -1.11155939802322, 1.97896062813978, 2.34449642252038, -1.11155939802322, 1.97896062813978, 2.34449642252038, -0.862357708685933, -1.5548643796591, -1.70314919425028, 1.98849454708394, -1.5548643796591, -1.70314919425028, 1.98849454708394, -6.11637879189553E-17, -4.79695239985449E-17, 0.0313780976365884, -1.41383220880015, 7.79009045809917, -0.0313780976365884, 1.41383220880015, -7.79009045809917, -5.45666559587501E-17, -0.945524264476216, 1.94598558199536, 4.07786448889072, 0.945524264476216, -1.94598558199536, -4.07786448889072, -0.854887153611129, -0.124788851245166, 0.594542218404294, 0.760752724745457, 0.957793598700929, -1.53748528891728, 0.760752724745457, 0.957793598700929, -1.53748528891728, 1.00760066357486, 0.884790964265378, -1.68363749086776, -1.07391675519032, 0.884790964265378, -1.68363749086776, -1.07391675519032, 2.87922936823689E-17, 2.63885278408208E-17, 0.0427992390747824, -0.982282749429476, -0.627035878127249, -0.0427992390747823, 0.982282749429476, 0.627035878127249, 1.7019480184855E-17, -0.00592021574889225, 2.18799810355824, -1.32408123662573, 0.00592021574889231, -2.18799810355824, 1.32408123662573, 1.43566255610034, 1.57932517557856, 1.70940351164603, 1.34079760022902, -0.326156828395397, 1.70940351164603, 1.34079760022902, -0.326156828395397, 1.61550112667063, 1.59438617934391, -0.945301734607545, -1.4507723825316, 1.59438617934391, -0.945301734607528, -1.4507723825316, 0, -1.14199452482802, -0.908274325058428, -1.23592692595839, -0.0488368203386743, 1.78428901641138, -1.23592692595839, -0.0488368203386725, 1.78428901641138, -0.0206058483765944, -0.0498759350552304, -1.9514425427784, -0.975952785179369, -0.0498759350552304, -1.9514425427784, -0.97595278517937, 4.80753168309656E-18, 1.25999345120496E-17, -0.0778248096444307, -1.05713452199503, 0.140159622942414, 0.0778248096444309, 1.05713452199503, -0.140159622942414, 2.63885278408208E-17, 0.0958178614773403, -2.29016183152658, -0.981655940758735, -0.0958178614773402, 2.29016183152658, 0.981655940758735, 0.873163814765254, 0.691630217779826, 0.460659242794834, -1.21243959156637, -4.95415159635425, 0.460659242794834, -1.21243959156637, -4.95415159635425, 0.912366138079486, 1.1111424379197, 0.506354668509017, -0.645344827798356, 1.1111424379197, 0.506354668509017, -0.645344827798356, 0]; 6 | var nervousaxis = [1.608, -4.892, -5.1408, -10.2248, 4.3596, -5.1408, -10.2248, 4.3596, -0.4336, 0.817, 1.139, 12.0732, 0.817, 1.139, 12.0732, 0, 0, 12.227, 2.881, -0.9562, -12.227, -2.881, 0.9562, 0, 8.3682, -2.2468, -5.0328, -8.3682, 2.2468, 5.0328, 5.182, 2.5256, -9.0168, -9.2494, -9.1792, -9.0168, -9.2494, -9.1792, 15.8384, 15.6524, 1.5146, 1.9362, 15.6524, 1.5146, 1.9362, 14.974, 0, 0, 1.93498627759188, 8.55163596816083, 15.1677381022684, -1.93498627759188, -8.55163596816083, -15.1677381022684, 0, 0.0238269291828461, -0.244238930292991, 4.39508124233437, -0.0238269291828461, 0.244238930292991, -4.39508124233437, -1.89858387288271, -0.927809352857772, -1.10742752703369, 1.23096755420124, -2.22327591578999, -1.10742752703369, 1.23096755420124, -2.22327591578999, -0.574144540287477, -0.272324131191442, -1.66297412423435, -3.52473328883379, -0.272324131191442, -1.66297412423435, -3.52473328883379, -4.44089209850063E-17, -4.44089209850063E-17, 0.295973921644049, -0.952476234327165, 4.62764712369284, -0.29597392164405, 0.952476234327165, -4.62764712369284, -4.44089209850063E-17, 0.755561531385885, 0.96965704641076, -1.04874475563672, -0.755561531385885, -0.96965704641076, 1.04874475563672, 0, -8.88178419700125E-17, -8.88178419700125E-17, -2.27213865455679, 2.62068190134895, 10.46424956607, 2.27213865455679, -2.62068190134895, -10.46424956607, -1.33226762955019E-16, 0.505149005191256, 9.023283935737, 12.4419154069332, -0.505149005191256, -9.023283935737, -12.4419154069332, 1.31302213143179, -1.56994681589844, -1.6132516828964, -1.93476231111313, 1.24600961564034, -1.6132516828964, -1.93476231111313, 1.24600961564034, -0.916102246945221, -1.15341023385907, 0.0679548535942194, 1.21923750048419, -1.15341023385907, 0.0679548535942194, 1.21923750048419, 4.44089209850063E-17, 4.44089209850063E-17, -0.866748197406053, -2.37620306856168, -1.04181193052172, 0.866748197406053, 2.37620306856168, 1.04181193052172, 4.44089209850063E-17, -0.296525162996019, 1.25545730805391, 3.71906045091021, 0.29652516299602, -1.25545730805391, -3.71906045091021, 0, 2.15229559017491, 2.63997203948315, 2.88310527131121, 1.08475359067976, -1.84315670321758, 2.88310527131121, 1.08475359067976, -1.84315670321758, 1.85591583782068, 1.31826611955976, -4.08303895625175, -6.91689571702907, 1.31826611955976, -4.08303895625175, -6.91689571702907, 0, 0, 0.0988529041750603, 0.0502665499295525, 1.01706930838328, -0.0988529041750603, -0.0502665499295526, -1.01706930838328, 4.44089209850063E-17, 0.0182012962139708, 0.618271764328891, 0.528820419727892, -0.0182012962139707, -0.618271764328891, -0.528820419727892, 1.27953376484632, 1.05464034445745, 1.06849192617536, 1.29477915707343, -1.80131176088519, 1.06849192617536, 1.29477915707343, -1.80131176088519, 1.05127818065678, 1.14328402799826, 0.147983699397682, 0.758893489554762, 1.14328402799826, 0.147983699397682, 0.758893489554763, 0, -0.762854122695589, -0.950093864177193, -0.896770402353652, -1.16680283146184, -1.26709316444533, -0.896770402353652, -1.16680283146184, -1.26709316444533, -1.68350389453852, -1.96917864045415, -1.073952457854, 2.29589238418201, -1.96917864045415, -1.073952457854, 2.29589238418201, -7.7715611723761E-17, -5.55111512312578E-17, 0.0240354599738873, -1.13762060193993, -1.84086075028633, -0.0240354599738874, 1.13762060193993, 1.84086075028633, -5.55111512312578E-17, -0.00731797896493922, -1.00726341412445, -1.67921538930502, 0.00731797896493909, 1.00726341412445, 1.67921538930502, -1.77067835154163, -1.72694930552193, -2.02147369107245, -3.46120440517578, -5.42293017289516, -2.02147369107245, -3.46120440517578, -5.42293017289516, -1.81913811099514, -1.80524552106467, -0.308170447500367, -1.31680547975447, -1.80524552106467, -0.308170447500367, -1.31680547975447, 0]; 7 | var happyaxis = [-3.6804, 3.8492, 3.1128, 0.3552, 1.2418, 3.1128, 0.3552, 1.2418, -5.3888, -7.6816, 0.0542000000000002, 4.2798, -7.6816, 0.0542000000000002, 4.2798, 0, 0, -3.5408, 3.0712, 7.0442, 3.5408, -3.0712, -7.0442, 0, 2.1176, 2.575, 2.1302, -2.1176, -2.575, -2.1302, 4.72, -2.9876, 1.291, 1.9114, 3.0876, 1.291, 1.9114, 3.0876, -6.9384, -6.1032, -6.0298, 2.6348, -6.1032, -6.0298, 2.6348, -11.7576, -4.44089209850063E-17, -3.33066907387547E-17, -0.666342789075971, -6.0838299041835, -8.09295988385648, 0.666342789075971, 6.0838299041835, 8.09295988385648, -4.44089209850063E-17, 0.335225594087923, 2.46216812769978, -2.29332046445224, -0.335225594087923, -2.46216812769978, 2.29332046445224, -1.31118412456019, -0.256508018691095, -0.358033814045386, 1.44243860485824, 3.33623660331717, -0.358033814045386, 1.44243860485824, 3.33623660331717, 1.02104033366303, 2.37903282916426, 1.83761034778044, 1.17579017959672, 2.37903282916426, 1.83761034778044, 1.17579017959672, 4.44089209850063E-17, 4.44089209850063E-17, 1.44553490065014, 3.25201037152906, 1.52786297776612, -1.44553490065014, -3.25201037152906, -1.52786297776612, 4.44089209850063E-17, 1.41987741110572, 2.03949815862409, 0.704496177795203, -1.41987741110572, -2.03949815862409, -0.704496177795203, 0, 0, 0, 2.32089005501046, 8.2004699241545, 9.02785264380681, -2.32089005501046, -8.2004699241545, -9.02785264380682, 0, 1.80607391904883, 19.5478576675537, 40.2099356339615, -1.80607391904883, -19.5478576675537, -40.2099356339615, 3.31999492040294, 2.47801758596406, 2.63198730012136, 0.250964203054187, -4.2740278434618, 2.63198730012136, 0.250964203054187, -4.2740278434618, -0.380111558668358, -0.937259386594074, -1.36618028449039, -0.662055959541116, -0.937259386594074, -1.36618028449039, -0.662055959541116, -4.44089209850063E-17, -4.44089209850063E-17, -1.34022486583498, -2.76114288356605, -1.42272873070436, 1.34022486583498, 2.76114288356605, 1.42272873070436, -4.44089209850063E-17, -0.981461694327258, 4.8738444231396, -3.72794395551649, 0.981461694327258, -4.8738444231396, 3.72794395551649, 0, 1.30627261918698, 1.81803679205044, 1.68843663143742, 2.56463742946301, 1.43182649653633, 1.68843663143742, 2.56463742946301, 1.43182649653633, 1.18074184338601, 1.43513171383725, 6.90719763233261, -1.1115336009357, 1.43513171383725, 6.90719763233261, -1.1115336009357, -3.88578058618805E-17, -3.33066907387547E-17, -0.0601636152042345, -0.41317835167411, 0.627694869579082, 0.0601636152042344, 0.41317835167411, -0.627694869579082, -2.77555756156289E-17, 0.00366706940309695, 0.297968425724437, 1.09982632273336, -0.00366706940309698, -0.297968425724437, -1.09982632273336, -1.60810360624062, -1.52910873346637, -1.53785179605942, -0.812853930949932, -0.767842482084008, -1.53785179605942, -0.812853930949932, -0.767842482084008, -1.66422626280928, -1.7494947574052, -1.26111226605018, 3.21392723077718, -1.7494947574052, -1.26111226605018, 3.21392723077718, 0, -0.0833652467301549, 0.372450671567337, 0.387201887418256, 1.10961312870629, 1.03513527802723, 0.387201887418255, 1.10961312870629, 1.03513527802723, 1.44049499106293, 1.53278623556534, 2.20949939757829, -1.11392398932374, 1.53278623556534, 2.20949939757829, -1.11392398932374, 0, 2.22044604925031E-17, 0.0876067315082398, 1.18328003858253, 1.74422204741945, -0.0876067315082397, -1.18328003858253, -1.74422204741945, -2.22044604925031E-17, -0.001718313706187, 0.68205874913478, 0.581814282931261, 0.001718313706187, -0.68205874913478, -0.581814282931261, -6.12734886158736, -6.16231355914618, -6.30453521311102, -6.78278462041507, -7.60669697586982, -6.30453521311102, -6.78278462041507, -7.60669697586982, -6.09902206473922, -6.12172192882131, -2.59588583193055, 3.35944140524417, -6.12172192882131, -2.59588583193055, 3.35944140524417, 0]; 8 | 9 | 10 | function Walker( rm ) { 11 | 12 | this.rm = rm; 13 | this.paused = false; 14 | 15 | this.markers = []; 16 | for ( i = 0; i < 46; i++ ) this.markers.push( 0 ); 17 | 18 | this.vertices = []; 19 | this.values = []; 20 | for ( i = 0; i < 15; i++ ) 21 | { 22 | this.vertices.push( new THREE.Vector3(0,0,0) ); 23 | this.values.push( 0,0,0 ); 24 | } 25 | 26 | this.rm.setUniform( "anchors", "v3v", this.vertices ); 27 | 28 | this.reset(); 29 | 30 | } 31 | 32 | function reset() { 33 | 34 | this.speed = 1; 35 | this.gender = 5; 36 | this.nervous = 0; 37 | this.weight = 0; 38 | this.happy = 0; 39 | 40 | this.walkertime = 0; 41 | this.initphase = 0; 42 | 43 | this.starttime = 44 | this.lasttime = Date.now() * .001; 45 | 46 | this.sizes = [ 47 | 1.25, //head 48 | 1.25, // neck 49 | 50 | 1, //shoulder L 51 | 1, //elbow L 52 | .5,//hand L 53 | 54 | 1, //shoulder R 55 | 1, //elbow R 56 | .5,//hand R 57 | 58 | 1, //plexus 59 | 60 | .75,//hip L 61 | 1., //knee L 62 | 1.5,//foot L 63 | 64 | .75,//hip R 65 | 1., //knee R 66 | 1.5 //foot R 67 | ]; 68 | 69 | } 70 | 71 | function update() { 72 | 73 | var curtime = Date.now() * .0005 - this.starttime; 74 | 75 | var timediff = (curtime - this.lasttime); 76 | 77 | var speed = ((((meanwalker[45] 78 | + (this.gender * genderaxis[45])) 79 | + (this.weight * weightaxis[45])) 80 | + (this.nervous * nervousaxis[45])) 81 | + (this.happy * happyaxis[45])); 82 | 83 | //this.walkertime = this.walkertime + ((((timediff ) * 2) * Math.PI) * (120 / (speed / this.speed))); 84 | this.walkertime = this.walkertime + (( timediff * 2 * Math.PI) * ( 120 / ( speed / this.speed ) )); 85 | 86 | var i = 0; 87 | while (i < 46) { 88 | 89 | this.markers[i] = ( 90 | ( 91 | ( 92 | ( 93 | (((meanwalker[i] + (weightaxis[i] * this.weight)) 94 | + (genderaxis[i] * this.gender)) 95 | + (nervousaxis[i] * this.nervous)) 96 | + (happyaxis[i] * this.happy) 97 | ) 98 | 99 | + 100 | (((((meanwalker[i + 46] + (genderaxis[i + 46] * this.gender)) 101 | + (weightaxis[i + 46] * this.weight)) 102 | + (nervousaxis[i + 46] * this.nervous)) 103 | + (happyaxis[i + 46] * this.happy)) * Math.sin(this.walkertime + ((this.initphase * Math.PI) / 180))) 104 | ) 105 | 106 | + (((((meanwalker[i + 92] 107 | + (genderaxis[i + 92] * this.gender)) 108 | + (weightaxis[i + 92] * this.weight)) 109 | + (nervousaxis[i + 92] * this.nervous)) 110 | + (happyaxis[i + 92] * this.happy)) * Math.cos(this.walkertime + ((this.initphase * Math.PI) / 180))) 111 | ) 112 | 113 | + (((((meanwalker[i + 138] 114 | + (genderaxis[i + 138] * this.gender)) 115 | + (weightaxis[i + 138] * this.weight)) 116 | + (nervousaxis[i + 138] * this.nervous)) 117 | + (happyaxis[i + 138] * this.happy)) * Math.sin(2 * (this.walkertime + ((this.initphase * Math.PI) / 180)))) 118 | ) 119 | 120 | + (((((meanwalker[i + 184] 121 | + (genderaxis[i + 184] * this.gender)) 122 | + (weightaxis[i + 184] * this.weight)) 123 | + (nervousaxis[i + 184] * this.nervous)) 124 | + (happyaxis[i + 184] * this.happy)) * Math.cos(2 * (this.walkertime + ((this.initphase * Math.PI) / 180)))); 125 | i++; 126 | } 127 | 128 | i = 0; 129 | this.values = []; 130 | this.sizes = []; 131 | while ( i < 15 ) 132 | { 133 | this.vertices[ i ].x = this.markers[i + 15]; 134 | this.vertices[ i ].y = this.markers[i + 30]; 135 | this.vertices[ i ].z = this.markers[i ]; 136 | 137 | var v = this.vertices[i].multiplyScalar( .01 ); 138 | this.values.push( v.x, v.y, v.z); 139 | 140 | //this.sizes.push( v.x ); 141 | 142 | if( i == 8 ) 143 | { 144 | this.rm.target.copy( v ); 145 | this.rm.target.y += 2; 146 | } 147 | 148 | i++; 149 | } 150 | 151 | this.rm.material.uniforms.anchors.value = this.vertices; 152 | this.rm.material.uniforms.anchors.needsUpdate = true; 153 | this.lasttime = curtime; 154 | 155 | } 156 | 157 | 158 | var _p = Walker.prototype; 159 | _p.constructor = Walker; 160 | _p.reset = reset; 161 | _p.update = update; 162 | return Walker; 163 | 164 | }(); -------------------------------------------------------------------------------- /cells.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 18 | 19 | 20 | 21 | 22 | 23 | 53 | 54 | 55 | -------------------------------------------------------------------------------- /colors.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 71 | 72 | 73 | -------------------------------------------------------------------------------- /composer.js: -------------------------------------------------------------------------------- 1 | var Composer = function(){ 2 | 3 | function Composer( raymarching ){ 4 | 5 | this.renderer = raymarching.renderer; 6 | this.scene = raymarching.scene; 7 | this.camera = raymarching.renderCamera; 8 | 9 | this.composer = new THREE.EffectComposer( this.renderer ); 10 | this.composer.addPass( new THREE.RenderPass( this.scene, this.camera ) ); 11 | 12 | this.fxaa = new THREE.ShaderPass( THREE.FXAAShader ); 13 | this.fxaa.renderToScreen = true; 14 | this.composer.addPass( this.fxaa ); 15 | 16 | } 17 | 18 | function setSize(width, height) { 19 | this.composer.setSize(width, height); 20 | this.fxaa.uniforms.resolution.value.set( 1 / width, 1 / height ); 21 | } 22 | 23 | function render() 24 | { 25 | this.composer.render(); 26 | } 27 | 28 | var _p = Composer.prototype; 29 | _p.render = render; 30 | _p.setSize = setSize; 31 | return Composer; 32 | 33 | }(); -------------------------------------------------------------------------------- /glsl/bits/draw/ao.glsl: -------------------------------------------------------------------------------- 1 | 2 | //https://www.shadertoy.com/view/Xds3zN 3 | 4 | float calcAO( in vec3 pos, in vec3 nor ) 5 | { 6 | float occ = 0.0; 7 | float sca = 1.0; 8 | for( int i=0; i maximumDistance) break; 12 | vec2 result = field( rayOrigin + rayDir * dist ); 13 | latest = result.x; 14 | dist += latest; 15 | type = result.y; 16 | } 17 | 18 | vec2 res = vec2(-1.0, -1.0 ); 19 | if (dist < maximumDistance) { res = vec2(dist, type ); } 20 | return res; 21 | 22 | } 23 | -------------------------------------------------------------------------------- /glsl/bits/draw/rim.glsl: -------------------------------------------------------------------------------- 1 | //http://www.roxlu.com/2014/037/opengl-rim-shader 2 | vec3 rimlight( vec3 pos, vec3 nor ) 3 | { 4 | return vec3(smoothstep(0., 1.0, 1.0 - max(dot( normalize(-pos), nor), 0.0) )); 5 | } 6 | -------------------------------------------------------------------------------- /glsl/bits/draw/shadows.glsl: -------------------------------------------------------------------------------- 1 | 2 | //https://www.shadertoy.com/view/Xds3zN 3 | 4 | float softshadow( in vec3 ro, in vec3 rd, in float mint, in float tmax, in float K ) 5 | { 6 | float res = 1.0; 7 | float t = mint; 8 | for( int i=0; itmax ) break; 14 | } 15 | return clamp( res, 0.0, 1.0 ); 16 | } -------------------------------------------------------------------------------- /glsl/bits/geom/box.glsl: -------------------------------------------------------------------------------- 1 | 2 | 3 | //-------- unit box 4 | vec2 box(vec3 p ) 5 | { 6 | return vec2( length( max( abs( p )-vec3(1.), 0.0 ) ),1.); 7 | } 8 | 9 | //-------- variable size box 10 | 11 | vec2 box(vec3 p, vec3 size ) 12 | { 13 | return vec2( length( max( abs( p )-size, 0.0 ) ),1.); 14 | } 15 | vec2 box(vec3 p, vec3 size, vec3 pos ) 16 | { 17 | return box( p-pos, size ); 18 | } 19 | 20 | 21 | 22 | //-------- variable size box + rounded corners 23 | 24 | vec2 box(vec3 p, vec3 size, float corner ) 25 | { 26 | return vec2( length( max( abs( p-pos )-size, 0.0 ) )-corner,1.); 27 | } 28 | vec2 box(vec3 p, vec3 size, float corner, vec3 pos ) 29 | { 30 | return box( p-pos, size, corner ); 31 | } 32 | 33 | 34 | //requires glsl/bits/util/rotation.glsl 35 | 36 | //-------- variable size box + rounded corners + transforms 37 | 38 | vec2 box(vec3 p, vec4 quat ) 39 | { 40 | return return box( p * rotationMatrix3( quat.xyz, quat.w ) ); 41 | } 42 | 43 | vec2 box(vec3 p, vec3 size, vec4 quat ) 44 | { 45 | return return box( p * rotationMatrix3( quat.xyz, quat.w ), size ); 46 | } 47 | 48 | vec2 box(vec3 p, vec3 size, float corner, vec4 quat ) 49 | { 50 | return return box( ( p-pos ) * rotationMatrix3( quat.xyz, quat.w ), size, corner ); 51 | } 52 | 53 | vec2 box(vec3 p, vec3 size, float corner, vec3 pos, vec4 quat ) 54 | { 55 | return return box( ( p-pos ) * rotationMatrix3( quat.xyz, quat.w ), size, corner ); 56 | } -------------------------------------------------------------------------------- /glsl/bits/geom/cylinder.glsl: -------------------------------------------------------------------------------- 1 | 2 | //requires glsl/bits/util/rotation.glsl 3 | 4 | //http://www.pouet.net/topic.php?post=365312 5 | vec2 cylinder( vec3 p, float h, float r, vec3 pos, vec4 quat ) { 6 | mat3 transform = rotationMatrix3( quat.xyz, quat.w ); 7 | vec3 pp = (p - pos ) * transform; 8 | return vec2( max(length(pp.xz)-r, abs(pp.y)-h),1. ); 9 | } 10 | vec2 cylinder( vec3 p, float h, float r, vec3 pos ) { 11 | vec3 pp = (p - pos ); 12 | return vec2( max(length(pp.xz)-r, abs(pp.y)-h),1. ); 13 | } 14 | vec2 cylinder( vec3 p, float h, float r ) { 15 | return vec2( max(length(p.xz)-r, abs(p.y)-h),1. ); 16 | } 17 | -------------------------------------------------------------------------------- /glsl/bits/geom/madelbulb.glsl: -------------------------------------------------------------------------------- 1 | 2 | //http://www.kevs3d.co.uk/dev/shaders/mandelbulb.html 3 | 4 | vec2 MandelBulb(vec3 pos) 5 | { 6 | const int Iterations = 12; 7 | const float Bailout = 8.0; 8 | float Power = 5.0 + sin(time*0.5)*4.0; 9 | 10 | vec3 z = pos; 11 | float dr = 1.0; 12 | float r = 0.0; 13 | for (int i = 0; i < Iterations; i++) 14 | { 15 | r = length(z); 16 | if (r > Bailout) break; // TODO: test if better to continue loop and if() rather than break? 17 | 18 | // convert to polar coordinates 19 | float theta = acos(z.z/r); 20 | float phi = atan(z.y,z.x); 21 | dr = pow(r, Power-1.0)*Power*dr + 1.0; 22 | 23 | // scale and rotate the point 24 | float zr = pow(r,Power); 25 | theta = theta*Power; 26 | phi = phi*Power; 27 | 28 | // convert back to cartesian coordinates 29 | z = zr*vec3(sin(theta)*cos(phi), sin(phi)*sin(theta), cos(theta)); 30 | z += pos; 31 | } 32 | return vec2( 0.5*log(r)*r/dr, 1. ); 33 | } -------------------------------------------------------------------------------- /glsl/bits/geom/mandelBox.glsl: -------------------------------------------------------------------------------- 1 | //http://www.kevs3d.co.uk/dev/shaders/mandelbox.html 2 | vec2 MandleBox(vec3 pos) 3 | { 4 | const int Iterations = 12; 5 | const float Scale = 3.0; 6 | const float FoldingLimit = 100.0; 7 | 8 | float MinRad2 = 0.15 + abs(sin(time*.25))*.75; 9 | vec4 scale = vec4(Scale, Scale, Scale, abs(Scale)) / MinRad2; 10 | float AbsScalem1 = abs(Scale - 1.0); 11 | float AbsScaleRaisedTo1mIters = pow(abs(Scale), float(1-Iterations)); 12 | 13 | vec4 p = vec4(pos,1.0), p0 = p; // p.w is the distance estimate 14 | 15 | for (int i=0; iFoldingLimit) break; 22 | } 23 | return vec2( ((length(p.xyz) - AbsScalem1) / p.w - AbsScaleRaisedTo1mIters), 1. ); 24 | } -------------------------------------------------------------------------------- /glsl/bits/geom/plane.glsl: -------------------------------------------------------------------------------- 1 | //no height 2 | vec2 plane( vec3 p , vec3 n) { return vec2( dot(p, n), 1. ); } 3 | //with height 4 | vec2 plane( vec3 p , vec4 n) { return vec2( dot(p, n.xyz) + n.w, 1. ); } 5 | -------------------------------------------------------------------------------- /glsl/bits/geom/platonic_solids_ref.glsl: -------------------------------------------------------------------------------- 1 | 2 | vec3 n1 = vec3(1.000,0.000,0.000); 3 | vec3 n2 = vec3(0.000,1.000,0.000); 4 | vec3 n3 = vec3(0.000,0.000,1.000); 5 | vec3 n4 = vec3(0.577,0.577,0.577); 6 | vec3 n5 = vec3(-0.577,0.577,0.577); 7 | vec3 n6 = vec3(0.577,-0.577,0.577); 8 | vec3 n7 = vec3(0.577,0.577,-0.577); 9 | vec3 n8 = vec3(0.000,0.357,0.934); 10 | vec3 n9 = vec3(0.000,-0.357,0.934); 11 | vec3 n10 = vec3(0.934,0.000,0.357); 12 | vec3 n11 = vec3(-0.934,0.000,0.357); 13 | vec3 n12 = vec3(0.357,0.934,0.000); 14 | vec3 n13 = vec3(-0.357,0.934,0.000); 15 | vec3 n14 = vec3(0.000,0.851,0.526); 16 | vec3 n15 = vec3(0.000,-0.851,0.526); 17 | vec3 n16 = vec3(0.526,0.000,0.851); 18 | vec3 n17 = vec3(-0.526,0.000,0.851); 19 | vec3 n18 = vec3(0.851,0.526,0.000); 20 | vec3 n19 = vec3(-0.851,0.526,0.000); 21 | 22 | // p as usual, e exponent (p in the paper), r radius or something like that 23 | float octahedral(vec3 p, float e, float r) { 24 | float s = pow(abs(dot(p,n4)),e); 25 | s += pow(abs(dot(p,n5)),e); 26 | s += pow(abs(dot(p,n6)),e); 27 | s += pow(abs(dot(p,n7)),e); 28 | s = pow(s, 1./e); 29 | return s-r; 30 | } 31 | 32 | 33 | float dodecahedral(vec3 p, float e, float r) { 34 | float s = pow(abs(dot(p,n14)),e); 35 | s += pow(abs(dot(p,n15)),e); 36 | s += pow(abs(dot(p,n16)),e); 37 | s += pow(abs(dot(p,n17)),e); 38 | s += pow(abs(dot(p,n18)),e); 39 | s += pow(abs(dot(p,n19)),e); 40 | s = pow(s, 1./e); 41 | return s-r; 42 | } 43 | 44 | float icosahedral(vec3 p, float e, float r) { 45 | float s = pow(abs(dot(p,n4)),e); 46 | s += pow(abs(dot(p,n5)),e); 47 | s += pow(abs(dot(p,n6)),e); 48 | s += pow(abs(dot(p,n7)),e); 49 | s += pow(abs(dot(p,n8)),e); 50 | s += pow(abs(dot(p,n9)),e); 51 | s += pow(abs(dot(p,n10)),e); 52 | s += pow(abs(dot(p,n11)),e); 53 | s += pow(abs(dot(p,n12)),e); 54 | s += pow(abs(dot(p,n13)),e); 55 | s = pow(s, 1./e); 56 | return s-r; 57 | } 58 | 59 | float toctahedral(vec3 p, float e, float r) { 60 | float s = pow(abs(dot(p,n1)),e); 61 | s += pow(abs(dot(p,n2)),e); 62 | s += pow(abs(dot(p,n3)),e); 63 | s += pow(abs(dot(p,n4)),e); 64 | s += pow(abs(dot(p,n5)),e); 65 | s += pow(abs(dot(p,n6)),e); 66 | s += pow(abs(dot(p,n7)),e); 67 | s = pow(s, 1./e); 68 | return s-r; 69 | } 70 | 71 | float ticosahedral(vec3 p, float e, float r) { 72 | float s = pow(abs(dot(p,n4)),e); 73 | s += pow(abs(dot(p,n5)),e); 74 | s += pow(abs(dot(p,n6)),e); 75 | s += pow(abs(dot(p,n7)),e); 76 | s += pow(abs(dot(p,n8)),e); 77 | s += pow(abs(dot(p,n9)),e); 78 | s += pow(abs(dot(p,n10)),e); 79 | s += pow(abs(dot(p,n11)),e); 80 | s += pow(abs(dot(p,n12)),e); 81 | s += pow(abs(dot(p,n13)),e); 82 | s += pow(abs(dot(p,n14)),e); 83 | s += pow(abs(dot(p,n15)),e); 84 | s += pow(abs(dot(p,n16)),e); 85 | s += pow(abs(dot(p,n17)),e); 86 | s += pow(abs(dot(p,n18)),e); 87 | s += pow(abs(dot(p,n19)),e); 88 | s = pow(s, 1./e); 89 | return s-r; 90 | } -------------------------------------------------------------------------------- /glsl/bits/geom/sierpinski.glsl: -------------------------------------------------------------------------------- 1 | //http://www.kevs3d.co.uk/dev/shaders/fractal.html 2 | vec2 sierpinski(vec3 pos) 3 | { 4 | const int Iterations = 14; 5 | const float Scale = 1.85; 6 | const float Offset = 2.0; 7 | 8 | vec3 a1 = vec3(1,1,1); 9 | vec3 a2 = vec3(-1,-1,1); 10 | vec3 a3 = vec3(1,-1,-1); 11 | vec3 a4 = vec3(-1,1,-1); 12 | vec3 c; 13 | float dist, d; 14 | for (int n = 0; n < Iterations; n++) 15 | { 16 | if(pos.x+pos.y<0.) pos.xy = -pos.yx; // fold 1 17 | if(pos.x+pos.z<0.) pos.xz = -pos.zx; // fold 2 18 | if(pos.y+pos.z<0.) pos.zy = -pos.yz; // fold 3 19 | pos = pos*Scale - Offset*(Scale-1.0); 20 | } 21 | return vec2( length(pos) * pow(Scale, -float(Iterations)), 1. ); 22 | } -------------------------------------------------------------------------------- /glsl/bits/geom/sphere.glsl: -------------------------------------------------------------------------------- 1 | 2 | //requires glsl/bits/util/rotation.glsl 3 | 4 | vec2 sphere( vec3 p, float radius, vec3 pos, vec4 quat) 5 | { 6 | return vec2(length( ( p-pos ) * rotationMatrix3( quat.xyz, quat.w ) ) - radius,1); 7 | } 8 | vec2 sphere( vec3 p, float radius, vec3 pos ) 9 | { 10 | return vec2( length( ( p-pos) ) - radius,1); 11 | } 12 | vec2 sphere( vec3 p, float radius ) 13 | { 14 | return vec2(length( p ) - radius,1); 15 | } -------------------------------------------------------------------------------- /glsl/bits/geom/torus.glsl: -------------------------------------------------------------------------------- 1 | 2 | //requires glsl/bits/util/rotation.glsl 3 | 4 | vec2 torus( vec3 p, vec2 radii, vec3 pos, vec4 quat ) 5 | { 6 | vec3 pp = ( p - pos ) * rotationMatrix3( quat.xyz, quat.w ); 7 | float d = length( vec2( length( pp.xz ) - radii.x, pp.y ) ) - radii.y; 8 | return vec2(d,1.); 9 | } 10 | 11 | vec2 torus( vec3 p, vec2 radii, vec4 quat ) 12 | { 13 | vec3 pp = p * rotationMatrix3( quat.xyz, quat.w ); 14 | return vec2(length( vec2( length( pp.xz ) - radii.x, pp.y ) ) - radii.y,1.); 15 | } 16 | 17 | vec2 torus( vec3 p, vec2 radii, vec3 pos ) 18 | { 19 | vec3 pp = ( p - pos ); 20 | return vec2(length( vec2( length( pp.xz ) - radii.x, pp.y ) ) - radii.y,1.); 21 | } 22 | 23 | vec2 torus( vec3 p, vec2 radii ) 24 | { 25 | return vec2(length( vec2( length( p.xz ) - radii.x, p.y ) ) - radii.y,1.); 26 | } 27 | 28 | 29 | vec2 torus( vec3 p, float radius, float section ) 30 | { 31 | return torus( p, vec2( radius, section ) ); 32 | } 33 | vec2 torus( vec3 p, float radius, float section, vec3 pos ) 34 | { 35 | return torus( p, vec2( radius, section ), pos ); 36 | } 37 | vec2 torus( vec3 p, float radius, float section, vec4 quat ) 38 | { 39 | return torus( p, vec2( radius, section ), quat ); 40 | } 41 | vec2 torus( vec3 p, float radius, float section, vec3 pos, vec4 quat ) 42 | { 43 | return torus( p, vec2( radius, section ), pos, quat ); 44 | } -------------------------------------------------------------------------------- /glsl/bits/util/lookat.glsl: -------------------------------------------------------------------------------- 1 | 2 | //https://github.com/stackgl/glsl-look-at/blob/gh-pages/index.glsl 3 | 4 | mat3 calcLookAtMatrix(vec3 origin, vec3 target, float roll) { 5 | vec3 rr = vec3(sin(roll), cos(roll), 0.0); 6 | vec3 ww = normalize(target - origin); 7 | vec3 uu = normalize(cross(ww, rr)); 8 | vec3 vv = normalize(cross(uu, ww)); 9 | return mat3(uu, vv, ww); 10 | } 11 | -------------------------------------------------------------------------------- /glsl/bits/util/noise.glsl: -------------------------------------------------------------------------------- 1 | //http://www.kevs3d.co.uk/dev/shaders/distancefield3.html 2 | 3 | float hash(in float n) 4 | { 5 | return fract(sin(n)*43758.5453123); 6 | } 7 | 8 | float noise(in vec2 x) 9 | { 10 | vec2 p = floor(x); 11 | vec2 f = fract(x); 12 | f = f*f*(3.0-2.0*f); 13 | float n = p.x + p.y*57.0; 14 | float res = mix(mix( hash(n+ 0.0), hash(n+ 1.0),f.x), 15 | mix( hash(n+ 57.0), hash(n+ 58.0),f.x),f.y); 16 | return res; 17 | } 18 | 19 | float fractalNoise(in vec2 xy) 20 | { 21 | const int octaves = 3; 22 | float w = 0.7; 23 | float f = 0.0; 24 | for (int i = 0; i < octaves; i++) 25 | { 26 | f += Noise(xy) * w; 27 | w *= 0.5; 28 | xy *= 2.333; 29 | } 30 | return f; 31 | } -------------------------------------------------------------------------------- /glsl/bits/util/operations.glsl: -------------------------------------------------------------------------------- 1 | 2 | //operations 3 | 4 | vec2 unite(vec2 a, vec2 b){return vec2(min(a.x, b.x),1.);} 5 | vec2 intersect(vec2 a, vec2 b){return vec2(max(a.x, b.x),1.);} 6 | vec2 subtract(vec2 a, vec2 b){ return vec2(max(-a.x, b.x),1.); } 7 | 8 | vec2 blend( vec2 a, vec2 b, float t ){ return vec2(mix(a.x, b.x, t ),1.);} 9 | //http://iquilezles.org/www/articles/smin/smin.htm 10 | vec2 smin( vec2 a, vec2 b, float k ) 11 | { 12 | float h = clamp( 0.5+0.5*(b.x-a.x)/k, 0.0, 1.0 ); 13 | return vec2( mix( b.x, a.x, h ) - k*h*(1.0-h), 1. ); 14 | } 15 | vec2 expBlend( vec2 a, vec2 b, float k ) 16 | { 17 | float res = exp( -k*a.x ) + exp( -k*b.x ); 18 | return vec2( -log( res )/k, 1. ); 19 | } 20 | vec2 powBlend( vec2 a, vec2 b, float k ) 21 | { 22 | float a = pow( a.x, k ); 23 | float b = pow( b.x, k ); 24 | return vec2( pow( (a*b)/(a+b), 1.0/k ), 1. ); 25 | } -------------------------------------------------------------------------------- /glsl/bits/util/perlin.glsl: -------------------------------------------------------------------------------- 1 | 2 | 3 | //http://www.pouet.net/topic.php?post=367360 4 | const vec3 pa = vec3(1., 57., 21.); 5 | const vec4 pb = vec4(0., 57., 21., 78.); 6 | float perlin(vec3 p) { 7 | vec3 i = floor(p); 8 | vec4 a = dot( i, pa ) + pb; 9 | vec3 f = cos((p-i)*acos(-1.))*(-.5)+.5; 10 | a = mix(sin(cos(a)*a),sin(cos(1.+a)*(1.+a)), f.x); 11 | a.xy = mix(a.xz, a.yw, f.y); 12 | return mix(a.x, a.y, f.z); 13 | } 14 | -------------------------------------------------------------------------------- /glsl/bits/util/rotation.glsl: -------------------------------------------------------------------------------- 1 | 2 | mat3 rotationMatrix3(vec3 axis, float angle) 3 | { 4 | axis = normalize(axis); 5 | float s = sin(angle); 6 | float c = cos(angle); 7 | float oc = 1.0 - c; 8 | 9 | return mat3(oc * axis.x * axis.x + c, oc * axis.x * axis.y - axis.z * s, oc * axis.z * axis.x + axis.y * s, 10 | oc * axis.x * axis.y + axis.z * s, oc * axis.y * axis.y + c, oc * axis.y * axis.z - axis.x * s, 11 | oc * axis.z * axis.x - axis.y * s, oc * axis.y * axis.z + axis.x * s, oc * axis.z * axis.z + c ); 12 | } 13 | -------------------------------------------------------------------------------- /glsl/bits/util/squareFrame.glsl: -------------------------------------------------------------------------------- 1 | 2 | //https://github.com/hughsk/glsl-square-frame 3 | 4 | vec2 squareFrame(vec2 screenSize) { 5 | vec2 position = 2.0 * (gl_FragCoord.xy / screenSize.xy) - 1.0; 6 | position.x *= screenSize.x / screenSize.y; 7 | return position; 8 | } 9 | vec2 squareFrame(vec2 screenSize, vec2 coord) { 10 | vec2 position = 2.0 * (coord.xy / screenSize.xy) - 1.0; 11 | position.x *= screenSize.x / screenSize.y; 12 | return position; 13 | } -------------------------------------------------------------------------------- /glsl/cells.glsl: -------------------------------------------------------------------------------- 1 | uniform vec2 resolution; 2 | uniform float time; 3 | #define PI 3.1415926535897932384626433832795 4 | 5 | float hash(in float n) 6 | { 7 | return fract(sin(n)*43758.5453123); 8 | } 9 | 10 | void main() { 11 | 12 | vec2 xy = ( ( gl_FragCoord.xy / resolution.xy )- .5) * 2.; 13 | xy.x *= resolution.x/resolution.y; 14 | 15 | float length = pow( 2.,53. ); 16 | int id = 0; 17 | vec2 p = vec2(0.); 18 | vec3 pp = vec3( 0.,0., .5 ); 19 | vec3 lightDir = vec3( sin( time ), 1., cos( time * .5 ) ); 20 | 21 | const int count = 200; 22 | for( int i = 0; i < count; i++ ) 23 | { 24 | float an = sin( time * PI * .00001 ) - hash( float(i) ) * PI * 2.; 25 | 26 | float ra = sqrt( hash( an ) ); 27 | 28 | p.x = lightDir.x + cos( an ) * ra; 29 | p.y = lightDir.z + sin( an ) * ra; 30 | 31 | float di = distance( xy, p ); 32 | length = min( length, di ); 33 | if( length == di ) 34 | { 35 | id = i; 36 | pp.xy = p; 37 | pp.z = float( id )/float( count ) * ( -xy.x * 1.25 ); 38 | } 39 | } 40 | 41 | gl_FragColor = vec4( pp + vec3( 1.) * ( 1. - max( 0.0, dot( pp, lightDir)) ), 1. ); 42 | 43 | } -------------------------------------------------------------------------------- /glsl/colors.glsl: -------------------------------------------------------------------------------- 1 | 2 | uniform vec2 resolution; 3 | uniform float time; 4 | uniform float fov; 5 | uniform float raymarchMaximumDistance; 6 | uniform float raymarchPrecision; 7 | uniform vec3 camera; 8 | uniform vec3 target; 9 | 10 | 11 | //uses most of the StackGL methods 12 | //https://github.com/stackgl 13 | 14 | //https://github.com/hughsk/glsl-square-frame 15 | 16 | vec2 squareFrame(vec2 screenSize) { 17 | vec2 position = 2.0 * (gl_FragCoord.xy / screenSize.xy) - 1.0; 18 | position.x *= screenSize.x / screenSize.y; 19 | return position; 20 | } 21 | vec2 squareFrame(vec2 screenSize, vec2 coord) { 22 | vec2 position = 2.0 * (coord.xy / screenSize.xy) - 1.0; 23 | position.x *= screenSize.x / screenSize.y; 24 | return position; 25 | } 26 | 27 | //https://github.com/stackgl/glsl-look-at/blob/gh-pages/index.glsl 28 | 29 | mat3 calcLookAtMatrix(vec3 origin, vec3 target, float roll) { 30 | vec3 rr = vec3(sin(roll), cos(roll), 0.0); 31 | vec3 ww = normalize(target - origin); 32 | vec3 uu = normalize(cross(ww, rr)); 33 | vec3 vv = normalize(cross(uu, ww)); 34 | return mat3(uu, vv, ww); 35 | } 36 | 37 | //https://github.com/stackgl/glsl-camera-ray 38 | 39 | vec3 getRay(mat3 camMat, vec2 screenPos, float lensLength) { 40 | return normalize(camMat * vec3(screenPos, lensLength)); 41 | } 42 | vec3 getRay(vec3 origin, vec3 target, vec2 screenPos, float lensLength) { 43 | mat3 camMat = calcLookAtMatrix(origin, target, 0.0); 44 | return getRay(camMat, screenPos, lensLength); 45 | } 46 | 47 | ///////////////////////////////////////////////////////////////////////// 48 | 49 | mat3 rotationMatrix3(vec3 axis, float angle) 50 | { 51 | axis = normalize(axis); 52 | float s = sin(angle); 53 | float c = cos(angle); 54 | float oc = 1.0 - c; 55 | 56 | return mat3(oc * axis.x * axis.x + c, oc * axis.x * axis.y - axis.z * s, oc * axis.z * axis.x + axis.y * s, 57 | oc * axis.x * axis.y + axis.z * s, oc * axis.y * axis.y + c, oc * axis.y * axis.z - axis.x * s, 58 | oc * axis.z * axis.x - axis.y * s, oc * axis.y * axis.z + axis.x * s, oc * axis.z * axis.z + c ); 59 | } 60 | 61 | ///////////////////////////////////////////////////////////////////////// 62 | 63 | //primitives 64 | 65 | vec2 sphere( vec3 p, float radius, vec3 pos , vec4 quat) 66 | { 67 | mat3 transform = rotationMatrix3( quat.xyz, quat.w ); 68 | float d = length( ( p * transform )-pos ) - radius; 69 | return vec2(d,0.); 70 | } 71 | 72 | vec2 roundBox(vec3 p, vec3 size, float corner, vec3 pos, vec4 quat ) 73 | { 74 | mat3 transform = rotationMatrix3( quat.xyz, quat.w ); 75 | return vec2( length( max( abs( ( p-pos ) * transform )-size, 0.0 ) )-corner,1.); 76 | } 77 | 78 | vec2 torus( vec3 p, vec2 radii, vec3 pos, vec4 quat ) 79 | { 80 | mat3 transform = rotationMatrix3( quat.xyz, quat.w ); 81 | vec3 pp = ( p - pos ) * transform; 82 | float d = length( vec2( length( pp.xz ) - radii.x, pp.y ) ) - radii.y; 83 | return vec2(d,1.); 84 | } 85 | 86 | 87 | //operations 88 | 89 | vec2 unionAB(vec2 a, vec2 b){return vec2(min(a.x, b.x),1.);} 90 | vec2 intersectionAB(vec2 a, vec2 b){return vec2(max(a.x, b.x),1.);} 91 | vec2 blendAB( vec2 a, vec2 b, float t ){ return vec2(mix(a.x, b.x, t ),1.);} 92 | vec2 subtract(vec2 a, vec2 b){ return vec2(max(-a.x, b.x),1.); } 93 | 94 | //http://iquilezles.org/www/articles/smin/smin.htm 95 | vec2 smin( vec2 a, vec2 b, float k ) { float h = clamp( 0.5+0.5*(b.x-a.x)/k, 0.0, 1.0 ); return vec2( mix( b.x, a.x, h ) - k*h*(1.0-h), 1. ); } 96 | 97 | //utils 98 | 99 | vec3 twist( vec3 pos, float amount ) 100 | { 101 | vec3 p = normalize( pos ); 102 | float c = cos(amount * p.y); 103 | float s = sin(amount * p.y); 104 | mat2 m = mat2(c,-s,s,c); 105 | vec3 q = vec3(m*pos.xz,pos.y); 106 | return q; 107 | } 108 | 109 | //http://www.pouet.net/topic.php?post=367360 110 | 111 | #define pa vec3(1., 57., 21.) 112 | #define pb vec4(0., 57., 21., 78.) 113 | float perlin(vec3 p) { 114 | vec3 i = floor(p); 115 | vec4 a = dot( i, pa ) + pb; 116 | vec3 f = cos((p-i)*acos(-1.))*(-.5)+.5; 117 | a = mix(sin(cos(a)*a),sin(cos(1.+a)*(1.+a)), f.x); 118 | a.xy = mix(a.xz, a.yw, f.y); 119 | return mix(a.x, a.y, f.z); 120 | } 121 | 122 | ///////////////////////////////////////////////////////////////////////// 123 | 124 | // STOP ! ! ! 125 | 126 | // HAMMER TIME ! 127 | 128 | ///////////////////////////////////////////////////////////////////////// 129 | 130 | const int raymarchSteps = 200; 131 | #define PI 3.14159 132 | vec2 field( vec3 position ) 133 | { 134 | 135 | //position 136 | vec3 zero = vec3(0.); 137 | 138 | //rotation 139 | vec4 quat = vec4( 1., 0.,0.,0. ); 140 | 141 | //twist the whole result 142 | position = twist( position, sin( time ) * .5 ); 143 | 144 | //box 145 | vec2 box = roundBox( position, vec3(2.0,2.0,2.0), 0.5, zero, quat + vec4( 1., 1., 1., PI / 4. ) ); 146 | 147 | //torus 148 | vec2 to0 = torus( position, vec2( 4.0,.15), zero, quat ); 149 | vec2 to1 = torus( position, vec2( 4.0,.15), zero, vec4( 0., 0., 1., PI *.5 ) ); 150 | 151 | //spheres 152 | vec2 sre = sphere( position, 3.0, zero, quat ); 153 | vec2 sce = sphere( position, 1., zero, quat ) + perlin( position + time ) * .25; 154 | 155 | //shape composition 156 | float blend = .5 + sin( time * .5 ) * .5; 157 | vec2 _out = unionAB( sce, smin( to0, smin( to1, subtract( sre, box ), blend ), blend ) ); 158 | 159 | //color attribution 160 | 161 | //the Y value of the return value will be used to apply a different shading 162 | // _out.y = 1. is the default value, here, it will be attributed to blended areas 163 | _out.y = 1.; 164 | //we can retrieve the elements by depth 165 | //we use the raymarch precision as a threshold 166 | float d = raymarchPrecision; 167 | 168 | //then an object is found like: 169 | 170 | if( _out.x > box.x - d )_out.y = 0.80; 171 | if( _out.x > to1.x - d )_out.y = 0.66; 172 | if( _out.x > to0.x - d )_out.y = 0.25; 173 | if( _out.x > sce.x - d )_out.y = 0.; 174 | 175 | //or 176 | _out.y = 1.; 177 | _out.y -= step( box.x - d, _out.x ) * .2 178 | + step( to0.x - d, _out.x ) * .35 179 | + step( to1.x - d, _out.x ) * .75 180 | + step( sce.x - d, _out.x ) * 1.0; 181 | 182 | return _out; 183 | } 184 | 185 | ///////////////////////////////////////////////////////////////////////// 186 | 187 | // the methods below this need the field function 188 | 189 | ///////////////////////////////////////////////////////////////////////// 190 | 191 | 192 | //the actual raymarching from: 193 | //https://github.com/stackgl/glsl-raytrace/blob/master/index.glsl 194 | 195 | vec2 raymarching( vec3 rayOrigin, vec3 rayDir, float maxd, float precis ) { 196 | 197 | float latest = precis * 2.0; 198 | float dist = 0.0; 199 | float type = -1.0; 200 | for (int i = 0; i < raymarchSteps; i++) { 201 | 202 | if (latest < precis || dist > maxd) break; 203 | 204 | vec2 result = field( rayOrigin + rayDir * dist ); 205 | latest = result.x; 206 | dist += latest; 207 | 208 | type = result.y; 209 | } 210 | 211 | vec2 res = vec2(-1.0, -1.0 ); 212 | if (dist < maxd) { res = vec2( dist, type ); } 213 | return res; 214 | 215 | } 216 | 217 | void main() { 218 | 219 | vec2 screenPos = squareFrame( resolution ); 220 | 221 | vec3 rayDirection = getRay( camera, target, screenPos, fov ); 222 | 223 | vec2 collision = raymarching( camera, rayDirection, raymarchMaximumDistance, raymarchPrecision ); 224 | 225 | gl_FragColor = vec4( vec3( .25,.25,.5), 1. ); 226 | 227 | if ( collision.x > -0.5) 228 | { 229 | 230 | //retrieve the Y value set in the field() method 231 | vec3 col = vec3( collision.y ); 232 | 233 | gl_FragColor = vec4( col, 1. ); 234 | 235 | } 236 | } -------------------------------------------------------------------------------- /glsl/fragment.glsl: -------------------------------------------------------------------------------- 1 | 2 | uniform vec2 resolution; 3 | uniform float time; 4 | uniform sampler2D map; 5 | 6 | //uses most of the StackGL methods 7 | //https://github.com/stackgl 8 | 9 | //https://github.com/hughsk/glsl-square-frame 10 | 11 | vec2 squareFrame(vec2 screenSize) { 12 | vec2 position = 2.0 * (gl_FragCoord.xy / screenSize.xy) - 1.0; 13 | position.x *= screenSize.x / screenSize.y; 14 | return position; 15 | } 16 | vec2 squareFrame(vec2 screenSize, vec2 coord) { 17 | vec2 position = 2.0 * (coord.xy / screenSize.xy) - 1.0; 18 | position.x *= screenSize.x / screenSize.y; 19 | return position; 20 | } 21 | 22 | //https://github.com/stackgl/glsl-look-at/blob/gh-pages/index.glsl 23 | 24 | mat3 calcLookAtMatrix(vec3 origin, vec3 target, float roll) { 25 | vec3 rr = vec3(sin(roll), cos(roll), 0.0); 26 | vec3 ww = normalize(target - origin); 27 | vec3 uu = normalize(cross(ww, rr)); 28 | vec3 vv = normalize(cross(uu, ww)); 29 | return mat3(uu, vv, ww); 30 | } 31 | 32 | //https://github.com/stackgl/glsl-camera-ray 33 | 34 | vec3 getRay(mat3 camMat, vec2 screenPos, float lensLength) { 35 | return normalize(camMat * vec3(screenPos, lensLength)); 36 | } 37 | vec3 getRay(vec3 origin, vec3 target, vec2 screenPos, float lensLength) { 38 | mat3 camMat = calcLookAtMatrix(origin, target, 0.0); 39 | return getRay(camMat, screenPos, lensLength); 40 | } 41 | 42 | ///////////////////////////////////////////////////////////////////////// 43 | 44 | mat3 rotationMatrix3(vec3 axis, float angle) 45 | { 46 | axis = normalize(axis); 47 | float s = sin(angle); 48 | float c = cos(angle); 49 | float oc = 1.0 - c; 50 | 51 | return mat3(oc * axis.x * axis.x + c, oc * axis.x * axis.y - axis.z * s, oc * axis.z * axis.x + axis.y * s, 52 | oc * axis.x * axis.y + axis.z * s, oc * axis.y * axis.y + c, oc * axis.y * axis.z - axis.x * s, 53 | oc * axis.z * axis.x - axis.y * s, oc * axis.y * axis.z + axis.x * s, oc * axis.z * axis.z + c ); 54 | } 55 | 56 | ///////////////////////////////////////////////////////////////////////// 57 | 58 | //primitives 59 | 60 | vec2 sphere( vec3 p, float radius, vec3 pos , vec4 quat) 61 | { 62 | mat3 transform = rotationMatrix3( quat.xyz, quat.w ); 63 | float d = length( ( p * transform )-pos ) - radius; 64 | return vec2(d,1); 65 | } 66 | 67 | vec2 roundBox(vec3 p, vec3 size, float corner, vec3 pos, vec4 quat ) 68 | { 69 | mat3 transform = rotationMatrix3( quat.xyz, quat.w ); 70 | return vec2( length( max( abs( ( p-pos ) * transform )-size, 0.0 ) )-corner,1.); 71 | } 72 | 73 | vec2 torus( vec3 p, vec2 radii, vec3 pos, vec4 quat ) 74 | { 75 | mat3 transform = rotationMatrix3( quat.xyz, quat.w ); 76 | vec3 pp = ( p - pos ) * transform; 77 | float d = length( vec2( length( pp.xz ) - radii.x, pp.y ) ) - radii.y; 78 | return vec2(d,1.); 79 | } 80 | 81 | vec2 cone( vec3 p, vec2 c, vec3 pos, vec4 quat ) 82 | { 83 | mat3 transform = rotationMatrix3( quat.xyz, quat.w ); 84 | vec3 pp = ( p - pos ) * transform; 85 | float q = length(pp.xy); 86 | return vec2( dot(c,vec2(q,pp.z)), 1. ); 87 | } 88 | 89 | //http://www.pouet.net/topic.php?post=365312 90 | vec2 cylinder( vec3 p, float h, float r, vec3 pos, vec4 quat ) { 91 | mat3 transform = rotationMatrix3( quat.xyz, quat.w ); 92 | vec3 pp = (p - pos ) * transform; 93 | return vec2( max(length(pp.xz)-r, abs(pp.y)-h),1. ); 94 | } 95 | 96 | 97 | //operations 98 | 99 | vec2 unionAB(vec2 a, vec2 b){return vec2(min(a.x, b.x),1.);} 100 | vec2 intersectionAB(vec2 a, vec2 b){return vec2(max(a.x, b.x),1.);} 101 | vec2 blendAB( vec2 a, vec2 b, float t ){ return vec2(mix(a.x, b.x, t ),1.);} 102 | vec2 subtract(vec2 a, vec2 b){ return vec2(max(-a.x, b.x),1.); } 103 | //http://iquilezles.org/www/articles/smin/smin.htm 104 | vec2 smin( vec2 a, vec2 b, float k ) { float h = clamp( 0.5+0.5*(b.x-a.x)/k, 0.0, 1.0 ); return vec2( mix( b.x, a.x, h ) - k*h*(1.0-h), 1. ); } 105 | 106 | //utils 107 | 108 | 109 | //http://www.pouet.net/topic.php?post=367360 110 | const vec3 pa = vec3(1., 57., 21.); 111 | const vec4 pb = vec4(0., 57., 21., 78.); 112 | float perlin(vec3 p) { 113 | vec3 i = floor(p); 114 | vec4 a = dot( i, pa ) + pb; 115 | vec3 f = cos((p-i)*acos(-1.))*(-.5)+.5; 116 | a = mix(sin(cos(a)*a),sin(cos(1.+a)*(1.+a)), f.x); 117 | a.xy = mix(a.xz, a.yw, f.y); 118 | return mix(a.x, a.y, f.z); 119 | } 120 | 121 | ///////////////////////////////////////////////////////////////////////// 122 | 123 | // STOP ! ! ! 124 | 125 | // HAMMER TIME ! 126 | 127 | ///////////////////////////////////////////////////////////////////////// 128 | 129 | 130 | const int steps = 50; 131 | const int shadowSteps = 4; 132 | const int ambienOcclusionSteps = 3; 133 | const float PI = 3.14159; 134 | vec2 field( vec3 position ) 135 | { 136 | 137 | 138 | //position 139 | vec3 zero = vec3(0.); 140 | 141 | //rotation 142 | vec4 quat = vec4( 1., sin( time ) *.1 , 0., time * .2 ); 143 | 144 | //noise 145 | vec3 noise = position * .25; 146 | //noise += time * .1; 147 | float pnoise = 1. + perlin( noise ); 148 | 149 | //box 150 | vec2 rb = roundBox( position, vec3(2.0,2.0,2.0), 0.5, zero, quat + vec4( 1., 1., 1., PI / 4. ) ); 151 | 152 | //torus 153 | vec2 to0 = torus( position, vec2( 4.0,.15), zero, vec4( 1., 0., 0., 0. + time * .2 ) ); 154 | vec2 to1 = torus( position, vec2( 4.0,.15), zero, vec4( 0., 0., 1., PI *.5 + time * .2 ) ); 155 | 156 | //spheres 157 | vec2 sre = sphere( position, 3.0, zero, quat ); 158 | vec2 sce = sphere( position, 1., zero, quat ) + perlin( position + time ) * .25; 159 | 160 | //composition 161 | return smin( sce, smin( to0, smin( to1, subtract( sre, rb ), pnoise ), pnoise ), pnoise); 162 | 163 | } 164 | 165 | ///////////////////////////////////////////////////////////////////////// 166 | 167 | // the methods below this need the field function 168 | 169 | ///////////////////////////////////////////////////////////////////////// 170 | 171 | 172 | //the actual raymarching from: 173 | //https://github.com/stackgl/glsl-raytrace/blob/master/index.glsl 174 | 175 | vec2 raymarching( vec3 rayOrigin, vec3 rayDir, float maxd, float precis ) { 176 | 177 | float latest = precis * 2.0; 178 | float dist = 0.0; 179 | float type = -1.0; 180 | vec2 res = vec2(-1.0, -1.0); 181 | for (int i = 0; i < steps; i++) { 182 | 183 | if (latest < precis || dist > maxd) break; 184 | 185 | vec2 result = field( rayOrigin + rayDir * dist ); 186 | latest = result.x; 187 | type = result.y; 188 | dist += latest; 189 | } 190 | 191 | if (dist < maxd) { res = vec2(dist, type); } 192 | return res; 193 | } 194 | 195 | //https://github.com/stackgl/glsl-sdf-normal 196 | 197 | vec3 calcNormal(vec3 pos, float eps) { 198 | const vec3 v1 = vec3( 1.0,-1.0,-1.0); 199 | const vec3 v2 = vec3(-1.0,-1.0, 1.0); 200 | const vec3 v3 = vec3(-1.0, 1.0,-1.0); 201 | const vec3 v4 = vec3( 1.0, 1.0, 1.0); 202 | 203 | return normalize( v1 * field( pos + v1*eps ).x + 204 | v2 * field( pos + v2*eps ).x + 205 | v3 * field( pos + v3*eps ).x + 206 | v4 * field( pos + v4*eps ).x ); 207 | } 208 | 209 | vec3 calcNormal(vec3 pos) { 210 | return calcNormal(pos, 0.002); 211 | } 212 | 213 | 214 | //shadows & AO 215 | 216 | //https://www.shadertoy.com/view/Xds3zN 217 | 218 | float softshadow( in vec3 ro, in vec3 rd, in float mint, in float tmax, in float K ) 219 | { 220 | float res = 1.0; 221 | float t = mint; 222 | for( int i=0; itmax ) break; 228 | } 229 | return clamp( res, 0.0, 1.0 ); 230 | } 231 | 232 | float calcAO( in vec3 pos, in vec3 nor ) 233 | { 234 | float occ = 0.0; 235 | float sca = 1.0; 236 | for( int i=0; i -0.5) 281 | { 282 | 283 | //"world" position 284 | vec3 pos = rayOrigin + rayDirection * collision.x; 285 | 286 | //diffuse color 287 | vec3 col = vec3( .8,.8,.8 ); 288 | 289 | //normal vector 290 | vec3 nor = calcNormal( pos ); 291 | 292 | //reflection (Spherical Environment Mapping) 293 | vec2 uv = nor.xy / 2. + .5; 294 | vec3 tex = texture2D( map, uv ).rgb; 295 | col += tex * .1; 296 | 297 | vec3 lig0 = normalize( vec3(-0.5, 0.75, -0.5) ); 298 | vec3 light0 = max( 0.0, dot( lig0, nor) ) * color0; 299 | 300 | vec3 lig1 = normalize( vec3( 0.5, -0.75, 0.5) ); 301 | vec3 light1 = max( 0.0, dot( lig1, nor) ) * color1; 302 | 303 | //AO : usually too strong 304 | float occ = calcAO( pos, nor ); 305 | 306 | //shadows ...? 307 | //float sha = softshadow( pos, lig0, .025, 2.5, 2. ); 308 | 309 | float dep = ( ( collision.x + .5 ) / ( maxDist * .5 ) ); 310 | gl_FragColor = vec4( ( col + light0 + light1 ) * occ * dep, 1. ); 311 | 312 | } 313 | 314 | } -------------------------------------------------------------------------------- /glsl/halibut.glsl: -------------------------------------------------------------------------------- 1 | uniform vec2 resolution; 2 | uniform float time; 3 | uniform float fov; 4 | uniform vec3 camera; 5 | uniform vec3 target; 6 | uniform float raymarchMaximumDistance; 7 | uniform float raymarchPrecision; 8 | uniform sampler2D map; 9 | 10 | ///////////////////////////////////////////////////////////////////////// 11 | 12 | mat3 rotationMatrix3(vec3 axis, float angle) 13 | { 14 | axis = normalize(axis); 15 | float s = sin(angle); 16 | float c = cos(angle); 17 | float oc = 1.0 - c; 18 | 19 | return mat3(oc * axis.x * axis.x + c, oc * axis.x * axis.y - axis.z * s, oc * axis.z * axis.x + axis.y * s, 20 | oc * axis.x * axis.y + axis.z * s, oc * axis.y * axis.y + c, oc * axis.y * axis.z - axis.x * s, 21 | oc * axis.z * axis.x - axis.y * s, oc * axis.y * axis.z + axis.x * s, oc * axis.z * axis.z + c ); 22 | } 23 | 24 | vec3 getRay(vec3 dir, vec2 pos) 25 | { 26 | pos = pos - 0.5; 27 | pos.x *= resolution.x/resolution.y; 28 | 29 | dir = normalize(dir); 30 | vec3 right = normalize(cross(vec3(0.,1.,0.),dir)); 31 | vec3 up = normalize(cross(dir,right)); 32 | 33 | return dir + right*pos.x + up*pos.y; 34 | } 35 | 36 | ///////////////////////////////////////////////////////////////////////// 37 | 38 | //primitives 39 | 40 | vec2 box(vec3 p, vec3 size, float corner, vec3 pos ) { return vec2( length( max( abs( p-pos )-size, 0.0 ) )-corner,1.); } 41 | 42 | vec2 plane( vec3 p , vec3 n) { return vec2( dot(p, n), 1. ); } 43 | vec2 plane( vec3 p , vec4 n) { return vec2( dot(p, n.xyz) - n.w, 1. ); } 44 | 45 | //operations 46 | 47 | vec2 unionAB(vec2 a, vec2 b){return vec2(min(a.x, b.x),1.);} 48 | vec2 intersectionAB(vec2 a, vec2 b){return vec2(max(a.x, b.x),1.);} 49 | vec2 blendAB( vec2 a, vec2 b, float t ){ return vec2(mix(a.x, b.x, t ),1.);} 50 | vec2 subtract(vec2 a, vec2 b){ return vec2(max(-a.x, b.x),1.); } 51 | //http://iquilezles.org/www/articles/smin/smin.htm 52 | vec2 smin( vec2 a, vec2 b, float k ) { float h = clamp( 0.5+0.5*(b.x-a.x)/k, 0.0, 1.0 ); return vec2( mix( b.x, a.x, h ) - k*h*(1.0-h), 1. ); } 53 | 54 | //utils 55 | 56 | vec3 repeat( vec3 p, vec3 r ) { return mod( p, r ) - .5 * r; } 57 | 58 | float hash(in float n) 59 | { 60 | return fract(sin(n)*43758.5453123); 61 | } 62 | 63 | float noise(in vec2 x) 64 | { 65 | vec2 p = floor(x); 66 | vec2 f = fract(x); 67 | f = f*f*(3.0-2.0*f); 68 | float n = p.x + p.y*57.0; 69 | float res = mix(mix( hash(n+ 0.0), hash(n+ 1.0),f.x), 70 | mix( hash(n+ 57.0), hash(n+ 58.0),f.x),f.y); 71 | return res; 72 | } 73 | 74 | ///////////////////////////////////////////////////////////////////////// 75 | 76 | // STOP ! ! ! 77 | 78 | // HAMMER TIME ! 79 | 80 | ///////////////////////////////////////////////////////////////////////// 81 | 82 | 83 | const int raymarchSteps = 30; 84 | 85 | const int shadowSteps = 4; 86 | const int ambienOcclusionSteps = 3; 87 | #define PI 3.14159 88 | float sdSphere( vec3 p, float s ) 89 | { 90 | return length(p)-s; 91 | } 92 | vec2 field( vec3 position ) 93 | { 94 | 95 | vec3 r = vec3( 3., 0., 3. ); 96 | vec3 p = repeat( position, r ); 97 | 98 | position.xz += time *.5; 99 | float n = noise( ( .75 * position.xz / r.xz ) ); 100 | 101 | float s = max( .5, n * 1.125 ); 102 | float h = n * 5.; 103 | 104 | vec2 pl = plane( position, vec4( 0.,1.,0., h * .9 ) ); 105 | vec2 rb = box( p, vec3( s, h, s ), .85 + ( .5+sin( time + n )*.5 ) * .1, vec3(0.) ); 106 | 107 | vec2 _out = smin( rb, pl, .5 ); 108 | _out.y = n; 109 | return _out; 110 | 111 | } 112 | 113 | ///////////////////////////////////////////////////////////////////////// 114 | 115 | // the methods below this need the field function 116 | 117 | ///////////////////////////////////////////////////////////////////////// 118 | 119 | 120 | //the actual raymarching from: 121 | //https://github.com/stackgl/glsl-raytrace/blob/master/index.glsl 122 | 123 | vec2 raymarching( vec3 rayOrigin, vec3 rayDir, float maxd, float precis ) { 124 | 125 | float latest = precis * 2.0; 126 | float dist = 0.0; 127 | float type = -1.0; 128 | for (int i = 0; i < raymarchSteps; i++) { 129 | 130 | 131 | vec2 result = field( rayOrigin + rayDir * dist ); 132 | if( result.x > precis ) result.x *= .3; 133 | latest = result.x; 134 | dist += latest; 135 | type = result.y; 136 | if (latest < precis || dist > maxd) break; 137 | } 138 | 139 | vec2 res = vec2(-1.0, -1.0 ); 140 | if (dist < maxd) { res = vec2( dist, type ); } 141 | return res; 142 | 143 | } 144 | 145 | 146 | //https://github.com/stackgl/glsl-sdf-normal 147 | 148 | vec3 calcNormal(vec3 pos, float eps) { 149 | const vec3 v1 = vec3( 1.0,-1.0,-1.0); 150 | const vec3 v2 = vec3(-1.0,-1.0, 1.0); 151 | const vec3 v3 = vec3(-1.0, 1.0,-1.0); 152 | const vec3 v4 = vec3( 1.0, 1.0, 1.0); 153 | 154 | return normalize( v1 * field( pos + v1*eps ).x + 155 | v2 * field( pos + v2*eps ).x + 156 | v3 * field( pos + v3*eps ).x + 157 | v4 * field( pos + v4*eps ).x ); 158 | } 159 | 160 | vec3 calcNormal(vec3 pos) { 161 | return calcNormal(pos, 0.002); 162 | } 163 | 164 | vec4 rimlight( vec3 pos, vec3 nor ) 165 | { 166 | vec3 v = normalize(-pos); 167 | float vdn = 1.0 - max(dot(v, nor), 0.0); 168 | return vec4( vec3( smoothstep(0., 1.0, vdn) ), 1.); 169 | } 170 | 171 | vec4 shading( vec3 pos, vec3 norm, vec3 rd, vec3 lightDir, vec3 lightColour, vec3 diffuse ) 172 | { 173 | 174 | float specularHardness = 128.; 175 | float specular = 4.; 176 | float ambientFactor = 0.0005; 177 | 178 | vec3 light = lightColour * max(0.0, dot(norm, lightDir)); 179 | 180 | vec3 heading = normalize(-rd + lightDir); 181 | 182 | float spec = pow(max(0.0, dot( heading, norm )), specularHardness) * specular; 183 | 184 | light = (diffuse * light) + ( spec * lightColour); 185 | 186 | return vec4(light, 1.0); 187 | } 188 | 189 | mat3 calcLookAtMatrix(vec3 origin, vec3 target, float roll) { 190 | vec3 rr = vec3(sin(roll), cos(roll), 0.0); 191 | vec3 ww = normalize(target - origin); 192 | vec3 uu = normalize(cross(ww, rr)); 193 | vec3 vv = normalize(cross(uu, ww)); 194 | return mat3(uu, vv, ww); 195 | } 196 | 197 | void main() { 198 | 199 | vec2 p = gl_FragCoord.xy / resolution.xy; 200 | vec3 rd = normalize( getRay( target-camera, p ) ); 201 | 202 | vec2 collision = raymarching( camera, rd, raymarchMaximumDistance, raymarchPrecision ); 203 | 204 | 205 | gl_FragColor = vec4( vec3( .25,.25,.5), 1. ); 206 | 207 | vec3 color = vec3(0.0, 0.2, 0.8); //blue 208 | if ( collision.x > -0.5 ) 209 | { 210 | 211 | //"world" position 212 | vec3 pos = camera + rd * collision.x; 213 | 214 | //normal vector 215 | vec3 nor = calcNormal( pos ); 216 | 217 | //diffuse color 218 | vec3 dif = vec3( collision.y ); 219 | 220 | //reflection (Spherical Environment Mapping) 221 | vec3 tex = texture2D( map, ( nor * calcLookAtMatrix( pos, camera,0. ) ).xy / 2. + .5 ).rgb; 222 | dif += tex * .5; 223 | 224 | vec3 lig = normalize( camera ) + vec3(-0.5, 0.75, -0.5) ; 225 | 226 | float depth = ( 1. / log( collision.x ) ); 227 | gl_FragColor = vec4( collision.y ) + shading( pos, nor, rd, lig, color, dif ) * 1.5 * rimlight( pos, nor ) * depth; 228 | 229 | } 230 | } -------------------------------------------------------------------------------- /glsl/hulkbuster.glsl: -------------------------------------------------------------------------------- 1 | uniform vec2 resolution; 2 | uniform float time; 3 | uniform float fov; 4 | uniform vec3 camera; 5 | uniform vec3 target; 6 | uniform float raymarchMaximumDistance; 7 | uniform float raymarchPrecision; 8 | uniform sampler2D map; 9 | 10 | ///////////////////////////////////////////////////////////////////////// 11 | 12 | mat3 rotationMatrix3(vec3 axis, float angle) 13 | { 14 | axis = normalize(axis); 15 | float s = sin(angle); 16 | float c = cos(angle); 17 | float oc = 1.0 - c; 18 | 19 | return mat3(oc * axis.x * axis.x + c, oc * axis.x * axis.y - axis.z * s, oc * axis.z * axis.x + axis.y * s, 20 | oc * axis.x * axis.y + axis.z * s, oc * axis.y * axis.y + c, oc * axis.y * axis.z - axis.x * s, 21 | oc * axis.z * axis.x - axis.y * s, oc * axis.y * axis.z + axis.x * s, oc * axis.z * axis.z + c ); 22 | } 23 | 24 | vec3 getRay(vec3 dir, vec2 pos) 25 | { 26 | pos = pos - 0.5; 27 | pos.x *= resolution.x/resolution.y; 28 | 29 | dir = normalize(dir); 30 | vec3 right = normalize(cross(vec3(0.,1.,0.),dir)); 31 | vec3 up = normalize(cross(dir,right)); 32 | 33 | return dir + right*pos.x + up*pos.y; 34 | } 35 | 36 | mat3 calcLookAtMatrix(vec3 origin, vec3 target, float roll) { 37 | vec3 rr = vec3(sin(roll), cos(roll), 0.0); 38 | vec3 ww = normalize(target - origin); 39 | vec3 uu = normalize(cross(ww, rr)); 40 | vec3 vv = normalize(cross(uu, ww)); 41 | return mat3(uu, vv, ww); 42 | } 43 | ///////////////////////////////////////////////////////////////////////// 44 | 45 | //primitives 46 | 47 | float voronoiDistribution( in vec3 p ) 48 | { 49 | vec3 i = floor(p + dot(p, vec3(0.333333)) ); p -= i - dot(i, vec3(0.166666)) ; 50 | vec3 i1 = step(0., p-p.yzx), i2 = max(i1, 1.0-i1.zxy); i1 = min(i1, 1.0-i1.zxy); 51 | vec3 p1 = p - i1 + 0.166666, p2 = p - i2 + 0.333333, p3 = p - 0.5; 52 | vec3 rnd = vec3(7, 157, 113); // I use this combination to pay homage to Shadertoy.com. :) 53 | vec4 v = max(0.5 - vec4(dot(p, p), dot(p1, p1), dot(p2, p2), dot(p3, p3)), 0.); 54 | vec4 d = vec4( dot(i, rnd), dot(i + i1, rnd), dot(i + i2, rnd), dot(i + 1., rnd) ); 55 | d = fract(sin(d)*262144.)*v*2.; 56 | v.x = max(d.x, d.y), v.y = max(d.z, d.w), v.z = max(min(d.x, d.y), min(d.z, d.w)), v.w = min(v.x, v.y); 57 | return max(v.x, v.y) - max(v.z, v.w); // Maximum minus second order, for that beveled Voronoi look. Range [0, 1]. 58 | } 59 | #define sphere(p, r) length(p)-r 60 | 61 | //operations 62 | 63 | vec2 unionAB(vec2 a, vec2 b){return vec2(min(a.x, b.x),1.);} 64 | vec2 intersectionAB(vec2 a, vec2 b){return vec2(max(a.x, b.x),1.);} 65 | vec2 blendAB( vec2 a, vec2 b, float t ){ return vec2(mix(a.x, b.x, t ),1.);} 66 | vec2 subtract(vec2 a, vec2 b){ return vec2(max(-a.x, b.x),1.); } 67 | //http://iquilezles.org/www/articles/smin/smin.htm 68 | float smin( float a, float b, float k ) { float h = clamp( 0.5+0.5*(b-a)/k, 0.0, 1.0 ); return mix( b, a, h ) - k*h*(1.0-h); } 69 | vec2 smin( vec2 a, vec2 b, float k ) { return vec2( smin( a.x, b.x, k ), 1. ); } 70 | 71 | //utils 72 | 73 | float hash(in float n) 74 | { 75 | return fract(sin(n)*43758.5453123); 76 | } 77 | float zigzag( float x, float m ) 78 | { 79 | return abs( mod( x, (2.*m) ) -m); 80 | } 81 | 82 | #define PI 3.1415926 83 | 84 | ///////////////////////////////////////////////////////////////////////// 85 | 86 | // STOP ! ! ! 87 | 88 | // HAMMER TIME ! 89 | 90 | ///////////////////////////////////////////////////////////////////////// 91 | 92 | 93 | const int raymarchSteps = 100; 94 | vec2 field( vec3 position ) 95 | { 96 | 97 | float e = sin(time*.5) * .5 + .5; 98 | float c = cos(time*.1) * .5 + .5; 99 | 100 | float off0 = zigzag( position.x, .25-c*.1 )+ zigzag( position.x, .15 ); 101 | float off1 = zigzag( position.z, .12 )- zigzag( position.z, .35-c*.1 ); 102 | 103 | float r = 31.5; 104 | vec3 plp = position; 105 | plp.y += r; 106 | vec2 pl = smin( vec2( sphere( plp, r + 1. )-off0, 1. ), 107 | vec2( sphere( plp, r + 1. )+off1, 1. ), e ); 108 | 109 | plp.y -= r + .75; 110 | vec2 sp = vec2( sphere( plp, 2. + abs( c * 2. ) ), 1. ); 111 | sp.x += zigzag( sp.x, .25-e*.1 ); 112 | 113 | vec2 si = vec2( sp.x - voronoiDistribution( position*.75 ), 1. ); 114 | vec2 res = unionAB( pl, smin( sp, si, .1 )); 115 | 116 | //color switch 117 | res.y = 1.; 118 | if( res.x > sp.x - raymarchPrecision )res.y = 0.; 119 | if( res.x > si.x - raymarchPrecision )res.y = 0.; 120 | if( res.x > pl.x - raymarchPrecision )res.y = 0.5; 121 | 122 | return res; 123 | } 124 | 125 | ///////////////////////////////////////////////////////////////////////// 126 | 127 | // the methods below this need the field function 128 | 129 | ///////////////////////////////////////////////////////////////////////// 130 | 131 | 132 | //the actual raymarching from: 133 | //https://github.com/stackgl/glsl-raytrace/blob/master/index.glsl 134 | 135 | vec2 raymarching( vec3 rayOrigin, vec3 rayDir, float maxd, float precis ) { 136 | 137 | float latest = precis * 2.0; 138 | float dist = 0.0; 139 | float type = 0.0; 140 | for (int i = 0; i < raymarchSteps; i++) { 141 | 142 | if (latest < precis || dist > maxd ) break; 143 | 144 | vec2 result = field( rayOrigin + rayDir * dist ); 145 | if( result.x > precis ) result.x *= .3; 146 | latest = result.x; 147 | dist += latest; 148 | type = result.y; 149 | 150 | } 151 | vec2 res = vec2(-1.0, -1.0 ); 152 | if (dist < maxd) { res = vec2( dist, type ); } 153 | return res; 154 | 155 | } 156 | 157 | 158 | //https://github.com/stackgl/glsl-sdf-normal 159 | 160 | vec3 calcNormal(vec3 pos, float eps) { 161 | const vec3 v1 = vec3( 1.0,-1.0,-1.0); 162 | const vec3 v2 = vec3(-1.0,-1.0, 1.0); 163 | const vec3 v3 = vec3(-1.0, 1.0,-1.0); 164 | const vec3 v4 = vec3( 1.0, 1.0, 1.0); 165 | 166 | return normalize( v1 * field( pos + v1*eps ).x + 167 | v2 * field( pos + v2*eps ).x + 168 | v3 * field( pos + v3*eps ).x + 169 | v4 * field( pos + v4*eps ).x ); 170 | } 171 | 172 | vec3 calcNormal(vec3 pos) { 173 | return calcNormal(pos, 0.002); 174 | } 175 | 176 | vec4 shading( vec3 pos, vec3 norm, vec3 rd, vec3 lightDir, vec3 lightColour, vec3 diffuse ) 177 | { 178 | float specularHardness = 32.; 179 | float specular = 2.; 180 | 181 | vec3 light = lightColour * max(0.0, dot(norm, lightDir)); 182 | 183 | vec3 heading = normalize(-rd + lightDir); 184 | 185 | float spec = pow(max(0.0, dot( heading, norm )), specularHardness) * specular; 186 | 187 | light = (diffuse * light) + ( spec * lightColour); 188 | 189 | //normal face camera (constant environment lighting) 190 | norm *= calcLookAtMatrix(pos,camera,0.); 191 | light += texture2D( map, norm.xy / 2. + .5 ).rgb * .2; 192 | 193 | return vec4(light, 1.0); 194 | } 195 | 196 | void main() { 197 | 198 | vec2 p = gl_FragCoord.xy / resolution.xy; 199 | //background 200 | gl_FragColor = vec4( mix( vec3( .1 ), vec3( 1. ), vec3( 1.-p.y ) ) , 1. ); 201 | 202 | vec3 red = vec3( .9, 0.1, 0.05); 203 | vec3 dark = vec3( .5, 0.1, 0.15); 204 | vec3 color = vec3( 0.9, 0.65, 0.05); 205 | 206 | vec3 rd = normalize( getRay( target-camera, p ) ); 207 | vec2 collision = raymarching( camera, rd, raymarchMaximumDistance, raymarchPrecision ); 208 | if ( collision.x > -0.5 ) 209 | { 210 | vec3 pos = camera + rd * collision.x; 211 | vec3 nor = calcNormal( pos ); 212 | vec3 lightDir = normalize( vec3( 1.,1.,0. ) ); 213 | vec3 dif = vec3( 1. );//collision.y ); 214 | 215 | float depth = ( 1. / log( collision.x ) ); 216 | vec4 s0 = shading( pos,nor, rd,lightDir, red , dif * depth ); 217 | vec4 s1 = shading( pos,nor, rd,-lightDir, dark, dif); 218 | 219 | gl_FragColor = ( s0 * .5 + s1 * .5 ); 220 | 221 | if( collision.y == 1. )gl_FragColor = shading( pos,nor, rd, normalize( camera + vec3( 0.,2.,0. ) ), color, dif * depth ); 222 | 223 | if( collision.y == .5 )gl_FragColor = shading( pos,nor, rd, normalize( camera + vec3( 0.,2.,0. ) ), vec3(.1), dif * depth ); 224 | } 225 | } -------------------------------------------------------------------------------- /glsl/interactive.glsl: -------------------------------------------------------------------------------- 1 | 2 | uniform vec2 resolution; 3 | uniform float time; 4 | uniform float fov; 5 | uniform float raymarchMaximumDistance; 6 | uniform float raymarchPrecision; 7 | uniform vec3 camera; 8 | uniform vec3 target; 9 | 10 | uniform vec3 color0; 11 | uniform vec3 color1; 12 | 13 | uniform vec3 light0; 14 | uniform vec3 light1; 15 | 16 | 17 | //uses most of the StackGL methods 18 | //https://github.com/stackgl 19 | 20 | //https://github.com/hughsk/glsl-square-frame 21 | 22 | vec2 squareFrame(vec2 screenSize) { 23 | vec2 position = 2.0 * (gl_FragCoord.xy / screenSize.xy) - 1.0; 24 | position.x *= screenSize.x / screenSize.y; 25 | return position; 26 | } 27 | vec2 squareFrame(vec2 screenSize, vec2 coord) { 28 | vec2 position = 2.0 * (coord.xy / screenSize.xy) - 1.0; 29 | position.x *= screenSize.x / screenSize.y; 30 | return position; 31 | } 32 | 33 | //https://github.com/stackgl/glsl-look-at/blob/gh-pages/index.glsl 34 | 35 | mat3 calcLookAtMatrix(vec3 origin, vec3 target, float roll) { 36 | vec3 rr = vec3(sin(roll), cos(roll), 0.0); 37 | vec3 ww = normalize(target - origin); 38 | vec3 uu = normalize(cross(ww, rr)); 39 | vec3 vv = normalize(cross(uu, ww)); 40 | return mat3(uu, vv, ww); 41 | } 42 | 43 | //https://github.com/stackgl/glsl-camera-ray 44 | 45 | vec3 getRay(mat3 camMat, vec2 screenPos, float lensLength) { 46 | return normalize(camMat * vec3(screenPos, lensLength)); 47 | } 48 | vec3 getRay(vec3 origin, vec3 target, vec2 screenPos, float lensLength) { 49 | mat3 camMat = calcLookAtMatrix(origin, target, 0.0); 50 | return getRay(camMat, screenPos, lensLength); 51 | } 52 | 53 | ///////////////////////////////////////////////////////////////////////// 54 | 55 | mat3 rotationMatrix3(vec3 axis, float angle) 56 | { 57 | axis = normalize(axis); 58 | float s = sin(angle); 59 | float c = cos(angle); 60 | float oc = 1.0 - c; 61 | 62 | return mat3(oc * axis.x * axis.x + c, oc * axis.x * axis.y - axis.z * s, oc * axis.z * axis.x + axis.y * s, 63 | oc * axis.x * axis.y + axis.z * s, oc * axis.y * axis.y + c, oc * axis.y * axis.z - axis.x * s, 64 | oc * axis.z * axis.x - axis.y * s, oc * axis.y * axis.z + axis.x * s, oc * axis.z * axis.z + c ); 65 | } 66 | 67 | ///////////////////////////////////////////////////////////////////////// 68 | 69 | //primitives 70 | 71 | vec2 sphere( vec3 p, float radius, vec3 pos , vec4 quat) 72 | { 73 | mat3 transform = rotationMatrix3( quat.xyz, quat.w ); 74 | float d = length( ( p * transform )-pos ) - radius; 75 | return vec2(d,0.); 76 | } 77 | 78 | vec2 roundBox(vec3 p, vec3 size, float corner, vec3 pos, vec4 quat ) 79 | { 80 | mat3 transform = rotationMatrix3( quat.xyz, quat.w ); 81 | return vec2( length( max( abs( ( p-pos ) * transform )-size, 0.0 ) )-corner,1.); 82 | } 83 | 84 | vec2 torus( vec3 p, vec2 radii, vec3 pos, vec4 quat ) 85 | { 86 | mat3 transform = rotationMatrix3( quat.xyz, quat.w ); 87 | vec3 pp = ( p - pos ) * transform; 88 | float d = length( vec2( length( pp.xz ) - radii.x, pp.y ) ) - radii.y; 89 | return vec2(d,1.); 90 | } 91 | 92 | vec2 cone( vec3 p, vec2 c, vec3 pos, vec4 quat ) 93 | { 94 | mat3 transform = rotationMatrix3( quat.xyz, quat.w ); 95 | vec3 pp = ( p - pos ) * transform; 96 | float q = length(pp.xy); 97 | return vec2( dot(c,vec2(q,pp.z)), 1. ); 98 | } 99 | 100 | //http://www.pouet.net/topic.php?post=365312 101 | vec2 cylinder( vec3 p, float h, float r, vec3 pos, vec4 quat ) { 102 | mat3 transform = rotationMatrix3( quat.xyz, quat.w ); 103 | vec3 pp = (p - pos ) * transform; 104 | return vec2( max(length(pp.xz)-r, abs(pp.y)-h),1. ); 105 | } 106 | 107 | 108 | //operations 109 | 110 | vec2 unionAB(vec2 a, vec2 b){return vec2(min(a.x, b.x),1.);} 111 | vec2 intersectionAB(vec2 a, vec2 b){return vec2(max(a.x, b.x),1.);} 112 | vec2 blendAB( vec2 a, vec2 b, float t ){ return vec2(mix(a.x, b.x, t ),1.);} 113 | vec2 subtract(vec2 a, vec2 b){ return vec2(max(-a.x, b.x),1.); } 114 | //http://iquilezles.org/www/articles/smin/smin.htm 115 | vec2 smin( vec2 a, vec2 b, float k ) { float h = clamp( 0.5+0.5*(b.x-a.x)/k, 0.0, 1.0 ); return vec2( mix( b.x, a.x, h ) - k*h*(1.0-h), 1. ); } 116 | 117 | //utils 118 | 119 | vec3 twist( vec3 pos, float amount ) 120 | { 121 | vec3 p = normalize( pos ); 122 | float c = cos(amount * p.y); 123 | float s = sin(amount * p.y); 124 | mat2 m = mat2(c,-s,s,c); 125 | vec3 q = vec3(m*pos.xz,pos.y); 126 | return q; 127 | } 128 | vec3 repeat( vec3 p, vec3 r ) 129 | { 130 | return mod( p, r ) - .5 * r; 131 | } 132 | 133 | //http://www.pouet.net/topic.php?post=367360 134 | const vec3 pa = vec3(1., 57., 21.); 135 | const vec4 pb = vec4(0., 57., 21., 78.); 136 | float perlin(vec3 p) { 137 | vec3 i = floor(p); 138 | vec4 a = dot( i, pa ) + pb; 139 | vec3 f = cos((p-i)*acos(-1.))*(-.5)+.5; 140 | a = mix(sin(cos(a)*a),sin(cos(1.+a)*(1.+a)), f.x); 141 | a.xy = mix(a.xz, a.yw, f.y); 142 | return mix(a.x, a.y, f.z); 143 | } 144 | 145 | ///////////////////////////////////////////////////////////////////////// 146 | 147 | // STOP ! ! ! 148 | 149 | // HAMMER TIME ! 150 | 151 | ///////////////////////////////////////////////////////////////////////// 152 | 153 | 154 | const int raymarchSteps = 50; 155 | 156 | const int shadowSteps = 4; 157 | const int ambienOcclusionSteps = 3; 158 | const float PI = 3.14159; 159 | vec2 field( vec3 position ) 160 | { 161 | //repetition 162 | vec3 r = vec3(9.,0.,9.); 163 | //position 164 | vec3 zero = vec3(0.); 165 | 166 | //rotation 167 | vec4 quat = vec4( 1., sin( time ) *.1 , 0., time * .2 ); 168 | 169 | //noise 170 | vec3 noise = position * .25; 171 | //noise += time * .1; 172 | float pnoise = 1. + perlin( noise ); 173 | 174 | //box 175 | vec2 rb = roundBox( position, vec3(2.0,2.0,2.0), 0.5, zero, quat + vec4( 1., 1., 1., PI / 4. ) ); 176 | 177 | //torus 178 | vec2 to0 = torus( twist( position, PI * sin( time ) ), vec2( 4.0,.15), zero, vec4( 1., 0., 0., 0. + time * .2 ) ); 179 | vec2 to1 = torus( position, vec2( 4.0,.15), zero, vec4( 0., 0., 1., PI *.5 + time * .2 ) ); 180 | 181 | //spheres 182 | vec2 sre = sphere( position, 3.0, zero, quat ); 183 | vec2 sce = sphere( position, 1., zero, quat ) + perlin( position + time ) * .25; 184 | 185 | //composition 186 | return smin( sce, smin( to0, smin( to1, subtract( sre, rb ), pnoise ), pnoise ), pnoise); 187 | } 188 | 189 | ///////////////////////////////////////////////////////////////////////// 190 | 191 | // the methods below this need the field function 192 | 193 | ///////////////////////////////////////////////////////////////////////// 194 | 195 | 196 | //the actual raymarching from: 197 | //https://github.com/stackgl/glsl-raytrace/blob/master/index.glsl 198 | 199 | vec2 raymarching( vec3 rayOrigin, vec3 rayDir, float maxd, float precis ) { 200 | 201 | float latest = precis * 2.0; 202 | float dist = 0.0; 203 | float type = -1.0; 204 | for (int i = 0; i < raymarchSteps; i++) { 205 | 206 | if (latest < precis || dist > maxd) break; 207 | 208 | vec2 result = field( rayOrigin + rayDir * dist ); 209 | latest = result.x; 210 | dist += latest; 211 | 212 | type = result.y; 213 | } 214 | 215 | vec2 res = vec2(-1.0, -1.0 ); 216 | if (dist < maxd) { res = vec2( dist, type ); } 217 | return res; 218 | 219 | } 220 | 221 | //https://github.com/stackgl/glsl-sdf-normal 222 | 223 | vec3 calcNormal(vec3 pos, float eps) { 224 | const vec3 v1 = vec3( 1.0,-1.0,-1.0); 225 | const vec3 v2 = vec3(-1.0,-1.0, 1.0); 226 | const vec3 v3 = vec3(-1.0, 1.0,-1.0); 227 | const vec3 v4 = vec3( 1.0, 1.0, 1.0); 228 | 229 | return normalize( v1 * field( pos + v1*eps ).x + 230 | v2 * field( pos + v2*eps ).x + 231 | v3 * field( pos + v3*eps ).x + 232 | v4 * field( pos + v4*eps ).x ); 233 | } 234 | 235 | vec3 calcNormal(vec3 pos) { 236 | return calcNormal(pos, 0.002); 237 | } 238 | 239 | 240 | //shadows & AO 241 | 242 | //https://www.shadertoy.com/view/Xds3zN 243 | 244 | float softshadow( in vec3 ro, in vec3 rd, in float mint, in float tmax, in float K ) 245 | { 246 | float res = 1.0; 247 | float t = mint; 248 | for( int i=0; itmax ) break; 254 | } 255 | return clamp( res, 0.0, 1.0 ); 256 | } 257 | 258 | float calcAO( in vec3 pos, in vec3 nor ) 259 | { 260 | float occ = 0.0; 261 | float sca = 1.0; 262 | for( int i=0; i -0.5) 293 | { 294 | 295 | //"world" position 296 | vec3 pos = camera + rayDirection * collision.x; 297 | 298 | //diffuse color 299 | vec3 col = vec3( collision.y ); 300 | 301 | //normal vector 302 | vec3 nor = calcNormal( pos ); 303 | 304 | vec3 lig0 = normalize( light0 ); 305 | vec3 lightColor0 = max( 0.0, dot( lig0, nor) ) * color0; 306 | 307 | vec3 lightColor1 = max( 0.0, dot( normalize( light1 ), nor) ) * color1; 308 | 309 | float depth = 1./ log( collision.x ); 310 | 311 | gl_FragColor = vec4( ( col + lightColor0 + lightColor1 ) * depth, 1. ); 312 | 313 | } 314 | 315 | } -------------------------------------------------------------------------------- /glsl/noise_bulb.glsl: -------------------------------------------------------------------------------- 1 | 2 | uniform vec2 resolution; 3 | uniform float time; 4 | uniform sampler2D map; 5 | 6 | //uses most of the StackGL methods 7 | //https://github.com/stackgl 8 | 9 | //https://github.com/hughsk/glsl-square-frame 10 | 11 | vec2 squareFrame(vec2 screenSize) { 12 | vec2 position = 2.0 * (gl_FragCoord.xy / screenSize.xy) - 1.0; 13 | position.x *= screenSize.x / screenSize.y; 14 | return position; 15 | } 16 | vec2 squareFrame(vec2 screenSize, vec2 coord) { 17 | vec2 position = 2.0 * (coord.xy / screenSize.xy) - 1.0; 18 | position.x *= screenSize.x / screenSize.y; 19 | return position; 20 | } 21 | 22 | //https://github.com/stackgl/glsl-look-at/blob/gh-pages/index.glsl 23 | 24 | mat3 calcLookAtMatrix(vec3 origin, vec3 target, float roll) { 25 | vec3 rr = vec3(sin(roll), cos(roll), 0.0); 26 | vec3 ww = normalize(target - origin); 27 | vec3 uu = normalize(cross(ww, rr)); 28 | vec3 vv = normalize(cross(uu, ww)); 29 | return mat3(uu, vv, ww); 30 | } 31 | 32 | //https://github.com/stackgl/glsl-camera-ray 33 | 34 | vec3 getRay(mat3 camMat, vec2 screenPos, float lensLength) { 35 | return normalize(camMat * vec3(screenPos, lensLength)); 36 | } 37 | vec3 getRay(vec3 origin, vec3 target, vec2 screenPos, float lensLength) { 38 | mat3 camMat = calcLookAtMatrix(origin, target, 0.0); 39 | return getRay(camMat, screenPos, lensLength); 40 | } 41 | 42 | ///////////////////////////////////////////////////////////////////////// 43 | 44 | mat3 rotationMatrix3(vec3 axis, float angle) 45 | { 46 | axis = normalize(axis); 47 | float s = sin(angle); 48 | float c = cos(angle); 49 | float oc = 1.0 - c; 50 | 51 | return mat3(oc * axis.x * axis.x + c, oc * axis.x * axis.y - axis.z * s, oc * axis.z * axis.x + axis.y * s, 52 | oc * axis.x * axis.y + axis.z * s, oc * axis.y * axis.y + c, oc * axis.y * axis.z - axis.x * s, 53 | oc * axis.z * axis.x - axis.y * s, oc * axis.y * axis.z + axis.x * s, oc * axis.z * axis.z + c ); 54 | } 55 | 56 | ///////////////////////////////////////////////////////////////////////// 57 | 58 | //primitives 59 | 60 | vec2 sphere( vec3 p, float radius, vec3 pos , vec4 quat) 61 | { 62 | mat3 transform = rotationMatrix3( quat.xyz, quat.w ); 63 | float d = length( ( p * transform )-pos ) - radius; 64 | return vec2(d,1); 65 | } 66 | vec2 sphere( vec3 p, float radius, vec3 pos ) 67 | { 68 | float d = length( ( p-pos) ) - radius; 69 | return vec2(d,1); 70 | } 71 | vec2 sphere( vec3 p, float radius ) 72 | { 73 | float d = length( p ) - radius; 74 | return vec2(d,1); 75 | } 76 | 77 | 78 | vec2 roundBox(vec3 p, vec3 size, float corner, vec3 pos, vec4 quat ) 79 | { 80 | mat3 transform = rotationMatrix3( quat.xyz, quat.w ); 81 | return vec2( length( max( abs( ( p-pos ) * transform )-size, 0.0 ) )-corner,1.); 82 | } 83 | vec2 roundBox(vec3 p, vec3 size, float corner, vec3 pos ) 84 | { 85 | return vec2( length( max( abs( p-pos )-size, 0.0 ) )-corner,1.); 86 | } 87 | 88 | 89 | vec2 torus( vec3 p, vec2 radii, vec3 pos, vec4 quat ) 90 | { 91 | mat3 transform = rotationMatrix3( quat.xyz, quat.w ); 92 | vec3 pp = ( p - pos ) * transform; 93 | float d = length( vec2( length( pp.xz ) - radii.x, pp.y ) ) - radii.y; 94 | return vec2(d,1.); 95 | } 96 | 97 | vec2 cone( vec3 p, vec2 c, vec3 pos, vec4 quat ) 98 | { 99 | mat3 transform = rotationMatrix3( quat.xyz, quat.w ); 100 | vec3 pp = ( p - pos ) * transform; 101 | float q = length(pp.xy); 102 | return vec2( dot(c,vec2(q,pp.z)), 1. ); 103 | } 104 | 105 | //http://www.pouet.net/topic.php?post=365312 106 | vec2 cylinder( vec3 p, float h, float r, vec3 pos, vec4 quat ) { 107 | mat3 transform = rotationMatrix3( quat.xyz, quat.w ); 108 | vec3 pp = (p - pos ) * transform; 109 | return vec2( max(length(pp.xz)-r, abs(pp.y)-h),1. ); 110 | } 111 | vec2 cylinder( vec3 p, float h, float r, vec3 pos ) { 112 | vec3 pp = (p - pos ); 113 | return vec2( max(length(pp.xz)-r, abs(pp.y)-h),1. ); 114 | } 115 | vec2 cylinder( vec3 p, float h, float r ) { 116 | return vec2( max(length(p.xz)-r, abs(p.y)-h),1. ); 117 | } 118 | 119 | 120 | 121 | 122 | //operations 123 | 124 | vec2 unionAB(vec2 a, vec2 b){return vec2(min(a.x, b.x),1.);} 125 | vec2 intersectionAB(vec2 a, vec2 b){return vec2(max(a.x, b.x),1.);} 126 | vec2 blendAB( vec2 a, vec2 b, float t ){ return vec2(mix(a.x, b.x, t ),1.);} 127 | vec2 subtract(vec2 a, vec2 b){ return vec2(max(-a.x, b.x),1.); } 128 | //http://iquilezles.org/www/articles/smin/smin.htm 129 | vec2 smin( vec2 a, vec2 b, float k ) { float h = clamp( 0.5+0.5*(b.x-a.x)/k, 0.0, 1.0 ); return vec2( mix( b.x, a.x, h ) - k*h*(1.0-h), 1. ); } 130 | 131 | //utils 132 | 133 | 134 | //http://www.pouet.net/topic.php?post=367360 135 | const vec3 pa = vec3(1., 57., 21.); 136 | const vec4 pb = vec4(0., 57., 21., 78.); 137 | float perlin(vec3 pos, vec4 quat ) { 138 | mat3 transform = rotationMatrix3( quat.xyz, quat.w ); 139 | vec3 p = pos * transform; 140 | vec3 i = floor(p); 141 | vec4 a = dot( i, pa ) + pb; 142 | vec3 f = cos((p-i)*acos(-1.))*(-.5)+.5; 143 | a = mix(sin(cos(a)*a),sin(cos(1.+a)*(1.+a)), f.x); 144 | a.xy = mix(a.xz, a.yw, f.y); 145 | return mix(a.x, a.y, f.z); 146 | } 147 | float perlin(vec3 p ) { 148 | vec3 i = floor(p); 149 | vec4 a = dot( i, pa ) + pb; 150 | vec3 f = cos((p-i)*acos(-1.))*(-.5)+.5; 151 | a = mix(sin(cos(a)*a),sin(cos(1.+a)*(1.+a)), f.x); 152 | a.xy = mix(a.xz, a.yw, f.y); 153 | return mix(a.x, a.y, f.z); 154 | } 155 | 156 | 157 | 158 | ///////////////////////////////////////////////////////////////////////// 159 | 160 | // STOP ! ! ! 161 | 162 | // HAMMER TIME ! 163 | 164 | ///////////////////////////////////////////////////////////////////////// 165 | 166 | 167 | const int steps = 80; 168 | const int shadowSteps = 4; 169 | const int ambienOcclusionSteps = 3; 170 | const float PI = 3.14159; 171 | vec2 field( vec3 position ) 172 | { 173 | 174 | vec2 sph = sphere( position, 5. ); 175 | 176 | vec3 nPos = position * .45; 177 | nPos.y -= time * .05; 178 | 179 | vec4 quat = vec4( 0., 1., 0., -time * .1 ); 180 | vec2 noi = vec2( max( -.5, .5-abs( perlin( nPos, quat ) ) ), 0. ); 181 | 182 | vec2 cyl = cylinder( position, 10.,4., vec3( 0.,-12.5,0.) ); 183 | 184 | return intersectionAB( smin( sph, cyl, .99 ), noi ); 185 | 186 | } 187 | 188 | ///////////////////////////////////////////////////////////////////////// 189 | 190 | // the methods below this need the field function 191 | 192 | ///////////////////////////////////////////////////////////////////////// 193 | 194 | 195 | //the actual raymarching from: 196 | //https://github.com/stackgl/glsl-raytrace/blob/master/index.glsl 197 | 198 | vec2 raymarching( vec3 rayOrigin, vec3 rayDir, float maxd, float precis ) { 199 | 200 | float latest = precis * 2.0; 201 | float dist = 0.0; 202 | float type = -1.0; 203 | vec2 res = vec2(-1.0, -1.0); 204 | for (int i = 0; i < steps; i++) { 205 | 206 | if (latest < precis || dist > maxd) break; 207 | 208 | vec2 result = field( rayOrigin + rayDir * dist ); 209 | latest = result.x; 210 | type = result.y; 211 | dist += latest; 212 | } 213 | 214 | if (dist < maxd) { res = vec2(dist, type); } 215 | return res; 216 | } 217 | 218 | //https://github.com/stackgl/glsl-sdf-normal 219 | 220 | vec3 calcNormal(vec3 pos, float eps) { 221 | const vec3 v1 = vec3( 1.0,-1.0,-1.0); 222 | const vec3 v2 = vec3(-1.0,-1.0, 1.0); 223 | const vec3 v3 = vec3(-1.0, 1.0,-1.0); 224 | const vec3 v4 = vec3( 1.0, 1.0, 1.0); 225 | 226 | return normalize( v1 * field( pos + v1*eps ).x + 227 | v2 * field( pos + v2*eps ).x + 228 | v3 * field( pos + v3*eps ).x + 229 | v4 * field( pos + v4*eps ).x ); 230 | } 231 | 232 | vec3 calcNormal(vec3 pos) { 233 | return calcNormal(pos, 0.002); 234 | } 235 | 236 | vec3 rimlight( vec3 pos, vec3 nor ) 237 | { 238 | vec3 v = normalize(-pos); 239 | float vdn = 1.0 - max(dot(v, nor), 0.0); 240 | return vec3(smoothstep(0., 1.0, vdn)); 241 | } 242 | 243 | 244 | 245 | void main() { 246 | 247 | 248 | vec3 color = vec3( 0.4, 0.8, 0.99 ); //blue 249 | vec2 screenPos = squareFrame( resolution ); 250 | float col = pow( max( 0., 1.- length( screenPos - vec2( 0.,.35 ) ) ), 1.5 ); 251 | gl_FragColor = vec4( vec3( col ), 1. ); 252 | 253 | 254 | float cameraAngle = 0.2 * time; 255 | float cameraRadius = 20.+sin( time*.1); 256 | 257 | float lensLength = 2.5; 258 | float y = cameraRadius * .38 + ( cameraRadius * .32 * sin(cameraAngle) ); 259 | vec3 rayOrigin = vec3( cameraRadius * sin(cameraAngle), y, cameraRadius * cos(cameraAngle)); 260 | vec3 rayTarget = vec3(0, 0, 0); 261 | vec3 rayDirection = getRay(rayOrigin, rayTarget, screenPos, lensLength); 262 | 263 | 264 | float maxDist = 50.; 265 | vec2 collision = raymarching( rayOrigin, rayDirection, maxDist, .01 ); 266 | 267 | if ( collision.x > -0.5) 268 | { 269 | 270 | //"world" position 271 | vec3 pos = rayOrigin + rayDirection * collision.x; 272 | 273 | //diffuse color 274 | vec3 col = vec3( .8 ); 275 | 276 | //normal vector 277 | vec3 nor = calcNormal( pos ); 278 | 279 | vec3 lig1 = normalize( vec3( 0.0, 5.0, -0.0) ); 280 | vec3 light1 = max( 0.0, dot( lig1, nor) ) * color; 281 | 282 | vec3 rim1 = rimlight( pos, -lig1 ); 283 | vec3 rim2 = rimlight( lig1, -nor ) * .25; 284 | 285 | float dep = ( ( collision.x + .5 ) / ( maxDist * .5 ) ); 286 | gl_FragColor = vec4( ( col + rim2 + light1 * rim1 ) - rim1 * dep, 1. ); 287 | 288 | } 289 | 290 | 291 | } -------------------------------------------------------------------------------- /glsl/tmp.glsl: -------------------------------------------------------------------------------- 1 | // Created by Stephane Cuillerdier - Aiekick/2015 2 | // License Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License. 3 | 4 | precision highp float; 5 | uniform float time; 6 | uniform vec2 resolution; 7 | 8 | //////2D FUNC TO MODIFY//////////////////// 9 | vec3 effect(vec2 v) 10 | { 11 | vec3 col = vec3(0.); 12 | 13 | v/= 1.5; 14 | 15 | float t = time; 16 | 17 | // vars 18 | 19 | const int n = 15; 20 | 21 | vec3 startColor = normalize(vec3(1.,0.,0.)); 22 | vec3 endColor = normalize(vec3(1.,1.,0.5)); 23 | 24 | float power = 0.5; 25 | float duration = 3.; 26 | // 27 | 28 | float dMax = duration; 29 | 30 | float mb = 0.; 31 | float mbRadius = 0.; 32 | float sum = 0.; 33 | for(int i=0;itmax ) break; 99 | } 100 | return clamp( res, 0.0, 1.0 ); 101 | } 102 | 103 | vec3 calcNormal( in vec3 pos ) 104 | { 105 | vec3 eps = vec3( 0.1, 0., 0. ); 106 | vec3 nor = vec3( 107 | map(pos+eps.xyy).x - map(pos-eps.xyy).x, 108 | map(pos+eps.yxy).x - map(pos-eps.yxy).x, 109 | map(pos+eps.yyx).x - map(pos-eps.yyx).x ); 110 | return normalize(nor); 111 | } 112 | 113 | float calcAO( in vec3 pos, in vec3 nor ) 114 | { 115 | float occ = 0.0; 116 | float sca = 1.0; 117 | for( int i=0; i<5; i++ ) 118 | { 119 | float hr = 0.01 + 0.12*float(i)/4.0; 120 | vec3 aopos = nor * hr + pos; 121 | float dd = map( aopos ).x; 122 | occ += -(dd-hr)*sca; 123 | sca *= 0.95; 124 | } 125 | return clamp( 1.0 - 3.0*occ, 0.0, 1.0 ); 126 | } 127 | 128 | /////////////////////////////////////////// 129 | float march(vec3 ro, vec3 rd, float rmPrec, float maxd, float mapPrec) 130 | { 131 | float s = rmPrec; 132 | float d = 0.; 133 | for(int i=0;i<40;i++) 134 | { 135 | if (smaxd) break; 136 | s = map(ro+rd*d).x*mapPrec; 137 | d += s; 138 | } 139 | return d; 140 | } 141 | 142 | ////////MAIN/////////////////////////////// 143 | void mainImage( out vec4 fragColor, in vec2 fragCoord ) 144 | { 145 | 146 | float cam_a = time; // angle z 147 | 148 | float cam_e = 5.52; // elevation 149 | float cam_d = 1.88; // distance to origin axis 150 | 151 | vec3 camUp=vec3(0,1,0);//Change camere up vector here 152 | vec3 camView=vec3(0,0,0); //Change camere view here 153 | float li = 0.6; // light intensity 154 | float prec = 0.00001; // ray marching precision 155 | float maxd = 50.; // ray marching distance max 156 | float refl_i = 0.45; // reflexion intensity 157 | float refr_a = 0.7; // refraction angle 158 | float refr_i = 0.8; // refraction intensity 159 | float bii = 0.35; // bright init intensity 160 | float marchPrecision = 1.; // ray marching tolerance precision 161 | 162 | vec2 uv = fragCoord.xy / resolution.xy * 2. -1.; 163 | uv.x*=resolution.x/resolution.y; 164 | 165 | vec3 col = vec3(0.); 166 | 167 | vec3 ro = vec3(-sin(cam_a)*cam_d, cam_e+1., cos(cam_a)*cam_d); // 168 | vec3 rov = normalize(camView-ro); 169 | vec3 u = normalize(cross(camUp,rov)); 170 | vec3 v = cross(rov,u); 171 | vec3 rd = normalize(rov + uv.x*u + uv.y*v); 172 | 173 | float b = bii; 174 | 175 | float d = march(ro, rd, prec, maxd, marchPrecision); 176 | 177 | if (d 6500.) col.y = 352e5 * pow(Temp,(-3. / 2.)) + 184.; 128 | col.z = 194.18 * log(Temp) - 1448.6; 129 | col = clamp(col, 0., 255.)/255.; 130 | if (Temp < 1000.) col *= Temp/1000.; 131 | return col; 132 | } 133 | 134 | const vec3 RockColor = vec3(.2,.4,.58); 135 | const vec3 DeepSpaceColor = vec3(0,.02,.15); 136 | 137 | void main() 138 | { 139 | 140 | vec4 f = gl_FragColor; 141 | vec2 g = gl_FragCoord.xy; 142 | 143 | vec2 si = resolution.xy; 144 | float t = time; 145 | 146 | float ca = t*.2; // angle z 147 | float ce = 2.; // elevation 148 | float cd = 4.; // distance to origin axis 149 | 150 | vec3 cu=vec3(0,1,0);//Change camere up vector here 151 | vec3 cv=vec3(0,0,0); //Change camere view here 152 | vec2 uv = (g+g-si)/min(si.x, si.y); 153 | vec3 ro = vec3(sin(ca)*cd, ce+1., cos(ca)*cd); // 154 | vec3 rd = cam(uv, ro, cu, cv); 155 | 156 | vec3 d = vec3(0.); 157 | vec3 p = ro+rd*d.x; 158 | vec2 s = vec2(DPrec.y, 0.); 159 | for(int i=0;i<200;i++) 160 | { 161 | if(s.xDPrec.y) break; 162 | s = map(p); 163 | s.x *= (s.x>DPrec.x?RMPrec.x:RMPrec.y); 164 | d.x += s.x; 165 | p = ro+rd*d.x; 166 | } 167 | float alpha = 1.; 168 | if (d.x maxd) break; 224 | 225 | vec2 result = field( rayOrigin + rayDir * dist ); 226 | latest = result.x; 227 | dist += latest; 228 | type = result.y; 229 | } 230 | 231 | vec2 res = vec2(-1.0, -1.0 ); 232 | if (dist < maxd) { res = vec2( dist, type ); } 233 | return res; 234 | 235 | } 236 | 237 | //https://github.com/stackgl/glsl-sdf-normal 238 | 239 | vec3 calcNormal(vec3 pos, float eps) { 240 | const vec3 v1 = vec3( 1.0,-1.0,-1.0); 241 | const vec3 v2 = vec3(-1.0,-1.0, 1.0); 242 | const vec3 v3 = vec3(-1.0, 1.0,-1.0); 243 | const vec3 v4 = vec3( 1.0, 1.0, 1.0); 244 | 245 | return normalize( v1 * field( pos + v1*eps ).x + 246 | v2 * field( pos + v2*eps ).x + 247 | v3 * field( pos + v3*eps ).x + 248 | v4 * field( pos + v4*eps ).x ); 249 | } 250 | 251 | vec3 calcNormal(vec3 pos) { 252 | return calcNormal(pos, 0.002); 253 | } 254 | 255 | vec3 rimlight( vec3 pos, vec3 nor ) 256 | { 257 | vec3 v = normalize(-pos); 258 | float vdn = 1.0 - max(dot(v, nor), 0.0); 259 | return vec3(smoothstep(0., 1.0, vdn)); 260 | } 261 | 262 | void main() { 263 | 264 | vec2 screenPos = squareFrame( resolution ); 265 | 266 | vec3 rayDirection = getRay( camera, target, screenPos, fov ); 267 | 268 | vec2 collision = raymarching( camera, rayDirection, raymarchMaximumDistance, raymarchPrecision ); 269 | 270 | vec3 col = vec3( 0.85 ); 271 | 272 | gl_FragColor = vec4(mix( col, vec3(1.), screenPos.y), 1. ); 273 | if ( collision.x > -0.5) 274 | { 275 | 276 | vec3 pos = camera + rayDirection * collision.x; 277 | 278 | vec3 nor = calcNormal( pos,.1 ); 279 | vec3 tex = textureCube( cubemap, nor ).rgb; 280 | 281 | col = mix( col, tex, collision.y ); 282 | 283 | col = col * rimlight( pos, nor ) + tex * .2; 284 | 285 | gl_FragColor = vec4( col, 1. ); 286 | } 287 | 288 | } -------------------------------------------------------------------------------- /halibut.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 18 | 19 | 20 | 21 | 22 | 23 | 63 | 64 | 65 | -------------------------------------------------------------------------------- /hulkbuster.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 70 | 71 | 72 | -------------------------------------------------------------------------------- /img/colors.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nicoptere/raymarching-for-THREE/b6954fa8fda6c11f64406b0ee54506ea6223361e/img/colors.png -------------------------------------------------------------------------------- /img/cover.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nicoptere/raymarching-for-THREE/b6954fa8fda6c11f64406b0ee54506ea6223361e/img/cover.jpg -------------------------------------------------------------------------------- /img/cubemap/cube03_0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nicoptere/raymarching-for-THREE/b6954fa8fda6c11f64406b0ee54506ea6223361e/img/cubemap/cube03_0.png -------------------------------------------------------------------------------- /img/cubemap/cube03_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nicoptere/raymarching-for-THREE/b6954fa8fda6c11f64406b0ee54506ea6223361e/img/cubemap/cube03_1.png -------------------------------------------------------------------------------- /img/cubemap/cube03_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nicoptere/raymarching-for-THREE/b6954fa8fda6c11f64406b0ee54506ea6223361e/img/cubemap/cube03_2.png -------------------------------------------------------------------------------- /img/cubemap/cube03_3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nicoptere/raymarching-for-THREE/b6954fa8fda6c11f64406b0ee54506ea6223361e/img/cubemap/cube03_3.png -------------------------------------------------------------------------------- /img/cubemap/cube03_4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nicoptere/raymarching-for-THREE/b6954fa8fda6c11f64406b0ee54506ea6223361e/img/cubemap/cube03_4.png -------------------------------------------------------------------------------- /img/cubemap/cube03_5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nicoptere/raymarching-for-THREE/b6954fa8fda6c11f64406b0ee54506ea6223361e/img/cubemap/cube03_5.png -------------------------------------------------------------------------------- /img/env.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nicoptere/raymarching-for-THREE/b6954fa8fda6c11f64406b0ee54506ea6223361e/img/env.png -------------------------------------------------------------------------------- /img/halibut.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nicoptere/raymarching-for-THREE/b6954fa8fda6c11f64406b0ee54506ea6223361e/img/halibut.jpg -------------------------------------------------------------------------------- /img/hulkbuster.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nicoptere/raymarching-for-THREE/b6954fa8fda6c11f64406b0ee54506ea6223361e/img/hulkbuster.jpg -------------------------------------------------------------------------------- /img/matcap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nicoptere/raymarching-for-THREE/b6954fa8fda6c11f64406b0ee54506ea6223361e/img/matcap.png -------------------------------------------------------------------------------- /img/noise_bulb.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nicoptere/raymarching-for-THREE/b6954fa8fda6c11f64406b0ee54506ea6223361e/img/noise_bulb.jpg -------------------------------------------------------------------------------- /img/walker.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nicoptere/raymarching-for-THREE/b6954fa8fda6c11f64406b0ee54506ea6223361e/img/walker.jpg -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 18 | 19 | 20 | 21 | 22 | 23 | 59 | 60 | 61 | -------------------------------------------------------------------------------- /interactive.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 18 | 19 | 20 | 21 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 102 | 103 | 104 | -------------------------------------------------------------------------------- /noise_bulb.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 66 | 67 | -------------------------------------------------------------------------------- /raymarcher.js: -------------------------------------------------------------------------------- 1 | var RayMarcher = function(){ 2 | 3 | var tl = new THREE.TextureLoader(); 4 | var cl = new THREE.CubeTextureLoader(); 5 | var rc = new THREE.Raycaster(); 6 | var mouse = new THREE.Vector2(); 7 | function RayMarcher( distance, precision ){ 8 | 9 | this.distance = distance || 50; 10 | this.precision = precision || 0.01; 11 | 12 | //scene setup 13 | 14 | this.scene = new THREE.Scene(); 15 | 16 | this.renderer = new THREE.WebGLRenderer(); 17 | this.renderer.setSize( window.innerWidth, window.innerHeight ); 18 | this.domElement = this.renderer.domElement; 19 | 20 | //used only to render the scene 21 | 22 | this.renderCamera = new THREE.OrthographicCamera(-1,1,1,-1,1/Math.pow( 2, 53 ),1); 23 | 24 | //geometry setup 25 | 26 | this.geom = new THREE.BufferGeometry(); 27 | this.geom.addAttribute( 'position', new THREE.BufferAttribute( new Float32Array([ -1,-1,0, 1,-1,0, 1,1,0, -1, -1, 0, 1, 1, 0, -1, 1, 0]), 3 ) ); 28 | this.mesh = new THREE.Mesh( this.geom, null ); 29 | this.scene.add( this.mesh ); 30 | 31 | //some helpers 32 | 33 | this.camera = new THREE.PerspectiveCamera( 60, 1, 0.1,1 ); 34 | this.target = new THREE.Vector3(); 35 | 36 | return this; 37 | 38 | } 39 | 40 | function loadFragmentShader( fragmentUrl, callback ) 41 | { 42 | this.loaded = false; 43 | 44 | var scope = this; 45 | var req = new XMLHttpRequest(); 46 | req.open( "GET", fragmentUrl ); 47 | req.onload = function (e) { 48 | scope.setFragmentShader( e.target.responseText, callback ); 49 | }; 50 | req.send(); 51 | return this; 52 | } 53 | 54 | function setFragmentShader( fs, cb ){ 55 | 56 | this.startTime = Date.now(); 57 | this.mesh.material = this.material = new THREE.ShaderMaterial({ 58 | 59 | uniforms :{ 60 | resolution:{ type:"v2", value:new THREE.Vector2( this.width, this.height ) }, 61 | time:{ type:"f", value:0 }, 62 | randomSeed:{ type:"f", value:Math.random() }, 63 | fov:{ type:"f", value:45 }, 64 | camera:{ type:"v3", value:this.camera.position }, 65 | target:{ type:"v3", value:this.target }, 66 | raymarchMaximumDistance:{ type:"f", value:this.distance }, 67 | raymarchPrecision:{ type:"f", value:this.precision} 68 | 69 | }, 70 | vertexShader : "void main() {gl_Position = vec4( position, 1.0 );}", 71 | fragmentShader : fs, 72 | transparent:true 73 | }); 74 | this.update(); 75 | 76 | if( cb != null )cb( this ); 77 | this.loaded = true; 78 | return this; 79 | } 80 | 81 | function setTexture( name, url ){ 82 | 83 | if( this.material == null ) 84 | { 85 | throw new Error("material not initialised, use setFragmentShader() first."); 86 | } 87 | rm.loaded = false; 88 | 89 | var scope = this; 90 | this.material.uniforms[ name ] = {type:'t', value:null }; 91 | tl.load( url, function(texture){ 92 | 93 | scope.material.uniforms[ name ].value = texture; 94 | scope.material.needsUpdate = true; 95 | scope.loaded = true; 96 | texture.needsUpdate = true; 97 | 98 | }); 99 | return this; 100 | } 101 | 102 | function setCubemap( name, urls ){ 103 | 104 | if( this.material == null ) 105 | { 106 | throw new Error("material not initialised, use setFragmentShader() first."); 107 | } 108 | rm.loaded = false; 109 | 110 | var scope = this; 111 | this.material.uniforms[ name ] = {type:'t', value:null }; 112 | cl.load( urls, function(texture) { 113 | scope.material.uniforms[ name ].value = texture; 114 | scope.material.needsUpdate = true; 115 | scope.loaded = true; 116 | texture.needsUpdate = true; 117 | }); 118 | } 119 | 120 | function setUniform( name, type, value ){ 121 | 122 | if( this.material == null ) 123 | { 124 | throw new Error("material not initialised, use setFragmentShader() first."); 125 | } 126 | 127 | this.material.uniforms[ name ] = {type:type, value:value }; 128 | return this; 129 | 130 | } 131 | 132 | function getUniform( name ){ 133 | 134 | 135 | if( this.material == null ) 136 | { 137 | console.warn("raymarcher.getUniform: material not initialised, use setFragmentShader() first."); 138 | return null; 139 | } 140 | 141 | return this.material.uniforms[name]; 142 | 143 | } 144 | 145 | function setSize( width, height ){ 146 | 147 | this.width = width; 148 | this.height = height; 149 | 150 | this.renderer.setSize( width, height ); 151 | 152 | this.camera.aspect = width / height; 153 | this.camera.updateProjectionMatrix(); 154 | 155 | if( this.material != null ) 156 | { 157 | this.material.uniforms.resolution.value.x = width; 158 | this.material.uniforms.resolution.value.y = height; 159 | } 160 | return this; 161 | } 162 | 163 | function update(){ 164 | 165 | if( this.material == null )return; 166 | 167 | this.material.uniforms.time.value = ( Date.now() - this.startTime ) * .001; 168 | this.material.uniforms.randomSeed.value = Math.random(); 169 | 170 | this.material.uniforms.fov.value = this.camera.fov * Math.PI / 180; 171 | 172 | this.material.uniforms.raymarchMaximumDistance.value = this.distance; 173 | this.material.uniforms.raymarchPrecision.value = this.precision; 174 | 175 | this.material.uniforms.camera.value = this.camera.position; 176 | 177 | this.material.uniforms.target.value = this.target; 178 | this.camera.lookAt( this.target ); 179 | 180 | } 181 | 182 | function render(){ 183 | 184 | if( this.loaded ) 185 | { 186 | this.update(); 187 | this.renderer.render( this.scene, this.renderCamera ); 188 | } 189 | } 190 | 191 | var _p = RayMarcher.prototype; 192 | _p.constructor = RayMarcher; 193 | 194 | _p.loadFragmentShader = loadFragmentShader; 195 | _p.setFragmentShader = setFragmentShader; 196 | _p.setTexture = setTexture; 197 | _p.setCubemap = setCubemap; 198 | _p.setUniform = setUniform; 199 | _p.getUniform = getUniform; 200 | _p.setSize = setSize; 201 | _p.update = update; 202 | _p.render = render; 203 | 204 | return RayMarcher; 205 | }(); -------------------------------------------------------------------------------- /tmp.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /vendor/controls/OrbitControls.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author qiao / https://github.com/qiao 3 | * @author mrdoob / http://mrdoob.com 4 | * @author alteredq / http://alteredqualia.com/ 5 | * @author WestLangley / http://github.com/WestLangley 6 | * @author erich666 / http://erichaines.com 7 | */ 8 | /*global THREE, console */ 9 | 10 | // This set of controls performs orbiting, dollying (zooming), and panning. It maintains 11 | // the "up" direction as +Y, unlike the TrackballControls. Touch on tablet and phones is 12 | // supported. 13 | // 14 | // Orbit - left mouse / touch: one finger move 15 | // Zoom - middle mouse, or mousewheel / touch: two finger spread or squish 16 | // Pan - right mouse, or arrow keys / touch: three finter swipe 17 | // 18 | // This is a drop-in replacement for (most) TrackballControls used in examples. 19 | // That is, include this js file and wherever you see: 20 | // controls = new THREE.TrackballControls( camera ); 21 | // controls.target.z = 150; 22 | // Simple substitute "OrbitControls" and the control should work as-is. 23 | 24 | THREE.OrbitControls = function ( object, domElement ) { 25 | 26 | this.object = object; 27 | this.domElement = ( domElement !== undefined ) ? domElement : document; 28 | 29 | // API 30 | 31 | // Set to false to disable this control 32 | this.enabled = true; 33 | 34 | // "target" sets the location of focus, where the control orbits around 35 | // and where it pans with respect to. 36 | this.target = new THREE.Vector3(); 37 | 38 | // center is old, deprecated; use "target" instead 39 | this.center = this.target; 40 | 41 | // This option actually enables dollying in and out; left as "zoom" for 42 | // backwards compatibility 43 | this.noZoom = false; 44 | this.zoomSpeed = 1.0; 45 | 46 | // Limits to how far you can dolly in and out 47 | this.minDistance = 0; 48 | this.maxDistance = Infinity; 49 | 50 | // Set to true to disable this control 51 | this.noRotate = false; 52 | this.rotateSpeed = 1.0; 53 | 54 | // Set to true to disable this control 55 | this.noPan = false; 56 | this.keyPanSpeed = 7.0; // pixels moved per arrow key push 57 | 58 | // Set to true to automatically rotate around the target 59 | this.autoRotate = false; 60 | this.autoRotateSpeed = 2.0; // 30 seconds per round when fps is 60 61 | 62 | // How far you can orbit vertically, upper and lower limits. 63 | // Range is 0 to Math.PI radians. 64 | this.minPolarAngle = 0; // radians 65 | this.maxPolarAngle = Math.PI; // radians 66 | 67 | // Set to true to disable use of the keys 68 | this.noKeys = false; 69 | 70 | // The four arrow keys 71 | this.keys = { LEFT: 37, UP: 38, RIGHT: 39, BOTTOM: 40 }; 72 | 73 | //////////// 74 | // internals 75 | 76 | var scope = this; 77 | 78 | var EPS = 0.000001; 79 | 80 | var rotateStart = new THREE.Vector2(); 81 | var rotateEnd = new THREE.Vector2(); 82 | var rotateDelta = new THREE.Vector2(); 83 | 84 | var panStart = new THREE.Vector2(); 85 | var panEnd = new THREE.Vector2(); 86 | var panDelta = new THREE.Vector2(); 87 | var panOffset = new THREE.Vector3(); 88 | 89 | var offset = new THREE.Vector3(); 90 | 91 | var dollyStart = new THREE.Vector2(); 92 | var dollyEnd = new THREE.Vector2(); 93 | var dollyDelta = new THREE.Vector2(); 94 | 95 | var phiDelta = 0; 96 | var thetaDelta = 0; 97 | var scale = 1; 98 | var pan = new THREE.Vector3(); 99 | 100 | var lastPosition = new THREE.Vector3(); 101 | var lastQuaternion = new THREE.Quaternion(); 102 | 103 | var STATE = { NONE : -1, ROTATE : 0, DOLLY : 1, PAN : 2, TOUCH_ROTATE : 3, TOUCH_DOLLY : 4, TOUCH_PAN : 5 }; 104 | 105 | var state = STATE.NONE; 106 | 107 | // for reset 108 | 109 | this.target0 = this.target.clone(); 110 | this.position0 = this.object.position.clone(); 111 | 112 | // so camera.up is the orbit axis 113 | 114 | var quat = new THREE.Quaternion().setFromUnitVectors( object.up, new THREE.Vector3( 0, 1, 0 ) ); 115 | var quatInverse = quat.clone().inverse(); 116 | 117 | // events 118 | 119 | var changeEvent = { type: 'change' }; 120 | var startEvent = { type: 'start'}; 121 | var endEvent = { type: 'end'}; 122 | 123 | 124 | this.rotateLeft = function ( angle ) { 125 | 126 | if ( angle === undefined ) { 127 | 128 | angle = getAutoRotationAngle(); 129 | 130 | } 131 | 132 | thetaDelta -= angle; 133 | 134 | }; 135 | 136 | this.rotateUp = function ( angle ) { 137 | 138 | if ( angle === undefined ) { 139 | 140 | angle = getAutoRotationAngle(); 141 | 142 | } 143 | 144 | phiDelta -= angle; 145 | 146 | }; 147 | 148 | // pass in distance in world space to move left 149 | this.panLeft = function ( distance ) { 150 | 151 | var te = this.object.matrix.elements; 152 | 153 | // get X column of matrix 154 | panOffset.set( te[ 0 ], te[ 1 ], te[ 2 ] ); 155 | panOffset.multiplyScalar( - distance ); 156 | 157 | pan.add( panOffset ); 158 | 159 | }; 160 | 161 | // pass in distance in world space to move up 162 | this.panUp = function ( distance ) { 163 | 164 | var te = this.object.matrix.elements; 165 | 166 | // get Y column of matrix 167 | panOffset.set( te[ 4 ], te[ 5 ], te[ 6 ] ); 168 | panOffset.multiplyScalar( distance ); 169 | 170 | pan.add( panOffset ); 171 | 172 | }; 173 | 174 | // pass in x,y of change desired in pixel space, 175 | // right and down are positive 176 | this.pan = function ( deltaX, deltaY ) { 177 | 178 | var element = scope.domElement === document ? scope.domElement.body : scope.domElement; 179 | 180 | if ( scope.object.fov !== undefined ) { 181 | 182 | // perspective 183 | var position = scope.object.position; 184 | var offset = position.clone().sub( scope.target ); 185 | var targetDistance = offset.length(); 186 | 187 | // half of the fov is center to top of screen 188 | targetDistance *= Math.tan( ( scope.object.fov / 2 ) * Math.PI / 180.0 ); 189 | 190 | // we actually don't use screenWidth, since perspective camera is fixed to screen height 191 | scope.panLeft( 2 * deltaX * targetDistance / element.clientHeight ); 192 | scope.panUp( 2 * deltaY * targetDistance / element.clientHeight ); 193 | 194 | } else if ( scope.object.top !== undefined ) { 195 | 196 | // orthographic 197 | scope.panLeft( deltaX * (scope.object.right - scope.object.left) / element.clientWidth ); 198 | scope.panUp( deltaY * (scope.object.top - scope.object.bottom) / element.clientHeight ); 199 | 200 | } else { 201 | 202 | // camera neither orthographic or perspective 203 | console.warn( 'WARNING: OrbitControls.js encountered an unknown camera type - pan disabled.' ); 204 | 205 | } 206 | 207 | }; 208 | 209 | this.dollyIn = function ( dollyScale ) { 210 | 211 | if ( dollyScale === undefined ) { 212 | 213 | dollyScale = getZoomScale(); 214 | 215 | } 216 | 217 | scale /= dollyScale; 218 | 219 | }; 220 | 221 | this.dollyOut = function ( dollyScale ) { 222 | 223 | if ( dollyScale === undefined ) { 224 | 225 | dollyScale = getZoomScale(); 226 | 227 | } 228 | 229 | scale *= dollyScale; 230 | 231 | }; 232 | 233 | this.setAngles = function( theta, phi, radius ) 234 | { 235 | 236 | var position = this.object.position; 237 | offset.copy( position ).sub( this.target ); 238 | offset.applyQuaternion( quat ); 239 | 240 | theta = theta || Math.atan2( offset.x, offset.z ); 241 | phi = phi || Math.atan2( Math.sqrt( offset.x * offset.x + offset.z * offset.z ), offset.y ); 242 | 243 | // restrict radius to be between desired limits 244 | radius = radius || offset.length() * scale; 245 | radius = Math.max( this.minDistance, Math.min( this.maxDistance, radius ) ); 246 | 247 | offset.x = radius * Math.sin( phi ) * Math.sin( theta ); 248 | offset.y = radius * Math.cos( phi ); 249 | offset.z = radius * Math.sin( phi ) * Math.cos( theta ); 250 | 251 | // rotate offset back to "camera-up-vector-is-up" space 252 | offset.applyQuaternion( quatInverse ); 253 | position.copy( this.target ).add( offset ); 254 | this.object.lookAt( this.target ); 255 | 256 | if ( lastPosition.distanceToSquared( this.object.position ) > EPS 257 | || 8 * (1 - lastQuaternion.dot(this.object.quaternion)) > EPS ) { 258 | this.dispatchEvent( changeEvent ); 259 | lastPosition.copy( this.object.position ); 260 | lastQuaternion.copy (this.object.quaternion ); 261 | } 262 | }; 263 | 264 | this.getAngles = function() 265 | { 266 | var position = this.object.position; 267 | offset.copy( position ).sub( this.target ); 268 | offset.applyQuaternion( quat ); 269 | var theta = Math.atan2( offset.x, offset.z ); 270 | var phi = Math.atan2( Math.sqrt( offset.x * offset.x + offset.z * offset.z ), offset.y ); 271 | return { theta:theta, phi:phi }; 272 | }; 273 | 274 | this.update = function () { 275 | 276 | 277 | var position = this.object.position; 278 | 279 | offset.copy( position ).sub( this.target ); 280 | 281 | // rotate offset to "y-axis-is-up" space 282 | offset.applyQuaternion( quat ); 283 | 284 | // angle from z-axis around y-axis 285 | 286 | var theta = Math.atan2( offset.x, offset.z ); 287 | 288 | // angle from y-axis 289 | 290 | var phi = Math.atan2( Math.sqrt( offset.x * offset.x + offset.z * offset.z ), offset.y ); 291 | 292 | if ( this.autoRotate ) { 293 | 294 | this.rotateLeft( getAutoRotationAngle() ); 295 | 296 | } 297 | 298 | theta += thetaDelta; 299 | phi += phiDelta; 300 | 301 | // restrict phi to be between desired limits 302 | phi = Math.max( this.minPolarAngle, Math.min( this.maxPolarAngle, phi ) ); 303 | 304 | // restrict phi to be betwee EPS and PI-EPS 305 | phi = Math.max( EPS, Math.min( Math.PI - EPS, phi ) ); 306 | 307 | var radius = offset.length() * scale; 308 | 309 | // restrict radius to be between desired limits 310 | radius = Math.max( this.minDistance, Math.min( this.maxDistance, radius ) ); 311 | 312 | // move target to panned location 313 | this.target.add( pan ); 314 | 315 | offset.x = radius * Math.sin( phi ) * Math.sin( theta ); 316 | offset.y = radius * Math.cos( phi ); 317 | offset.z = radius * Math.sin( phi ) * Math.cos( theta ); 318 | 319 | // rotate offset back to "camera-up-vector-is-up" space 320 | offset.applyQuaternion( quatInverse ); 321 | 322 | position.copy( this.target ).add( offset ); 323 | 324 | //var pos = offset.normalize().multiplyScalar( EARTH_RADIUS ); 325 | this.object.lookAt( this.target ); 326 | 327 | thetaDelta = 0; 328 | phiDelta = 0; 329 | scale = 1; 330 | pan.set( 0, 0, 0 ); 331 | 332 | // update condition is: 333 | // min(camera displacement, camera rotation in radians)^2 > EPS 334 | // using small-angle approximation cos(x/2) = 1 - x^2 / 8 335 | 336 | if ( lastPosition.distanceToSquared( this.object.position ) > EPS 337 | || 8 * (1 - lastQuaternion.dot(this.object.quaternion)) > EPS ) { 338 | 339 | this.dispatchEvent( changeEvent ); 340 | 341 | lastPosition.copy( this.object.position ); 342 | lastQuaternion.copy (this.object.quaternion ); 343 | 344 | } 345 | 346 | }; 347 | 348 | 349 | this.reset = function () { 350 | 351 | state = STATE.NONE; 352 | 353 | this.target.copy( this.target0 ); 354 | this.object.position.copy( this.position0 ); 355 | 356 | this.update(); 357 | 358 | }; 359 | 360 | function getAutoRotationAngle() { 361 | 362 | return 2 * Math.PI / 60 / 60 * scope.autoRotateSpeed; 363 | 364 | } 365 | 366 | function getZoomScale() { 367 | 368 | return Math.pow( 0.95, scope.zoomSpeed ); 369 | 370 | } 371 | 372 | function onMouseDown( event ) { 373 | 374 | if ( scope.enabled === false ) return; 375 | // event.preventDefault(); 376 | 377 | if ( event.button === 0 ) { 378 | if ( scope.noRotate === true ) return; 379 | 380 | state = STATE.ROTATE; 381 | 382 | rotateStart.set( event.clientX, event.clientY ); 383 | 384 | } else if ( event.button === 1 ) { 385 | if ( scope.noZoom === true ) return; 386 | 387 | state = STATE.DOLLY; 388 | 389 | dollyStart.set( event.clientX, event.clientY ); 390 | 391 | } else if ( event.button === 2 ) { 392 | if ( scope.noPan === true ) return; 393 | 394 | state = STATE.PAN; 395 | 396 | panStart.set( event.clientX, event.clientY ); 397 | 398 | } 399 | 400 | document.addEventListener( 'mousemove', onMouseMove, false ); 401 | document.addEventListener( 'mouseup', onMouseUp, false ); 402 | scope.dispatchEvent( startEvent ); 403 | 404 | } 405 | 406 | function onMouseMove( event ) { 407 | 408 | if ( scope.enabled === false ) 409 | { 410 | document.removeEventListener( 'mousemove', onMouseMove, false ); 411 | return; 412 | } 413 | 414 | // event.preventDefault(); 415 | var element = scope.domElement === document ? scope.domElement.body : scope.domElement; 416 | 417 | if ( state === STATE.ROTATE ) { 418 | 419 | if ( scope.noRotate === true ) return; 420 | 421 | rotateEnd.set( event.clientX, event.clientY ); 422 | rotateDelta.subVectors( rotateEnd, rotateStart ); 423 | 424 | // rotating across whole screen goes 360 degrees around 425 | scope.rotateLeft( 2 * Math.PI * rotateDelta.x / element.clientWidth * scope.rotateSpeed ); 426 | 427 | // rotating up and down along whole screen attempts to go 360, but limited to 180 428 | scope.rotateUp( 2 * Math.PI * rotateDelta.y / element.clientHeight * scope.rotateSpeed ); 429 | 430 | rotateStart.copy( rotateEnd ); 431 | 432 | } else if ( state === STATE.DOLLY ) { 433 | 434 | if ( scope.noZoom === true ) return; 435 | 436 | dollyEnd.set( event.clientX, event.clientY ); 437 | dollyDelta.subVectors( dollyEnd, dollyStart ); 438 | 439 | if ( dollyDelta.y > 0 ) { 440 | 441 | scope.dollyIn(); 442 | 443 | } else { 444 | 445 | scope.dollyOut(); 446 | 447 | } 448 | 449 | dollyStart.copy( dollyEnd ); 450 | 451 | } else if ( state === STATE.PAN ) { 452 | 453 | if ( scope.noPan === true ) return; 454 | 455 | panEnd.set( event.clientX, event.clientY ); 456 | panDelta.subVectors( panEnd, panStart ); 457 | 458 | scope.pan( panDelta.x, panDelta.y ); 459 | 460 | panStart.copy( panEnd ); 461 | 462 | } 463 | 464 | scope.update(); 465 | 466 | } 467 | 468 | function onMouseUp( /* event */ ) { 469 | 470 | if ( scope.enabled === false ) return; 471 | 472 | document.removeEventListener( 'mousemove', onMouseMove, false ); 473 | document.removeEventListener( 'mouseup', onMouseUp, false ); 474 | scope.dispatchEvent( endEvent ); 475 | state = STATE.NONE; 476 | 477 | } 478 | 479 | function onMouseWheel( event ) { 480 | 481 | if ( scope.enabled === false || scope.noZoom === true ) return; 482 | 483 | // event.preventDefault(); 484 | event.stopPropagation(); 485 | 486 | var delta = 0; 487 | 488 | if ( event.wheelDelta !== undefined ) { // WebKit / Opera / Explorer 9 489 | 490 | delta = event.wheelDelta; 491 | 492 | } else if ( event.detail !== undefined ) { // Firefox 493 | 494 | delta = - event.detail; 495 | 496 | } 497 | 498 | if ( delta > 0 ) { 499 | 500 | scope.dollyOut(); 501 | 502 | } else { 503 | 504 | scope.dollyIn(); 505 | 506 | } 507 | 508 | scope.update(); 509 | scope.dispatchEvent( startEvent ); 510 | scope.dispatchEvent( endEvent ); 511 | 512 | } 513 | 514 | function onKeyDown( event ) { 515 | 516 | if ( scope.enabled === false || scope.noKeys === true || scope.noPan === true ) return; 517 | 518 | switch ( event.keyCode ) { 519 | 520 | case scope.keys.UP: 521 | scope.pan( 0, scope.keyPanSpeed ); 522 | scope.update(); 523 | break; 524 | 525 | case scope.keys.BOTTOM: 526 | scope.pan( 0, - scope.keyPanSpeed ); 527 | scope.update(); 528 | break; 529 | 530 | case scope.keys.LEFT: 531 | scope.pan( scope.keyPanSpeed, 0 ); 532 | scope.update(); 533 | break; 534 | 535 | case scope.keys.RIGHT: 536 | scope.pan( - scope.keyPanSpeed, 0 ); 537 | scope.update(); 538 | break; 539 | 540 | } 541 | 542 | } 543 | 544 | function touchstart( event ) { 545 | 546 | if ( scope.enabled === false ) return; 547 | 548 | switch ( event.touches.length ) { 549 | 550 | case 1: // one-fingered touch: rotate 551 | 552 | if ( scope.noRotate === true ) return; 553 | 554 | state = STATE.TOUCH_ROTATE; 555 | 556 | rotateStart.set( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY ); 557 | break; 558 | 559 | case 2: // two-fingered touch: dolly 560 | 561 | if ( scope.noZoom === true ) return; 562 | 563 | state = STATE.TOUCH_DOLLY; 564 | 565 | var dx = event.touches[ 0 ].pageX - event.touches[ 1 ].pageX; 566 | var dy = event.touches[ 0 ].pageY - event.touches[ 1 ].pageY; 567 | var distance = Math.sqrt( dx * dx + dy * dy ); 568 | dollyStart.set( 0, distance ); 569 | break; 570 | 571 | case 3: // three-fingered touch: pan 572 | 573 | if ( scope.noPan === true ) return; 574 | 575 | state = STATE.TOUCH_PAN; 576 | 577 | panStart.set( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY ); 578 | break; 579 | 580 | default: 581 | 582 | state = STATE.NONE; 583 | 584 | } 585 | 586 | scope.dispatchEvent( startEvent ); 587 | 588 | } 589 | 590 | function touchmove( event ) { 591 | 592 | if ( scope.enabled === false ) return; 593 | 594 | event.preventDefault(); 595 | event.stopPropagation(); 596 | 597 | var element = scope.domElement === document ? scope.domElement.body : scope.domElement; 598 | 599 | switch ( event.touches.length ) { 600 | 601 | case 1: // one-fingered touch: rotate 602 | 603 | if ( scope.noRotate === true ) return; 604 | if ( state !== STATE.TOUCH_ROTATE ) return; 605 | 606 | rotateEnd.set( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY ); 607 | rotateDelta.subVectors( rotateEnd, rotateStart ); 608 | 609 | // rotating across whole screen goes 360 degrees around 610 | scope.rotateLeft( 2 * Math.PI * rotateDelta.x / element.clientWidth * scope.rotateSpeed ); 611 | // rotating up and down along whole screen attempts to go 360, but limited to 180 612 | scope.rotateUp( 2 * Math.PI * rotateDelta.y / element.clientHeight * scope.rotateSpeed ); 613 | 614 | rotateStart.copy( rotateEnd ); 615 | 616 | scope.update(); 617 | break; 618 | 619 | case 2: // two-fingered touch: dolly 620 | 621 | if ( scope.noZoom === true ) return; 622 | if ( state !== STATE.TOUCH_DOLLY ) return; 623 | 624 | var dx = event.touches[ 0 ].pageX - event.touches[ 1 ].pageX; 625 | var dy = event.touches[ 0 ].pageY - event.touches[ 1 ].pageY; 626 | var distance = Math.sqrt( dx * dx + dy * dy ); 627 | 628 | dollyEnd.set( 0, distance ); 629 | dollyDelta.subVectors( dollyEnd, dollyStart ); 630 | 631 | if ( dollyDelta.y > 0 ) { 632 | 633 | scope.dollyOut(); 634 | 635 | } else { 636 | 637 | scope.dollyIn(); 638 | 639 | } 640 | 641 | dollyStart.copy( dollyEnd ); 642 | 643 | scope.update(); 644 | break; 645 | 646 | case 3: // three-fingered touch: pan 647 | 648 | if ( scope.noPan === true ) return; 649 | if ( state !== STATE.TOUCH_PAN ) return; 650 | 651 | panEnd.set( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY ); 652 | panDelta.subVectors( panEnd, panStart ); 653 | 654 | scope.pan( panDelta.x, panDelta.y ); 655 | 656 | panStart.copy( panEnd ); 657 | 658 | scope.update(); 659 | break; 660 | 661 | default: 662 | 663 | state = STATE.NONE; 664 | 665 | } 666 | 667 | } 668 | 669 | function touchend( /* event */ ) { 670 | 671 | if ( scope.enabled === false ) return; 672 | 673 | scope.dispatchEvent( endEvent ); 674 | state = STATE.NONE; 675 | 676 | } 677 | 678 | this.domElement.addEventListener( 'contextmenu', function ( event ) { event.preventDefault(); }, false ); 679 | this.domElement.addEventListener( 'mousedown', onMouseDown, false ); 680 | this.domElement.addEventListener( 'mousewheel', onMouseWheel, false ); 681 | this.domElement.addEventListener( 'DOMMouseScroll', onMouseWheel, false ); // firefox 682 | 683 | this.domElement.addEventListener( 'touchstart', touchstart, false ); 684 | this.domElement.addEventListener( 'touchend', touchend, false ); 685 | this.domElement.addEventListener( 'touchmove', touchmove, false ); 686 | 687 | window.addEventListener( 'keydown', onKeyDown, false ); 688 | scope.enabled = true; 689 | // force an update at start 690 | this.update(); 691 | 692 | }; 693 | 694 | THREE.OrbitControls.prototype = Object.create( THREE.EventDispatcher.prototype ); 695 | -------------------------------------------------------------------------------- /vendor/postprocessing/EffectComposer.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author alteredq / http://alteredqualia.com/ 3 | */ 4 | 5 | THREE.EffectComposer = function ( renderer, renderTarget ) { 6 | 7 | this.renderer = renderer; 8 | 9 | if ( renderTarget === undefined ) { 10 | 11 | var pixelRatio = renderer.getPixelRatio(); 12 | 13 | var width = Math.floor( renderer.context.canvas.width / pixelRatio ) || 1; 14 | var height = Math.floor( renderer.context.canvas.height / pixelRatio ) || 1; 15 | var parameters = { minFilter: THREE.LinearFilter, magFilter: THREE.LinearFilter, format: THREE.RGBFormat, stencilBuffer: false }; 16 | 17 | renderTarget = new THREE.WebGLRenderTarget( width, height, parameters ); 18 | 19 | } 20 | 21 | this.renderTarget1 = renderTarget; 22 | this.renderTarget2 = renderTarget.clone(); 23 | 24 | this.writeBuffer = this.renderTarget1; 25 | this.readBuffer = this.renderTarget2; 26 | 27 | this.passes = []; 28 | 29 | if ( THREE.CopyShader === undefined ) 30 | console.error( "THREE.EffectComposer relies on THREE.CopyShader" ); 31 | 32 | this.copyPass = new THREE.ShaderPass( THREE.CopyShader ); 33 | 34 | }; 35 | 36 | THREE.EffectComposer.prototype = { 37 | 38 | swapBuffers: function() { 39 | 40 | var tmp = this.readBuffer; 41 | this.readBuffer = this.writeBuffer; 42 | this.writeBuffer = tmp; 43 | 44 | }, 45 | 46 | addPass: function ( pass ) { 47 | 48 | this.passes.push( pass ); 49 | 50 | }, 51 | 52 | insertPass: function ( pass, index ) { 53 | 54 | this.passes.splice( index, 0, pass ); 55 | 56 | }, 57 | 58 | render: function ( delta ) { 59 | 60 | this.writeBuffer = this.renderTarget1; 61 | this.readBuffer = this.renderTarget2; 62 | 63 | var maskActive = false; 64 | 65 | var pass, i, il = this.passes.length; 66 | 67 | for ( i = 0; i < il; i ++ ) { 68 | 69 | pass = this.passes[ i ]; 70 | 71 | if ( ! pass.enabled ) continue; 72 | 73 | pass.render( this.renderer, this.writeBuffer, this.readBuffer, delta, maskActive ); 74 | 75 | if ( pass.needsSwap ) { 76 | 77 | if ( maskActive ) { 78 | 79 | var context = this.renderer.context; 80 | 81 | context.stencilFunc( context.NOTEQUAL, 1, 0xffffffff ); 82 | 83 | this.copyPass.render( this.renderer, this.writeBuffer, this.readBuffer, delta ); 84 | 85 | context.stencilFunc( context.EQUAL, 1, 0xffffffff ); 86 | 87 | } 88 | 89 | this.swapBuffers(); 90 | 91 | } 92 | 93 | if ( pass instanceof THREE.MaskPass ) { 94 | 95 | maskActive = true; 96 | 97 | } else if ( pass instanceof THREE.ClearMaskPass ) { 98 | 99 | maskActive = false; 100 | 101 | } 102 | 103 | } 104 | 105 | }, 106 | 107 | reset: function ( renderTarget ) { 108 | 109 | if ( renderTarget === undefined ) { 110 | 111 | renderTarget = this.renderTarget1.clone(); 112 | 113 | var pixelRatio = this.renderer.getPixelRatio(); 114 | 115 | renderTarget.width = Math.floor( this.renderer.context.canvas.width / pixelRatio ); 116 | renderTarget.height = Math.floor( this.renderer.context.canvas.height / pixelRatio ); 117 | 118 | } 119 | 120 | this.renderTarget1.dispose(); 121 | this.renderTarget1 = renderTarget; 122 | this.renderTarget2.dispose(); 123 | this.renderTarget2 = renderTarget.clone(); 124 | 125 | this.writeBuffer = this.renderTarget1; 126 | this.readBuffer = this.renderTarget2; 127 | 128 | }, 129 | 130 | setSize: function ( width, height ) { 131 | 132 | this.renderTarget1.setSize( width, height ); 133 | this.renderTarget2.setSize( width, height ); 134 | 135 | } 136 | 137 | }; 138 | -------------------------------------------------------------------------------- /vendor/postprocessing/MaskPass.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author alteredq / http://alteredqualia.com/ 3 | */ 4 | 5 | THREE.MaskPass = function ( scene, camera ) { 6 | 7 | this.scene = scene; 8 | this.camera = camera; 9 | 10 | this.enabled = true; 11 | this.clear = true; 12 | this.needsSwap = false; 13 | 14 | this.inverse = false; 15 | 16 | }; 17 | 18 | THREE.MaskPass.prototype = { 19 | 20 | render: function ( renderer, writeBuffer, readBuffer, delta ) { 21 | 22 | var context = renderer.context; 23 | 24 | // don't update color or depth 25 | 26 | context.colorMask( false, false, false, false ); 27 | context.depthMask( false ); 28 | 29 | // set up stencil 30 | 31 | var writeValue, clearValue; 32 | 33 | if ( this.inverse ) { 34 | 35 | writeValue = 0; 36 | clearValue = 1; 37 | 38 | } else { 39 | 40 | writeValue = 1; 41 | clearValue = 0; 42 | 43 | } 44 | 45 | context.enable( context.STENCIL_TEST ); 46 | context.stencilOp( context.REPLACE, context.REPLACE, context.REPLACE ); 47 | context.stencilFunc( context.ALWAYS, writeValue, 0xffffffff ); 48 | context.clearStencil( clearValue ); 49 | 50 | // draw into the stencil buffer 51 | 52 | renderer.render( this.scene, this.camera, readBuffer, this.clear ); 53 | renderer.render( this.scene, this.camera, writeBuffer, this.clear ); 54 | 55 | // re-enable update of color and depth 56 | 57 | context.colorMask( true, true, true, true ); 58 | context.depthMask( true ); 59 | 60 | // only render where stencil is set to 1 61 | 62 | context.stencilFunc( context.EQUAL, 1, 0xffffffff ); // draw if == 1 63 | context.stencilOp( context.KEEP, context.KEEP, context.KEEP ); 64 | 65 | } 66 | 67 | }; 68 | 69 | 70 | THREE.ClearMaskPass = function () { 71 | 72 | this.enabled = true; 73 | 74 | }; 75 | 76 | THREE.ClearMaskPass.prototype = { 77 | 78 | render: function ( renderer, writeBuffer, readBuffer, delta ) { 79 | 80 | var context = renderer.context; 81 | 82 | context.disable( context.STENCIL_TEST ); 83 | 84 | } 85 | 86 | }; 87 | -------------------------------------------------------------------------------- /vendor/postprocessing/RenderPass.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author alteredq / http://alteredqualia.com/ 3 | */ 4 | 5 | THREE.RenderPass = function ( scene, camera, overrideMaterial, clearColor, clearAlpha ) { 6 | 7 | this.scene = scene; 8 | this.camera = camera; 9 | 10 | this.overrideMaterial = overrideMaterial; 11 | 12 | this.clearColor = clearColor; 13 | this.clearAlpha = ( clearAlpha !== undefined ) ? clearAlpha : 1; 14 | 15 | this.oldClearColor = new THREE.Color(); 16 | this.oldClearAlpha = 1; 17 | 18 | this.enabled = true; 19 | this.clear = true; 20 | this.needsSwap = false; 21 | 22 | }; 23 | 24 | THREE.RenderPass.prototype = { 25 | 26 | render: function ( renderer, writeBuffer, readBuffer, delta ) { 27 | 28 | this.scene.overrideMaterial = this.overrideMaterial; 29 | 30 | if ( this.clearColor ) { 31 | 32 | this.oldClearColor.copy( renderer.getClearColor() ); 33 | this.oldClearAlpha = renderer.getClearAlpha(); 34 | 35 | renderer.setClearColor( this.clearColor, this.clearAlpha ); 36 | 37 | } 38 | 39 | renderer.render( this.scene, this.camera, readBuffer, this.clear ); 40 | 41 | if ( this.clearColor ) { 42 | 43 | renderer.setClearColor( this.oldClearColor, this.oldClearAlpha ); 44 | 45 | } 46 | 47 | this.scene.overrideMaterial = null; 48 | 49 | } 50 | 51 | }; 52 | -------------------------------------------------------------------------------- /vendor/postprocessing/ShaderPass.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author alteredq / http://alteredqualia.com/ 3 | */ 4 | 5 | THREE.ShaderPass = function ( shader, textureID ) { 6 | 7 | this.textureID = ( textureID !== undefined ) ? textureID : "tDiffuse"; 8 | 9 | this.uniforms = THREE.UniformsUtils.clone( shader.uniforms ); 10 | 11 | this.material = new THREE.ShaderMaterial( { 12 | 13 | defines: shader.defines || {}, 14 | uniforms: this.uniforms, 15 | vertexShader: shader.vertexShader, 16 | fragmentShader: shader.fragmentShader 17 | 18 | } ); 19 | 20 | this.renderToScreen = false; 21 | 22 | this.enabled = true; 23 | this.needsSwap = true; 24 | this.clear = false; 25 | 26 | 27 | this.camera = new THREE.OrthographicCamera( - 1, 1, 1, - 1, 0, 1 ); 28 | this.scene = new THREE.Scene(); 29 | 30 | this.quad = new THREE.Mesh( new THREE.PlaneBufferGeometry( 2, 2 ), null ); 31 | this.scene.add( this.quad ); 32 | 33 | }; 34 | 35 | THREE.ShaderPass.prototype = { 36 | 37 | render: function ( renderer, writeBuffer, readBuffer, delta ) { 38 | 39 | if ( this.uniforms[ this.textureID ] ) { 40 | 41 | this.uniforms[ this.textureID ].value = readBuffer; 42 | 43 | } 44 | 45 | this.quad.material = this.material; 46 | 47 | if ( this.renderToScreen ) { 48 | 49 | renderer.render( this.scene, this.camera ); 50 | 51 | } else { 52 | 53 | renderer.render( this.scene, this.camera, writeBuffer, this.clear ); 54 | 55 | } 56 | 57 | } 58 | 59 | }; 60 | -------------------------------------------------------------------------------- /vendor/shaders/CopyShader.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author alteredq / http://alteredqualia.com/ 3 | * 4 | * Full-screen textured quad shader 5 | */ 6 | 7 | THREE.CopyShader = { 8 | 9 | uniforms: { 10 | 11 | "tDiffuse": { type: "t", value: null }, 12 | "opacity": { type: "f", value: 1.0 } 13 | 14 | }, 15 | 16 | vertexShader: [ 17 | 18 | "varying vec2 vUv;", 19 | 20 | "void main() {", 21 | 22 | "vUv = uv;", 23 | "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", 24 | 25 | "}" 26 | 27 | ].join( "\n" ), 28 | 29 | fragmentShader: [ 30 | 31 | "uniform float opacity;", 32 | 33 | "uniform sampler2D tDiffuse;", 34 | 35 | "varying vec2 vUv;", 36 | 37 | "void main() {", 38 | 39 | "vec4 texel = texture2D( tDiffuse, vUv );", 40 | "gl_FragColor = opacity * texel;", 41 | 42 | "}" 43 | 44 | ].join( "\n" ) 45 | 46 | }; 47 | -------------------------------------------------------------------------------- /vendor/shaders/FXAAShader.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author alteredq / http://alteredqualia.com/ 3 | * @author davidedc / http://www.sketchpatch.net/ 4 | * 5 | * NVIDIA FXAA by Timothy Lottes 6 | * http://timothylottes.blogspot.com/2011/06/fxaa3-source-released.html 7 | * - WebGL port by @supereggbert 8 | * http://www.glge.org/demos/fxaa/ 9 | */ 10 | 11 | THREE.FXAAShader = { 12 | 13 | uniforms: { 14 | 15 | "tDiffuse": { type: "t", value: null }, 16 | "resolution": { type: "v2", value: new THREE.Vector2( 1 / 1024, 1 / 512 ) } 17 | 18 | }, 19 | 20 | vertexShader: [ 21 | 22 | "void main() {", 23 | 24 | "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", 25 | 26 | "}" 27 | 28 | ].join( "\n" ), 29 | 30 | fragmentShader: [ 31 | 32 | "uniform sampler2D tDiffuse;", 33 | "uniform vec2 resolution;", 34 | 35 | "#define FXAA_REDUCE_MIN (1.0/128.0)", 36 | "#define FXAA_REDUCE_MUL (1.0/8.0)", 37 | "#define FXAA_SPAN_MAX 8.0", 38 | 39 | "void main() {", 40 | 41 | "vec3 rgbNW = texture2D( tDiffuse, ( gl_FragCoord.xy + vec2( -1.0, -1.0 ) ) * resolution ).xyz;", 42 | "vec3 rgbNE = texture2D( tDiffuse, ( gl_FragCoord.xy + vec2( 1.0, -1.0 ) ) * resolution ).xyz;", 43 | "vec3 rgbSW = texture2D( tDiffuse, ( gl_FragCoord.xy + vec2( -1.0, 1.0 ) ) * resolution ).xyz;", 44 | "vec3 rgbSE = texture2D( tDiffuse, ( gl_FragCoord.xy + vec2( 1.0, 1.0 ) ) * resolution ).xyz;", 45 | "vec4 rgbaM = texture2D( tDiffuse, gl_FragCoord.xy * resolution );", 46 | "vec3 rgbM = rgbaM.xyz;", 47 | "vec3 luma = vec3( 0.299, 0.587, 0.114 );", 48 | 49 | "float lumaNW = dot( rgbNW, luma );", 50 | "float lumaNE = dot( rgbNE, luma );", 51 | "float lumaSW = dot( rgbSW, luma );", 52 | "float lumaSE = dot( rgbSE, luma );", 53 | "float lumaM = dot( rgbM, luma );", 54 | "float lumaMin = min( lumaM, min( min( lumaNW, lumaNE ), min( lumaSW, lumaSE ) ) );", 55 | "float lumaMax = max( lumaM, max( max( lumaNW, lumaNE) , max( lumaSW, lumaSE ) ) );", 56 | 57 | "vec2 dir;", 58 | "dir.x = -((lumaNW + lumaNE) - (lumaSW + lumaSE));", 59 | "dir.y = ((lumaNW + lumaSW) - (lumaNE + lumaSE));", 60 | 61 | "float dirReduce = max( ( lumaNW + lumaNE + lumaSW + lumaSE ) * ( 0.25 * FXAA_REDUCE_MUL ), FXAA_REDUCE_MIN );", 62 | 63 | "float rcpDirMin = 1.0 / ( min( abs( dir.x ), abs( dir.y ) ) + dirReduce );", 64 | "dir = min( vec2( FXAA_SPAN_MAX, FXAA_SPAN_MAX),", 65 | "max( vec2(-FXAA_SPAN_MAX, -FXAA_SPAN_MAX),", 66 | "dir * rcpDirMin)) * resolution;", 67 | "vec4 rgbA = (1.0/2.0) * (", 68 | "texture2D(tDiffuse, gl_FragCoord.xy * resolution + dir * (1.0/3.0 - 0.5)) +", 69 | "texture2D(tDiffuse, gl_FragCoord.xy * resolution + dir * (2.0/3.0 - 0.5)));", 70 | "vec4 rgbB = rgbA * (1.0/2.0) + (1.0/4.0) * (", 71 | "texture2D(tDiffuse, gl_FragCoord.xy * resolution + dir * (0.0/3.0 - 0.5)) +", 72 | "texture2D(tDiffuse, gl_FragCoord.xy * resolution + dir * (3.0/3.0 - 0.5)));", 73 | "float lumaB = dot(rgbB, vec4(luma, 0.0));", 74 | 75 | "if ( ( lumaB < lumaMin ) || ( lumaB > lumaMax ) ) {", 76 | 77 | "gl_FragColor = rgbA;", 78 | 79 | "} else {", 80 | "gl_FragColor = rgbB;", 81 | 82 | "}", 83 | 84 | "}" 85 | 86 | ].join( "\n" ) 87 | 88 | }; 89 | -------------------------------------------------------------------------------- /walker.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 96 | 97 | 98 | --------------------------------------------------------------------------------