├── .gitignore ├── .gitmodules ├── LICENSES ├── README.md ├── binding.gyp ├── doc ├── WebGL_support.ods └── webgl.idl ├── examples ├── lightgl │ ├── camera.js │ ├── cessna.js │ ├── csg.js │ ├── csg.min.js │ ├── gazebo.js │ ├── gpulightmap.js │ ├── immediatemode.js │ ├── lightgl.js │ ├── multitexture.js │ ├── normalmatrix.js │ ├── raytracing.js │ ├── rtt.js │ ├── scenemanip.js │ ├── shadowmap.js │ ├── texture.png │ └── texture2.png ├── shadertoy │ ├── presets │ │ ├── 704.fs │ │ ├── BigEarth.jpg │ │ ├── apple.fs │ │ ├── clod.fs │ │ ├── deform.fs │ │ ├── droid.fs │ │ ├── earth.fs │ │ ├── earth_day.jpg │ │ ├── julia.fs │ │ ├── kinderpainter.fs │ │ ├── landscape.fs │ │ ├── leizex.fs │ │ ├── lunaquatic.fs │ │ ├── mandel.fs │ │ ├── mandelbulb.fs │ │ ├── metatunnel.fs │ │ ├── quaternion.fs │ │ ├── red.fs │ │ ├── shapes.fs │ │ ├── slisesix.fs │ │ ├── square_tunnel.fs │ │ ├── sult.fs │ │ ├── tex0.jpg │ │ ├── tex1.jpg │ │ ├── tex2.jpg │ │ ├── tex3.jpg │ │ ├── tex4.jpg │ │ └── water.fs │ └── shadertoy.js ├── tunnel │ ├── glUtils.js │ ├── sylvester.js │ ├── texture.jpg │ └── tunnel.js ├── wavefront.js └── wavefront_icon.png ├── index.js ├── lib ├── image.js ├── platform_glfw.js ├── platform_sdl.js ├── platform_sfml.js └── webgl.js ├── package-lock.json ├── package.json ├── src ├── GLES2 │ ├── gl2.h │ ├── gl2ext.h │ └── gl2platform.h ├── KHR │ └── khrplatform.h ├── arch_wrapper.h ├── bindings.cc ├── common.h ├── image.cc ├── image.h ├── webgl.cc └── webgl.h ├── test ├── cube.js ├── extensions.js ├── glMatrix-0.9.5.min.js ├── glass.gif ├── glversion.js ├── lena.jpg ├── lesson02.js ├── lesson05.js ├── lesson08.js ├── nehe.gif ├── node_logo.png ├── screen_aligned.js ├── test_image.js └── test_typed_arrays.html └── tools └── api.js /.gitignore: -------------------------------------------------------------------------------- 1 | build 2 | .lock-wscript 3 | npm-debug.log 4 | 5 | .idea 6 | Debug 7 | *.log 8 | node_modules 9 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "deps"] 2 | path = deps 3 | url = https://github.com/mikeseven/node-native-graphics-deps.git 4 | -------------------------------------------------------------------------------- /LICENSES: -------------------------------------------------------------------------------- 1 | This document lists all the licenses used in this node-webgl repository: 2 | 3 | - Part I - node-webgl distributed under BSD license 4 | - Part II - LightGL.js from Evan Wallace under MIT license 5 | 6 | No specific license found for: 7 | - Some tests adapted from LearningWebGL.com lessons, themselves adapted from NeHe lessons. 8 | - Travelling wavefront demo adapted from https://github.com/webos-commons/com.creationix.minimason webOS demo, itself adapted from the minimason nko2 demo. 9 | 10 | node-webgl depends on node-glfw, also under BSD license. 11 | 12 | ------------------------------------------------------------------------------ 13 | Part I - node-webgl distributed under BSD license 14 | 15 | Copyright (c) 2011-2012, Mikael Bourges-Sevenier 16 | All rights reserved. 17 | 18 | Redistribution and use in source and binary forms, with or without 19 | modification, are permitted provided that the following conditions are met: 20 | 21 | * Redistributions of source code must retain the above copyright 22 | notice, this list of conditions and the following disclaimer. 23 | * Redistributions in binary form must reproduce the above copyright 24 | notice, this list of conditions and the following disclaimer in the 25 | documentation and/or other materials provided with the distribution. 26 | 27 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 28 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 29 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 30 | ARE DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY 31 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 32 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 33 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 34 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 35 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 36 | THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 37 | 38 | ------------------------------------------------------------------------------ 39 | Part II - LightGL.js from Evan Wallace under MIT license 40 | 41 | Copyright (C) 2011 by Evan Wallace 42 | 43 | Permission is hereby granted, free of charge, to any person obtaining a copy 44 | of this software and associated documentation files (the "Software"), to deal 45 | in the Software without restriction, including without limitation the rights 46 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 47 | copies of the Software, and to permit persons to whom the Software is 48 | furnished to do so, subject to the following conditions: 49 | 50 | The above copyright notice and this permission notice shall be included in 51 | all copies or substantial portions of the Software. 52 | 53 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 54 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 55 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 56 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 57 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 58 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 59 | THE SOFTWARE. 60 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | This is a set of WebGL like bindings to OpenGL for Node.JS for desktops: windows, linux, mac 2 | 3 | It started as an extension of creationix/node-webgl and their great example com.creationix.minimason that 4 | you can find in examples/wavefront.js. However, it is now quite different and support different platform 5 | bindings, mainly GLFW instead of SDL. 6 | 7 | Unlike WebGL it calls directly into the OpenGL driver. This has the benefit of speed and 8 | access to many features of desktop OpenGL at the expensive of compatibily and security. 9 | If you're looking for an actual WebGL implementation for Node.JS see 10 | [headless-gl](https://github.com/stackgl/headless-gl). 11 | 12 | Dependencies 13 | ============ 14 | - node-glfw, which depends on GLEW, GLFW as well as AntTweakBar. See [node-glfw](https://github.com/mikeseven/node-glfw) for installation instructions. 15 | - freeimage is used to load/save a variety of image formats. 16 | - node-gyp if not already available in your distribution 17 | 18 | Installation 19 | ============ 20 | `npm install node-webgl` 21 | 22 | ### Installation Notes for Windows 7 23 | Beware of the Node.JS distribution you use. The default Node.JS is 32-bit and this means that modules 24 | will be compiled by node-gyp with 32-bit settings, which often leads to compilation errors especially 25 | on 64-bit systems. 26 | 27 | So for Windows 7 64-bit, instead of downloading the default Node.JS windows installer, select 'Other release files'. 28 | This will show you an ftp site for the latest release. Go into x64 folder and download that distribution. 29 | 30 | ### Installation Notes for OSX 31 | `brew install anttweakbar freeimage` 32 | 33 | Usage 34 | ===== 35 | examples/ contains examples from other the web 36 | test/ contains lessons from www.learningwebgl.com and other tests 37 | 38 | simply type: `node test/lesson02.js` 39 | 40 | Enjoy! 41 | 42 | Limitations 43 | =========== 44 | WebGL is based on OpenGL ES, a restriction of OpenGL found on desktops, for embedded systems. 45 | Because this module wraps OpenGL, it is possible to do things that may not work on web browsers. 46 | Please read http://www.khronos.org/webgl/wiki_1_15/index.php/WebGL_and_OpenGL_Differences 47 | to learn about the differences. 48 | 49 | - shaders 50 | Remember to add this on top of your fragment shaders: 51 | ```glsl 52 | #ifdef GL_ES 53 | precision highp float; 54 | #endif 55 | ``` 56 | 57 | - loading external scripts 58 | If your code uses external libraries, you can load them like this. No code change to external scripts ;-) 59 | ```js 60 | fs=require('fs'); 61 | eval(fs.readFileSync(__dirname+ '/glMatrix-0.9.5.min.js','utf8')); 62 | ``` 63 | 64 | - frame rate 65 | `requestAnimationFrame(callback [, delay])` works as in the browser. 66 | If delay is specified, it is the requested delay in milliseconds between animation frames 67 | e.g. 16 will provide 1000 / 16 = 62 fps at best, which is the default value if delay is undefined. 68 | If delay = 0, then the fastest possible framerate on your machine is used. 69 | 70 | The timestamp now uses the high-resolution timer in your machine (not new Date()). This provides a much more precise 71 | framerate as well as much better timing for animations. 72 | -------------------------------------------------------------------------------- /binding.gyp: -------------------------------------------------------------------------------- 1 | { 2 | 'variables': { 3 | 'platform': '<(OS)', 4 | }, 5 | 'conditions': [ 6 | # Replace gyp platform with node platform, blech 7 | ['platform == "mac"', {'variables': {'platform': 'darwin'}}], 8 | ['platform == "win"', {'variables': {'platform': 'win32'}}], 9 | ], 10 | 'targets': [ 11 | { 12 | 'target_name': 'webgl', 13 | 'defines': [ 14 | 'VERSION=0.5.5' 15 | ], 16 | 'sources': [ 17 | 'src/bindings.cc', 18 | 'src/image.cc', 19 | 'src/webgl.cc', 20 | ], 21 | 'include_dirs': [ 22 | "0&&b((e+1)/g,d/a);d0.5,d=(new CSG.Vector(e,!e,0)).cross(h).unit(),k=d.cross(h).unit();e=new CSG.Vertex(c,h.negated());f=new CSG.Vertex(f,h.unit());for(var j= 14 | [],l=0;lCSG.Plane.EPSILON?1:0;i|=d;h.push(d)}switch(i){case 0:(this.normal.dot(a.plane.normal)>0?b:c).push(a);break;case 1:f.push(a);break;case 2:g.push(a);break;case 3:b=[];c=[];for(e=0;e=3&&f.push(new CSG.Polygon(b,a.shared));c.length>=3&&g.push(new CSG.Polygon(c,a.shared))}}};CSG.Polygon=function(a,b){this.vertices=a;this.shared=b;this.plane=CSG.Plane.fromPoints(a[0].pos,a[1].pos,a[2].pos)}; 20 | CSG.Polygon.prototype={clone:function(){var a=this.vertices.map(function(b){return b.clone()});return new CSG.Polygon(a,this.shared)},flip:function(){this.vertices.reverse().map(function(a){a.flip()});this.plane.flip()}};CSG.Node=function(){this.back=this.front=this.plane=null;this.polygons=[]}; 21 | CSG.Node.prototype={clone:function(){var a=new CSG.Node;a.plane=this.plane&&this.plane.clone();a.front=this.front&&this.front.clone();a.back=this.back&&this.back.clone();a.polygons=this.polygons.map(function(b){return b.clone()});return a},invert:function(){for(var a=0;a 0.0) ? 1.0 : 0.0;\ 96 | \ 97 | /* Points on polygons facing away from the light are always in shadow */\ 98 | float color = dot(normal, light) > 0.0 ? 1.0 - shadow : 0.0;\ 99 | gl_FragColor = vec4(vec3(color), 1.0 / (1.0 + sampleCount));\ 100 | }\ 101 | '); 102 | 103 | function QuadMesh(numQuads, texelsPerSide) { 104 | this.size = Math.ceil(Math.sqrt(numQuads)); 105 | this.texelsPerSide = texelsPerSide; 106 | this.mesh = new GL.Mesh({ normals: true, coords: true }); 107 | this.index = 0; 108 | this.lightmapTexture = null; 109 | this.bounds = null; 110 | this.sampleCount = 0; 111 | 112 | // Also need values offset by 0.5 texels to avoid seams between lightmap cells 113 | this.mesh.addVertexBuffer('offsetCoords', 'offsetCoord'); 114 | this.mesh.addVertexBuffer('offsetPositions', 'offsetPosition'); 115 | } 116 | 117 | // Add a quad given its four vertices and allocate space for it in the lightmap 118 | QuadMesh.prototype.addQuad = function(a, b, c, d) { 119 | var half = 0.5 / this.texelsPerSide; 120 | 121 | // Add vertices 122 | this.mesh.vertices.push(a.toArray()); 123 | this.mesh.vertices.push(b.toArray()); 124 | this.mesh.vertices.push(c.toArray()); 125 | this.mesh.vertices.push(d.toArray()); 126 | 127 | // Add normal 128 | var normal = b.subtract(a).cross(c.subtract(a)).unit().toArray(); 129 | this.mesh.normals.push(normal); 130 | this.mesh.normals.push(normal); 131 | this.mesh.normals.push(normal); 132 | this.mesh.normals.push(normal); 133 | 134 | // Add fake positions 135 | function lerp(x, y) { 136 | return a.multiply((1-x)*(1-y)).add(b.multiply(x*(1-y))) 137 | .add(c.multiply((1-x)*y)).add(d.multiply(x*y)).toArray(); 138 | } 139 | this.mesh.offsetPositions.push(lerp(-half, -half)); 140 | this.mesh.offsetPositions.push(lerp(1 + half, -half)); 141 | this.mesh.offsetPositions.push(lerp(-half, 1 + half)); 142 | this.mesh.offsetPositions.push(lerp(1 + half, 1 + half)); 143 | 144 | // Compute location of texture cell 145 | var i = this.index++; 146 | var s = i % this.size; 147 | var t = (i - s) / this.size; 148 | 149 | // Coordinates that are in the center of border texels (to avoid leaking) 150 | var s0 = (s + half) / this.size; 151 | var t0 = (t + half) / this.size; 152 | var s1 = (s + 1 - half) / this.size; 153 | var t1 = (t + 1 - half) / this.size; 154 | this.mesh.coords.push([s0, t0]); 155 | this.mesh.coords.push([s1, t0]); 156 | this.mesh.coords.push([s0, t1]); 157 | this.mesh.coords.push([s1, t1]); 158 | 159 | // Coordinates that are on the edge of border texels (to avoid cracks when rendering) 160 | var rs0 = s / this.size; 161 | var rt0 = t / this.size; 162 | var rs1 = (s + 1) / this.size; 163 | var rt1 = (t + 1) / this.size; 164 | this.mesh.offsetCoords.push([rs0, rt0]); 165 | this.mesh.offsetCoords.push([rs1, rt0]); 166 | this.mesh.offsetCoords.push([rs0, rt1]); 167 | this.mesh.offsetCoords.push([rs1, rt1]); 168 | 169 | // A quad is two triangles 170 | this.mesh.triangles.push([4 * i, 4 * i + 1, 4 * i + 3]); 171 | this.mesh.triangles.push([4 * i, 4 * i + 3, 4 * i + 2]); 172 | }; 173 | 174 | QuadMesh.prototype.addDoubleQuad = function(a, b, c, d) { 175 | // Need a separate lightmap for each side of the quad 176 | this.addQuad(a, b, c, d); 177 | this.addQuad(a, c, b, d); 178 | }; 179 | 180 | QuadMesh.prototype.compile = function() { 181 | // Finalize mesh 182 | this.mesh.compile(); 183 | this.bounds = this.mesh.getBoundingSphere(); 184 | 185 | // Create textures 186 | var size = this.size * this.texelsPerSide; 187 | this.lightmapTexture = new GL.Texture(size, size, { format: gl.RED, type: gl.FLOAT }); 188 | }; 189 | 190 | QuadMesh.prototype.drawShadow = function(dir) { 191 | // Construct a camera looking from the light toward the object 192 | var r = this.bounds.radius, c = this.bounds.center; 193 | gl.matrixMode(gl.PROJECTION); 194 | gl.pushMatrix(); 195 | gl.loadIdentity(); 196 | gl.ortho(-r, r, -r, r, -r, r); 197 | gl.matrixMode(gl.MODELVIEW); 198 | gl.pushMatrix(); 199 | gl.loadIdentity(); 200 | var at = c.subtract(dir); 201 | var useY = (dir.max() != dir.y); 202 | var up = new GL.Vector(!useY, useY, 0).cross(dir); 203 | gl.lookAt(c.x, c.y, c.z, at.x, at.y, at.z, up.x, up.y, up.z); 204 | 205 | // Render the object viewed from the light using a shader that returns the fragment depth 206 | var mesh = this.mesh; 207 | var shadowMapMatrix = gl.projectionMatrix.multiply(gl.modelviewMatrix); 208 | depthMap.drawTo(function() { 209 | gl.clearColor(1, 1, 1, 1); 210 | gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); 211 | depthShader.draw(mesh); 212 | }); 213 | 214 | // Reset the transform 215 | gl.matrixMode(gl.PROJECTION); 216 | gl.popMatrix(); 217 | gl.matrixMode(gl.MODELVIEW); 218 | gl.popMatrix(); 219 | 220 | // Run the shadow test for each texel in the lightmap and 221 | // accumulate that onto the existing lightmap contents 222 | var sampleCount = this.sampleCount++; 223 | depthMap.bind(); 224 | this.lightmapTexture.drawTo(function() { 225 | gl.enable(gl.BLEND); 226 | gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA); 227 | shadowTestShader.uniforms({ 228 | shadowMapMatrix: shadowMapMatrix, 229 | sampleCount: sampleCount, 230 | light: dir 231 | }).draw(mesh); 232 | gl.disable(gl.BLEND); 233 | }); 234 | depthMap.unbind(); 235 | }; 236 | 237 | // Make a mesh of quads 238 | var numArcQuads = 32; 239 | var groundTilesPerSide = 5; 240 | var quadMesh = new QuadMesh((numArcQuads + groundTilesPerSide * groundTilesPerSide) * 2, 64); 241 | // Arc of randomly oriented quads 242 | for (var i = 0; i < numArcQuads; i++) { 243 | var r = 0.3; 244 | var center = GL.Vector.fromAngles(0, ((i + Math.random()) / numArcQuads) * Math.PI); 245 | var a = GL.Vector.randomDirection().multiply(r); 246 | var b = GL.Vector.randomDirection().cross(a).unit().multiply(r); 247 | quadMesh.addDoubleQuad( 248 | center.subtract(a).subtract(b), 249 | center.subtract(a).add(b), 250 | center.add(a).subtract(b), 251 | center.add(a).add(b) 252 | ); 253 | } 254 | // Plane of quads 255 | for (var x = 0; x < groundTilesPerSide; x++) { 256 | for (var z = 0; z < groundTilesPerSide; z++) { 257 | var dx = x - groundTilesPerSide / 2; 258 | var dz = z - groundTilesPerSide / 2; 259 | quadMesh.addDoubleQuad( 260 | new GL.Vector(dx, 0, dz), 261 | new GL.Vector(dx, 0, dz + 1), 262 | new GL.Vector(dx + 1, 0, dz), 263 | new GL.Vector(dx + 1, 0, dz + 1) 264 | ); 265 | } 266 | } 267 | quadMesh.compile(); 268 | 269 | // The mesh will be drawn with texture mapping 270 | var mesh = quadMesh.mesh; 271 | var textureMapShader = new GL.Shader('\ 272 | varying vec2 coord;\ 273 | void main() {\ 274 | coord = gl_TexCoord.st;\ 275 | gl_Position = ftransform();\ 276 | }\ 277 | ', '\ 278 | uniform sampler2D texture;\ 279 | varying vec2 coord;\ 280 | void main() {\ 281 | gl_FragColor = texture2D(texture, coord);\ 282 | }\ 283 | '); 284 | 285 | gl.onmousemove = function(e) { 286 | if (e.dragging) { 287 | angleY += e.deltaX; 288 | angleX += e.deltaY; 289 | angleX = Math.max(-90, Math.min(90, angleX)); 290 | } 291 | }; 292 | 293 | var flip = false; 294 | 295 | gl.ondraw = function() { 296 | gl.clearColor(0.9, 0.9, 0.9, 1); 297 | gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); 298 | gl.loadIdentity(); 299 | gl.translate(0, 0, -4); 300 | gl.rotate(angleX, 1, 0, 0); 301 | gl.rotate(angleY, 0, 1, 0); 302 | gl.translate(0, -0.25, 0); 303 | 304 | // Alternate between a shadow from a random point on the sky hemisphere 305 | // and a random point near the light (creates a soft shadow) 306 | var dir = GL.Vector.randomDirection(); 307 | flip = !flip; 308 | if (flip) dir = new GL.Vector(1, 1, 1).add(dir.multiply(0.3 * Math.sqrt(Math.random()))).unit(); 309 | quadMesh.drawShadow(dir.y < 0 ? dir.negative() : dir); 310 | 311 | // Draw the mesh with the ambient occlusion so far 312 | quadMesh.lightmapTexture.bind(); 313 | textureMapShader.draw(mesh); 314 | }; 315 | 316 | gl.fullscreen(); 317 | gl.animate(); 318 | gl.enable(gl.CULL_FACE); 319 | gl.enable(gl.DEPTH_TEST); 320 | -------------------------------------------------------------------------------- /examples/lightgl/immediatemode.js: -------------------------------------------------------------------------------- 1 | var nodejs = (typeof window === 'undefined'); 2 | if(nodejs) { 3 | WebGL = require('../../index'); 4 | document = WebGL.document(); 5 | alert=console.log; 6 | window = document; 7 | 8 | //Read and eval library 9 | var fs=require('fs'); 10 | eval(fs.readFileSync(__dirname+ '/lightgl.js','utf8')); 11 | } 12 | 13 | requestAnimationFrame = document.requestAnimationFrame; 14 | 15 | //Read and eval library 16 | fs=require('fs'); 17 | eval(fs.readFileSync(__dirname+ '/lightgl.js','utf8')); 18 | 19 | var angle = 0; 20 | var gl = GL.create(); 21 | document.setTitle("Immediate mode"); 22 | 23 | gl.onupdate = function(seconds) { 24 | angle += 45 * seconds; 25 | }; 26 | 27 | gl.ondraw = function() { 28 | gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); 29 | gl.loadIdentity(); 30 | gl.translate(0, 0, -5); 31 | gl.rotate(30, 1, 0, 0); 32 | gl.rotate(angle, 0, 1, 0); 33 | 34 | gl.color(0.5, 0.5, 0.5); 35 | gl.lineWidth(1); 36 | gl.begin(gl.LINES); 37 | for (var i = -10; i <= 10; i++) { 38 | gl.vertex(i, 0, -10); 39 | gl.vertex(i, 0, +10); 40 | gl.vertex(-10, 0, i); 41 | gl.vertex(+10, 0, i); 42 | } 43 | gl.end(); 44 | 45 | gl.pointSize(10); 46 | gl.begin(gl.POINTS); 47 | gl.color(1, 0, 0); gl.vertex(1, 0, 0); 48 | gl.color(0, 1, 0); gl.vertex(0, 1, 0); 49 | gl.color(0, 0, 1); gl.vertex(0, 0, 1); 50 | gl.end(); 51 | 52 | gl.lineWidth(2); 53 | gl.begin(gl.LINE_LOOP); 54 | gl.color(1, 0, 0); gl.vertex(1, 0, 0); 55 | gl.color(0, 1, 0); gl.vertex(0, 1, 0); 56 | gl.color(0, 0, 1); gl.vertex(0, 0, 1); 57 | gl.end(); 58 | 59 | gl.begin(gl.TRIANGLES); 60 | gl.color(1, 1, 0); gl.vertex(0.5, 0.5, 0); 61 | gl.color(0, 1, 1); gl.vertex(0, 0.5, 0.5); 62 | gl.color(1, 0, 1); gl.vertex(0.5, 0, 0.5); 63 | gl.end(); 64 | }; 65 | 66 | gl.fullscreen(); 67 | gl.animate(); 68 | -------------------------------------------------------------------------------- /examples/lightgl/multitexture.js: -------------------------------------------------------------------------------- 1 | var nodejs = (typeof window === 'undefined'); 2 | if(nodejs) { 3 | WebGL = require('../../index'); 4 | Image = WebGL.Image; 5 | document = WebGL.document(); 6 | alert=console.log; 7 | window = document; 8 | 9 | //Read and eval library 10 | var fs=require('fs'); 11 | eval(fs.readFileSync(__dirname+ '/lightgl.js','utf8')); 12 | } 13 | 14 | requestAnimationFrame = document.requestAnimationFrame; 15 | 16 | var angle = 0; 17 | var gl = GL.create(); 18 | document.setTitle("Multitexture"); 19 | var mesh = GL.Mesh.plane({ coords: true }); 20 | var texture = GL.Texture.fromURL(__dirname+'/'+'texture.png'); 21 | var texture2 = GL.Texture.fromURL(__dirname+'/'+'texture2.png'); 22 | var shader = new GL.Shader('\ 23 | varying vec2 coord;\ 24 | void main() {\ 25 | coord = gl_TexCoord.xy;\ 26 | gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;\ 27 | }\ 28 | ', '\ 29 | uniform sampler2D texture;\ 30 | uniform sampler2D texture2;\ 31 | varying vec2 coord;\ 32 | void main() {\ 33 | gl_FragColor = texture2D(texture, coord) - texture2D(texture2, coord);\ 34 | }\ 35 | '); 36 | 37 | gl.onupdate = function(seconds) { 38 | angle += 45 * seconds; 39 | }; 40 | 41 | gl.ondraw = function() { 42 | gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); 43 | gl.loadIdentity(); 44 | gl.translate(0, 0, -5); 45 | gl.rotate(30, 1, 0, 0); 46 | gl.rotate(angle, 0, 1, 0); 47 | 48 | texture.bind(0); 49 | texture2.bind(1); 50 | shader.uniforms({ 51 | texture: 0, 52 | texture2: 1 53 | }).draw(mesh); 54 | }; 55 | 56 | gl.fullscreen(); 57 | gl.animate(); 58 | -------------------------------------------------------------------------------- /examples/lightgl/normalmatrix.js: -------------------------------------------------------------------------------- 1 | var nodejs = (typeof window === 'undefined'); 2 | if(nodejs) { 3 | WebGL = require('../../index'); 4 | Image = WebGL.Image; 5 | document = WebGL.document(); 6 | alert=console.log; 7 | window = document; 8 | 9 | //Read and eval library 10 | var fs=require('fs'); 11 | eval(fs.readFileSync(__dirname+ '/lightgl.js','utf8')); 12 | } 13 | 14 | requestAnimationFrame = document.requestAnimationFrame; 15 | 16 | var time = 0; 17 | var gl = GL.create(); 18 | document.setTitle("Normal matrix"); 19 | var mesh = GL.Mesh.sphere({ normals: true }); 20 | var badShader = new GL.Shader('\ 21 | varying vec3 normal;\ 22 | void main() {\ 23 | normal = (gl_ModelViewMatrix * vec4(gl_Normal, 0.0)).xyz;\ 24 | gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;\ 25 | }\ 26 | ', '\ 27 | varying vec3 normal;\ 28 | void main() {\ 29 | gl_FragColor = vec4(normalize(normal) * 0.5 + 0.5, 1.0);\ 30 | }\ 31 | '); 32 | var goodShader = new GL.Shader('\ 33 | varying vec3 normal;\ 34 | void main() {\ 35 | normal = gl_NormalMatrix * gl_Normal;\ 36 | gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;\ 37 | }\ 38 | ', '\ 39 | varying vec3 normal;\ 40 | void main() {\ 41 | gl_FragColor = vec4(normalize(normal) * 0.5 + 0.5, 1.0);\ 42 | }\ 43 | '); 44 | 45 | gl.onupdate = function(seconds) { 46 | time += seconds; 47 | }; 48 | 49 | gl.ondraw = function() { 50 | gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); 51 | gl.loadIdentity(); 52 | gl.translate(0, 0, -10); 53 | gl.rotate(10, 1, 0, 0); 54 | 55 | var scale = 1.2 + 0.7 * Math.cos(time); 56 | 57 | gl.pushMatrix(); 58 | gl.translate(-2, 0, 0); 59 | gl.scale(1 / scale, scale, 1); 60 | badShader.draw(mesh); 61 | gl.popMatrix(); 62 | 63 | gl.pushMatrix(); 64 | gl.translate(2, 0, 0); 65 | gl.scale(1 / scale, scale, 1); 66 | goodShader.draw(mesh); 67 | gl.popMatrix(); 68 | }; 69 | 70 | gl.fullscreen(); 71 | gl.animate(); 72 | gl.enable(gl.DEPTH_TEST); 73 | -------------------------------------------------------------------------------- /examples/lightgl/raytracing.js: -------------------------------------------------------------------------------- 1 | var nodejs = (typeof window === 'undefined'); 2 | if(nodejs) { 3 | WebGL = require('../../index'); 4 | document = WebGL.document(); 5 | alert=console.log; 6 | window = document; 7 | 8 | //Read and eval library 9 | var fs=require('fs'); 10 | eval(fs.readFileSync(__dirname+ '/lightgl.js','utf8')); 11 | } 12 | 13 | requestAnimationFrame = document.requestAnimationFrame; 14 | 15 | var angleX = 30; 16 | var angleY = 10; 17 | var gl = GL.create(); 18 | document.setTitle("Raytracing"); 19 | var mesh = GL.Mesh.plane(); 20 | var shader = new GL.Shader('\ 21 | uniform vec3 ray00;\ 22 | uniform vec3 ray10;\ 23 | uniform vec3 ray01;\ 24 | uniform vec3 ray11;\ 25 | varying vec3 initialRay;\ 26 | \ 27 | void main() {\ 28 | vec2 t = gl_Vertex.xy * 0.5 + 0.5;\ 29 | initialRay = mix(mix(ray00, ray10, t.x), mix(ray01, ray11, t.x), t.y);\ 30 | gl_Position = gl_Vertex;\ 31 | }\ 32 | ', '\ 33 | const float INFINITY = 1.0e9;\ 34 | uniform vec3 eye;\ 35 | varying vec3 initialRay;\ 36 | \ 37 | float intersectSphere(vec3 origin, vec3 ray, vec3 sphereCenter, float sphereRadius) {\ 38 | vec3 toSphere = origin - sphereCenter;\ 39 | float a = dot(ray, ray);\ 40 | float b = 2.0 * dot(toSphere, ray);\ 41 | float c = dot(toSphere, toSphere) - sphereRadius * sphereRadius;\ 42 | float discriminant = b * b - 4.0 * a * c;\ 43 | if (discriminant > 0.0) {\ 44 | float t = (-b - sqrt(discriminant)) / (2.0 * a);\ 45 | if (t > 0.0) return t;\ 46 | }\ 47 | return INFINITY;\ 48 | }\ 49 | \ 50 | void main() {\ 51 | vec3 origin = eye, ray = initialRay, color = vec3(0.0), mask = vec3(1.0);\ 52 | vec3 sphereCenter = vec3(0.0, 1.6, 0.0);\ 53 | float sphereRadius = 1.5;\ 54 | \ 55 | for (int bounce = 0; bounce < 2; bounce++) {\ 56 | /* Find the closest intersection with the scene */\ 57 | float planeT = -origin.y / ray.y;\ 58 | vec3 hit = origin + ray * planeT;\ 59 | if (planeT < 0.0 || abs(hit.x) > 4.0 || abs(hit.z) > 4.0) planeT = INFINITY;\ 60 | float sphereT = intersectSphere(origin, ray, sphereCenter, sphereRadius);\ 61 | float t = min(planeT, sphereT);\ 62 | \ 63 | /* The background is white */\ 64 | if (t == INFINITY) {\ 65 | color += mask;\ 66 | break;\ 67 | }\ 68 | \ 69 | /* Calculate the intersection */\ 70 | hit = origin + ray * t;\ 71 | if (t == planeT) {\ 72 | /* Look up the checkerboard color */\ 73 | vec3 c = fract(hit * 0.5) - 0.5;\ 74 | float checkerboard = c.x * c.z > 0.0 ? 1.0 : 0.0;\ 75 | color += vec3(1.0, checkerboard, 0.0) * mask;\ 76 | break;\ 77 | } else {\ 78 | /* Get the sphere color and reflect a new ray for the next iteration */\ 79 | vec3 normal = (hit - sphereCenter) / sphereRadius;\ 80 | ray = reflect(ray, normal);\ 81 | origin = hit;\ 82 | mask *= 0.8 * (0.5 + 0.5 * max(0.0, normal.y));\ 83 | }\ 84 | }\ 85 | \ 86 | gl_FragColor = vec4(color, 1.0);\ 87 | }\ 88 | '); 89 | 90 | gl.onmousemove = function(e) { 91 | if (e.dragging) { 92 | angleY += e.deltaX; 93 | angleX += e.deltaY; 94 | angleX = Math.max(-90, Math.min(90, angleX)); 95 | gl.ondraw(); 96 | } 97 | }; 98 | 99 | gl.ondraw = function() { 100 | // Camera setup 101 | gl.loadIdentity(); 102 | gl.translate(0, 0, -10); 103 | gl.rotate(angleX, 1, 0, 0); 104 | gl.rotate(angleY, 0, 1, 0); 105 | 106 | // Get corner rays 107 | var w = gl.canvas.width; 108 | var h = gl.canvas.height; 109 | var tracer = new GL.Raytracer(); 110 | shader.uniforms({ 111 | eye: tracer.eye, 112 | ray00: tracer.getRayForPixel(0, h), 113 | ray10: tracer.getRayForPixel(w, h), 114 | ray01: tracer.getRayForPixel(0, 0), 115 | ray11: tracer.getRayForPixel(w, 0) 116 | }); 117 | 118 | // Trace the rays 119 | shader.draw(mesh); 120 | 121 | // Draw debug output to show that the raytraced scene lines up correctly with 122 | // the rasterized scene 123 | gl.color(0, 0, 0, 0.5); 124 | gl.enable(gl.BLEND); 125 | gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA); 126 | gl.begin(gl.LINES); 127 | for (var s = 4, i = -s; i <= s; i++) { 128 | gl.vertex(-s, 0, i); 129 | gl.vertex(s, 0, i); 130 | gl.vertex(i, 0, -s); 131 | gl.vertex(i, 0, s); 132 | } 133 | gl.end(); 134 | gl.disable(gl.BLEND); 135 | }; 136 | 137 | gl.fullscreen(); 138 | gl.animate(); 139 | -------------------------------------------------------------------------------- /examples/lightgl/rtt.js: -------------------------------------------------------------------------------- 1 | var nodejs = (typeof window === 'undefined'); 2 | if(nodejs) { 3 | WebGL = require('../../index'); 4 | Image = WebGL.Image; 5 | document = WebGL.document(); 6 | alert=console.log; 7 | window = document; 8 | 9 | //Read and eval library 10 | var fs=require('fs'); 11 | eval(fs.readFileSync(__dirname+ '/lightgl.js','utf8')); 12 | eval(fs.readFileSync(__dirname+ '/gazebo.js','utf8')); 13 | } 14 | 15 | requestAnimationFrame = document.requestAnimationFrame; 16 | 17 | var angle = 0; 18 | var gl = GL.create(); 19 | document.setTitle("Render to texture"); 20 | var mesh = GL.Mesh.load(gazebo); 21 | var plane = GL.Mesh.plane({ coords: true }); 22 | var texture = GL.Texture.fromURL(__dirname+'/'+'texture.png'); 23 | var overlay = new GL.Texture(256, 256); 24 | var meshShader = new GL.Shader('\ 25 | varying vec3 normal;\ 26 | void main() {\ 27 | normal = gl_Normal;\ 28 | gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;\ 29 | }\ 30 | ', '\ 31 | varying vec3 normal;\ 32 | void main() {\ 33 | gl_FragColor = vec4(normal * 0.5 + 0.5, 1.0);\ 34 | }\ 35 | '); 36 | var planeShader = new GL.Shader('\ 37 | varying vec2 coord;\ 38 | void main() {\ 39 | coord = gl_TexCoord.xy;\ 40 | gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;\ 41 | }\ 42 | ', '\ 43 | uniform sampler2D texture;\ 44 | uniform sampler2D overlay;\ 45 | varying vec2 coord;\ 46 | void main() {\ 47 | gl_FragColor = (texture2D(overlay, coord) + texture2D(texture, coord)) / 2.0;\ 48 | }\ 49 | '); 50 | 51 | gl.onupdate = function(seconds) { 52 | angle += 45 * seconds; 53 | }; 54 | 55 | gl.ondraw = function() { 56 | gl.loadIdentity(); 57 | gl.translate(0, 0, -5); 58 | gl.rotate(30, 1, 0, 0); 59 | gl.rotate(angle, 0, 1, 0); 60 | 61 | overlay.drawTo(function() { 62 | gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); 63 | gl.pushMatrix(); 64 | gl.scale(0.01, 0.01, 0.01); 65 | meshShader.draw(mesh); 66 | gl.popMatrix(); 67 | }); 68 | 69 | gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); 70 | texture.bind(0); 71 | overlay.bind(1); 72 | planeShader.uniforms({ 73 | texture: 0, 74 | overlay: 1 75 | }).draw(plane); 76 | texture.unbind(0); 77 | overlay.unbind(1); 78 | }; 79 | 80 | gl.fullscreen(); 81 | gl.animate(); 82 | gl.enable(gl.DEPTH_TEST); 83 | -------------------------------------------------------------------------------- /examples/lightgl/scenemanip.js: -------------------------------------------------------------------------------- 1 | var nodejs = (typeof window === 'undefined'); 2 | if(nodejs) { 3 | WebGL = require('../../index'); 4 | Image = WebGL.Image; 5 | document = WebGL.document(); 6 | alert=console.log; 7 | window = document; 8 | 9 | //Read and eval library 10 | var fs=require('fs'); 11 | eval(fs.readFileSync(__dirname+ '/lightgl.js','utf8')); 12 | } 13 | 14 | requestAnimationFrame = document.requestAnimationFrame; 15 | 16 | var gl = GL.create(); 17 | document.setTitle("Scene manipulation"); 18 | var angleX = 30; 19 | var angleY = 45; 20 | var mesh = GL.Mesh.cube({ normals: true }); 21 | var offset = new GL.Vector(); 22 | var shader = new GL.Shader('\ 23 | varying vec3 normal;\ 24 | void main() {\ 25 | normal = gl_Normal;\ 26 | gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;\ 27 | }\ 28 | ', '\ 29 | varying vec3 normal;\ 30 | void main() {\ 31 | gl_FragColor = vec4(normal * 0.5 + 0.5, 1.0);\ 32 | }\ 33 | '); 34 | 35 | var result; 36 | var originalOffset; 37 | 38 | gl.onmousedown = function(e) { 39 | var tracer = new GL.Raytracer(); 40 | var ray = tracer.getRayForPixel(e.x, e.y); 41 | result = GL.Raytracer.hitTestBox(tracer.eye, ray, offset.subtract(1), offset.add(1)); 42 | originalOffset = offset; 43 | }; 44 | 45 | gl.onmousemove = function(e) { 46 | if (e.dragging) { 47 | if (result) { 48 | var tracer = new GL.Raytracer(); 49 | var ray = tracer.getRayForPixel(e.x, e.y); 50 | var t = result.hit.subtract(tracer.eye).dot(result.normal) / ray.dot(result.normal); 51 | var hit = tracer.eye.add(ray.multiply(t)); 52 | offset = originalOffset.add(hit.subtract(result.hit)); 53 | } else { 54 | angleY += e.deltaX; 55 | angleX = Math.max(-90, Math.min(90, angleX + e.deltaY)); 56 | } 57 | gl.ondraw(); 58 | } 59 | }; 60 | 61 | gl.ondraw = function() { 62 | gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); 63 | gl.loadIdentity(); 64 | gl.translate(0, 0, -10); 65 | gl.rotate(angleX, 1, 0, 0); 66 | gl.rotate(angleY, 0, 1, 0); 67 | 68 | // Use push and pop to guard the transform so gl is left in world space when 69 | // gl.ondraw() ends. This way, when the GL.Raytracer reads the modelview and 70 | // projection matrices, the rays it generates will be in world space. 71 | gl.pushMatrix(); 72 | gl.translate(offset.x, offset.y, offset.z); 73 | shader.draw(mesh); 74 | gl.popMatrix(); 75 | }; 76 | 77 | gl.fullscreen(); 78 | gl.enable(gl.DEPTH_TEST); 79 | gl.animate(); 80 | -------------------------------------------------------------------------------- /examples/lightgl/shadowmap.js: -------------------------------------------------------------------------------- 1 | var nodejs = (typeof window === 'undefined'); 2 | if(nodejs) { 3 | WebGL = require('../../index'); 4 | Image = WebGL.Image; 5 | document = WebGL.document(); 6 | alert=console.log; 7 | window = document; 8 | 9 | //Read and eval library 10 | var fs=require('fs'); 11 | var mesh_name = 'cessna'; 12 | eval(fs.readFileSync(__dirname+ '/lightgl.js','utf8')); 13 | eval(fs.readFileSync(__dirname+ '/'+mesh_name+'.js','utf8')); 14 | 15 | } 16 | 17 | requestAnimationFrame = document.requestAnimationFrame; 18 | 19 | var time = 0; 20 | var angleX = 20; 21 | var angleY = 20; 22 | var useBoundingSphere = false; 23 | var gl = GL.create(); 24 | document.setTitle("Shadow mapping"); 25 | var mesh = GL.Mesh.load(eval(mesh_name)); 26 | var cube = GL.Mesh.cube().computeWireframe(); 27 | var sphere = GL.Mesh.sphere({ detail: 3 }).computeWireframe(); 28 | var plane = GL.Mesh.plane({ normals: true, coords: true }).transform(GL.Matrix.scale(300, 300, 1)); 29 | var depthMap = new GL.Texture(1024, 1024, { format: gl.RGB }); 30 | var texturePlane = GL.Mesh.plane({ coords: true }); 31 | var boundingSphere = mesh.getBoundingSphere(); 32 | var boundingBox = mesh.getAABB(); 33 | var colorShader = new GL.Shader('\ 34 | uniform vec3 center;\ 35 | uniform vec3 radius;\ 36 | void main() {\ 37 | gl_Position = gl_ModelViewProjectionMatrix * vec4(gl_Vertex.xyz * radius + center, 1.0);\ 38 | }\ 39 | ', '\ 40 | void main() {\ 41 | gl_FragColor = vec4(0.0, 0.0, 1.0, 1.0);\ 42 | }\ 43 | '); 44 | var depthShader = new GL.Shader('\ 45 | varying vec4 pos;\ 46 | void main() {\ 47 | gl_Position = pos = gl_ModelViewProjectionMatrix * gl_Vertex;\ 48 | }\ 49 | ', '\ 50 | varying vec4 pos;\ 51 | void main() {\ 52 | float depth = pos.z / pos.w;\ 53 | gl_FragColor = vec4(depth * 0.5 + 0.5);\ 54 | }\ 55 | '); 56 | var displayShader = new GL.Shader('\ 57 | uniform mat4 shadowMapMatrix;\ 58 | uniform vec3 light;\ 59 | varying vec4 coord;\ 60 | varying vec3 normal;\ 61 | varying vec3 toLight;\ 62 | void main() {\ 63 | toLight = light - (gl_ModelViewMatrix * gl_Vertex).xyz;\ 64 | normal = gl_NormalMatrix * gl_Normal;\ 65 | gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;\ 66 | coord = shadowMapMatrix * gl_Position;\ 67 | }\ 68 | ', '\ 69 | uniform sampler2D depthMap;\ 70 | varying vec4 coord;\ 71 | varying vec3 normal;\ 72 | varying vec3 toLight;\ 73 | void main() {\ 74 | float shadow = 0.0;\ 75 | if (coord.w > 0.0) {\ 76 | float depth = 0.0;\ 77 | vec2 sample = coord.xy / coord.w * 0.5 + 0.5;\ 78 | if (clamp(sample, 0.0, 1.0) == sample) {\ 79 | float sampleDepth = texture2D(depthMap, sample).r;\ 80 | depth = (sampleDepth == 1.0) ? 1.0e9 : sampleDepth;\ 81 | }\ 82 | if (depth > 0.0) {\ 83 | float bias = -0.002;\ 84 | shadow = clamp(300.0 * (bias + coord.z / coord.w * 0.5 + 0.5 - depth), 0.0, 1.0);\ 85 | }\ 86 | }\ 87 | float ambient = 0.1;\ 88 | float diffuse = max(0.0, dot(normalize(toLight), normalize(normal)));\ 89 | gl_FragColor = vec4((normal * 0.5 + 0.5) * mix(ambient, 1.0, diffuse * (1.0 - shadow)), 1.0);\ 90 | }\ 91 | '); 92 | var textureShader = new GL.Shader('\ 93 | varying vec2 coord;\ 94 | void main() {\ 95 | coord = gl_TexCoord.xy;\ 96 | gl_Position = vec4(coord * 2.0 - 1.0, 0.0, 1.0);\ 97 | }\ 98 | ', '\ 99 | uniform sampler2D texture;\ 100 | varying vec2 coord;\ 101 | void main() {\ 102 | gl_FragColor = texture2D(texture, coord);\ 103 | }\ 104 | '); 105 | 106 | gl.onupdate = function(seconds) { 107 | time += seconds; 108 | }; 109 | 110 | gl.onmousemove = function(e) { 111 | if (e.dragging) { 112 | angleY += e.deltaX; 113 | angleX = Math.max(-90, Math.min(90, angleX + e.deltaY)); 114 | } 115 | }; 116 | 117 | function cameraForBoundingSphere(light, boundingSphere) { 118 | var distance = boundingSphere.center.subtract(light).length(); 119 | var angle = 180 - 2 * Math.acos(boundingSphere.radius / distance) * 180 / Math.PI; 120 | gl.matrixMode(gl.PROJECTION); 121 | gl.loadIdentity(); 122 | gl.perspective(angle, 1, distance - boundingSphere.radius, distance + boundingSphere.radius); 123 | gl.matrixMode(gl.MODELVIEW); 124 | gl.loadIdentity(); 125 | gl.lookAt(light.x, light.y, light.z, boundingSphere.center.x, boundingSphere.center.y, boundingSphere.center.z, 0, 1, 0); 126 | } 127 | 128 | function cameraForBoundingBox(light, boundingBox) { 129 | var center = boundingBox.min.add(boundingBox.max).divide(2); 130 | var axisZ = center.subtract(light).unit(); 131 | var axisX = axisZ.cross(new GL.Vector(0, 1, 0)).unit(); 132 | var axisY = axisX.cross(axisZ); 133 | var near = Number.MAX_VALUE; 134 | var far = -Number.MAX_VALUE; 135 | var slopeNegX = 0; 136 | var slopePosX = 0; 137 | var slopeNegY = 0; 138 | var slopePosY = 0; 139 | 140 | // Loop over all the points and find the maximum slope for each direction. 141 | // Incidentally, this algorithm works for convex hulls of any shape and will 142 | // return the optimal bounding frustum for every hull. 143 | for (var i = 0; i < 8; i++) { 144 | point = GL.Vector.lerp(boundingBox.min, boundingBox.max, new GL.Vector(!!(i & 1), !!(i & 2), !!(i & 4))); 145 | var toPoint = point.subtract(light); 146 | var dotZ = toPoint.dot(axisZ); 147 | var slopeX = toPoint.dot(axisX) / dotZ; 148 | var slopeY = toPoint.dot(axisY) / dotZ; 149 | slopeNegX = Math.min(slopeNegX, slopeX); 150 | slopeNegY = Math.min(slopeNegY, slopeY); 151 | slopePosX = Math.max(slopePosX, slopeX); 152 | slopePosY = Math.max(slopePosY, slopeY); 153 | near = Math.min(near, dotZ); 154 | far = Math.max(far, dotZ); 155 | } 156 | 157 | // Need to fit an oblique view frustum to get optimal bounds 158 | gl.matrixMode(gl.PROJECTION); 159 | gl.loadIdentity(); 160 | gl.frustum(slopeNegX * near, slopePosX * near, slopeNegY * near, slopePosY * near, near, far); 161 | gl.matrixMode(gl.MODELVIEW); 162 | gl.loadIdentity(); 163 | gl.lookAt(light.x, light.y, light.z, center.x, center.y, center.z, 0, 1, 0); 164 | } 165 | 166 | gl.ondraw = function() { 167 | // Move the light around 168 | var light = new GL.Vector(100 * Math.sin(time * 0.2), 25, 20 * Math.cos(time * 0.2)); 169 | 170 | // Construct a camera looking from the light toward the object. The view 171 | // frustum is fit so it tightly encloses the bounding volume of the object 172 | // (sphere or box) to make best use of shadow map resolution. A frustum is 173 | // a pyramid shape with the apex chopped off. 174 | if (useBoundingSphere) { 175 | cameraForBoundingSphere(light, boundingSphere); 176 | } else { 177 | cameraForBoundingBox(light, boundingBox); 178 | } 179 | 180 | // Render the object viewed from the light using a shader that returns the 181 | // fragment depth. 182 | var shadowMapMatrix = gl.projectionMatrix.multiply(gl.modelviewMatrix); 183 | depthMap.unbind(); 184 | depthMap.drawTo(function() { 185 | gl.clearColor(1, 1, 1, 1); 186 | gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); 187 | depthShader.draw(mesh); 188 | }); 189 | 190 | // Recover the corners of the view frustum 191 | var w = gl.canvas.width, h = gl.canvas.height; 192 | var eye = gl.modelviewMatrix.inverse().transformPoint(new GL.Vector()); 193 | var corners = [ 194 | gl.unProject(0, 0, 0), 195 | gl.unProject(w, 0, 0), 196 | gl.unProject(0, h, 0), 197 | gl.unProject(w, h, 0), 198 | gl.unProject(0, 0, 1), 199 | gl.unProject(w, 0, 1), 200 | gl.unProject(0, h, 1), 201 | gl.unProject(w, h, 1) 202 | ]; 203 | 204 | // Set up the camera for the scene 205 | gl.clearColor(0, 0, 0, 1); 206 | gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); 207 | gl.matrixMode(gl.PROJECTION); 208 | gl.loadIdentity(); 209 | gl.perspective(45, gl.canvas.width / gl.canvas.height, 1, 1000); 210 | gl.matrixMode(gl.MODELVIEW); 211 | gl.loadIdentity(); 212 | gl.translate(0, 0, -100); 213 | gl.rotate(angleX, 1, 0, 0); 214 | gl.rotate(angleY, 0, 1, 0); 215 | 216 | // Draw view frustum 217 | gl.pointSize(20); 218 | gl.begin(gl.LINES); 219 | for (var i = 0; i < 8; i++) { 220 | if (i < 4) { 221 | gl.color(1, 0, 0); 222 | gl.vertex(eye); 223 | gl.vertex(corners[i]); 224 | } 225 | gl.color(1, 1, 0); 226 | for (var j = 0; j < 3; j++) { 227 | gl.vertex(corners[i]); 228 | gl.vertex(corners[i ^ (1 << j)]); 229 | } 230 | } 231 | gl.end(); 232 | 233 | // Draw the bounding volume 234 | if (useBoundingSphere) { 235 | colorShader.uniforms({ 236 | center: boundingSphere.center, 237 | radius: new GL.Vector(boundingSphere.radius, boundingSphere.radius, boundingSphere.radius) 238 | }).draw(sphere, gl.LINES); 239 | } else { 240 | colorShader.uniforms({ 241 | center: boundingBox.min.add(boundingBox.max).divide(2), 242 | radius: boundingBox.max.subtract(boundingBox.min).divide(2) 243 | }).draw(cube, gl.LINES); 244 | } 245 | 246 | // Draw mesh 247 | depthMap.bind(); 248 | displayShader.uniforms({ 249 | shadowMapMatrix: shadowMapMatrix.multiply(gl.projectionMatrix.multiply(gl.modelviewMatrix).inverse()), 250 | light: gl.modelviewMatrix.transformPoint(light) 251 | }).draw(mesh); 252 | 253 | // Draw plane 254 | gl.pushMatrix(); 255 | gl.rotate(-90, 1, 0, 0); 256 | displayShader.draw(plane); 257 | gl.popMatrix(); 258 | 259 | // Draw depth map overlay 260 | gl.viewport(10, 10, 10 + 256, 10 + 256); 261 | textureShader.draw(texturePlane); 262 | gl.viewport(0, 0, gl.canvas.width, gl.canvas.height); 263 | }; 264 | 265 | document.onkeydown = function(e) { 266 | if (e.which == 'S'.charCodeAt(0)) { 267 | useBoundingSphere = true; 268 | } else if (e.which == 'B'.charCodeAt(0)) { 269 | useBoundingSphere = false; 270 | } 271 | }; 272 | 273 | gl.fullscreen(); 274 | gl.animate(); 275 | gl.enable(gl.DEPTH_TEST); 276 | -------------------------------------------------------------------------------- /examples/lightgl/texture.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikeseven/node-webgl/a918e74acc7860db1bb63029934e8f54a2730ce2/examples/lightgl/texture.png -------------------------------------------------------------------------------- /examples/lightgl/texture2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikeseven/node-webgl/a918e74acc7860db1bb63029934e8f54a2730ce2/examples/lightgl/texture2.png -------------------------------------------------------------------------------- /examples/shadertoy/presets/704.fs: -------------------------------------------------------------------------------- 1 | #ifdef GL_ES 2 | precision highp float; 3 | #endif 4 | 5 | uniform vec2 resolution; 6 | uniform float time; 7 | 8 | float stime=sin(time); 9 | float ctime=cos(time); 10 | 11 | float inObj(in vec3 p){ 12 | float oP=length(p); 13 | p.x=sin(p.x)+stime; 14 | p.z=sin(p.z)+ctime; 15 | return float(min(length(p)-1.5-sin(oP-time*4.0),p.y+3.0)); 16 | } 17 | 18 | void main(void){ 19 | vec2 vPos=-1.0+2.0*gl_FragCoord.xy/resolution.xy; 20 | 21 | //Camera animation 22 | vec3 vuv=vec3(stime,1,0);//view up vector 23 | vec3 vrp=vec3(sin(time*0.7)*10.0,0,cos(time*0.9)*10.0); //view reference point 24 | vec3 prp=vec3(sin(time*0.7)*20.0+vrp.x+20.0, 25 | stime*4.0+4.0+vrp.y+3.0, 26 | cos(time*0.6)*20.0+vrp.z+14.0); //camera position 27 | 28 | //Camera setup 29 | vec3 vpn=normalize(vrp-prp); 30 | vec3 u=normalize(cross(vuv,vpn)); 31 | vec3 v=cross(vpn,u); 32 | vec3 vcv=(prp+vpn); 33 | vec3 scrCoord=vcv+vPos.x*u*resolution.x/resolution.y+vPos.y*v; 34 | vec3 scp=normalize(scrCoord-prp); 35 | 36 | //Raymarching 37 | const vec3 e = vec3(0.1,0,0); 38 | const float maxd=200.0; 39 | 40 | float s=0.1; 41 | vec3 c,p,n; 42 | 43 | //speed optimization -advance ray (simple raytracing) until plane y=2.5 44 | float f=-(prp.y-2.5)/scp.y; 45 | if (f>0.0) p=prp+scp*f; 46 | else f=maxd; 47 | 48 | for(int i=0;i<256;i++){ 49 | if (abs(s)<.01||f>maxd) break; 50 | f+=s; 51 | p=prp+scp*f; 52 | s=inObj(p); 53 | } 54 | 55 | if (f.5) 58 | if (fract(p.z*.5)>.5) 59 | c=vec3(0,0,0); 60 | else 61 | c=vec3(1,1,1); 62 | else 63 | if (fract(p.z*.5)>.5) 64 | c = vec3(1,1,1); 65 | else 66 | c = vec3(0,0,0); 67 | n=vec3(0,1,0); 68 | } 69 | else{ 70 | float d=length(p); 71 | c=vec3((sin(d*.25-time*4.0)+1.0)/2.0, 72 | (stime+1.0)/2.0, 73 | (sin(d-time*4.0)+1.0)/2.0); //color 74 | n=normalize( 75 | vec3(s-inObj(p-e.xyy), 76 | s-inObj(p-e.yxy), 77 | s-inObj(p-e.yyx))); 78 | } 79 | float b=dot(n,normalize(prp-p)); 80 | gl_FragColor=vec4((b*c+pow(b,54.0))*(1.0-f*.005),1.0); 81 | } 82 | else gl_FragColor=vec4(0,0,0,1); 83 | } 84 | -------------------------------------------------------------------------------- /examples/shadertoy/presets/BigEarth.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikeseven/node-webgl/a918e74acc7860db1bb63029934e8f54a2730ce2/examples/shadertoy/presets/BigEarth.jpg -------------------------------------------------------------------------------- /examples/shadertoy/presets/apple.fs: -------------------------------------------------------------------------------- 1 | #ifdef GL_ES 2 | precision highp float; 3 | #endif 4 | 5 | uniform vec2 resolution; 6 | uniform float time; 7 | 8 | mat3 m = mat3( 0.00, 0.80, 0.60, 9 | -0.80, 0.36, -0.48, 10 | -0.60, -0.48, 0.64 ); 11 | 12 | float hash( float n ) 13 | { 14 | return fract(sin(n)*43758.5453); 15 | } 16 | 17 | 18 | float noise( in vec3 x ) 19 | { 20 | vec3 p = floor(x); 21 | vec3 f = fract(x); 22 | 23 | f = f*f*(3.0-2.0*f); 24 | 25 | float n = p.x + p.y*57.0 + 113.0*p.z; 26 | 27 | float res = mix(mix(mix( hash(n+ 0.0), hash(n+ 1.0),f.x), 28 | mix( hash(n+ 57.0), hash(n+ 58.0),f.x),f.y), 29 | mix(mix( hash(n+113.0), hash(n+114.0),f.x), 30 | mix( hash(n+170.0), hash(n+171.0),f.x),f.y),f.z); 31 | return res; 32 | } 33 | 34 | float fbm( vec3 p ) 35 | { 36 | float f = 0.0; 37 | 38 | f += 0.5000*noise( p ); p = m*p*2.02; 39 | f += 0.2500*noise( p ); p = m*p*2.03; 40 | f += 0.1250*noise( p ); p = m*p*2.01; 41 | f += 0.0625*noise( p ); 42 | 43 | return f/0.9375; 44 | } 45 | 46 | vec2 map( vec3 p ) 47 | { 48 | vec2 d2 = vec2( p.y+0.55, 2.0 ); 49 | 50 | p.y -= 0.75*pow(dot(p.xz,p.xz),0.2); 51 | vec2 d1 = vec2( length(p) - 1.0, 1.0 ); 52 | 53 | if( d2.x0.0) { lh=nh; t+=dt; } lm=ma.y; 139 | } 140 | 141 | if( nh>0.0 ) return vec2(-1.0); 142 | t = t - dt*nh/(nh-lh); 143 | 144 | return vec2(t,lm); 145 | } 146 | 147 | float softshadow( in vec3 ro, in vec3 rd, float mint, float maxt, float k ) 148 | { 149 | float res = 1.0; 150 | float dt = 0.1; 151 | float t = mint; 152 | for( int i=0; i<30; i++ ) 153 | { 154 | float h = map(ro + rd*t).x; 155 | if( h>0.001 ) 156 | res = min( res, k*h/t ); 157 | else 158 | res = 0.0; 159 | t += dt; 160 | } 161 | return res; 162 | } 163 | vec3 calcNormal( in vec3 pos ) 164 | { 165 | vec3 eps = vec3(.001,0.0,0.0); 166 | vec3 nor; 167 | nor.x = map(pos+eps.xyy).x - map(pos-eps.xyy).x; 168 | nor.y = map(pos+eps.yxy).x - map(pos-eps.yxy).x; 169 | nor.z = map(pos+eps.yyx).x - map(pos-eps.yyx).x; 170 | return normalize(nor); 171 | } 172 | 173 | void main(void) 174 | { 175 | vec2 q = gl_FragCoord.xy / resolution.xy; 176 | vec2 p = -1.0 + 2.0 * q; 177 | p.x *= resolution.x/resolution.y; 178 | 179 | // camera 180 | vec3 ro = 2.5*normalize(vec3(cos(0.2*time),1.15+0.4*cos(time*.11),sin(0.2*time))); 181 | vec3 ww = normalize(vec3(0.0,0.5,0.0) - ro); 182 | vec3 uu = normalize(cross( vec3(0.0,1.0,0.0), ww )); 183 | vec3 vv = normalize(cross(ww,uu)); 184 | vec3 rd = normalize( p.x*uu + p.y*vv + 1.5*ww ); 185 | 186 | // raymarch 187 | vec3 col = vec3(0.96,0.98,1.0); 188 | vec2 tmat = intersect(ro,rd); 189 | if( tmat.y>0.5 ) 190 | { 191 | // geometry 192 | vec3 pos = ro + tmat.x*rd; 193 | vec3 nor = calcNormal(pos); 194 | vec3 ref = reflect(rd,nor); 195 | vec3 lig = normalize(vec3(1.0,0.8,-0.6)); 196 | 197 | float con = 1.0; 198 | float amb = 0.5 + 0.5*nor.y; 199 | float dif = max(dot(nor,lig),0.0); 200 | float bac = max(0.2 + 0.8*dot(nor,vec3(-lig.x,lig.y,-lig.z)),0.0); 201 | float rim = pow(1.0+dot(nor,rd),3.0); 202 | float spe = pow(clamp(dot(lig,ref),0.0,1.0),16.0); 203 | 204 | // shadow 205 | float sh = softshadow( pos, lig, 0.06, 4.0, 4.0 ); 206 | 207 | // lights 208 | col = 0.10*con*vec3(0.80,0.90,1.00); 209 | col += 0.70*dif*vec3(1.00,0.97,0.85)*vec3(sh, (sh+sh*sh)*0.5, sh*sh ); 210 | col += 0.15*bac*vec3(1.00,0.97,0.85); 211 | col += 0.20*amb*vec3(0.10,0.15,0.20); 212 | 213 | 214 | // color 215 | vec2 pro; 216 | if( tmat.y<1.5 ) 217 | col *= appleColor(pos,nor,pro); 218 | else 219 | col *= floorColor(pos,nor,pro); 220 | 221 | // rim and spec 222 | col += 0.60*rim*vec3(1.0,0.97,0.85)*amb*amb; 223 | col += 0.60*pow(spe,pro.y)*vec3(1.0)*pro.x*sh; 224 | 225 | col = 0.3*col + 0.7*sqrt(col); 226 | } 227 | 228 | col *= 0.25 + 0.75*pow( 16.0*q.x*q.y*(1.0-q.x)*(1.0-q.y), 0.15 ); 229 | 230 | gl_FragColor = vec4(col,1.0); 231 | } 232 | -------------------------------------------------------------------------------- /examples/shadertoy/presets/clod.fs: -------------------------------------------------------------------------------- 1 | #ifdef GL_ES 2 | precision highp float; 3 | #endif 4 | 5 | uniform vec2 resolution; 6 | uniform float time; 7 | 8 | float f(vec3 o) { 9 | float a = (sin(o.x) + o.y * .25) * .35; 10 | o = vec3(cos(a) * o.x - sin(a) * o.y, sin(a) * o.x + cos(a) * o.y, o.z); 11 | return dot(cos(o) * cos(o), vec3(1)) - 1.2; 12 | } 13 | 14 | #if 1 15 | // 16 | // modified by iq: 17 | // removed the break inside the marching loop (GLSL compatibility) 18 | // replaced 10 step binary search by a linear interpolation 19 | // 20 | vec3 s(vec3 o, vec3 d) { 21 | float t = 0.0; 22 | float dt = 0.2; 23 | float nh = 0.0; 24 | float lh = 0.0; 25 | for (int i = 0; i < 50; i++) { 26 | nh = f(o + d * t); 27 | if (nh > 0.0) { 28 | lh = nh; 29 | t += dt; 30 | } 31 | } 32 | 33 | if (nh > 0.0) 34 | return vec3(.93, .94, .85); 35 | 36 | t = t - dt * nh / (nh - lh); 37 | 38 | vec3 e = vec3(.1, 0.0, 0.0); 39 | vec3 p = o + d * t; 40 | vec3 n = -normalize(vec3(f(p + e), f(p + e.yxy), f(p + e.yyx)) + vec3((sin(p * 75.))) * .01); 41 | 42 | return vec3(mix(((max(-dot(n, vec3(.577)), 0.) + 0.125 * max(-dot(n, vec3(-.707, -.707, 0)), 0.))) * (mod 43 | 44 | (length(p.xy) * 20., 2.) < 1.0 ? vec3(.71, .85, .25) : vec3(.79, .93, .4)), vec3(.93, .94, .85), vec3(pow(t / 9., 5.)))); 45 | } 46 | #else 47 | // 48 | // original marching 49 | // 50 | vec3 s(vec3 o,vec3 d) 51 | { 52 | float t=0.,a,b; 53 | for(int i=0;i<75;i++) 54 | { 55 | if(f(o+d*t)<0.0) 56 | { 57 | a=t-.125;b=t; 58 | for(int i=0; i<10;i++) 59 | { 60 | t=(a+b)*.5; 61 | if(f(o+d*t)<0.0) 62 | b=t; 63 | else 64 | a=t; 65 | } 66 | vec3 e=vec3(.1,0.0,0.0); 67 | vec3 p=o+d*t; 68 | vec3 n=-normalize(vec3(f(p+e),f(p+e.yxy),f(p+e.yyx))+vec3((sin(p*75.)))*.01); 69 | 70 | return vec3( mix( ((max(-dot(n,vec3(.577)),0.) + 0.125*max(-dot(n,vec3(-.707,-.707,0)),0.)))*(mod(length(p.xy)*20.,2.)<1.0?vec3(.71,.85,.25):vec3(.79,.93,.4)) 71 | ,vec3(.93,.94,.85), vec3(pow(t/9.,5.)) ) ); 72 | } 73 | t+=.125; 74 | } 75 | return vec3(.93,.94,.85); 76 | } 77 | #endif 78 | 79 | void main() { 80 | vec2 p = -1.0 + 2.0 * gl_FragCoord.xy / resolution.xy; 81 | gl_FragColor = vec4(s(vec3(sin(time * 1.5) * .5, cos(time) * .5, time), normalize(vec3(p.xy, 1.0))), 1.0); 82 | } -------------------------------------------------------------------------------- /examples/shadertoy/presets/deform.fs: -------------------------------------------------------------------------------- 1 | #ifdef GL_ES 2 | precision highp float; 3 | #endif 4 | 5 | uniform float time; 6 | uniform vec2 resolution; 7 | uniform vec4 mouse; 8 | uniform sampler2D tex0; 9 | uniform sampler2D tex1; 10 | 11 | void main(void) 12 | { 13 | vec2 p = -1.0 + 2.0 * gl_FragCoord.xy / resolution.xy; 14 | vec2 m = -1.0 + 2.0 * mouse.xy / resolution.xy; 15 | 16 | float a1 = atan(p.y-m.y,p.x-m.x); 17 | float r1 = sqrt(dot(p-m,p-m)); 18 | float a2 = atan(p.y+m.y,p.x+m.x); 19 | float r2 = sqrt(dot(p+m,p+m)); 20 | 21 | vec2 uv; 22 | uv.x = 0.2*time + (r1-r2)*0.25; 23 | uv.y = sin(2.0*(a1-a2)); 24 | 25 | float w = r1*r2*0.8; 26 | vec3 col = texture2D(tex0,uv).xyz; 27 | 28 | gl_FragColor = vec4(col/(.1+w),1.0); 29 | } 30 | -------------------------------------------------------------------------------- /examples/shadertoy/presets/droid.fs: -------------------------------------------------------------------------------- 1 | // distance field ray caster 2 | // simon green 06/01/2011 3 | // 4 | // based on Inigo Quilezles's: 5 | // http://www.iquilezles.org/www/material/nvscene2008/rwwtt.pdf 6 | // http://www.iquilezles.org/apps/shadertoy/ 7 | // 8 | // Google Android robot: 9 | // http://www.android.com/branding.html 10 | 11 | #ifdef GL_ES 12 | precision highp float; 13 | #endif 14 | 15 | uniform vec2 resolution; 16 | uniform float time; 17 | 18 | // CSG operations 19 | float _union(float a, float b) 20 | { 21 | return min(a, b); 22 | } 23 | 24 | float intersect(float a, float b) 25 | { 26 | return max(a, b); 27 | } 28 | 29 | float difference(float a, float b) 30 | { 31 | return max(a, -b); 32 | } 33 | 34 | // primitive functions 35 | // these all return the distance to the surface from a given point 36 | 37 | float plane(vec3 p, vec3 planeN, vec3 planePos) 38 | { 39 | return dot(p - planePos, planeN); 40 | } 41 | 42 | float box(vec3 p, vec3 abc ) 43 | { 44 | vec3 di=max(abs(p)-abc, 0.0); 45 | //return dot(di,di); 46 | return length(di); 47 | } 48 | 49 | float sphere(vec3 p, float r) 50 | { 51 | return length(p) - r; 52 | } 53 | 54 | // capsule in Y axis 55 | float capsuleY(vec3 p, float r, float h) 56 | { 57 | p.y -= clamp(p.y, 0.0, h); 58 | return length(p) - r; 59 | } 60 | 61 | // given segment ab and point c, computes closest point d on ab 62 | // also returns t for the position of d, d(t) = a + t(b-a) 63 | vec3 closestPtPointSegment(vec3 c, vec3 a, vec3 b, out float t) 64 | { 65 | vec3 ab = b - a; 66 | // project c onto ab, computing parameterized position d(t) = a + t(b-a) 67 | t = dot(c - a, ab) / dot(ab, ab); 68 | // clamp to closest endpoint 69 | t = clamp(t, 0.0, 1.0); 70 | // compute projected position 71 | return a + t * ab; 72 | } 73 | 74 | // generic capsule 75 | float capsule(vec3 p, vec3 a, vec3 b, float r) 76 | { 77 | float t; 78 | vec3 c = closestPtPointSegment(p, a, b, t); 79 | return length(c - p) - r; 80 | } 81 | 82 | float cylinderY(vec3 p, float r, float h) 83 | { 84 | float d = length(vec2(p.x, p.z)) - r; 85 | d = difference(d, plane(p, vec3(0.0, -1.0, 0.0), vec3(0.0, h, 0.0))); 86 | d = difference(d, plane(p, vec3(0.0, 1.0, 0.0), vec3(0.0))); 87 | return d; 88 | } 89 | 90 | 91 | // transforms 92 | vec3 rotateX(vec3 p, float a) 93 | { 94 | float sa = sin(a); 95 | float ca = cos(a); 96 | vec3 r; 97 | r.x = p.x; 98 | r.y = ca*p.y - sa*p.z; 99 | r.z = sa*p.y + ca*p.z; 100 | return r; 101 | } 102 | 103 | vec3 rotateY(vec3 p, float a) 104 | { 105 | float sa = sin(a); 106 | float ca = cos(a); 107 | vec3 r; 108 | r.x = ca*p.x + sa*p.z; 109 | r.y = p.y; 110 | r.z = -sa*p.x + ca*p.z; 111 | return r; 112 | } 113 | 114 | 115 | float halfSphere(vec3 p, float r) 116 | { 117 | return difference( 118 | sphere(p, r), 119 | plane(p, vec3(0.0, 1.0, 0.0), vec3(0.0)) ); 120 | } 121 | 122 | // distance to scene 123 | float scene(vec3 p) 124 | { 125 | float d = 1e10; 126 | 127 | p -= vec3(0.0, 1.0, 0.0); 128 | vec3 hp = rotateY(p, sin(time*0.5)*0.5); 129 | 130 | // head 131 | //d = sphere(p, 1.0); 132 | d = halfSphere(hp, 1.0); 133 | 134 | // eyes 135 | d = _union(d, sphere(hp - vec3(-0.3, 0.3, 0.9), 0.1)); 136 | d = _union(d, sphere(hp - vec3(0.3, 0.3, 0.9), 0.1)); 137 | 138 | // antenna 139 | d = _union(d, capsule(hp, vec3(-0.4, 0.7, 0.0), vec3(-0.75, 1.2, 0.0), 0.05)); 140 | d = _union(d, capsule(hp, vec3(0.4, 0.7, 0.0), vec3(0.75, 1.2, 0.0), 0.05)); 141 | 142 | // body 143 | d = _union(d, capsuleY((p*vec3(1.0, 4.0, 1.0) - vec3(0.0, -4.6, 0.0)), 1.0, 4.0)); 144 | //d = _union(d, cylinderY(p - vec3(0.0, -1.1, 0.0), 1.0, 1.0)); 145 | 146 | // arms 147 | //d = _union(d, capsuleY(p - vec3(-1.2, -0.9, 0.0), 0.2, 0.7)); 148 | //d = _union(d, capsuleY(p - vec3(1.2, -0.9, 0.0), 0.2, 0.7)); 149 | d = _union(d, capsuleY(rotateX(p, cos(time)) - vec3(-1.2, -0.9, 0.0), 0.2, 0.7)); 150 | d = _union(d, capsuleY(rotateX(p, sin(time)) - vec3(1.2, -0.9, 0.0), 0.2, 0.7)); 151 | 152 | // legs 153 | d = _union(d, capsuleY(p - vec3(-0.4, -1.8, 0.0), 0.2, 0.5)); 154 | d = _union(d, capsuleY(p - vec3(0.4, -1.8, 0.0), 0.2, 0.5)); 155 | 156 | // floor 157 | p += vec3(0.0, 1.0, 0.0); 158 | d = _union(d, plane(p, vec3(0.0, 1.0, 0.0), vec3(0.0, -1.0, 0.0))); 159 | 160 | return d; 161 | } 162 | 163 | // calculate scene normal 164 | vec3 sceneNormal( in vec3 pos ) 165 | { 166 | float eps = 0.0001; 167 | vec3 n; 168 | n.x = scene( vec3(pos.x+eps, pos.y, pos.z) ) - scene( vec3(pos.x-eps, pos.y, pos.z) ); 169 | n.y = scene( vec3(pos.x, pos.y+eps, pos.z) ) - scene( vec3(pos.x, pos.y-eps, pos.z) ); 170 | n.z = scene( vec3(pos.x, pos.y, pos.z+eps) ) - scene( vec3(pos.x, pos.y, pos.z-eps) ); 171 | return normalize(n); 172 | } 173 | 174 | // ambient occlusion approximation 175 | float ambientOcclusion(vec3 p, vec3 n) 176 | { 177 | const int steps = 3; 178 | const float delta = 0.5; 179 | 180 | float a = 0.0; 181 | float weight = 1.0; 182 | for(int i=1; i<=steps; i++) { 183 | float d = (float(i) / float(steps)) * delta; 184 | a += weight*(d - scene(p + n*d)); 185 | weight *= 0.5; 186 | } 187 | return clamp(1.0 - a, 0.0, 1.0); 188 | } 189 | 190 | // lighting 191 | vec3 shade(vec3 pos, vec3 n, vec3 eyePos) 192 | { 193 | const vec3 lightPos = vec3(5.0, 10.0, 5.0); 194 | const vec3 color = vec3(0.643, 0.776, 0.223); 195 | const float shininess = 100.0; 196 | 197 | vec3 l = normalize(lightPos - pos); 198 | vec3 v = normalize(eyePos - pos); 199 | vec3 h = normalize(v + l); 200 | float diff = dot(n, l); 201 | float spec = max(0.0, pow(dot(n, h), shininess)) * float(diff > 0.0); 202 | //diff = max(0.0, diff); 203 | diff = 0.5+0.5*diff; 204 | 205 | float fresnel = pow(1.0 - dot(n, v), 5.0); 206 | float ao = ambientOcclusion(pos, n); 207 | 208 | // return vec3(diff*ao) * color + vec3(spec + fresnel*0.5); 209 | return vec3(diff*ao) * color + vec3(spec); 210 | // return vec3(ao); 211 | // return vec3(fresnel); 212 | } 213 | 214 | // trace ray using sphere tracing 215 | vec3 trace(vec3 ro, vec3 rd, out bool hit) 216 | { 217 | const int maxSteps = 128; 218 | const float hitThreshold = 0.01; 219 | hit = false; 220 | vec3 pos = ro; 221 | 222 | for(int i=0; i0.0 ) 27 | { 28 | float t = -b - sqrt(h); 29 | vec3 pos = ro + t*rd; 30 | vec3 nor = pos; 31 | 32 | // texture mapping 33 | vec2 uv; 34 | uv.x = atan(nor.x,nor.z)/6.2831 - 0.05*time - mouse.x/resolution.x; 35 | uv.y = -acos(nor.y)/3.1416; 36 | uv.y = 0.5 + spow( uv.y-0.5, 1.2 ); 37 | col = texture2D(tex0,uv).xyz; 38 | 39 | // lighting 40 | col *= 0.3 + 0.7*max(nor.x*2.0+nor.z,0.0); 41 | } 42 | 43 | return col; 44 | } 45 | 46 | void main(void) 47 | { 48 | // render this with four sampels per pixel 49 | vec3 col0 = doit( (gl_FragCoord.xy+vec2(0.0,0.0) )/resolution.xy ); 50 | vec3 col1 = doit( (gl_FragCoord.xy+vec2(0.5,0.0) )/resolution.xy ); 51 | vec3 col2 = doit( (gl_FragCoord.xy+vec2(0.0,0.5) )/resolution.xy ); 52 | vec3 col3 = doit( (gl_FragCoord.xy+vec2(0.5,0.5) )/resolution.xy ); 53 | vec3 col = 0.25*(col0 + col1 + col2 + col3); 54 | 55 | gl_FragColor = vec4(col,1.0); 56 | } 57 | -------------------------------------------------------------------------------- /examples/shadertoy/presets/earth_day.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikeseven/node-webgl/a918e74acc7860db1bb63029934e8f54a2730ce2/examples/shadertoy/presets/earth_day.jpg -------------------------------------------------------------------------------- /examples/shadertoy/presets/julia.fs: -------------------------------------------------------------------------------- 1 | #ifdef GL_ES 2 | precision highp float; 3 | #endif 4 | 5 | uniform vec2 resolution; 6 | uniform float time; 7 | 8 | void main(void) { 9 | vec2 p = -1.0 + 2.0 * gl_FragCoord.xy / resolution.xy; 10 | vec2 cc = vec2(cos(.25 * time), sin(.25 * time * 1.423)); 11 | 12 | float dmin = 1000.0; 13 | vec2 z = p * vec2(1.33, 1.0); 14 | for (int i = 0; i < 64; i++) { 15 | z = cc + vec2(z.x * z.x - z.y * z.y, 2.0 * z.x * z.y); 16 | float m2 = dot(z, z); 17 | if (m2 > 100.0) 18 | break; 19 | dmin = min(dmin, m2); 20 | } 21 | 22 | float color = sqrt(sqrt(dmin)) * 0.7; 23 | gl_FragColor = vec4(color, color, color, 1.0); 24 | } 25 | -------------------------------------------------------------------------------- /examples/shadertoy/presets/kinderpainter.fs: -------------------------------------------------------------------------------- 1 | #ifdef GL_ES 2 | precision highp float; 3 | #endif 4 | 5 | uniform vec2 resolution; 6 | uniform float time; 7 | uniform vec4 mouse; 8 | uniform sampler2D tex0; 9 | uniform sampler2D tex1; 10 | 11 | vec4 fpar00[6]; 12 | vec4 fpar01[6]; 13 | 14 | 15 | float cylinder( in vec4 sph, in vec3 ro, in vec3 rd ) 16 | { 17 | vec3 d = ro - sph.xyz; 18 | float a = dot( rd.xz, rd.xz ); 19 | float b = dot( rd.xz, d.xz ); 20 | float c = dot( d.xz, d.xz ) - sph.w*sph.w; 21 | float t; 22 | 23 | t = b*b - a*c; 24 | if( t>0.0 ) 25 | { 26 | t = -(b+sqrt( t ))/a; 27 | } 28 | 29 | return t-.001; 30 | 31 | } 32 | 33 | 34 | float esfera( in vec4 sph, in vec3 ro, in vec3 rd ) 35 | { 36 | vec3 d = ro - sph.xyz; 37 | float b = dot( rd, d ); 38 | float c = dot( d, d ) - sph.w*sph.w; 39 | float t = b*b - c; 40 | 41 | if( t>0.0 ) 42 | { 43 | t = -b - sqrt( t ); 44 | } 45 | 46 | return t-.001; 47 | } 48 | 49 | 50 | bool esfera2( in vec4 sph, in vec3 ro, in vec3 rd, in float tmin ) 51 | { 52 | vec3 d = ro - sph.xyz; 53 | float b = dot( rd, d ); 54 | float c = dot( d, d ) - sph.w*sph.w; 55 | 56 | float t = b*b - c; 57 | bool r = false; 58 | 59 | if( t>0.0 ) 60 | { 61 | t = -b - sqrt( t ); 62 | r = (t>0.0) && (t0.0 ) 78 | { 79 | t = -(b+sqrt(t)); 80 | r = (t>0.0) && (t<(tmin*a)); 81 | } 82 | return r; 83 | } 84 | 85 | 86 | float plane( in vec4 pla, in vec3 ro, in vec3 rd ) 87 | { 88 | float de = dot(pla.xyz, rd); 89 | de = sign(de)*max( abs(de), 0.001); 90 | float t = -(dot(pla.xyz, ro) + pla.w)/de; 91 | return t-.001; 92 | } 93 | 94 | 95 | vec3 calcnor( in vec4 obj, in vec4 col, in vec3 inter, out vec2 uv ) 96 | { 97 | vec3 nor; 98 | if( col.w>2.5 ) 99 | { 100 | nor.xz = inter.xz - obj.xz; 101 | nor.y = 0.0; 102 | nor = nor/obj.w; 103 | //uv = vec2( atan(nor.x,nor.z)/3.14159, inter.y ); 104 | uv = vec2( nor.x, inter.y ); 105 | } 106 | else if( col.w>1.5 ) 107 | { 108 | nor = obj.xyz; 109 | uv = inter.xz*.2; 110 | } 111 | else 112 | { 113 | nor = inter - obj.xyz; 114 | nor = nor/obj.w; 115 | uv = nor.xy; 116 | } 117 | 118 | return nor; 119 | } 120 | 121 | vec4 cmov( in vec4 a, in vec4 b, in bool cond ) 122 | { 123 | return cond?b:a; 124 | } 125 | 126 | float cmov( in float a, in float b, in bool cond ) 127 | { 128 | return cond?b:a; 129 | } 130 | 131 | int cmov( in int a, in int b, in bool cond ) 132 | { 133 | return cond?b:a; 134 | } 135 | 136 | float intersect( in vec3 ro, in vec3 rd, out vec4 obj, out vec4 col ) 137 | { 138 | float tmin = 10000.0; 139 | float t; 140 | 141 | col.w = -1.0; 142 | 143 | bool isok; 144 | 145 | t = esfera( fpar00[0], ro, rd ); 146 | isok = (t>0.0) && (t0.0) && (t0.0 && t0.0 && t0.0 && t0.0 && t thresh) 71 | { 72 | w *= 0.50; 73 | x *= 2.55; 74 | y *= 2.55; 75 | f -= w * NoiseNonLinear(x, y); 76 | } 77 | if (f < water) f = water; 78 | return f; 79 | } 80 | 81 | // Get height map at varying subtractive Perlin noise levels... 82 | float terrain(in float x, in float y, in float thresh, in float dis) 83 | { 84 | float w = 7.0; 85 | float v = NoiseNonLinear(x, y); 86 | float f = w * v; 87 | float d = 65.0; 88 | 89 | if (f > thresh && dis < d) 90 | { 91 | w *= 0.50; 92 | x *= 2.55; 93 | y *= 2.55; 94 | f -= w * NoiseNonLinear(x, y); 95 | d *= fracDistanceMult; 96 | if (f > thresh && dis < d) 97 | { 98 | float dt = clamp((d-dis)*0.15, 0.0, 1.0); 99 | w *= 0.24; 100 | x *= 2.55; 101 | y *= 2.55; 102 | f -= w * NoiseNonLinear(x, y)*dt; 103 | d *= fracDistanceMult; 104 | if (f > thresh && dis < d) 105 | { 106 | float dt = clamp((d-dis)*.15, 0.0, 1.0); 107 | w *= 0.34; 108 | x *= 2.55; 109 | y *= 2.55; 110 | f -= w * NoiseNonLinear(x, y) * dt; 111 | d *= fracDistanceMult; 112 | if (f > thresh && dis < d) 113 | { 114 | float dt = clamp((d-dis)*.15, 0.0, 1.0); 115 | w *= 0.34; 116 | x *= 2.55; 117 | y *= 2.55; 118 | f -= w * NoiseNonLinear(x, y)*dt; 119 | d *= fracDistanceMult; 120 | if (f > thresh && dis < d) 121 | { 122 | float dt = clamp((d-dis)*.15, 0.0, 1.0); 123 | w *= 0.34; 124 | x *= 2.55; 125 | y *= 2.55; 126 | f -= w * NoiseNonLinear(x, y)*dt; 127 | d *= fracDistanceMult; 128 | if (f > thresh && dis < d) 129 | { 130 | w *= 0.34; 131 | x *= 2.55; 132 | y *= 2.55; 133 | f -= w * NoiseNonLinear(x, y); 134 | } 135 | } 136 | } 137 | } 138 | } 139 | } 140 | if (f < water) f = water; 141 | return f; 142 | } 143 | 144 | int castRay( in vec3 ro, in vec3 rd, out float dis) 145 | { 146 | float delt = .1; 147 | float maxt = 45.0; 148 | int ret = 0; 149 | dis = 1.0; 150 | float lh = 0.0; 151 | float ly = 0.0; 152 | for (int l = 0; l < 120; l++) 153 | { 154 | if (ret == 0 && dis < maxt) 155 | { 156 | vec3 p = ro + rd*dis; 157 | float h = terrainLow(p.x*scale, p.z*scale,p.y,dis); 158 | if (p.y < h) 159 | { 160 | ret = 0; 161 | dis -= delt * 1.1; 162 | for (int c = 0; c < 14; c++) 163 | { 164 | if (ret == 0 && dis < maxt) 165 | { 166 | vec3 p = ro + rd*dis; 167 | float h = terrain(p.x*scale, p.z*scale,p.y, dis); 168 | if (p.y < h) 169 | { 170 | float f = delt*0.1; 171 | dis = dis - f + f *(lh-ly)/(p.y - ly - h + lh); 172 | ret = 1; 173 | }else 174 | { 175 | lh = h; 176 | ly = p.y; 177 | delt+= 0.003; 178 | dis += delt*0.1; 179 | } 180 | } 181 | } 182 | }else 183 | { 184 | lh = h; 185 | ly = p.y; 186 | delt += 0.005; 187 | dis += delt; 188 | } 189 | } 190 | }; 191 | 192 | return ret; 193 | } 194 | 195 | vec3 getTerrain(vec3 scrCoord, vec3 rd, float dis) 196 | { 197 | vec3 pos = (scrCoord + rd * dis)*scale; 198 | float p = 5.0 * pow(0.36,9.0); 199 | vec3 nor = vec3(0.0, terrain(pos.x, pos.z,0.0,dis*scale), 0.0); 200 | vec3 v2 = vec3(p, terrain(pos.x+p, pos.z,0.0,dis*scale), 0.0); 201 | vec3 v3 = vec3(0.0, terrain(pos.x, pos.z-p,0.0,dis*scale), -p); 202 | v2 = nor-v2; 203 | v3 = nor-v3; 204 | nor = cross(v2,v3); 205 | nor = normalize(nor); 206 | float diffuse = dot(light,nor); 207 | vec3 mat; 208 | 209 | if (pos.y <= water) 210 | { 211 | // Water... 212 | mat = vec3(.0, .00, 0.1); 213 | }else 214 | { 215 | //Ground texture... 216 | float f = NoiseNonLinear(pos.x*4.0, pos.z*4.0)*0.4+0.3; 217 | mat = vec3(f*.5, f*.38, f*0.3); 218 | if (nor.y < .2 && nor.y > 0.0) 219 | { 220 | float v = clamp((.2-nor.y)*4.2, 0.0,1.0); 221 | mat = mix(mat, vec3(.8,.8,.8), v); 222 | } 223 | if (pos.y < .35 && nor.y > .1) 224 | { 225 | vec3 m = vec3(.0, clamp(NoiseNonLinear(pos.x*98.0, pos.z*98.0)*.55+.0, 0.0, .5), 0.0); 226 | mat = mix(mat, m, clamp((nor.y-.1)*4.0, 0.0, 1.0)); 227 | } 228 | mat.xyz = mat*vec3(.9,.9,.75)*diffuse + vec3(0.1,0.1,0.1); 229 | 230 | float v = clamp((.52-pos.y)*.55, 0.0,1.0); 231 | mat = mix(mat, vec3(.1, .05, .0), v); 232 | 233 | } 234 | return vec3(applyFog(mat, dis, scrCoord, rd, light)); 235 | } 236 | 237 | void main(void) 238 | { 239 | //Camera animation 240 | vec2 vPos=(-1.0+2.0*(gl_FragCoord.xy/resolution.xy)) * 0.3; 241 | vec3 vuv=vec3(stime*0.01,.3,0); //view up vector 242 | vec3 vrp=vec3(sin(offTime*0.027)*35.0, 1, cos(offTime*0.19)*20.0); //view reference point 243 | vec3 prp=vec3(sin(offTime*0.027)*40.0 + vrp.x+1.0, stime*.01+5.0+vrp.y+1.0, cos(offTime*0.06)*20.0+vrp.z+1.0); //camera position 244 | vec3 vpn=normalize(vrp-prp); //Camera setup 245 | vec3 u=normalize(cross(vuv,vpn)); 246 | vec3 v=cross(vpn,u); 247 | vec3 vcv=(prp+vpn); 248 | vec3 scrCoord=vcv+vPos.x*u*resolution.x/resolution.y+vPos.y*v; 249 | vec3 rd=normalize(scrCoord-prp); 250 | 251 | float dis = 0.0; 252 | if (castRay(scrCoord, rd, dis) == 1) 253 | { 254 | gl_FragColor = vec4(getTerrain(scrCoord, rd, dis), 1.0); 255 | }else 256 | { 257 | gl_FragColor= vec4(getSky(rd, light), 1.0); 258 | } 259 | } 260 | -------------------------------------------------------------------------------- /examples/shadertoy/presets/leizex.fs: -------------------------------------------------------------------------------- 1 | #ifdef GL_ES 2 | precision highp float; 3 | #endif 4 | 5 | #extension GL_EXT_gpu_shader4: enable 6 | 7 | uniform vec2 resolution; 8 | uniform float time; 9 | uniform sampler2D tex0; 10 | uniform sampler2D tex1; 11 | 12 | float coolfFunc3d2( int n ) 13 | { 14 | n = (n << 13) ^ n; 15 | n = (n * (n * n * 15731 + 789221) + 1376312589) & 0x7fffffff; 16 | return float(n); 17 | } 18 | 19 | //----------------------------------------------------------------------------- 20 | 21 | float noise3f( in vec3 x, int sem ) 22 | { 23 | ivec3 ip = ivec3(floor(x)); 24 | vec3 f = fract(x); 25 | 26 | f = f*f*(3.0-2.0*f); 27 | //f = f*f*f*(f*(f*6.0-15.0)+10.0); 28 | 29 | int n = ip.x + ip.y * 57 + 113*ip.z + sem; 30 | 31 | float res = mix(mix(mix( coolfFunc3d2(n+(0+57*0+113*0)), coolfFunc3d2(n+(1+57*0+113*0)),f.x), 32 | mix( coolfFunc3d2(n+(0+57*1+113*0)), coolfFunc3d2(n+(1+57*1+113*0)),f.x),f.y), 33 | mix(mix( coolfFunc3d2(n+(0+57*0+113*1)), coolfFunc3d2(n+(1+57*0+113*1)),f.x), 34 | mix( coolfFunc3d2(n+(0+57*1+113*1)), coolfFunc3d2(n+(1+57*1+113*1)),f.x),f.y),f.z); 35 | return 1.0 - res*(1.0/1073741824.0); 36 | } 37 | 38 | //---------------------------------------------------------------------------- 39 | 40 | vec2 celular( in vec3 x ) 41 | { 42 | ivec3 ip = ivec3(floor(x)); 43 | vec3 f = fract(x); 44 | 45 | vec2 dmin = vec2( 1.0, 1.0 ); 46 | 47 | for( int k=-1; k<=1; k++ ) 48 | for( int j=-1; j<=1; j++ ) 49 | for( int i=-1; i<=1; i++ ) 50 | { 51 | int nn = (ip.x+i) + 57*(ip.y+j) + 113*(ip.z+k); 52 | 53 | vec3 di = vec3(float(i),float(j),float(k)) - f + vec3(coolfFunc3d2(nn), coolfFunc3d2(nn+1217), coolfFunc3d2(nn+2513))/2147483647.0; 54 | 55 | float d2 = dot(di,di); 56 | 57 | if( d21024.0 ) break; 36 | co += 1.0; 37 | } 38 | */ 39 | 40 | for( int i=0; i<256; i++ ) 41 | { 42 | if( m2<1024.0 ) 43 | { 44 | z = cc + vec2( z.x*z.x - z.y*z.y, 2.0*z.x*z.y ); 45 | m2 = dot(z,z); 46 | co += 1.0; 47 | } 48 | } 49 | 50 | co = co + 1.0 - log2(.5*log2(m2)); 51 | 52 | co = sqrt(co/256.0); 53 | gl_FragColor = vec4( .5+.5*cos(6.2831*co+0.0), 54 | .5+.5*cos(6.2831*co+0.4), 55 | .5+.5*cos(6.2831*co+0.7), 56 | 1.0 ); 57 | } 58 | -------------------------------------------------------------------------------- /examples/shadertoy/presets/mandelbulb.fs: -------------------------------------------------------------------------------- 1 | #ifdef GL_ES 2 | precision highp float; 3 | #endif 4 | 5 | uniform vec2 resolution; 6 | uniform float time; 7 | 8 | bool isphere( in vec4 sph, in vec3 ro, in vec3 rd, out vec2 t ) 9 | { 10 | vec3 oc = ro - sph.xyz; 11 | float b = dot(oc,rd); 12 | float c = dot(oc,oc) - sph.w*sph.w; 13 | 14 | float h = b*b - c; 15 | if( h<0.0 ) 16 | return false; 17 | 18 | float g = sqrt( h ); 19 | t.x = - b - g; 20 | t.y = - b + g; 21 | 22 | return true; 23 | } 24 | 25 | const int NumIte = 7; 26 | const float Bailout = 100.0; 27 | 28 | bool iterate( in vec3 q, out float resPot, out vec4 resColor ) 29 | { 30 | vec4 trap = vec4(100.0); 31 | vec3 zz = q; 32 | float m = dot(zz,zz); 33 | if( m > Bailout ) 34 | { 35 | resPot = 0.5*log(m)/pow(8.0,0.0); 36 | resColor = vec4(1.0); 37 | return false; 38 | } 39 | 40 | for( int i=1; i Bailout ) 72 | { 73 | resColor = trap; 74 | resPot = 0.5*log(m)/pow(8.0,float(i)); 75 | return false; 76 | } 77 | } 78 | 79 | resColor = trap; 80 | resPot = 0.0; 81 | return true; 82 | } 83 | 84 | bool ifractal( in vec3 ro, in vec3 rd, out float rest, in float maxt, out vec3 resnor, out vec4 rescol, float fov ) 85 | { 86 | vec4 sph = vec4( 0.0, 0.0, 0.0, 1.25 ); 87 | vec2 dis; 88 | 89 | // bounding sphere 90 | if( !isphere(sph,ro,rd,dis) ) 91 | return false; 92 | 93 | // early skip 94 | if( dis.y<0.001 ) return false; 95 | // clip to near! 96 | if( dis.x<0.001 )dis.x = 0.001; 97 | 98 | if( dis.y>maxt) dis.y = maxt; 99 | 100 | float dt; 101 | vec3 gra; 102 | vec4 color; 103 | 104 | float fovfactor = 1.0/sqrt(1.0+fov*fov); 105 | 106 | // raymarch! 107 | for( float t=dis.x; t0.001 ) if( ifractal(xyz,light1,lt1,1e20,ln,lc,fov) ) dif1 = 0.1; 178 | 179 | // material color 180 | rgb = vec3(1.0,1.0,1.0); 181 | rgb = mix( rgb, vec3(0.8,0.6,0.2), sqrt(col.x)*1.25 ); 182 | rgb = mix( rgb, vec3(0.8,0.3,0.3), sqrt(col.y)*1.25 ); 183 | rgb = mix( rgb, vec3(0.7,0.4,0.3), sqrt(col.z)*1.25 ); 184 | 185 | // lighting 186 | rgb *= (0.5+0.5*nor.y)*vec3(.14,.15,.16)*0.8 + dif1*vec3(1.0,.85,.4) + 0.5*dif2*vec3(.08,.10,.14); 187 | rgb *= vec3( pow(ao,0.8), pow(ao,1.00), pow(ao,1.1) ); 188 | 189 | // gamma 190 | rgb = 1.5*(rgb*0.15 + 0.85*sqrt(rgb)); 191 | } 192 | 193 | vec2 uv = p*0.5+0.5; 194 | rgb *= 0.7 + 0.3*16.0*uv.x*uv.y*(1.0-uv.x)*(1.0-uv.y); 195 | 196 | rgb = clamp( rgb, 0.0, 1.0 ); 197 | gl_FragColor = vec4(rgb,1.0); 198 | } -------------------------------------------------------------------------------- /examples/shadertoy/presets/metatunnel.fs: -------------------------------------------------------------------------------- 1 | #ifdef GL_ES 2 | precision highp float; 3 | #endif 4 | 5 | uniform vec2 resolution; 6 | uniform float time; 7 | 8 | float h(vec3 q) 9 | { 10 | float f=1.*distance(q,vec3(cos(time)+sin(time*.2),.3,2.+cos(time*.5)*.5)); 11 | f*=distance(q,vec3(-cos(time*.7),.3,2.+sin(time*.5))); 12 | f*=distance(q,vec3(-sin(time*.2)*.5,sin(time),2.)); 13 | f*=cos(q.y)*cos(q.x)-.1-cos(q.z*7.+time*7.)*cos(q.x*3.)*cos(q.y*4.)*.1; 14 | return f; 15 | } 16 | 17 | void main() 18 | { 19 | vec2 p = -1.0 + 2.0 * gl_FragCoord.xy / resolution.xy; 20 | vec3 o=vec3(p.x,p.y*1.25-0.3,0.); 21 | vec3 d=vec3(p.x+cos(time)*0.3,p.y,1.)/64.; 22 | vec4 c=vec4(0.); 23 | float t=0.; 24 | for(int i=0;i<75;i++) 25 | { 26 | if(h(o+d*t)<.4) 27 | { 28 | t-=5.; 29 | for(int j=0;j<5;j++) 30 | { 31 | if(h(o+d*t)<.4) 32 | break; 33 | t+=1.; 34 | } 35 | vec3 e=vec3(.01,.0,.0); 36 | vec3 n=vec3(.0); 37 | n.x=h(o+d*t)-h(vec3(o+d*t+e.xyy)); 38 | n.y=h(o+d*t)-h(vec3(o+d*t+e.yxy)); 39 | n.z=h(o+d*t)-h(vec3(o+d*t+e.yyx)); 40 | n=normalize(n); 41 | c+=max(dot(vec3(.0,.0,-.5),n),.0)+max(dot(vec3(.0,-.5,.5),n),.0)*.5; 42 | break; 43 | } 44 | t+=5.; 45 | } 46 | gl_FragColor=c+vec4(.1,.2,.5,1.)*(t*.025); 47 | } 48 | -------------------------------------------------------------------------------- /examples/shadertoy/presets/quaternion.fs: -------------------------------------------------------------------------------- 1 | #ifdef GL_ES 2 | precision highp float; 3 | #endif 4 | 5 | uniform vec2 resolution; 6 | uniform float time; 7 | uniform sampler2D tex0; 8 | uniform sampler2D tex1; 9 | 10 | float jinteresct(in vec3 rO, in vec3 rD, in vec4 c, out float ao) 11 | { 12 | float mz2,md2,dist,t; 13 | float res=1000.0; 14 | vec4 z,nz; 15 | 16 | ao = 0.0; 17 | for(t=0.0;t<6.0;t+=dist) 18 | { 19 | ao += 1.0; 20 | vec3 p=rO+t*rD; 21 | 22 | // calc distance 23 | z=vec4(p,(c.y+c.x)*.3); 24 | md2=1.0; 25 | mz2=dot(z,z); 26 | 27 | for(int i=0;i<9;i++) 28 | { 29 | // |dz|^2 -> 4*|dz|^2 30 | md2*=4.0*mz2; 31 | // z -> z2 + c 32 | nz.x=z.x*z.x-dot(z.yzw,z.yzw); 33 | nz.yzw=2.0*z.x*z.yzw; 34 | z=nz+c; 35 | 36 | mz2=dot(z,z); 37 | if(mz2>4.0) 38 | break; 39 | } 40 | 41 | dist=0.25*sqrt(mz2/md2)*log(mz2); 42 | 43 | if(dist<0.0005) 44 | { 45 | res=t; 46 | break; 47 | } 48 | 49 | } 50 | 51 | return res; 52 | } 53 | 54 | 55 | vec3 calcNormal(in vec3 p, in vec4 c) 56 | { 57 | vec4 nz,ndz,dz[4]; 58 | 59 | vec4 z=vec4(p,(c.y+c.x)*.3); 60 | 61 | dz[0]=vec4(1.0,0.0,0.0,0.0); 62 | dz[1]=vec4(0.0,1.0,0.0,0.0); 63 | dz[2]=vec4(0.0,0.0,1.0,0.0); 64 | //dz[3]=vec4(0.0,0.0,0.0,1.0); 65 | 66 | for(int i=0;i<9;i++) 67 | { 68 | vec4 mz = vec4(z.x,-z.y,-z.z,-z.w); 69 | // derivative 70 | dz[0]=vec4(dot(mz,dz[0]),z.x*dz[0].yzw+dz[0].x*z.yzw); 71 | dz[1]=vec4(dot(mz,dz[1]),z.x*dz[1].yzw+dz[1].x*z.yzw); 72 | dz[2]=vec4(dot(mz,dz[2]),z.x*dz[2].yzw+dz[2].x*z.yzw); 73 | //dz[3]=vec4(dot(mz,dz[3]),z.x*dz[3].yzw+dz[3].x*z.yzw); 74 | 75 | // z = z2 + c 76 | nz.x=dot(z, mz); 77 | nz.yzw=2.0*z.x*z.yzw; 78 | z=nz+c; 79 | 80 | if(dot(z,z)>4.0) 81 | break; 82 | } 83 | 84 | return normalize(vec3(dot(z,dz[0]),dot(z,dz[1]),dot(z,dz[2]))); 85 | } 86 | 87 | 88 | void main(void) 89 | { 90 | vec2 p = -1.0 + 2.0 * gl_FragCoord.xy / resolution.xy; 91 | vec3 color = vec3(0.0); 92 | vec4 cccc = vec4( .7*cos(.5*time), .7*sin(.3*time), .7*cos(1.0*time), 0.0 ); 93 | vec3 edir = normalize(vec3(p,1.0)); 94 | vec3 wori = vec3(0.0,0.0,-2.0); 95 | 96 | float ao; 97 | float t = jinteresct(wori,edir,cccc,ao); 98 | if(t<100.0) 99 | { 100 | vec3 inter = wori + t*edir; 101 | vec3 nor = calcNormal(inter,cccc); 102 | 103 | float dif = .5 + .5*dot( nor, vec3(0.57703) ); 104 | ao = max( 1.0-ao*0.005, 0.0 ); 105 | 106 | color = vec3(1.0,.9,.5)*dif*ao + .5*vec3(.6,.7,.8)*ao; 107 | } 108 | else 109 | { 110 | color = vec3(0.5,0.51,0.52)+vec3(0.5,0.47,0.45)*p.y; 111 | } 112 | 113 | gl_FragColor = vec4(color,1.0); 114 | } 115 | -------------------------------------------------------------------------------- /examples/shadertoy/presets/red.fs: -------------------------------------------------------------------------------- 1 | #ifdef GL_ES 2 | precision highp float; 3 | #endif 4 | 5 | uniform float time; 6 | uniform vec2 resolution; 7 | 8 | float j, k, g=acos(-1.0), h= sqrt( 0.75 ), expand; 9 | 10 | 11 | vec2 r(vec2 v,float y) 12 | { 13 | return cos(y)*v+sin(y)*vec2(-v.y,v.x); 14 | } 15 | 16 | void s(inout vec2 v,float x, float y) 17 | { 18 | float z=mod(atan(v.y,v.x),y)-y*.5; 19 | v=(length(v))*vec2(cos(z),sin(z)); 20 | v.x-=x; 21 | } 22 | 23 | float l(vec3 p,float f) 24 | { 25 | return length(vec2(length(p.xz) - f,p.y)); 26 | } 27 | 28 | float i( vec2 p, float y, float z ) 29 | { 30 | return length( max( abs(p) - vec2(y) + vec2(z), 0.0 ) ) - z; 31 | } 32 | 33 | float u( vec3 p ) 34 | { 35 | return fract( sin( p.x * 151.0 + p.y * 33.0 + p.z ) * 11.0 ); 36 | } 37 | 38 | float w(vec3 p) 39 | { 40 | vec2 e = vec2(1.0, 0.0); 41 | vec3 o= smoothstep(0.0,1.0,fract( p )); 42 | p= floor( p ); 43 | 44 | vec4 n= mix( 45 | vec4( 46 | u( p+e.yyy),//n000, 47 | u( p+e.xyy),//n100, 48 | u( p+e.yxy),//n010, 49 | u( p+e.xxy)),//n110), 50 | vec4( 51 | u( p+e.yyx),//n001, 52 | u( p+e.xyx),//n101, 53 | u( p+e.yxx),//n011, 54 | u( p+e.xxx)),//n111), 55 | o.z); 56 | e = mix(n.xy, n.zw, o.y); 57 | return mix(e.x, e.y, o.x); 58 | } 59 | 60 | float A(vec3 p) 61 | { 62 | vec3 o= p; 63 | p.x= mod( p.x + step( 2.0 * h, mod( p.y, 4.0 * h ) ), 2.0 ) - 1.0; 64 | p.y= mod( p.y, 2.0 * h )- h; 65 | 66 | o-= p; 67 | p.z-= (k == 10.0 ? 0.0 : 44.0) + 2.0 * smoothstep( -0.3, 0.3, cos( o.x * 0.03 + cos( o.y * 0.03 ) + j * 4.0 ) * cos( o.y * 0.01 + cos( o.x * 0.02 ) ) ); 68 | float z= length( p )- 1.5; 69 | s( p.xy, 0.7, g/3.0); 70 | return max( z, p.x ); 71 | } 72 | 73 | float B(vec3 p) 74 | { 75 | 76 | return length( p+vec3(sin( j* 3.0) * 22.0,j * 11.0,-22.0))- 22.0; 77 | } 78 | 79 | float C(vec3 p) 80 | { 81 | vec3 o= p; 82 | p.x= mod( p.x + step( 2.0 * h, mod( p.y, 4.0 * h ) ), 2.0 ) - 1.0; 83 | p.y= mod( p.y, 2.0 * h )- h; 84 | 85 | return max( abs( p.z + 1.0 ) - 0.2, h - length( p.xy ) ); 86 | } 87 | 88 | float D(vec3 p) 89 | { 90 | return length( p-vec3(22.0,22.0,-14.0))- expand * 33.0 - 12.0; 91 | } 92 | 93 | float f(vec3 p) 94 | { 95 | float z= min( min( A(p), B(p) ), C(p) ); 96 | return max(length(p) - 77.0, min( z, max( 0.5 - z, D(p) ) ) ); 97 | } 98 | 99 | void main() 100 | { 101 | float CurTime= mod( time, 60.0 ); 102 | j= CurTime / 12.0; 103 | 104 | vec3 q = vec3((gl_FragCoord.xy / resolution.xy - 0.5), 1.0); 105 | 106 | vec3 p; 107 | k= 0.0; 108 | if( j < 1.0 ) 109 | { 110 | expand= 0.0; 111 | k= 10.0; 112 | p= vec3( 33.0, 33.0, -11.0 + j * 5.0); 113 | q.yz= r( q.yz, 0.8 - j ); 114 | q.xz= r( q.xz, 0.5 + j ); 115 | } 116 | else if( j < 2.0 ) 117 | { 118 | j-= 1.0; 119 | expand= j*j; 120 | p= vec3(-11.0, -11.0, -11.0); 121 | q.yz= r( q.yz, -j * 0.7 ); 122 | q.xz= r( q.xz, -j ); 123 | } 124 | else if( j < 3.0 ) 125 | { 126 | j-= 2.0; 127 | expand= j*j; 128 | p= vec3(33.0, 11.0, 33.0); 129 | q.yz= r( q.yz, j * 0.4 ); 130 | q.xz= r( q.xz, 1.2 + j * 0.6); 131 | } 132 | else 133 | { 134 | j= ( j - 3.0 ) * 0.5; 135 | expand= j*j * 2.0; 136 | p= vec3( mix( 22.0 - 88.0 * expand, -44.0 * j, j), 22.0, 6.0 ); 137 | q.yz= r( q.yz, j * 0.2 ); 138 | q.xz= r( q.xz, 3.4 + sqrt(j) * 1.4 ); 139 | } 140 | 141 | q = normalize(q); 142 | 143 | vec3 b= vec3( .0,.0,.0 ); 144 | float a=1.0; 145 | 146 | float t=w( q*666.0 )*0.5,y,z,d; 147 | float m= 0.0; 148 | 149 | for(int mm= 0; mm < 2; ++mm) 150 | { 151 | for( int tt= 0; tt < 256; ++tt ) 152 | { 153 | d = f(p+q*t); 154 | t+=max( 0.01, d+0.01); 155 | if( !(t<66.0 && d>t*.003) ) 156 | { 157 | break; 158 | } 159 | } 160 | 161 | if( t > 66.0 ) 162 | { 163 | break; 164 | } 165 | 166 | m+= 1.0; 167 | 168 | p+= q*t; 169 | 170 | vec2 e = vec2(0.04, 0.0); 171 | vec3 n= vec3( f(p + e.xyy) - f(p - e.xyy), f(p + e.yxy) - f(p - e.yxy), f(p + e.yyx) - f(p - e.yyx) ); 172 | n= normalize(n); 173 | 174 | z= A(p); 175 | 176 | vec3 c = vec3(0.8,.0,.0 ); 177 | d= .15; 178 | 179 | if( z > D(p) ) 180 | { 181 | z= D(p); 182 | c = vec3(1.0,0.0,0.0 ); 183 | d= .15; 184 | } 185 | if( z > B(p) ) 186 | { 187 | z= B(p); 188 | c = vec3(0.05,.1,.2 ); 189 | d= .7; 190 | e.y= 0.3; 191 | } 192 | if( z > C(p) ) 193 | { 194 | z= C(p); 195 | c = vec3(0.0,0.6,0.8 ) * (0.9 - 0.15 / clamp(dot( n, q ), -1.0, -0.05)); 196 | d= .2; 197 | e.y= 2.0; 198 | } 199 | 200 | n+= (w( p * e.y ) + w( p * e.y * 2.0 ) + w( p * e.y * 4.0 )) * e.x; 201 | n= normalize(n); 202 | q= reflect( q, n ); 203 | 204 | z= 1.0; 205 | for (float yy=6.0;yy>0.;yy--) 206 | { 207 | z-=(yy*.5-f(p+n*yy*.5))/exp2(yy); 208 | } 209 | c*= z; 210 | 211 | n.yz= r( n.yz, 0.6 ); 212 | 213 | c*= .4 + .3 * ( 1.0 - abs( n.y - .9 ) ); 214 | 215 | 216 | b+= a*c; 217 | a*= d; 218 | t= 0.3; 219 | } 220 | 221 | q.yz= r( q.yz, 0.6 ); 222 | p=vec3(0.7 + q.y * 0.2); 223 | if( m < 1.0 ) 224 | { 225 | p*= vec3( 0.95, 1.1, 1.2); 226 | } 227 | 228 | if( q.y > 0.0 ) 229 | { 230 | s(q.xz, 0.4, g/8.0); 231 | q.x= abs( q.x ) - .2; 232 | p+= pow( smoothstep(.2, .0, mix( abs(q.z),length(q.xz), step(0.0, q.x) ) ), 22.0 ); 233 | } 234 | 235 | gl_FragColor.xyz = b + a*p; 236 | } 237 | -------------------------------------------------------------------------------- /examples/shadertoy/presets/shapes.fs: -------------------------------------------------------------------------------- 1 | #ifdef GL_ES 2 | precision highp float; 3 | #endif 4 | 5 | 6 | uniform vec2 resolution; 7 | uniform float time; 8 | 9 | float segm( float a, float b, float c, float x ) 10 | { 11 | return smoothstep(a-c,a,x) - smoothstep(b,b+c,x); 12 | } 13 | 14 | vec3 clover( float x, float y ) 15 | { 16 | float a = atan(x,y); 17 | float r = sqrt(x*x+y*y); 18 | float s = 0.5 + 0.5*sin(3.0*a + time); 19 | float g = sin(1.57+3.0*a+time); 20 | float d = 0.3 + 0.6*sqrt(s) + 0.15*g*g; 21 | float h = r/d; 22 | float f = 1.0-smoothstep( 0.95, 1.0, h ); 23 | h *= 1.0-0.5*(1.0-h)*smoothstep(0.95+0.05*h,1.0,sin(3.0*a+time)); 24 | return mix( vec3(1.0), vec3(0.4*h,0.2+0.3*h,0.0), f ); 25 | } 26 | 27 | vec3 heart( float x, float y ) 28 | { 29 | float s = mod( time, 2.0 )/2.0; 30 | s = 0.9 + 0.1*(1.0-exp(-5.0*s)*sin(50.0*s)); 31 | x *= s; 32 | y *= s; 33 | float a = atan(x,y)/3.141593; 34 | float r = sqrt(x*x+y*y); 35 | 36 | float h = abs(a); 37 | float d = (13.0*h - 22.0*h*h + 10.0*h*h*h)/(6.0-5.0*h); 38 | 39 | float f = smoothstep(d-0.02,d,r); 40 | float g = pow(1.0-clamp(r/d,0.0,1.0),0.25); 41 | return mix(vec3(0.5+0.5*g,0.2,0.1),vec3(1.0),f); 42 | } 43 | 44 | vec3 yinyan( float x, float y ) 45 | { 46 | float nx = x; 47 | float ny = y; 48 | x = 1.5*(nx*cos(0.2*time) - ny*sin(0.2*time)); 49 | y = 1.5*(nx*sin(0.2*time) + ny*cos(0.2*time)); 50 | float h = x*x + y*y; 51 | float d = abs(y)-h; 52 | float a = d-0.23; 53 | float b = h-1.00; 54 | float c = sign(a*b*(y+x + (y-x)*sign(d))); 55 | 56 | c = mix( c, 0.0, smoothstep(0.98,1.00,h) ); 57 | c = mix( c, 1.0, smoothstep(1.00,1.02,h) ); 58 | return vec3(c); 59 | } 60 | 61 | vec3 sun( float x, float y ) 62 | { 63 | float a = atan(x,y); 64 | float r = sqrt(x*x+y*y); 65 | 66 | float s = 0.5 + 0.5*sin(a*17.0+1.5*time); 67 | float d = 0.5 + 0.2*pow(s,1.0); 68 | float h = r/d; 69 | float f = 1.0-smoothstep(0.92,1.0,h); 70 | 71 | float b = pow(0.5 + 0.5*sin(3.0*time),500.0); 72 | vec2 e = vec2( abs(x)-0.15,(y-0.1)*(1.0+10.0*b) ); 73 | float g = 1.0 - (segm(0.06,0.09,0.01,length(e)))*step(0.0,e.y); 74 | 75 | float t = 0.5 + 0.5*sin(12.0*time); 76 | vec2 m = vec2( x, (y+0.15)*(1.0+10.0*t) ); 77 | g *= 1.0 - (segm(0.06,0.09,0.01,length(m))); 78 | 79 | return mix(vec3(1.0),vec3(0.9,0.8,0.0)*g,f); 80 | } 81 | 82 | void main(void) 83 | { 84 | vec2 p = (-1.0+2.0*gl_FragCoord.xy/resolution.xy); 85 | 86 | vec3 col = yinyan(1.0+2.0*p.x,1.0+2.0*p.y); 87 | col *= heart( -1.0+2.0*p.x, 1.0+2.0*p.y ); 88 | col *= sun( -1.0+2.0*p.x, -1.0+2.0*p.y ); 89 | col *= clover( 1.0+2.0*p.x, -1.0+2.0*p.y ); 90 | gl_FragColor = vec4(col,1.0); 91 | 92 | } 93 | -------------------------------------------------------------------------------- /examples/shadertoy/presets/square_tunnel.fs: -------------------------------------------------------------------------------- 1 | #ifdef GL_ES 2 | precision highp float; 3 | #endif 4 | 5 | uniform vec2 resolution; 6 | uniform float time; 7 | uniform sampler2D tex0; 8 | uniform sampler2D tex1; 9 | 10 | void main(void) 11 | { 12 | vec2 p = -1.0 + 2.0 * gl_FragCoord.xy / resolution.xy; 13 | vec2 uv; 14 | 15 | float r = pow( pow(p.x*p.x,16.0) + pow(p.y*p.y,16.0), 1.0/32.0 ); 16 | uv.x = .5*time + 0.5/r; 17 | uv.y = 1.0*atan(p.y,p.x)/3.1416; 18 | 19 | vec3 col = texture2D(tex0,uv).xyz; 20 | 21 | gl_FragColor = vec4(col*r*r*r,1.0); 22 | } 23 | -------------------------------------------------------------------------------- /examples/shadertoy/presets/sult.fs: -------------------------------------------------------------------------------- 1 | #ifdef GL_ES 2 | precision highp float; 3 | #endif 4 | 5 | // Scene from Sult by Loonies 6 | // Exclusive source release for ShaderToy 7 | // Blame the scene chosen on iq ;) 8 | // Feel free to be inspired, but please mention it (.readme) then :) 9 | // -Psycho/Loonies 10 | 11 | // Actual, ugly, size optimized 4k version with minimal changes for ShaderToy 12 | // but before auto-obfuscation (whitespaces, comments, variable names) 13 | 14 | // Inputs changed into more readable constants: 15 | float shaderparm=5.0, fov=.9, pitch=0.0, heading=90.0, dheading=0.0; 16 | vec3 lightdir=vec3(1,1,1), position=vec3(0,0,1), speed=vec3(0,0,1.5); 17 | 18 | // constants for the other worm tunnel part: 19 | //float shaderparm=8, fov=.8, pitch=0, heading=-90, dheading=0; 20 | //vec3 lightdir=vec3(1,1,1), position=vec3(0,0,0), speed=vec3(0,0,0); 21 | 22 | // shadertoy input 23 | uniform vec2 resolution; 24 | uniform float time; 25 | 26 | 27 | vec3 rotatey(vec3 r, float v) 28 | { return vec3(r.x*cos(v)+r.z*sin(v),r.y,r.z*cos(v)-r.x*sin(v)); 29 | } 30 | vec3 rotatex(vec3 r, float v) 31 | { return vec3(r.y*cos(v)+r.z*sin(v),r.x,r.z*cos(v)-r.y*sin(v)); 32 | } 33 | float mat=0.0, tmax=10.0; 34 | float eval(vec3 p) 35 | { 36 | ////// this is the (only) part that changes for the scenes in Sult 37 | float t = time,r,c=0.0,g,r2,r3; 38 | vec3 pp; 39 | p += ( sin(p.zxy*1.7+t)+sin(p.yzx+t*3.) )*.2; 40 | if (shaderparm<6.0) 41 | c = length(p.xyz*vec3(1,1,.1)-vec3(0,-.1,t*.15-.3))-.34; 42 | else 43 | c = length(p.xy+vec2(.0,.7))-.3+ (sin(p.z*17.0+t*.6)+sin(p.z*2.0)*6.0)*.01; 44 | 45 | p.xy = vec2( atan(p.x,p.y)*1.113, 1.6-length(p.xy)-sin(t*2.0)*.3); 46 | pp = fract(p.xzz+.5).xyz -.5; pp.y=(p.y-.35)*1.3; 47 | r = max( abs(p.y-.3)-.05, abs(length(fract(p.xz)-.5)-.4)-.03); 48 | mat = step(c,r); 49 | return min(min(r,c),p.y-.2); 50 | } 51 | vec3 diffdark= vec3(.19,.2,.24), difflight=vec3(1), 52 | diffrefl= vec3(.45,.01,0), background=vec3(.17,0,0); 53 | ////////// 54 | 55 | 56 | void main(void) 57 | { 58 | vec2 p = -1.0 + 2.0 * gl_FragCoord.xy / resolution.xy; 59 | vec3 vdir= normalize( 60 | rotatey(rotatey(vec3(p.y*fov,p.x*fov*1.33,1), 61 | -pitch*.035).yxz,(heading+dheading*time)*.035)), 62 | vpos= position + speed*time; 63 | 64 | float cf=1.0,rf=0.0,t,stp,tmin=0.0,c,r,m,d; 65 | vec3 e=vec3(.01,0,0),cx=e.yyy,n; 66 | while (cf>.1) 67 | { 68 | for (t=tmin,stp=1.0;t.005;t+=stp) 69 | stp = eval(vpos+vdir*t); 70 | if (t 0) { 237 | mMousePosX = ev.pageX; 238 | mMousePosY = ev.pageY; 239 | } 240 | }); 241 | document.on("mouseup", function(ev) { 242 | mMouseOriX = -1; 243 | mMouseOriY = -1; 244 | }); 245 | 246 | var presets=__dirname+ '/presets/'; 247 | //mEffect.NewShader(require('fs').readFileSync(presets+ 'deform.fs','utf8')); 248 | //mEffect.NewTexture(0, presets+ 'tex3.jpg') 249 | 250 | //mEffect.NewShader(require('fs').readFileSync(presets+ 'water.fs','utf8')); 251 | //mEffect.NewTexture(0, presets+ 'tex0.jpg') 252 | 253 | //mEffect.NewShader(require('fs').readFileSync(presets+ 'mandelbulb.fs','utf8')); 254 | 255 | //mEffect.NewShader(require('fs').readFileSync(presets+ 'landscape.fs','utf8')); 256 | 257 | //mEffect.NewShader(require('fs').readFileSync(presets+ 'clod.fs','utf8')); 258 | 259 | //mEffect.NewShader(require('fs').readFileSync(presets+ 'droid.fs','utf8')); 260 | 261 | //mEffect.NewShader(require('fs').readFileSync(presets+ 'slisesix.fs','utf8')); 262 | 263 | //mEffect.NewShader(require('fs').readFileSync(presets+ 'square_tunnel.fs','utf8')); 264 | //mEffect.NewTexture(0, presets+ 'tex0.jpg') 265 | 266 | mEffect.NewShader(require('fs').readFileSync(presets+ '704.fs','utf8')); 267 | 268 | //mEffect.NewShader(require('fs').readFileSync(presets+ 'earth.fs','utf8')); 269 | //mEffect.NewTexture(0, presets+ 'earth_day.jpg') 270 | 271 | //mEffect.NewShader(require('fs').readFileSync(presets+ 'sult.fs','utf8')); 272 | 273 | //mEffect.NewShader(require('fs').readFileSync(presets+ 'kinderpainter.fs','utf8')); 274 | //mEffect.NewTexture(0, presets+ 'tex0.jpg') 275 | 276 | //mEffect.NewShader(require('fs').readFileSync(presets+ 'red.fs','utf8')); 277 | 278 | //mEffect.NewShader(require('fs').readFileSync(presets+ 'quaternion.fs','utf8')); 279 | 280 | //mEffect.NewShader(require('fs').readFileSync(presets+ 'lunaquatic.fs','utf8')); 281 | 282 | //mEffect.NewShader(require('fs').readFileSync(presets+ 'metatunnel.fs','utf8')); 283 | 284 | //mEffect.NewShader(require('fs').readFileSync(presets+ 'leizex.fs','utf8')); 285 | 286 | //mEffect.NewShader(require('fs').readFileSync(presets+ 'mandel.fs','utf8')); 287 | 288 | //mEffect.NewShader(require('fs').readFileSync(presets+ 'julia.fs','utf8')); 289 | 290 | //mEffect.NewShader(require('fs').readFileSync(presets+ 'shapes.fs','utf8')); 291 | 292 | //mEffect.NewShader(require('fs').readFileSync(presets+ 'apple.fs','utf8')); 293 | 294 | render(); 295 | } 296 | 297 | -------------------------------------------------------------------------------- /examples/tunnel/glUtils.js: -------------------------------------------------------------------------------- 1 | // augment Sylvester some 2 | Matrix.Translation = function (v) 3 | { 4 | if (v.elements.length == 2) { 5 | var r = Matrix.I(3); 6 | r.elements[2][0] = v.elements[0]; 7 | r.elements[2][1] = v.elements[1]; 8 | return r; 9 | } 10 | 11 | if (v.elements.length == 3) { 12 | var r = Matrix.I(4); 13 | r.elements[0][3] = v.elements[0]; 14 | r.elements[1][3] = v.elements[1]; 15 | r.elements[2][3] = v.elements[2]; 16 | return r; 17 | } 18 | 19 | throw "Invalid length for Translation"; 20 | } 21 | 22 | Matrix.prototype.flatten = function () 23 | { 24 | var result = []; 25 | if (this.elements.length == 0) 26 | return []; 27 | 28 | 29 | for (var j = 0; j < this.elements[0].length; j++) 30 | for (var i = 0; i < this.elements.length; i++) 31 | result.push(this.elements[i][j]); 32 | return result; 33 | } 34 | 35 | Matrix.prototype.ensure4x4 = function() 36 | { 37 | if (this.elements.length == 4 && 38 | this.elements[0].length == 4) 39 | return this; 40 | 41 | if (this.elements.length > 4 || 42 | this.elements[0].length > 4) 43 | return null; 44 | 45 | for (var i = 0; i < this.elements.length; i++) { 46 | for (var j = this.elements[i].length; j < 4; j++) { 47 | if (i == j) 48 | this.elements[i].push(1); 49 | else 50 | this.elements[i].push(0); 51 | } 52 | } 53 | 54 | for (var i = this.elements.length; i < 4; i++) { 55 | if (i == 0) 56 | this.elements.push([1, 0, 0, 0]); 57 | else if (i == 1) 58 | this.elements.push([0, 1, 0, 0]); 59 | else if (i == 2) 60 | this.elements.push([0, 0, 1, 0]); 61 | else if (i == 3) 62 | this.elements.push([0, 0, 0, 1]); 63 | } 64 | 65 | return this; 66 | }; 67 | 68 | Matrix.prototype.make3x3 = function() 69 | { 70 | if (this.elements.length != 4 || 71 | this.elements[0].length != 4) 72 | return null; 73 | 74 | return Matrix.create([[this.elements[0][0], this.elements[0][1], this.elements[0][2]], 75 | [this.elements[1][0], this.elements[1][1], this.elements[1][2]], 76 | [this.elements[2][0], this.elements[2][1], this.elements[2][2]]]); 77 | }; 78 | 79 | Vector.prototype.flatten = function () 80 | { 81 | return this.elements; 82 | }; 83 | 84 | function mht(m) { 85 | var s = ""; 86 | if (m.length == 16) { 87 | for (var i = 0; i < 4; i++) { 88 | s += "[" + m[i*4+0].toFixed(4) + "," + m[i*4+1].toFixed(4) + "," + m[i*4+2].toFixed(4) + "," + m[i*4+3].toFixed(4) + "]
"; 89 | } 90 | } else if (m.length == 9) { 91 | for (var i = 0; i < 3; i++) { 92 | s += "[" + m[i*3+0].toFixed(4) + "," + m[i*3+1].toFixed(4) + "," + m[i*3+2].toFixed(4) + "]
"; 93 | } 94 | } else { 95 | return m.toString(); 96 | } 97 | return s; 98 | } 99 | 100 | // 101 | // gluLookAt 102 | // 103 | function makeLookAt(ex, ey, ez, 104 | cx, cy, cz, 105 | ux, uy, uz) 106 | { 107 | var eye = $V([ex, ey, ez]); 108 | var center = $V([cx, cy, cz]); 109 | var up = $V([ux, uy, uz]); 110 | 111 | var mag; 112 | 113 | var z = eye.subtract(center).toUnitVector(); 114 | var x = up.cross(z).toUnitVector(); 115 | var y = z.cross(x).toUnitVector(); 116 | 117 | var m = $M([[x.e(1), x.e(2), x.e(3), 0], 118 | [y.e(1), y.e(2), y.e(3), 0], 119 | [z.e(1), z.e(2), z.e(3), 0], 120 | [0, 0, 0, 1]]); 121 | 122 | var t = $M([[1, 0, 0, -ex], 123 | [0, 1, 0, -ey], 124 | [0, 0, 1, -ez], 125 | [0, 0, 0, 1]]); 126 | return m.x(t); 127 | } 128 | 129 | // 130 | // gluPerspective 131 | // 132 | function makePerspective(fovy, aspect, znear, zfar) 133 | { 134 | var ymax = znear * Math.tan(fovy * Math.PI / 360.0); 135 | var ymin = -ymax; 136 | var xmin = ymin * aspect; 137 | var xmax = ymax * aspect; 138 | 139 | return makeFrustum(xmin, xmax, ymin, ymax, znear, zfar); 140 | } 141 | 142 | // 143 | // glFrustum 144 | // 145 | function makeFrustum(left, right, 146 | bottom, top, 147 | znear, zfar) 148 | { 149 | var X = 2*znear/(right-left); 150 | var Y = 2*znear/(top-bottom); 151 | var A = (right+left)/(right-left); 152 | var B = (top+bottom)/(top-bottom); 153 | var C = -(zfar+znear)/(zfar-znear); 154 | var D = -2*zfar*znear/(zfar-znear); 155 | 156 | return $M([[X, 0, A, 0], 157 | [0, Y, B, 0], 158 | [0, 0, C, D], 159 | [0, 0, -1, 0]]); 160 | } 161 | 162 | // 163 | // glOrtho 164 | // 165 | function makeOrtho(left, right, bottom, top, znear, zfar) 166 | { 167 | var tx = - (right + left) / (right - left); 168 | var ty = - (top + bottom) / (top - bottom); 169 | var tz = - (zfar + znear) / (zfar - znear); 170 | 171 | return $M([[2 / (right - left), 0, 0, tx], 172 | [0, 2 / (top - bottom), 0, ty], 173 | [0, 0, -2 / (zfar - znear), tz], 174 | [0, 0, 0, 1]]); 175 | } 176 | -------------------------------------------------------------------------------- /examples/tunnel/texture.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikeseven/node-webgl/a918e74acc7860db1bb63029934e8f54a2730ce2/examples/tunnel/texture.jpg -------------------------------------------------------------------------------- /examples/wavefront_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikeseven/node-webgl/a918e74acc7860db1bb63029934e8f54a2730ce2/examples/wavefront_icon.png -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | webgl: require('./lib/webgl'), 3 | Image: require('./lib/image'), 4 | document: require('./lib/platform_glfw') 5 | //document: require('./lib/platform_sdl') 6 | //document: require('./lib/platform_sfml') 7 | }; -------------------------------------------------------------------------------- /lib/image.js: -------------------------------------------------------------------------------- 1 | // javascript shim that lets our object inherit from EventEmitter 2 | var Image = module.exports = require('bindings')('webgl').Image; 3 | var events = require('events'); 4 | 5 | 6 | Object.defineProperty(Image.prototype, 'onload', { 7 | set: function(callback) { 8 | this.on('load', callback); 9 | }, 10 | }); 11 | 12 | inherits(Image, events.EventEmitter); 13 | 14 | // extend prototype 15 | function inherits(target, source) { 16 | for (var k in source.prototype) 17 | target.prototype[k] = source.prototype[k]; 18 | } 19 | -------------------------------------------------------------------------------- /lib/platform_glfw.js: -------------------------------------------------------------------------------- 1 | var GLFW = require('node-glfw'); 2 | var WebGL = require('./webgl'); 3 | 4 | module.exports = function () { 5 | 6 | if (process.platform !== 'win32') 7 | process.on('SIGINT', function () { process.exit(0); }); 8 | //process.on('exit', function () { console.log('exiting app'); }); 9 | 10 | var platform; 11 | var window; 12 | 13 | var events; 14 | Object.defineProperty(GLFW, 'events', { 15 | get: function () { 16 | if (events) return events; 17 | events = new (require('events').EventEmitter); 18 | 19 | var _emit=events.emit; 20 | events.emit=function() { 21 | var args = Array.prototype.slice.call(arguments); 22 | var evt= args[1]; // args[1] is the event, args[0] is the type of event 23 | //console.log("emitting event: "+require('util').inspect(args)); 24 | if(args[0] != 'quit') { 25 | evt.preventDefault = function () {}; 26 | evt.stopPropagation = function () {}; 27 | } 28 | //_emit.apply(this,args); 29 | events.listeners(args[0]).forEach(function(listener) { 30 | listener(args[1]); 31 | }); 32 | }; 33 | return events; 34 | }, 35 | // enumerable: true, 36 | // configurable: true 37 | }); 38 | 39 | GLFW.Init(); 40 | // GLFW.events.on('event', console.dir); 41 | GLFW.events.on('quit', function () { process.exit(0); }); 42 | GLFW.events.on("keydown", function (evt) { 43 | if (evt.keyCode === 'C'.charCodeAt(0) && evt.ctrlKey) { process.exit(0); }// Control+C 44 | if (evt.keyCode === 27) process.exit(0); // ESC 45 | }); 46 | 47 | platform = { 48 | type: "nodeGLFW", 49 | ratio: 1, // ratio between window and framebuffer, normally 1 except on screens like Mac Retina 50 | setTitle: function(title) { 51 | GLFW.SetWindowTitle(window, title); 52 | }, 53 | setIcon: function () { }, 54 | flip: function() { 55 | GLFW.SwapBuffers(window); 56 | }, 57 | getElementById: function (name) { 58 | return this.createElement(name); 59 | }, 60 | createElement: function (name, width, height) { 61 | if (name.toLowerCase().indexOf('canvas') >= 0) { 62 | this.createWindow(width || 800, height || 800); 63 | this.canvas = this; 64 | WebGL.canvas = this; 65 | return this; 66 | } 67 | return null; 68 | }, 69 | createWindow: function (width, height) { 70 | var attribs = GLFW.WINDOW; 71 | 72 | if (width == 0 || height == 0) { 73 | attribs = GLFW.FULLSCREEN; 74 | width = height = 0; 75 | } 76 | 77 | var resizeListeners = [], rl = GLFW.events.listeners("framebuffer_resize"); 78 | for (var l = 0, ln = rl.length; l < ln; ++l) 79 | resizeListeners[l] = rl[l]; 80 | GLFW.events.removeAllListeners("framebuffer_resize"); 81 | 82 | GLFW.DefaultWindowHints(); 83 | 84 | // we use OpenGL 2.1, GLSL 1.20. Comment this for now as this is for GLSL 1.50 85 | //GLFW.OpenWindowHint(GLFW.OPENGL_FORWARD_COMPAT, 1); 86 | //GLFW.OpenWindowHint(GLFW.OPENGL_VERSION_MAJOR, 3); 87 | //GLFW.OpenWindowHint(GLFW.OPENGL_VERSION_MINOR, 2); 88 | //GLFW.OpenWindowHint(GLFW.OPENGL_PROFILE, GLFW.OPENGL_CORE_PROFILE); 89 | GLFW.WindowHint(GLFW.RESIZABLE, 1); 90 | GLFW.WindowHint(GLFW.VISIBLE, 1); 91 | GLFW.WindowHint(GLFW.DECORATED, 1); 92 | GLFW.WindowHint(GLFW.RED_BITS, 8); 93 | GLFW.WindowHint(GLFW.GREEN_BITS, 8); 94 | GLFW.WindowHint(GLFW.BLUE_BITS, 8); 95 | GLFW.WindowHint(GLFW.DEPTH_BITS, 24); 96 | GLFW.WindowHint(GLFW.REFRESH_RATE, 0); 97 | 98 | if (!(window=GLFW.CreateWindow(width, height))) { 99 | GLFW.Terminate(); 100 | throw "Can't initialize GL surface"; 101 | } 102 | 103 | GLFW.MakeContextCurrent(window); 104 | 105 | GLFW.SetWindowTitle(window, "WebGL"); 106 | 107 | // make sure GLEW is initialized 108 | WebGL.Init(); 109 | 110 | GLFW.SwapBuffers(window); 111 | GLFW.SwapInterval(0); // Disable VSync (we want to get as high FPS as possible!) 112 | 113 | for (var l = 0, ln = resizeListeners.length; l < ln; ++l) 114 | GLFW.events.addListener("framebuffer_resize", resizeListeners[l]); 115 | 116 | var sizeWin = GLFW.GetWindowSize(window); 117 | var sizeFB = GLFW.GetFramebufferSize(window); 118 | this.ratio=sizeFB.width / sizeWin.width; 119 | this.width = this.drawingBufferWidth = sizeFB.width; 120 | this.height = this.drawingBufferHeight = sizeFB.height; 121 | }, 122 | getContext: function (name) { 123 | return WebGL; 124 | }, 125 | on: function (name, callback) { 126 | this.addEventListener(name,callback); 127 | }, 128 | addEventListener: function (name, callback) { 129 | if (callback && typeof(callback) === "function") { 130 | if(name=="resize") { 131 | name="framebuffer_resize"; 132 | var tmpcb=callback; 133 | var self=callback.this; 134 | callback=function (evt) { 135 | platform.width=evt.width; 136 | platform.height=evt.height; 137 | tmpcb.call(self,evt); 138 | } 139 | } 140 | else if(name=="mousemove" || name=="mousedown" || name=="mouseup") { 141 | var tmpcb=callback; 142 | var self=callback.this; 143 | callback=function (evt) { 144 | evt.x *= platform.ratio; 145 | evt.y *= platform.ratio; 146 | tmpcb.call(self,evt); 147 | } 148 | } 149 | GLFW.events.on(name, callback); 150 | } 151 | }, 152 | removeEventListener: function (name, callback) { 153 | if (callback && typeof(callback) === "function") { 154 | if(name=="resize") 155 | name="framebuffer_resize"; 156 | GLFW.events.removeListener(name, callback); 157 | } 158 | }, 159 | requestAnimationFrame: function (callback, delay) { 160 | GLFW.SwapBuffers(window); 161 | GLFW.PollEvents(); 162 | 163 | var timer = setImmediate;//process.nextTick; 164 | var d = 16; 165 | if (delay == undefined || delay > 0) { 166 | timer = setTimeout; 167 | d = delay; 168 | } 169 | timer(function () { 170 | callback(GLFW.GetTime()*1000.0); 171 | }, d); 172 | } 173 | }; 174 | 175 | Object.defineProperty(platform, 'AntTweakBar', { 176 | get: function (cb) { 177 | return new GLFW.AntTweakBar(); 178 | } 179 | }); 180 | 181 | Object.defineProperty(platform, 'onkeydown', { 182 | set: function (cb) { 183 | this.on('keydown', cb); 184 | } 185 | }); 186 | 187 | Object.defineProperty(platform, 'onkeyup', { 188 | set: function (cb) { 189 | this.on('keyup', cb); 190 | } 191 | }); 192 | 193 | return platform; 194 | }; 195 | 196 | -------------------------------------------------------------------------------- /lib/platform_sdl.js: -------------------------------------------------------------------------------- 1 | var SDL = require('node-sdl'); 2 | var WebGL = require('./webgl'); 3 | 4 | module.exports = function () { 5 | 6 | process.on('SIGINT', function () { process.exit(0); }); 7 | 8 | SDL.init(SDL.INIT.VIDEO); 9 | // SDL.events.on('event', console.dir); 10 | SDL.events.on('QUIT', function () { process.exit(0); }); 11 | SDL.events.on("KEYDOWN", function (evt) { 12 | if (evt.sym === 99 && evt.mod === 64) process.exit(0); // Control+C 13 | if (evt.sym === 27) process.exit(0); // ESC 14 | }); 15 | var platform = { 16 | type: "nodeSDL", 17 | loadTexture: loadTexture, 18 | setTitle: setTitle, 19 | setIcon: setIcon, 20 | flip: SDL.GL.swapBuffers, 21 | getElementById: function(name) { 22 | return this; 23 | }, 24 | createWindow: function(width, height) { 25 | SDL.GL.setAttribute(SDL.GL.DOUBLEBUFFER, 1); 26 | 27 | var attribs=SDL.SURFACE.OPENGL; 28 | 29 | if(width==0 || height==0) { 30 | attribs |= SDL.SURFACE.FULLSCREEN; 31 | width=height=0; 32 | } 33 | else 34 | attribs |= SDL.SURFACE.RESIZABLE; 35 | 36 | var screen = SDL.setVideoMode(width, height, 0, attribs); 37 | this.width = screen.w; this.height = screen.h; 38 | WebGL.viewport(0, 0, screen.w, screen.h); 39 | }, 40 | getContext: function(name) { 41 | return WebGL; 42 | }, 43 | on: function (name, callback) { 44 | if (name === "mousemove") name = "MOUSEMOTION"; 45 | SDL.events.on(name, callback); 46 | }, 47 | requestAnimationFrame: function (callback, delay) { 48 | SDL.GL.swapBuffers(); 49 | var timer= (delay==0) ? process.nextTick : setTimeout; 50 | var d= (delay==undefined || delay<0) ? 16 : delay; 51 | timer(function(){ 52 | callback(new Date().getTime()); 53 | }, d); 54 | } 55 | }; 56 | 57 | return platform; 58 | 59 | function loadTexture(path, callback) { 60 | var gl = WebGL; 61 | try { 62 | // TODO: Get actual image from SDL and convert it 63 | var gltexture = gl.createTexture(); 64 | gl.bindTexture(gl.TEXTURE_2D, gltexture); 65 | gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, img); 66 | gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR); 67 | gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR); 68 | gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); 69 | gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); 70 | } catch(err) { 71 | return callback(err); 72 | } 73 | callback(null, gltexture); 74 | } 75 | 76 | function setTitle(title) { 77 | SDL.WM.setCaption(title, title); 78 | } 79 | 80 | function setIcon(path) { 81 | var img = SDL.IMG.load(path) 82 | SDL.WM.setIcon(img); 83 | } 84 | }; 85 | 86 | -------------------------------------------------------------------------------- /lib/platform_sfml.js: -------------------------------------------------------------------------------- 1 | var sfml = require('node-sfml'); 2 | var WebGL = require('./webgl'); 3 | var log=console.log; 4 | 5 | module.exports = function () { 6 | process.on('SIGINT', function () { process.exit(0); }); 7 | 8 | var window; 9 | var events; 10 | 11 | var platform = { 12 | type: "nodeSFML", 13 | setTitle: function(title) { 14 | if(window) 15 | window.SetTitle(title); 16 | }, 17 | setIcon: function(filename) { 18 | // TODO 19 | }, 20 | flip: function() { 21 | if(window) 22 | window.Display(); 23 | }, 24 | getElementById: function(name) { 25 | return null;//this; 26 | }, 27 | createElement: function(name, width, height) { 28 | if(name.indexOf('canvas')!=-1) { 29 | this.createWindow(width || 800, height || 800); 30 | this.canvas = this; 31 | WebGL.canvas = this; 32 | return this; 33 | } 34 | return null; 35 | }, 36 | createWindow : function(width, height) { 37 | window = new sfml.RenderWindow(new sfml.VideoMode(width, height, 32), 38 | "SFML window", sfml.Style.Default, new sfml.ContextSettings(24)); 39 | //window.EnableVerticalSync(0); 40 | log("OpenGL"); 41 | log(" vendor : "+WebGL.getParameter(WebGL.VENDOR)); 42 | log(" version : "+WebGL.getParameter(WebGL.VERSION)); 43 | log(" shading language version : "+WebGL.getParameter(WebGL.SHADING_LANGUAGE_VERSION)); 44 | log(" renderer : "+WebGL.getParameter(WebGL.RENDERER)); 45 | var self=this; 46 | 47 | Object.defineProperty(window, 'events', { 48 | get : function() { 49 | if (events) 50 | return events; 51 | events = new (require('events').EventEmitter); 52 | var now = Date.now(); 53 | setInterval(function() { 54 | var after = Date.now(); 55 | var delta = after - now; 56 | now = after; 57 | var evt; 58 | // console.log(require('util').inspect(this)) 59 | while (evt = window.PollEvent()) { 60 | evt.preventDefault = function () {}; 61 | evt.stopPropagation = function () {}; 62 | if(evt.type=='resize') { 63 | //console.log(require('util').inspect(evt)) 64 | self.width = self.drawingBufferWidth=evt.width; 65 | self.height = self.drawingBufferHeight=evt.height; 66 | } 67 | 68 | events.emit('event', evt); 69 | events.emit(evt.type, evt); 70 | } 71 | //events.emit('tick', delta); 72 | }, 16); 73 | return events; 74 | } 75 | }); 76 | window.events.on('quit', function () { process.exit(0); }); 77 | window.events.on("keydown", function (evt) { 78 | if (evt.keyCode === 'C'.charCodeAt(0) && evt.ctrlKey) process.exit(0); // Control+C 79 | if (evt.keyCode === 27) process.exit(0); // ESC 80 | }); 81 | this.width = this.drawingBufferWidth=width; 82 | this.height = this.drawingBufferHeight=height; 83 | return window; 84 | }, 85 | getContext: function(name) { 86 | return WebGL; 87 | }, 88 | on: function (name, callback) { 89 | if(window) 90 | window.events.addListener(name, callback); 91 | }, 92 | addEventListener: function(name,callback) { 93 | if(window) 94 | window.events.addListener(name, callback); 95 | }, 96 | removeEventListener: function(name,callback) { 97 | if(window) 98 | window.events.removeListener(name,callback); 99 | }, 100 | requestAnimationFrame: function (callback, delay) { 101 | if(!window) return; 102 | 103 | window.Display(); 104 | var timer= (delay==0) ? process.nextTick : setTimeout; 105 | var d= (delay==undefined || delay<0) ? 16 : delay; 106 | timer(function(){ 107 | callback(new Date().getTime()); 108 | }, d); 109 | } 110 | }; 111 | 112 | 113 | Object.defineProperty(platform, 'onkeydown', { 114 | set: function(cb) { 115 | this.on('keydown',cb); 116 | } 117 | }); 118 | 119 | Object.defineProperty(platform, 'onkeyup', { 120 | set: function(cb) { 121 | this.on('keyup',cb); 122 | } 123 | }); 124 | 125 | 126 | return platform; 127 | } 128 | -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "node-webgl", 3 | "version": "0.5.5", 4 | "lockfileVersion": 1, 5 | "dependencies": { 6 | "bindings": { 7 | "version": "1.2.1", 8 | "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.2.1.tgz", 9 | "integrity": "sha1-FK1hE4EtLTfXLme0ystLtyZQXxE=" 10 | }, 11 | "nan": { 12 | "version": "2.6.2", 13 | "resolved": "https://registry.npmjs.org/nan/-/nan-2.6.2.tgz", 14 | "integrity": "sha1-5P805slf37WuzAjeZZb0NgWn20U=" 15 | }, 16 | "node-glfw": { 17 | "version": "0.4.6", 18 | "resolved": "https://registry.npmjs.org/node-glfw/-/node-glfw-0.4.6.tgz", 19 | "integrity": "sha1-y3X8irKSUiOoGS3WFQSIZDm88Vg=" 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "author": "Mikael Bourges-Sevenier ", 3 | "name": "node-webgl", 4 | "description": "WebGL bindings for node", 5 | "version": "0.5.5", 6 | "main": "index.js", 7 | "keywords": [ 8 | "webgl", 9 | "opengl" 10 | ], 11 | "engines": { 12 | "node": ">=0.7.0" 13 | }, 14 | "directories": { 15 | "src": "src", 16 | "lib": "lib", 17 | "doc": "doc", 18 | "examples": "examples", 19 | "test": "test" 20 | }, 21 | "repository": { 22 | "type": "git", 23 | "url": "https://github.com/mikeseven/node-webgl.git" 24 | }, 25 | "scripts": { 26 | "install": "node-gyp rebuild" 27 | }, 28 | "license": "BSD-3-Clause", 29 | "dependencies": { 30 | "bindings": "^1.2.1", 31 | "nan": "^2.1.0", 32 | "node-glfw": ">=0.4.0" 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/GLES2/gl2platform.h: -------------------------------------------------------------------------------- 1 | #ifndef __gl2platform_h_ 2 | #define __gl2platform_h_ 3 | 4 | /* $Revision: 10602 $ on $Date:: 2010-03-04 22:35:34 -0800 #$ */ 5 | 6 | /* 7 | * This document is licensed under the SGI Free Software B License Version 8 | * 2.0. For details, see http://oss.sgi.com/projects/FreeB/ . 9 | */ 10 | 11 | /* Platform-specific types and definitions for OpenGL ES 2.X gl2.h 12 | * 13 | * Adopters may modify khrplatform.h and this file to suit their platform. 14 | * You are encouraged to submit all modifications to the Khronos group so that 15 | * they can be included in future versions of this file. Please submit changes 16 | * by sending them to the public Khronos Bugzilla (http://khronos.org/bugzilla) 17 | * by filing a bug against product "OpenGL-ES" component "Registry". 18 | */ 19 | 20 | //#include 21 | #include "../KHR/khrplatform.h" 22 | 23 | #ifndef GL_APICALL 24 | #define GL_APICALL KHRONOS_APICALL 25 | #endif 26 | 27 | #ifndef GL_APIENTRY 28 | #define GL_APIENTRY KHRONOS_APIENTRY 29 | #endif 30 | 31 | #endif /* __gl2platform_h_ */ 32 | -------------------------------------------------------------------------------- /src/KHR/khrplatform.h: -------------------------------------------------------------------------------- 1 | #ifndef __khrplatform_h_ 2 | #define __khrplatform_h_ 3 | 4 | /* 5 | ** Copyright (c) 2008-2009 The Khronos Group Inc. 6 | ** 7 | ** Permission is hereby granted, free of charge, to any person obtaining a 8 | ** copy of this software and/or associated documentation files (the 9 | ** "Materials"), to deal in the Materials without restriction, including 10 | ** without limitation the rights to use, copy, modify, merge, publish, 11 | ** distribute, sublicense, and/or sell copies of the Materials, and to 12 | ** permit persons to whom the Materials are furnished to do so, subject to 13 | ** the following conditions: 14 | ** 15 | ** The above copyright notice and this permission notice shall be included 16 | ** in all copies or substantial portions of the Materials. 17 | ** 18 | ** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 19 | ** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20 | ** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 21 | ** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 22 | ** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 23 | ** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 24 | ** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. 25 | */ 26 | 27 | /* Khronos platform-specific types and definitions. 28 | * 29 | * $Revision: 9356 $ on $Date: 2009-10-21 02:52:25 -0700 (Wed, 21 Oct 2009) $ 30 | * 31 | * Adopters may modify this file to suit their platform. Adopters are 32 | * encouraged to submit platform specific modifications to the Khronos 33 | * group so that they can be included in future versions of this file. 34 | * Please submit changes by sending them to the public Khronos Bugzilla 35 | * (http://khronos.org/bugzilla) by filing a bug against product 36 | * "Khronos (general)" component "Registry". 37 | * 38 | * A predefined template which fills in some of the bug fields can be 39 | * reached using http://tinyurl.com/khrplatform-h-bugreport, but you 40 | * must create a Bugzilla login first. 41 | * 42 | * 43 | * See the Implementer's Guidelines for information about where this file 44 | * should be located on your system and for more details of its use: 45 | * http://www.khronos.org/registry/implementers_guide.pdf 46 | * 47 | * This file should be included as 48 | * #include 49 | * by Khronos client API header files that use its types and defines. 50 | * 51 | * The types in khrplatform.h should only be used to define API-specific types. 52 | * 53 | * Types defined in khrplatform.h: 54 | * khronos_int8_t signed 8 bit 55 | * khronos_uint8_t unsigned 8 bit 56 | * khronos_int16_t signed 16 bit 57 | * khronos_uint16_t unsigned 16 bit 58 | * khronos_int32_t signed 32 bit 59 | * khronos_uint32_t unsigned 32 bit 60 | * khronos_int64_t signed 64 bit 61 | * khronos_uint64_t unsigned 64 bit 62 | * khronos_intptr_t signed same number of bits as a pointer 63 | * khronos_uintptr_t unsigned same number of bits as a pointer 64 | * khronos_ssize_t signed size 65 | * khronos_usize_t unsigned size 66 | * khronos_float_t signed 32 bit floating point 67 | * khronos_time_ns_t unsigned 64 bit time in nanoseconds 68 | * khronos_utime_nanoseconds_t unsigned time interval or absolute time in 69 | * nanoseconds 70 | * khronos_stime_nanoseconds_t signed time interval in nanoseconds 71 | * khronos_boolean_enum_t enumerated boolean type. This should 72 | * only be used as a base type when a client API's boolean type is 73 | * an enum. Client APIs which use an integer or other type for 74 | * booleans cannot use this as the base type for their boolean. 75 | * 76 | * Tokens defined in khrplatform.h: 77 | * 78 | * KHRONOS_FALSE, KHRONOS_TRUE Enumerated boolean false/true values. 79 | * 80 | * KHRONOS_SUPPORT_INT64 is 1 if 64 bit integers are supported; otherwise 0. 81 | * KHRONOS_SUPPORT_FLOAT is 1 if floats are supported; otherwise 0. 82 | * 83 | * Calling convention macros defined in this file: 84 | * KHRONOS_APICALL 85 | * KHRONOS_APIENTRY 86 | * KHRONOS_APIATTRIBUTES 87 | * 88 | * These may be used in function prototypes as: 89 | * 90 | * KHRONOS_APICALL void KHRONOS_APIENTRY funcname( 91 | * int arg1, 92 | * int arg2) KHRONOS_APIATTRIBUTES; 93 | */ 94 | 95 | /*------------------------------------------------------------------------- 96 | * Definition of KHRONOS_APICALL 97 | *------------------------------------------------------------------------- 98 | * This precedes the return type of the function in the function prototype. 99 | */ 100 | #if defined(_WIN32) && !defined(__SCITECH_SNAP__) 101 | # define KHRONOS_APICALL __declspec(dllimport) 102 | #elif defined (__SYMBIAN32__) 103 | # define KHRONOS_APICALL IMPORT_C 104 | #else 105 | # define KHRONOS_APICALL 106 | #endif 107 | 108 | /*------------------------------------------------------------------------- 109 | * Definition of KHRONOS_APIENTRY 110 | *------------------------------------------------------------------------- 111 | * This follows the return type of the function and precedes the function 112 | * name in the function prototype. 113 | */ 114 | #if defined(_WIN32) && !defined(_WIN32_WCE) && !defined(__SCITECH_SNAP__) 115 | /* Win32 but not WinCE */ 116 | # define KHRONOS_APIENTRY __stdcall 117 | #else 118 | # define KHRONOS_APIENTRY 119 | #endif 120 | 121 | /*------------------------------------------------------------------------- 122 | * Definition of KHRONOS_APIATTRIBUTES 123 | *------------------------------------------------------------------------- 124 | * This follows the closing parenthesis of the function prototype arguments. 125 | */ 126 | #if defined (__ARMCC_2__) 127 | #define KHRONOS_APIATTRIBUTES __softfp 128 | #else 129 | #define KHRONOS_APIATTRIBUTES 130 | #endif 131 | 132 | /*------------------------------------------------------------------------- 133 | * basic type definitions 134 | *-----------------------------------------------------------------------*/ 135 | #if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || defined(__GNUC__) || defined(__SCO__) || defined(__USLC__) 136 | 137 | 138 | /* 139 | * Using 140 | */ 141 | #include 142 | typedef int32_t khronos_int32_t; 143 | typedef uint32_t khronos_uint32_t; 144 | typedef int64_t khronos_int64_t; 145 | typedef uint64_t khronos_uint64_t; 146 | #define KHRONOS_SUPPORT_INT64 1 147 | #define KHRONOS_SUPPORT_FLOAT 1 148 | 149 | #elif defined(__VMS ) || defined(__sgi) 150 | 151 | /* 152 | * Using 153 | */ 154 | #include 155 | typedef int32_t khronos_int32_t; 156 | typedef uint32_t khronos_uint32_t; 157 | typedef int64_t khronos_int64_t; 158 | typedef uint64_t khronos_uint64_t; 159 | #define KHRONOS_SUPPORT_INT64 1 160 | #define KHRONOS_SUPPORT_FLOAT 1 161 | 162 | #elif defined(_WIN32) && !defined(__SCITECH_SNAP__) 163 | 164 | /* 165 | * Win32 166 | */ 167 | typedef __int32 khronos_int32_t; 168 | typedef unsigned __int32 khronos_uint32_t; 169 | typedef __int64 khronos_int64_t; 170 | typedef unsigned __int64 khronos_uint64_t; 171 | #define KHRONOS_SUPPORT_INT64 1 172 | #define KHRONOS_SUPPORT_FLOAT 1 173 | 174 | #elif defined(__sun__) || defined(__digital__) 175 | 176 | /* 177 | * Sun or Digital 178 | */ 179 | typedef int khronos_int32_t; 180 | typedef unsigned int khronos_uint32_t; 181 | #if defined(__arch64__) || defined(_LP64) 182 | typedef long int khronos_int64_t; 183 | typedef unsigned long int khronos_uint64_t; 184 | #else 185 | typedef long long int khronos_int64_t; 186 | typedef unsigned long long int khronos_uint64_t; 187 | #endif /* __arch64__ */ 188 | #define KHRONOS_SUPPORT_INT64 1 189 | #define KHRONOS_SUPPORT_FLOAT 1 190 | 191 | #elif 0 192 | 193 | /* 194 | * Hypothetical platform with no float or int64 support 195 | */ 196 | typedef int khronos_int32_t; 197 | typedef unsigned int khronos_uint32_t; 198 | #define KHRONOS_SUPPORT_INT64 0 199 | #define KHRONOS_SUPPORT_FLOAT 0 200 | 201 | #else 202 | 203 | /* 204 | * Generic fallback 205 | */ 206 | #include 207 | typedef int32_t khronos_int32_t; 208 | typedef uint32_t khronos_uint32_t; 209 | typedef int64_t khronos_int64_t; 210 | typedef uint64_t khronos_uint64_t; 211 | #define KHRONOS_SUPPORT_INT64 1 212 | #define KHRONOS_SUPPORT_FLOAT 1 213 | 214 | #endif 215 | 216 | 217 | /* 218 | * Types that are (so far) the same on all platforms 219 | */ 220 | typedef signed char khronos_int8_t; 221 | typedef unsigned char khronos_uint8_t; 222 | typedef signed short int khronos_int16_t; 223 | typedef unsigned short int khronos_uint16_t; 224 | typedef signed long int khronos_intptr_t; 225 | typedef unsigned long int khronos_uintptr_t; 226 | typedef signed long int khronos_ssize_t; 227 | typedef unsigned long int khronos_usize_t; 228 | 229 | #if KHRONOS_SUPPORT_FLOAT 230 | /* 231 | * Float type 232 | */ 233 | typedef float khronos_float_t; 234 | #endif 235 | 236 | #if KHRONOS_SUPPORT_INT64 237 | /* Time types 238 | * 239 | * These types can be used to represent a time interval in nanoseconds or 240 | * an absolute Unadjusted System Time. Unadjusted System Time is the number 241 | * of nanoseconds since some arbitrary system event (e.g. since the last 242 | * time the system booted). The Unadjusted System Time is an unsigned 243 | * 64 bit value that wraps back to 0 every 584 years. Time intervals 244 | * may be either signed or unsigned. 245 | */ 246 | typedef khronos_uint64_t khronos_utime_nanoseconds_t; 247 | typedef khronos_int64_t khronos_stime_nanoseconds_t; 248 | #endif 249 | 250 | /* 251 | * Dummy value used to pad enum types to 32 bits. 252 | */ 253 | #ifndef KHRONOS_MAX_ENUM 254 | #define KHRONOS_MAX_ENUM 0x7FFFFFFF 255 | #endif 256 | 257 | /* 258 | * Enumerated boolean type 259 | * 260 | * Values other than zero should be considered to be true. Therefore 261 | * comparisons should not be made against KHRONOS_TRUE. 262 | */ 263 | typedef enum { 264 | KHRONOS_FALSE = 0, 265 | KHRONOS_TRUE = 1, 266 | KHRONOS_BOOLEAN_ENUM_FORCE_SIZE = KHRONOS_MAX_ENUM 267 | } khronos_boolean_enum_t; 268 | 269 | #endif /* __khrplatform_h_ */ 270 | -------------------------------------------------------------------------------- /src/arch_wrapper.h: -------------------------------------------------------------------------------- 1 | #ifndef _INCLUDE_ARCH_WRAPPER_ 2 | #define _INCLUDE_ARCH_WRAPPER_ 3 | 4 | #ifdef __IPHONE_OS_VERSION_MIN_REQUIRED 5 | #include 6 | #include 7 | typedef double GLclampd; 8 | #else 9 | /*#if defined (__APPLE__) || defined(MACOSX) 10 | #include 11 | #include 12 | #define GL_ALIASED_POINT_SIZE_RANGE 0x846D 13 | #define GL_RED_BITS 0x0D52 14 | #define GL_GREEN_BITS 0x0D53 15 | #define GL_BLUE_BITS 0x0D54 16 | #define GL_ALPHA_BITS 0x0D55 17 | #define GL_DEPTH_BITS 0x0D56 18 | #define GL_STENCIL_BITS 0x0D57 19 | #define GL_LUMINANCE 0x1909 20 | #define GL_LUMINANCE_ALPHA 0x190A 21 | #define GL_GENERATE_MIPMAP_HINT 0x8192 22 | //#include "GLES2/gl2.h" 23 | //#include "GLES2/gl2ext.h" 24 | #define glClearDepthf glClearDepth 25 | #define glDepthRangef glDepthRange 26 | #else 27 | #ifdef _WIN32*/ 28 | #include 29 | /*#else 30 | #include "GLES2/gl2.h" 31 | #include "GLES2/gl2ext.h" 32 | #endif 33 | #endif*/ 34 | #endif 35 | 36 | #endif 37 | -------------------------------------------------------------------------------- /src/common.h: -------------------------------------------------------------------------------- 1 | /* 2 | * common.h 3 | * 4 | * Created on: Dec 13, 2011 5 | * Author: ngk437 6 | */ 7 | 8 | #ifndef COMMON_H_ 9 | #define COMMON_H_ 10 | 11 | #include 12 | #include "nan.h" 13 | #include 14 | #include "arch_wrapper.h" 15 | 16 | namespace { 17 | #define JS_STR(...) Nan::New(__VA_ARGS__).ToLocalChecked() 18 | #define JS_INT(val) Nan::New(val) 19 | #define JS_FLOAT(val) Nan::New(val) 20 | #define JS_BOOL(val) Nan::New(val) 21 | } 22 | #endif /* COMMON_H_ */ 23 | -------------------------------------------------------------------------------- /src/image.cc: -------------------------------------------------------------------------------- 1 | #include "image.h" 2 | #include 3 | #include 4 | #include 5 | 6 | using namespace v8; 7 | using namespace node; 8 | using namespace std; 9 | 10 | static vector images; 11 | 12 | static void registerImage(Image *obj) { 13 | images.push_back(obj); 14 | } 15 | 16 | 17 | static void unregisterImage(Image* obj) { 18 | vector::iterator it = images.begin(); 19 | while(it != images.end()) { 20 | if(*it==obj) { 21 | images.erase(it); 22 | break; 23 | } 24 | it++; 25 | } 26 | } 27 | 28 | 29 | Persistent Image::constructor_template; 30 | 31 | void Image::Initialize (Handle target) { 32 | Nan::HandleScope scope; 33 | 34 | // constructor 35 | Local ctor = Nan::New(New); 36 | ctor->InstanceTemplate()->SetInternalFieldCount(1); 37 | ctor->SetClassName(JS_STR("Image")); 38 | 39 | // prototype 40 | Nan::SetPrototypeMethod(ctor, "save",save);// NODE_SET_PROTOTYPE_METHOD(ctor, "save", save); 41 | Local proto = ctor->PrototypeTemplate(); 42 | 43 | Nan::SetAccessor(proto,JS_STR("width"), WidthGetter); 44 | Nan::SetAccessor(proto,JS_STR("height"), HeightGetter); 45 | Nan::SetAccessor(proto,JS_STR("pitch"), PitchGetter); 46 | Nan::SetAccessor(proto,JS_STR("src"), SrcGetter, SrcSetter); 47 | Nan::Set(target, JS_STR("Image"), ctor->GetFunction()); 48 | 49 | constructor_template.Reset(Isolate::GetCurrent(), ctor->GetFunction()); 50 | 51 | FreeImage_Initialise(true); 52 | } 53 | 54 | int Image::GetWidth () { 55 | return FreeImage_GetWidth(image_bmp); 56 | } 57 | 58 | int Image::GetHeight () { 59 | return FreeImage_GetHeight(image_bmp); 60 | } 61 | 62 | int Image::GetPitch () { 63 | return FreeImage_GetPitch(image_bmp); 64 | } 65 | 66 | void *Image::GetData () { 67 | BYTE *pixels = FreeImage_GetBits(image_bmp); 68 | 69 | // FreeImage stores data in BGR 70 | // Convert from BGR to RGB 71 | int sz=FreeImage_GetWidth(image_bmp) * FreeImage_GetHeight(image_bmp); 72 | for(int i = 0; i < sz; i++) 73 | { 74 | int i4=i<<2; 75 | BYTE temp = pixels[i4 + 0]; 76 | pixels[i4 + 0] = pixels[i4 + 2]; 77 | pixels[i4 + 2] = temp; 78 | } 79 | 80 | return pixels; 81 | } 82 | 83 | void Image::Load (const char *filename) { 84 | this->filename = (char *)filename; 85 | 86 | if (image_bmp) { 87 | FreeImage_Unload(image_bmp); 88 | } 89 | 90 | FREE_IMAGE_FORMAT format = FreeImage_GetFileType(filename, 0); 91 | FIBITMAP *tmp = FreeImage_Load(format, filename, 0); 92 | image_bmp = FreeImage_ConvertTo32Bits(tmp); 93 | FreeImage_Unload(tmp); 94 | } 95 | 96 | NAN_METHOD(Image::New) { 97 | Nan::HandleScope scope; 98 | 99 | Image *image = new Image(); 100 | image->Wrap(info.This()); 101 | registerImage(image); 102 | info.GetReturnValue().Set(info.This()); 103 | } 104 | 105 | NAN_GETTER(Image::WidthGetter) { 106 | Nan::HandleScope scope; 107 | 108 | Image *image = ObjectWrap::Unwrap(info.This()); 109 | 110 | info.GetReturnValue().Set(JS_INT(image->GetWidth())); 111 | } 112 | 113 | NAN_GETTER(Image::HeightGetter) { 114 | Nan::HandleScope scope; 115 | 116 | Image *image = ObjectWrap::Unwrap(info.This()); 117 | 118 | info.GetReturnValue().Set(JS_INT(image->GetHeight())); 119 | } 120 | 121 | NAN_GETTER(Image::PitchGetter) { 122 | Nan::HandleScope scope; 123 | 124 | Image *image = ObjectWrap::Unwrap(info.This()); 125 | 126 | info.GetReturnValue().Set(JS_INT(image->GetPitch())); 127 | } 128 | 129 | NAN_GETTER(Image::SrcGetter) { 130 | Nan::HandleScope scope; 131 | 132 | Image *image = ObjectWrap::Unwrap(info.This()); 133 | 134 | info.GetReturnValue().Set(JS_STR(image->filename)); 135 | } 136 | 137 | NAN_SETTER(Image::SrcSetter) { 138 | Nan::HandleScope scope; 139 | Nan::MaybeLocal buffer; 140 | 141 | Image *image = ObjectWrap::Unwrap(info.This()); 142 | String::Utf8Value filename_s(value->ToString()); 143 | image->Load(*filename_s); 144 | 145 | // adjust internal fields 146 | size_t num_pixels = FreeImage_GetWidth(image->image_bmp) * FreeImage_GetHeight(image->image_bmp); 147 | BYTE *pixels = FreeImage_GetBits(image->image_bmp); 148 | size_t num_bytes = num_pixels * 4; 149 | 150 | // FreeImage stores data in BGR 151 | // Convert from BGR to RGB 152 | for(size_t i = 0; i < num_pixels; i++) 153 | { 154 | size_t i4=i<<2; 155 | BYTE temp = pixels[i4 + 0]; 156 | pixels[i4 + 0] = pixels[i4 + 2]; 157 | pixels[i4 + 2] = temp; 158 | } 159 | 160 | buffer= Nan::NewBuffer((int)num_bytes); 161 | 162 | std::memcpy(node::Buffer::Data(buffer.ToLocalChecked()),pixels, (int)num_bytes); 163 | 164 | Nan::Set(info.This(), JS_STR("data"), buffer.ToLocalChecked()); 165 | 166 | // emit event 167 | Nan::MaybeLocal emit_v = Nan::Get(info.This(), JS_STR("emit"));//info.This()->Get(Nan::New("emit")); 168 | assert(emit_v.ToLocalChecked()->IsFunction()); 169 | Local emit_f = emit_v.ToLocalChecked().As(); 170 | 171 | Handle argv[2] = { 172 | JS_STR("load"), // event name 173 | value // argument 174 | }; 175 | 176 | TryCatch tc; 177 | 178 | emit_f->Call(info.This(), 2, argv); 179 | 180 | if (tc.HasCaught()) 181 | FatalException(info.GetIsolate(),tc); 182 | } 183 | 184 | NAN_METHOD(Image::save) { 185 | Nan::HandleScope scope; 186 | String::Utf8Value filename(info[0]->ToString()); 187 | 188 | FREE_IMAGE_FORMAT format = FreeImage_GetFIFFromFilename(*filename); 189 | 190 | void *buffer = node::Buffer::Data(info[1]); 191 | 192 | uint32_t width=info[2]->ToUint32()->Value(); 193 | uint32_t height=info[3]->ToUint32()->Value(); 194 | 195 | uint32_t pitch=width*4, bpp=32; 196 | uint32_t redMask=0xFF000000, greenMask=0x00FF0000, blueMask=0x0000FF00; 197 | 198 | if(info.Length()>4) pitch=info[4]->ToUint32()->Value(); 199 | if(info.Length()>5) bpp=info[5]->ToUint32()->Value(); 200 | if(info.Length()>6) redMask=info[6]->ToUint32()->Value(); 201 | if(info.Length()>7) greenMask=info[7]->ToUint32()->Value(); 202 | if(info.Length()>8) blueMask=info[8]->ToUint32()->Value(); 203 | 204 | FIBITMAP *image = FreeImage_ConvertFromRawBits( 205 | (BYTE*)buffer, 206 | width, height, pitch, bpp, 207 | redMask, greenMask, blueMask); 208 | 209 | if(format==FIF_JPEG && bpp!=24) { 210 | FIBITMAP *old=image; 211 | image=FreeImage_ConvertTo24Bits(image); 212 | FreeImage_Unload(old); 213 | } 214 | bool ret=FreeImage_Save(format, image, *filename)==1; 215 | FreeImage_Unload(image); 216 | info.GetReturnValue().Set(Nan::New(ret)); 217 | } 218 | 219 | Image::~Image () { 220 | if (image_bmp) { 221 | #ifdef LOGGING 222 | cout<<" Deleting image"<::iterator it = images.begin(); 234 | while(it != images.end()) { 235 | Image *img=*it; 236 | //v8::Persistent value = img->handle_; 237 | //v8::Object* obj = v8::Object::Cast(*value); 238 | //BYTE* ptr = (BYTE*) obj->GetIndexedPropertiesExternalArrayData(); 239 | //value.ClearWeak(); 240 | //value.Dispose(); 241 | if (img->image_bmp) { 242 | #ifdef LOGGING 243 | cout<<" Deleting image"<image_bmp); 246 | img->image_bmp=NULL; 247 | } 248 | 249 | it++; 250 | } 251 | FreeImage_DeInitialise(); 252 | } 253 | -------------------------------------------------------------------------------- /src/image.h: -------------------------------------------------------------------------------- 1 | #ifndef IMAGE_H_ 2 | #define IMAGE_H_ 3 | 4 | #include "common.h" 5 | 6 | #include 7 | 8 | using namespace v8; 9 | using namespace node; 10 | 11 | class Image : public ObjectWrap { 12 | public: 13 | static void Initialize (Handle target); 14 | static void AtExit(); 15 | int GetWidth (); 16 | int GetHeight (); 17 | int GetPitch (); 18 | void *GetData (); 19 | void Load (const char *filename); 20 | 21 | protected: 22 | static NAN_METHOD(New); 23 | static NAN_GETTER(WidthGetter); 24 | static NAN_GETTER(HeightGetter); 25 | static NAN_GETTER(SrcGetter); 26 | static NAN_SETTER(SrcSetter); 27 | static NAN_SETTER(OnloadSetter); 28 | static NAN_GETTER(PitchGetter); 29 | static NAN_METHOD(save); 30 | 31 | virtual ~Image (); 32 | 33 | private: 34 | static Persistent constructor_template; 35 | 36 | FIBITMAP *image_bmp; 37 | char *filename; 38 | void *data; 39 | }; 40 | 41 | #endif // IMAGE_H_ 42 | -------------------------------------------------------------------------------- /src/webgl.h: -------------------------------------------------------------------------------- 1 | /* 2 | * webgl.h 3 | * 4 | * Created on: Dec 13, 2011 5 | * Author: ngk437 6 | */ 7 | 8 | #ifndef WEBGL_H_ 9 | #define WEBGL_H_ 10 | 11 | #include "common.h" 12 | 13 | using namespace node; 14 | using namespace v8; 15 | 16 | namespace webgl { 17 | void AtExit(); 18 | 19 | NAN_METHOD(Init); 20 | 21 | NAN_METHOD(Uniform1f); 22 | NAN_METHOD(Uniform2f); 23 | NAN_METHOD(Uniform3f); 24 | NAN_METHOD(Uniform4f); 25 | NAN_METHOD(Uniform1i); 26 | NAN_METHOD(Uniform2i); 27 | NAN_METHOD(Uniform3i); 28 | NAN_METHOD(Uniform4i); 29 | NAN_METHOD(Uniform1fv); 30 | NAN_METHOD(Uniform2fv); 31 | NAN_METHOD(Uniform3fv); 32 | NAN_METHOD(Uniform4fv); 33 | NAN_METHOD(Uniform1iv); 34 | NAN_METHOD(Uniform2iv); 35 | NAN_METHOD(Uniform3iv); 36 | NAN_METHOD(Uniform4iv); 37 | NAN_METHOD(PixelStorei); 38 | NAN_METHOD(BindAttribLocation); 39 | NAN_METHOD(GetError); 40 | NAN_METHOD(DrawArrays); 41 | NAN_METHOD(UniformMatrix2fv); 42 | NAN_METHOD(UniformMatrix3fv); 43 | NAN_METHOD(UniformMatrix4fv); 44 | NAN_METHOD(GenerateMipmap); 45 | NAN_METHOD(GetAttribLocation); 46 | NAN_METHOD(DepthFunc); 47 | NAN_METHOD(Viewport); 48 | NAN_METHOD(CreateShader); 49 | NAN_METHOD(ShaderSource); 50 | NAN_METHOD(CompileShader); 51 | NAN_METHOD(GetShaderParameter); 52 | NAN_METHOD(GetShaderInfoLog); 53 | NAN_METHOD(CreateProgram); 54 | NAN_METHOD(AttachShader); 55 | NAN_METHOD(LinkProgram); 56 | NAN_METHOD(GetProgramParameter); 57 | NAN_METHOD(GetUniformLocation); 58 | NAN_METHOD(ClearColor); 59 | NAN_METHOD(ClearDepth); 60 | NAN_METHOD(Disable); 61 | NAN_METHOD(Enable); 62 | NAN_METHOD(CreateTexture); 63 | NAN_METHOD(BindTexture); 64 | NAN_METHOD(TexImage2D); 65 | NAN_METHOD(TexParameteri); 66 | NAN_METHOD(TexParameterf); 67 | NAN_METHOD(Clear); 68 | NAN_METHOD(UseProgram); 69 | NAN_METHOD(CreateBuffer); 70 | NAN_METHOD(BindBuffer); 71 | NAN_METHOD(CreateFramebuffer); 72 | NAN_METHOD(BindFramebuffer); 73 | NAN_METHOD(FramebufferTexture2D); 74 | NAN_METHOD(BufferData); 75 | NAN_METHOD(BufferSubData); 76 | NAN_METHOD(BlendEquation); 77 | NAN_METHOD(BlendFunc); 78 | NAN_METHOD(EnableVertexAttribArray); 79 | NAN_METHOD(VertexAttribPointer); 80 | NAN_METHOD(ActiveTexture); 81 | NAN_METHOD(DrawElements); 82 | NAN_METHOD(Flush); 83 | NAN_METHOD(Finish); 84 | 85 | NAN_METHOD(VertexAttrib1f); 86 | NAN_METHOD(VertexAttrib2f); 87 | NAN_METHOD(VertexAttrib3f); 88 | NAN_METHOD(VertexAttrib4f); 89 | NAN_METHOD(VertexAttrib1fv); 90 | NAN_METHOD(VertexAttrib2fv); 91 | NAN_METHOD(VertexAttrib3fv); 92 | NAN_METHOD(VertexAttrib4fv); 93 | 94 | NAN_METHOD(BlendColor); 95 | NAN_METHOD(BlendEquationSeparate); 96 | NAN_METHOD(BlendFuncSeparate); 97 | NAN_METHOD(ClearStencil); 98 | NAN_METHOD(ColorMask); 99 | NAN_METHOD(CopyTexImage2D); 100 | NAN_METHOD(CopyTexSubImage2D); 101 | NAN_METHOD(CullFace); 102 | NAN_METHOD(DepthMask); 103 | NAN_METHOD(DepthRange); 104 | NAN_METHOD(DisableVertexAttribArray); 105 | NAN_METHOD(Hint); 106 | NAN_METHOD(IsEnabled); 107 | NAN_METHOD(LineWidth); 108 | NAN_METHOD(PolygonOffset); 109 | 110 | NAN_METHOD(Scissor); 111 | NAN_METHOD(StencilFunc); 112 | NAN_METHOD(StencilFuncSeparate); 113 | NAN_METHOD(StencilMask); 114 | NAN_METHOD(StencilMaskSeparate); 115 | NAN_METHOD(StencilOp); 116 | NAN_METHOD(StencilOpSeparate); 117 | NAN_METHOD(BindRenderbuffer); 118 | NAN_METHOD(CreateRenderbuffer); 119 | 120 | NAN_METHOD(DeleteBuffer); 121 | NAN_METHOD(DeleteFramebuffer); 122 | NAN_METHOD(DeleteProgram); 123 | NAN_METHOD(DeleteRenderbuffer); 124 | NAN_METHOD(DeleteShader); 125 | NAN_METHOD(DeleteTexture); 126 | NAN_METHOD(DetachShader); 127 | NAN_METHOD(FramebufferRenderbuffer); 128 | NAN_METHOD(GetVertexAttribOffset); 129 | 130 | NAN_METHOD(IsBuffer); 131 | NAN_METHOD(IsFramebuffer); 132 | NAN_METHOD(IsProgram); 133 | NAN_METHOD(IsRenderbuffer); 134 | NAN_METHOD(IsShader); 135 | NAN_METHOD(IsTexture); 136 | 137 | NAN_METHOD(RenderbufferStorage); 138 | NAN_METHOD(GetShaderSource); 139 | NAN_METHOD(ValidateProgram); 140 | 141 | NAN_METHOD(TexSubImage2D); 142 | NAN_METHOD(ReadPixels); 143 | NAN_METHOD(GetTexParameter); 144 | NAN_METHOD(GetActiveAttrib); 145 | NAN_METHOD(GetActiveUniform); 146 | NAN_METHOD(GetAttachedShaders); 147 | NAN_METHOD(GetParameter); 148 | NAN_METHOD(GetBufferParameter); 149 | NAN_METHOD(GetFramebufferAttachmentParameter); 150 | NAN_METHOD(GetProgramInfoLog); 151 | NAN_METHOD(GetRenderbufferParameter); 152 | NAN_METHOD(GetVertexAttrib); 153 | NAN_METHOD(GetSupportedExtensions); 154 | NAN_METHOD(GetExtension); 155 | NAN_METHOD(CheckFramebufferStatus); 156 | 157 | NAN_METHOD(FrontFace); 158 | } 159 | 160 | #endif /* WEBGL_H_ */ 161 | -------------------------------------------------------------------------------- /test/extensions.js: -------------------------------------------------------------------------------- 1 | nodejs=true; 2 | 3 | var WebGL=require('../index'), 4 | Image = WebGL.Image, 5 | document = WebGL.document(); 6 | 7 | var gl, log=console.log, alert=log; 8 | 9 | function initGL(canvas) { 10 | try { 11 | gl = canvas.getContext("experimental-webgl"); 12 | gl.viewportWidth = canvas.width; 13 | gl.viewportHeight = canvas.height; 14 | } catch (e) { 15 | alert("Could not initialise WebGL, sorry :-("); 16 | process.exit(-1); 17 | } 18 | } 19 | 20 | 21 | (function webGLStart() { 22 | var canvas = document.createElement("test-canvas"); 23 | initGL(canvas); 24 | 25 | var extensions=gl.getSupportedExtensions(); 26 | var num=extensions.length; 27 | log("Supported extensions: "+num); 28 | 29 | var i=0; 30 | while(i 2 | 3 | 4 | 36 | 37 | 38 | 39 | 40 | --------------------------------------------------------------------------------