├── .gitignore ├── .npmignore ├── textures ├── 00001.png ├── 00002.png ├── 00003.png ├── 00004.png ├── 00005.png ├── 00006.png ├── 00007.png ├── 00008.png ├── 00009.png ├── 00010.png ├── 00011.png ├── 00012.png ├── 00013.png ├── 00014.png ├── 00015.png ├── 00016.png ├── 00017.png ├── 00018.png ├── 00019.png ├── 00020.png ├── 00021.png ├── 00022.png ├── 00023.png ├── 00024.png ├── 00025.png ├── 00026.png ├── 00027.png ├── 00028.png ├── 00029.png ├── 00030.png ├── 00031.png ├── 00032.png ├── 00033.png ├── 00034.png ├── 00035.png ├── 00036.png ├── 00037.png ├── 00038.png ├── 00039.png ├── 00040.png ├── 00041.png ├── 00042.png ├── 00043.png ├── 00044.png ├── 00045.png ├── 00046.png ├── 00047.png ├── 00048.png └── 00049.png ├── index.js ├── index.html ├── matcap.glsl ├── matcap.frag ├── matcap.vert ├── LICENSE.md ├── package.json ├── README.md └── demo.js /.gitignore: -------------------------------------------------------------------------------- 1 | npm-debug.log 2 | .DS_Store 3 | node_modules 4 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | bundle.js 2 | npm-debug.log 3 | .DS_Store 4 | node_modules 5 | textures 6 | -------------------------------------------------------------------------------- /textures/00001.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hughsk/matcap/HEAD/textures/00001.png -------------------------------------------------------------------------------- /textures/00002.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hughsk/matcap/HEAD/textures/00002.png -------------------------------------------------------------------------------- /textures/00003.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hughsk/matcap/HEAD/textures/00003.png -------------------------------------------------------------------------------- /textures/00004.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hughsk/matcap/HEAD/textures/00004.png -------------------------------------------------------------------------------- /textures/00005.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hughsk/matcap/HEAD/textures/00005.png -------------------------------------------------------------------------------- /textures/00006.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hughsk/matcap/HEAD/textures/00006.png -------------------------------------------------------------------------------- /textures/00007.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hughsk/matcap/HEAD/textures/00007.png -------------------------------------------------------------------------------- /textures/00008.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hughsk/matcap/HEAD/textures/00008.png -------------------------------------------------------------------------------- /textures/00009.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hughsk/matcap/HEAD/textures/00009.png -------------------------------------------------------------------------------- /textures/00010.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hughsk/matcap/HEAD/textures/00010.png -------------------------------------------------------------------------------- /textures/00011.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hughsk/matcap/HEAD/textures/00011.png -------------------------------------------------------------------------------- /textures/00012.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hughsk/matcap/HEAD/textures/00012.png -------------------------------------------------------------------------------- /textures/00013.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hughsk/matcap/HEAD/textures/00013.png -------------------------------------------------------------------------------- /textures/00014.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hughsk/matcap/HEAD/textures/00014.png -------------------------------------------------------------------------------- /textures/00015.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hughsk/matcap/HEAD/textures/00015.png -------------------------------------------------------------------------------- /textures/00016.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hughsk/matcap/HEAD/textures/00016.png -------------------------------------------------------------------------------- /textures/00017.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hughsk/matcap/HEAD/textures/00017.png -------------------------------------------------------------------------------- /textures/00018.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hughsk/matcap/HEAD/textures/00018.png -------------------------------------------------------------------------------- /textures/00019.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hughsk/matcap/HEAD/textures/00019.png -------------------------------------------------------------------------------- /textures/00020.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hughsk/matcap/HEAD/textures/00020.png -------------------------------------------------------------------------------- /textures/00021.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hughsk/matcap/HEAD/textures/00021.png -------------------------------------------------------------------------------- /textures/00022.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hughsk/matcap/HEAD/textures/00022.png -------------------------------------------------------------------------------- /textures/00023.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hughsk/matcap/HEAD/textures/00023.png -------------------------------------------------------------------------------- /textures/00024.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hughsk/matcap/HEAD/textures/00024.png -------------------------------------------------------------------------------- /textures/00025.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hughsk/matcap/HEAD/textures/00025.png -------------------------------------------------------------------------------- /textures/00026.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hughsk/matcap/HEAD/textures/00026.png -------------------------------------------------------------------------------- /textures/00027.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hughsk/matcap/HEAD/textures/00027.png -------------------------------------------------------------------------------- /textures/00028.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hughsk/matcap/HEAD/textures/00028.png -------------------------------------------------------------------------------- /textures/00029.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hughsk/matcap/HEAD/textures/00029.png -------------------------------------------------------------------------------- /textures/00030.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hughsk/matcap/HEAD/textures/00030.png -------------------------------------------------------------------------------- /textures/00031.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hughsk/matcap/HEAD/textures/00031.png -------------------------------------------------------------------------------- /textures/00032.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hughsk/matcap/HEAD/textures/00032.png -------------------------------------------------------------------------------- /textures/00033.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hughsk/matcap/HEAD/textures/00033.png -------------------------------------------------------------------------------- /textures/00034.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hughsk/matcap/HEAD/textures/00034.png -------------------------------------------------------------------------------- /textures/00035.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hughsk/matcap/HEAD/textures/00035.png -------------------------------------------------------------------------------- /textures/00036.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hughsk/matcap/HEAD/textures/00036.png -------------------------------------------------------------------------------- /textures/00037.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hughsk/matcap/HEAD/textures/00037.png -------------------------------------------------------------------------------- /textures/00038.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hughsk/matcap/HEAD/textures/00038.png -------------------------------------------------------------------------------- /textures/00039.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hughsk/matcap/HEAD/textures/00039.png -------------------------------------------------------------------------------- /textures/00040.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hughsk/matcap/HEAD/textures/00040.png -------------------------------------------------------------------------------- /textures/00041.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hughsk/matcap/HEAD/textures/00041.png -------------------------------------------------------------------------------- /textures/00042.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hughsk/matcap/HEAD/textures/00042.png -------------------------------------------------------------------------------- /textures/00043.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hughsk/matcap/HEAD/textures/00043.png -------------------------------------------------------------------------------- /textures/00044.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hughsk/matcap/HEAD/textures/00044.png -------------------------------------------------------------------------------- /textures/00045.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hughsk/matcap/HEAD/textures/00045.png -------------------------------------------------------------------------------- /textures/00046.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hughsk/matcap/HEAD/textures/00046.png -------------------------------------------------------------------------------- /textures/00047.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hughsk/matcap/HEAD/textures/00047.png -------------------------------------------------------------------------------- /textures/00048.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hughsk/matcap/HEAD/textures/00048.png -------------------------------------------------------------------------------- /textures/00049.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hughsk/matcap/HEAD/textures/00049.png -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | var glslify = require('glslify') 2 | 3 | module.exports = glslify({ 4 | fragment: './matcap.frag' 5 | , vertex: './matcap.vert' 6 | }) 7 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | matcap 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /matcap.glsl: -------------------------------------------------------------------------------- 1 | vec2 matcap(vec3 eye, vec3 normal) { 2 | vec3 reflected = reflect(eye, normal); 3 | float m = 2.8284271247461903 * sqrt( reflected.z+1.0 ); 4 | return reflected.xy / m + 0.5; 5 | } 6 | 7 | #pragma glslify: export(matcap) 8 | -------------------------------------------------------------------------------- /matcap.frag: -------------------------------------------------------------------------------- 1 | precision mediump float; 2 | 3 | uniform sampler2D uTexture; 4 | varying vec3 vNormal; 5 | varying vec3 vEye; 6 | 7 | #pragma glslify: matcap = require(./matcap) 8 | 9 | void main() { 10 | vec2 uv = matcap(vEye, vNormal).xy; 11 | 12 | gl_FragColor = vec4( 13 | texture2D(uTexture, uv).rgb, 14 | 1.0 15 | ); 16 | } 17 | -------------------------------------------------------------------------------- /matcap.vert: -------------------------------------------------------------------------------- 1 | precision mediump float; 2 | 3 | attribute vec3 aPosition; 4 | attribute vec3 aNormal; 5 | 6 | varying vec3 vNormal; 7 | varying vec3 vEye; 8 | 9 | uniform mat4 mProjection; 10 | uniform mat4 mModel; 11 | uniform mat4 mView; 12 | uniform mat4 mNormal; 13 | uniform vec3 uEye; 14 | 15 | void main() { 16 | vEye = uEye; 17 | vNormal = normalize((mNormal * vec4(aNormal, 0.0)).xyz); 18 | 19 | gl_Position = mProjection * mModel * mView * vec4(aPosition, 1.0); 20 | } 21 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | ## The MIT License (MIT) ## 2 | 3 | Copyright (c) 2014 Hugh Kennedy 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "matcap", 3 | "description": "GLSL shaders for calculating/rendering Spherical Environment Maps, or \"matcaps\"", 4 | "version": "0.0.2", 5 | "main": "index.js", 6 | "glslify": "matcap.glsl", 7 | "dependencies": { 8 | "glslify": "^1.2.1" 9 | }, 10 | "devDependencies": { 11 | "brfs": "git://github.com/hughsk/brfs.git#readdir", 12 | "budo": "^9.4.5", 13 | "es2040": "^1.2.4", 14 | "geom-center-and-normalize": "^1.0.1", 15 | "gl-mat3": "^1.0.0", 16 | "h": "^0.1.0", 17 | "normals": "^1.1.0", 18 | "regl": "^1.3.0", 19 | "regl-camera": "git://github.com/rreusser/regl-camera", 20 | "stanford-dragon": "0.0.0" 21 | }, 22 | "scripts": { 23 | "start": "budo --open --live --host localhost demo.js:bundle.js -- -t es2040 -t brfs -g glslify", 24 | "prepublish": "browserify demo.js -t es2040 -t brfs -g glslify -o bundle.js" 25 | }, 26 | "browserify": { 27 | "transform": [ 28 | "glslify" 29 | ] 30 | }, 31 | "author": "Hugh Kennedy (http://hughsk.io/)", 32 | "license": "MIT", 33 | "homepage": "http://hughsk.github.io/matcap", 34 | "repository": { 35 | "type": "git", 36 | "url": "git://github.com/hughsk/matcap" 37 | }, 38 | "bugs": { 39 | "url": "https://github.com/hughsk/matcap/issues" 40 | }, 41 | "keywords": [ 42 | "matcap", 43 | "material", 44 | "capture", 45 | "spherical", 46 | "environment", 47 | "reflection", 48 | "shader", 49 | "glsl", 50 | "webgl", 51 | "litsphere", 52 | "sem", 53 | "map", 54 | "texture" 55 | ] 56 | } 57 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # matcap [![Flattr this!](https://api.flattr.com/button/flattr-badge-large.png)](https://flattr.com/submit/auto?user_id=hughskennedy&url=http://github.com/hughsk/matcap&title=matcap&description=hughsk/matcap%20on%20GitHub&language=en_GB&tags=flattr,github,javascript&category=software)[![experimental](http://hughsk.github.io/stability-badges/dist/experimental.svg)](http://github.com/hughsk/stability-badges) # 2 | 3 | GLSL shaders for calculating/rendering Spherical Environment Maps, or "matcaps". 4 | 5 | For more information, check out 6 | [Creating a Spherical Reflection/Environment Mapping shader](http://www.clicktorelease.com/blog/creating-spherical-environment-mapping-shader), 7 | which was used as a reference when writing this module and the demo. 8 | 9 | Most of the images in the demo were sourced from 10 | [this demo](http://www.clicktorelease.com/code/spherical-normal-mapping/), 11 | though a couple I made myself. 12 | 13 | ### [view demo](http://hughsk.github.io/matcap/) ### 14 | 15 | ## Usage ## 16 | 17 | [![matcap](https://nodei.co/npm/matcap.png?mini=true)](https://nodei.co/npm/matcap) 18 | 19 | ### With glslify ### 20 | 21 | You can import the module using 22 | [glslify](http://github.com/chrisdickinson/glslify) to get the bare function 23 | responsible for generating the texture coordinate to look up. 24 | 25 | This function takes two arguments: 26 | 27 | * `vec3 eye`: the camera's current position. 28 | * `vec3 normal`: the surface's normal vector. 29 | 30 | Returning a `vec2` you can use on your `sampler2D`. 31 | 32 | ``` glsl 33 | #pragma glslify: matcap = require(matcap) 34 | 35 | uniform sampler2D texture; // the matcap texture you want to use 36 | uniform vec3 eyeVector; 37 | varying vec3 normalVector; 38 | 39 | void main() { 40 | vec2 uv = matcap(eyeVector, normalVector); 41 | 42 | gl_FragColor = vec4(texture2D( 43 | texture, uv 44 | ).rgb, 1.0); 45 | } 46 | ``` 47 | 48 | ### With browserify ### 49 | 50 | If you're looking to get started a little more quickly, you can require matcap 51 | as a module from [browserify](http://github.com/substack/node-browserify). 52 | 53 | The required function simply takes the current WebGL context, and returns a 54 | a GLSL program wrapped up in 55 | [gl-shader-core](http://github.com/gl-modules/gl-shader-core). 56 | 57 | You'll still need to take care of its uniforms and attributes though: 58 | 59 | ``` javascript 60 | shader.bind() 61 | shader.attributes.aPosition.location = 0 62 | shader.attributes.aNormal.location = 0 63 | 64 | shader.uniforms.uTexture = textureIndex 65 | shader.uniforms.uEye = eyeVector 66 | 67 | shader.uniforms.mView = viewMatrix 68 | shader.uniforms.mModel = modelMatrix 69 | shader.uniforms.mNormal = normalMatrix 70 | shader.uniforms.mProjection = projectionMatrix 71 | ``` 72 | 73 | If you're looking for a full example, check out the demo! 74 | 75 | ## License ## 76 | 77 | MIT. See [LICENSE.md](http://github.com/hughsk/matcap/blob/master/LICENSE.md) for details. 78 | -------------------------------------------------------------------------------- /demo.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs') 2 | const mesh = require('stanford-dragon/3') 3 | const textures = fs.readdirSync(__dirname + '/textures') 4 | const glslify = require('glslify') 5 | const regl = require('regl')() 6 | const h = require('h') 7 | const normalMatrix = require('gl-mat3/normal-from-mat4'); 8 | const identity = require('gl-mat4/identity'); 9 | 10 | const camera = require('regl-camera')(regl, { 11 | distance: 2, 12 | theta: 1.5, 13 | phi: 0.4 14 | }) 15 | 16 | const model = identity([]); 17 | const transformModel = regl({ 18 | uniforms: { 19 | model: model, 20 | normalMatrix: ctx => normalMatrix([], model) 21 | } 22 | }); 23 | 24 | var texture, drawMesh 25 | function init (img) { 26 | texture = regl.texture({data: img, flipY: true}) 27 | drawMesh = regl({ 28 | vert: ` 29 | precision mediump float; 30 | attribute vec3 position, normal; 31 | uniform vec3 eye; 32 | uniform mat4 projection, view, model; 33 | uniform mat3 normalMatrix; 34 | varying vec3 n, peye; 35 | void main () { 36 | // Transform the normal by the model matrix (which because normals transform 37 | // differently means multiplication by the normal matrix): 38 | n = normalize(normalMatrix * normal); 39 | 40 | // Transform the position by the model matrix: 41 | vec4 mp = model * vec4(position, 1); 42 | 43 | // Compute the direction of the eye relative to the position: 44 | peye = normalize(mp.xyz - eye); 45 | 46 | // Transfomr the *directions* of the normal and position-relative-to-eye so 47 | // that the matcap stays aligned with the view: 48 | n = mat3(view) * n; 49 | peye = mat3(view) * peye; 50 | 51 | gl_Position = projection * view * mp; 52 | } 53 | `, 54 | frag: glslify(` 55 | precision mediump float; 56 | #pragma glslify: matcap = require('./matcap.glsl') 57 | varying vec3 n, peye; 58 | uniform sampler2D texture; 59 | void main () { 60 | // This could be done in the vertex shader to optimize slightly: 61 | vec2 uv = matcap(peye, n); 62 | 63 | gl_FragColor = vec4(texture2D(texture, uv).rgb, 1); 64 | } 65 | `), 66 | cull: {enable: true, face: 'back'}, 67 | uniforms: {texture: texture}, 68 | attributes: { 69 | position: require('geom-center-and-normalize')(mesh.positions), 70 | normal: require('normals').vertexNormals(mesh.cells, mesh.positions) 71 | }, 72 | elements: mesh.cells, 73 | count: mesh.cells.length * 3 74 | }) 75 | } 76 | 77 | regl.frame(() => { 78 | regl.clear({color: [0, 0, 0, 1], depth: 1}) 79 | if (drawMesh) camera(() => { 80 | transformModel(() => { 81 | drawMesh() 82 | }) 83 | }) 84 | }) 85 | 86 | const textureSelect = document.body.appendChild(h('div', { 87 | style: { 88 | left: '1em', 89 | top: '1em', 90 | position: 'absolute', 91 | cursor: 'pointer', 92 | width: '128px' 93 | } 94 | })) 95 | 96 | textureSelect.addEventListener('click', function(e) { 97 | var img = e.target 98 | if (img.nodeName !== 'IMG') return 99 | texture = (texture || regl.texture)({data: img, flipY: true}) 100 | }, false) 101 | 102 | for (var i = 0; i < textures.length; i++) (function(src) { 103 | var img = h('img', {style: {width: '32px', height: '32px', float: 'left'}}); 104 | 105 | img.onload = function () { 106 | textureSelect.appendChild(img) 107 | if (src === '00001.png') init(img) 108 | } 109 | 110 | img.src = 'textures/' + src 111 | }(textures[i])) 112 | --------------------------------------------------------------------------------