diff --git a/core/Transform.js b/core/Transform.js index 5cda6cec..c184f5c5 100644 --- a/core/Transform.js +++ b/core/Transform.js @@ -24,6 +24,9 @@ 'use strict'; +var glMatrix = require('gl-matrix'); +var mat44 = glMatrix.mat4; + var QUAT = [0, 0, 0, 1]; var ONES = [1, 1, 1]; @@ -450,7 +453,7 @@ Transform.prototype.calculateWorldMatrix = function calculateWorldMatrix () { while (nearestBreakPoint && !nearestBreakPoint.isBreakPoint()) nearestBreakPoint = nearestBreakPoint.parent; - if (nearestBreakPoint) return multiply(this.global, nearestBreakPoint.getWorldTransform(), this.local); + if (nearestBreakPoint) return mat44.multiply(this.global, nearestBreakPoint.getWorldTransform(), this.local); else { for (var i = 0; i < 16 ; i++) this.global[i] = this.local[i]; return false; @@ -680,92 +683,4 @@ function fromNodeWithParent (node, transform) { return changed; } -/** - * private method to multiply two transforms. - * - * @method - * - * @param {Array} out The array to write the result to - * @param {Array} a the left hand transform - * @param {Array} b the right hand transform - * - * @return {undefined} undefined - */ -function multiply (out, a, b) { - var a00 = a[0], a01 = a[1], a02 = a[2], - a10 = a[4], a11 = a[5], a12 = a[6], - a20 = a[8], a21 = a[9], a22 = a[10], - a30 = a[12], a31 = a[13], a32 = a[14]; - - var changed = false; - var res; - - // Cache only the current line of the second matrix - var b0 = b[0], b1 = b[1], b2 = b[2], b3 = b[3]; - - res = b0*a00 + b1*a10 + b2*a20 + b3*a30; - changed = changed ? changed : out[0] === res; - out[0] = res; - - res = b0*a01 + b1*a11 + b2*a21 + b3*a31; - changed = changed ? changed : out[1] === res; - out[1] = res; - - res = b0*a02 + b1*a12 + b2*a22 + b3*a32; - changed = changed ? changed : out[2] === res; - out[2] = res; - - out[3] = 0; - - b0 = b[4]; b1 = b[5]; b2 = b[6]; b3 = b[7]; - - res = b0*a00 + b1*a10 + b2*a20 + b3*a30; - changed = changed ? changed : out[4] === res; - out[4] = res; - - res = b0*a01 + b1*a11 + b2*a21 + b3*a31; - changed = changed ? changed : out[5] === res; - out[5] = res; - - res = b0*a02 + b1*a12 + b2*a22 + b3*a32; - changed = changed ? changed : out[6] === res; - out[6] = res; - - out[7] = 0; - - b0 = b[8]; b1 = b[9]; b2 = b[10]; b3 = b[11]; - - res = b0*a00 + b1*a10 + b2*a20 + b3*a30; - changed = changed ? changed : out[8] === res; - out[8] = res; - - res = b0*a01 + b1*a11 + b2*a21 + b3*a31; - changed = changed ? changed : out[9] === res; - out[9] = res; - - res = b0*a02 + b1*a12 + b2*a22 + b3*a32; - changed = changed ? changed : out[10] === res; - out[10] = res; - - out[11] = 0; - - b0 = b[12]; b1 = b[13]; b2 = b[14]; b3 = b[15]; - - res = b0*a00 + b1*a10 + b2*a20 + b3*a30; - changed = changed ? changed : out[12] === res; - out[12] = res; - - res = b0*a01 + b1*a11 + b2*a21 + b3*a31; - changed = changed ? changed : out[13] === res; - out[13] = res; - - res = b0*a02 + b1*a12 + b2*a22 + b3*a32; - changed = changed ? changed : out[14] === res; - out[14] = res; - - out[15] = 1; - - return changed; -} - module.exports = Transform; diff --git a/package.json b/package.json index 502f0869..c38a33eb 100644 --- a/package.json +++ b/package.json @@ -49,6 +49,7 @@ "uglify-js": "^2.4.17" }, "dependencies": { + "gl-matrix": "^2.3.1", "glslify": "^2.0.0" }, "browserify": { diff --git a/webgl-geometries/GeometryHelper.js b/webgl-geometries/GeometryHelper.js index c9c75d7e..9281d464 100644 --- a/webgl-geometries/GeometryHelper.js +++ b/webgl-geometries/GeometryHelper.js @@ -26,6 +26,8 @@ var Vec3 = require('../math/Vec3'); var Vec2 = require('../math/Vec2'); +var glMatrix = require('gl-matrix'); +var vec3 = glMatrix.vec3; var outputs = [ new Vec3(), @@ -563,4 +565,101 @@ GeometryHelper.addBackfaceTriangles = function addBackfaceTriangles(vertices, in } }; +// http://www.terathon.com/code/tangent.html + +GeometryHelper.computeTangents = function computeTangents(vertices, indices, normals, textureCoords, out) { + var nFaces = indices.length / 3; + var nVerts = vertices.length / 3; + var tdir = vec3.create(); + var sdir = vec3.create(); + var tan1 = [], + tan2 = []; + var out = out || []; + + for (var i = 0; i < nVerts; i++) { + tan1[i] = vec3.create(); + tan2[i] = vec3.create(); + } + + for (var i = 0; i < nFaces; i++) + { + var i1 = indices[i * 3]; + var i2 = indices[i * 3 + 1]; + var i3 = indices[i * 3 + 2]; + + var v1 = vertices.slice(i1 * 3, i1 * 3 + 3); + var v2 = vertices.slice(i2 * 3, i2 * 3 + 3); + var v3 = vertices.slice(i3 * 3, i3 * 3 + 3); + + var w1 = textureCoords.slice(i1 * 2, i1 * 2 + 2); + var w2 = textureCoords.slice(i2 * 2, i2 * 2 + 2); + var w3 = textureCoords.slice(i3 * 2, i3 * 2 + 2); + + var x1 = v2[0] - v1[0]; + var x2 = v3[0] - v1[0]; + var y1 = v2[1] - v1[1]; + var y2 = v3[1] - v1[1]; + var z1 = v2[2] - v1[2]; + var z2 = v3[2] - v1[2]; + + var s1 = w2[0] - w1[0]; + var s2 = w3[0] - w1[0]; + var t1 = w2[1] - w1[1]; + var t2 = w3[1] - w1[1]; + + var r = 1.0 / (s1 * t2 - s2 * t1); + + vec3.set(sdir, + (t2 * x1 - t1 * x2) * r, + (t2 * y1 - t1 * y2) * r, + (t2 * z1 - t1 * z2) * r + ); + + vec3.set(tdir, + (s1 * x2 - s2 * x1) * r, + (s1 * y2 - s2 * y1) * r, + (s1 * z2 - s2 * z1) * r + ); + + vec3.add(tan1[i1], tan1[i1], sdir); + vec3.add(tan1[i2], tan1[i2], sdir); + vec3.add(tan1[i3], tan1[i3], sdir); + + vec3.add(tan2[i1], tan2[i1], tdir); + vec3.add(tan2[i2], tan2[i2], tdir); + vec3.add(tan2[i3], tan2[i3], tdir); + + } + + var normal = vec3.create(); + var t = vec3.create(); + + for (i = 0; i < nVerts; i++) + { + vec3.set(normal, + normals[i * 3], + normals[i * 3 + 1], + normals[i * 3 + 2] + ); + + vec3.set(t, + tan1[i][0], + tan1[i][1], + tan1[i][2] + ); + + // Gram-Schmidt orthogonalize + + vec3.scale(normal, normal, vec3.dot(normal, t)); + vec3.subtract(t, t, normal); + vec3.normalize(t, t); + + out[i * 3] = t[0]; + out[i * 3 + 1] = t[1]; + out[i * 3 + 2] = t[2]; + } + + return out; +} + module.exports = GeometryHelper; diff --git a/webgl-geometries/primitives/Box.js b/webgl-geometries/primitives/Box.js index 44adb223..75e8e902 100644 --- a/webgl-geometries/primitives/Box.js +++ b/webgl-geometries/primitives/Box.js @@ -25,6 +25,7 @@ 'use strict'; var Geometry = require('../Geometry'); +var GeometryHelper = require('../GeometryHelper'); function pickOctant(i) { return [(i & 1) * 2 - 1, (i & 2) - 1, (i & 4) / 2 - 1]; @@ -54,6 +55,8 @@ var boxData = [ function BoxGeometry(options) { options = options || {}; + var buffers = []; + var vertices = []; var textureCoords = []; var normals = []; @@ -77,16 +80,25 @@ function BoxGeometry(options) { } indices.push(v, v + 1, v + 2); indices.push(v + 2, v + 1, v + 3); + } + + buffers.push( + { name: 'a_pos', data: vertices }, + { name: 'a_texCoord', data: textureCoords, size: 2 }, + { name: 'a_normals', data: normals }, + { name: 'indices', data: indices, size: 1 } + ); + if (options.tangents) { + buffers.push({ + name: 'a_tangent', + data: GeometryHelper.computeTangents(vertices, indices, normals, textureCoords), + size: 3 + }); } return new Geometry({ - buffers: [ - { name: 'a_pos', data: vertices }, - { name: 'a_texCoord', data: textureCoords, size: 2 }, - { name: 'a_normals', data: normals }, - { name: 'indices', data: indices, size: 1 } - ] + buffers: buffers }); } diff --git a/webgl-geometries/primitives/Sphere.js b/webgl-geometries/primitives/Sphere.js index 7630add6..1ddca0b7 100644 --- a/webgl-geometries/primitives/Sphere.js +++ b/webgl-geometries/primitives/Sphere.js @@ -52,13 +52,26 @@ function ParametricSphere (options) { true ); + var vertices = buffers.vertices, + indices = buffers.indices, + textureCoords = GeometryHelper.getSpheroidUV(buffers.vertices), + normals = GeometryHelper.getSpheroidNormals(buffers.vertices); + + var buffers = [ + { name: 'a_pos', data: buffers.vertices }, + { name: 'a_texCoord', data: textureCoords, size: 2 }, + { name: 'a_normals', data: normals }, + { name: 'indices', data: buffers.indices, size: 1 } + ]; + + buffers.push({ + name: 'a_tangent', + data: GeometryHelper.computeTangents(vertices, indices, normals, textureCoords), + size: 3 + }); + return new Geometry({ - buffers: [ - { name: 'a_pos', data: buffers.vertices }, - { name: 'a_texCoord', data: GeometryHelper.getSpheroidUV(buffers.vertices), size: 2 }, - { name: 'a_normals', data: GeometryHelper.getSpheroidNormals(buffers.vertices) }, - { name: 'indices', data: buffers.indices, size: 1 } - ] + buffers: buffers }); } diff --git a/webgl-renderers/Program.js b/webgl-renderers/Program.js index 526f8e64..5696ea1b 100644 --- a/webgl-renderers/Program.js +++ b/webgl-renderers/Program.js @@ -43,12 +43,13 @@ var TYPES = { 2: 'vec2 ', 3: 'vec3 ', 4: 'vec4 ', + 9: 'mat3 ', 16: 'mat4 ' }; var inputTypes = { u_baseColor: 'vec4', - u_normals: 'vert', + u_normals: 'vec3', u_glossiness: 'vec4', u_positionOffset: 'vert' }; @@ -65,9 +66,9 @@ var masks = { */ var uniforms = keyValueToArrays({ u_perspective: identityMatrix, - u_view: identityMatrix, + u_mvMatrix: identityMatrix, u_resolution: [0, 0, 0], - u_transform: identityMatrix, + u_normalMatrix: [0, 0, 0, 0, 0, 0, 0, 0, 0], u_size: [1, 1, 1], u_time: 0, u_opacity: 1, @@ -89,7 +90,8 @@ var uniforms = keyValueToArrays({ var attributes = keyValueToArrays({ a_pos: [0, 0, 0], a_texCoord: [0, 0], - a_normals: [0, 0, 0] + a_normals: [0, 0, 0], + a_tangent: [0, 0, 0] }); /** @@ -99,7 +101,8 @@ var varyings = keyValueToArrays({ v_textureCoordinate: [0, 0], v_normal: [0, 0, 0], v_position: [0, 0, 0], - v_eyeVector: [0, 0, 0] + v_eyeVector: [0, 0, 0], + v_tangent: [0, 0, 0] }); /** diff --git a/webgl-renderers/WebGLRenderer.js b/webgl-renderers/WebGLRenderer.js index da718a16..204aa4cc 100644 --- a/webgl-renderers/WebGLRenderer.js +++ b/webgl-renderers/WebGLRenderer.js @@ -30,6 +30,9 @@ var sorter = require('./radixSort'); var keyValueToArrays = require('../utilities/keyValueToArrays'); var TextureManager = require('./TextureManager'); var compileMaterial = require('./compileMaterial'); +var glMatrix = require('gl-matrix'); +var mat44 = glMatrix.mat4; +var mat33 = glMatrix.mat3; var identity = [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1]; @@ -39,8 +42,12 @@ var globalUniforms = keyValueToArrays({ 'u_lightPosition': new Array(3), 'u_lightColor': new Array(3), 'u_perspective': new Array(16), - 'u_time': 0, - 'u_view': new Array(16) + 'u_time': 0 +}); + +var meshTransforms = keyValueToArrays({ + 'u_mvMatrix': new Array(16), + 'u_normalMatrix': new Array(9) }); /** @@ -535,8 +542,8 @@ WebGLRenderer.prototype.draw = function draw(renderState) { this.meshRegistryKeys = sorter(this.meshRegistryKeys, this.meshRegistry); this.setGlobalUniforms(renderState); - this.drawCutouts(); - this.drawMeshes(); + this.drawCutouts(renderState); + this.drawMeshes(renderState); }; /** @@ -548,7 +555,7 @@ WebGLRenderer.prototype.draw = function draw(renderState) { * * @return {undefined} undefined */ -WebGLRenderer.prototype.drawMeshes = function drawMeshes() { +WebGLRenderer.prototype.drawMeshes = function drawMeshes(renderState) { var gl = this.gl; var buffers; var mesh; @@ -575,7 +582,15 @@ WebGLRenderer.prototype.drawMeshes = function drawMeshes() { if (mesh.options) this.handleOptions(mesh.options, mesh); + // Model View Matrix from View Matrix multipled by the Mesh transform + mat44.multiply(meshTransforms.values[0], renderState.viewTransform, mesh.uniformValues[1]); + + // Normal Matrix calculated from the Model View Matrix + mat33.normalFromMat4(meshTransforms.values[1], mesh.uniformValues[1]); + this.program.setUniforms(mesh.uniformKeys, mesh.uniformValues); + this.program.setUniforms(meshTransforms.keys, meshTransforms.values); + this.drawBuffers(buffers, mesh.drawType, mesh.geometry); if (mesh.options) this.resetOptions(mesh.options); @@ -590,7 +605,7 @@ WebGLRenderer.prototype.drawMeshes = function drawMeshes() { * * @return {undefined} undefined */ -WebGLRenderer.prototype.drawCutouts = function drawCutouts() { +WebGLRenderer.prototype.drawCutouts = function drawCutouts(renderState) { var cutout; var buffers; var len = this.cutoutRegistryKeys.length; @@ -607,7 +622,11 @@ WebGLRenderer.prototype.drawCutouts = function drawCutouts() { if (!cutout.visible) continue; + mat44.multiply(meshTransforms.values[0], renderState.viewTransform, cutout.uniformValues[1]); + + this.program.setUniforms(meshTransforms.keys, meshTransforms.values); this.program.setUniforms(cutout.uniformKeys, cutout.uniformValues); + this.drawBuffers(buffers, cutout.drawType, cutout.geometry); } diff --git a/webgl-shaders/FragmentShader.glsl b/webgl-shaders/FragmentShader.glsl index b440695b..d4b89f5e 100644 --- a/webgl-shaders/FragmentShader.glsl +++ b/webgl-shaders/FragmentShader.glsl @@ -1,18 +1,18 @@ /** * The MIT License (MIT) - * + * * Copyright (c) 2015 Famous Industries Inc. - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -44,18 +44,28 @@ void main() { bool lightsEnabled = (u_flatShading == 0.0) && (u_numLights > 0.0 || length(u_ambientLight) > 0.0); vec3 normal = normalize(v_normal); + + if (u_normals.x < 0.0) { + vec3 tangent = normalize(v_tangent); + tangent = normalize(tangent - dot(tangent, normal) * normal); + vec3 bitangent = cross(tangent, normal); + vec3 normalOffset = applyMaterial(u_normals) * 2.0 - 1.0; + normalOffset.y *= 1.0; + mat3 TBNMatrix = mat3(tangent, bitangent, normal); + normal = normalize(TBNMatrix * normalOffset); + } + + // normal = normalize(u_normalMatrix * normal); + vec4 glossiness = u_glossiness.x < 0.0 ? applyMaterial(u_glossiness) : u_glossiness; + int numLights = int(u_numLights); + vec3 eyeVector = normalize(v_eyeVector); + vec3 ambience = u_ambientLight * u_baseColor.rgb; - vec4 color = lightsEnabled ? - applyLight(material, normalize(v_normal), glossiness, - int(u_numLights), - u_ambientLight * u_baseColor.rgb, - normalize(v_eyeVector), - u_lightPosition, - u_lightColor, - v_position) - : material; + vec4 color = !lightsEnabled ? material : + applyLight(material, normal, glossiness, numLights, ambience, + eyeVector, u_lightPosition, u_lightColor, v_position); gl_FragColor = color; - gl_FragColor.a *= u_opacity; + gl_FragColor.a *= u_opacity; } diff --git a/webgl-shaders/VertexShader.glsl b/webgl-shaders/VertexShader.glsl index d064b848..271660d2 100644 --- a/webgl-shaders/VertexShader.glsl +++ b/webgl-shaders/VertexShader.glsl @@ -1,18 +1,18 @@ /** * The MIT License (MIT) - * + * * Copyright (c) 2015 Famous Industries Inc. - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -22,56 +22,28 @@ * THE SOFTWARE. */ -#pragma glslify: getNormalMatrix = require(./chunks/getNormalMatrix) -#pragma glslify: inverse = require(./chunks/inverse) -#pragma glslify: transpose = require(./chunks/transpose) - /** - * Converts vertex from modelspace to screenspace using transform - * information from context. + * Placeholder for positionOffset chunks to be templated in. + * Used for mesh deformation. * - * @method applyTransform + * @method calculateOffset * @private * * */ +#vert_definitions +vec3 calculateOffset(vec3 ID) { + #vert_applications + return vec3(0.0); +} -vec4 applyTransform(vec4 pos) { - //TODO: move this multiplication to application code. - - /** - * Currently multiplied in the vertex shader to avoid consuming the complexity of holding an additional - * transform as state on the mesh object in WebGLRenderer. Multiplies the object's transformation from object space - * to world space with its transformation from world space to eye space. - */ - mat4 MVMatrix = u_view * u_transform; - - //TODO: move the origin, sizeScale and y axis inversion to application code in order to amortize redundant per-vertex calculations. - - /** - * The transform uniform should be changed to the result of the transformation chain: - * - * view * modelTransform * invertYAxis * sizeScale * origin - * - * which could be simplified to: - * - * view * modelTransform * convertToDOMSpace - * - * where convertToDOMSpace represents the transform matrix: - * - * size.x 0 0 size.x - * 0 -size.y 0 size.y - * 0 0 1 0 - * 0 0 0 1 - * - */ - +vec3 clipSpacePos(in vec3 pos) { /** * Assuming a unit volume, moves the object space origin [0, 0, 0] to the "top left" [1, -1, 0], the DOM space origin. * Later in the transformation chain, the projection transform negates the rigidbody translation. * Equivalent to (but much faster than) multiplying a translation matrix "origin" * - * 1 0 0 1 + * 1 0 0 1 * 0 1 0 -1 * 0 0 1 0 * 0 0 0 1 @@ -87,7 +59,7 @@ vec4 applyTransform(vec4 pos) { * by the inverse of the canvas' resolution. * Equivalent to (but much faster than) multiplying a scale matrix "sizeScale" * - * size.x 0 0 0 + * size.x 0 0 0 * 0 size.y 0 0 * 0 0 size.z 0 * 0 0 0 1 @@ -97,11 +69,11 @@ vec4 applyTransform(vec4 pos) { pos.xyz *= u_size * 0.5; /** - * Inverts the object space's y axis in order to match DOM space conventions. + * Inverts the object space's y axis in order to match DOM space conventions. * Later in the transformation chain, the projection transform reinverts the y axis to convert to clip space. * Equivalent to (but much faster than) multiplying a scale matrix "invertYAxis" * - * 1 0 0 0 + * 1 0 0 0 * 0 -1 0 0 * 0 0 1 0 * 0 0 0 1 @@ -110,50 +82,9 @@ vec4 applyTransform(vec4 pos) { */ pos.y *= -1.0; - /** - * Exporting the vertex's position as a varying, in DOM space, to be used for lighting calculations. This has to be in DOM space - * since light position and direction is derived from the scene graph, calculated in DOM space. - */ - - v_position = (MVMatrix * pos).xyz; - - /** - * Exporting the eye vector (a vector from the center of the screen) as a varying, to be used for lighting calculations. - * In clip space deriving the eye vector is a matter of simply taking the inverse of the position, as the position is a vector - * from the center of the screen. However, since our points are represented in DOM space, - * the position is a vector from the top left corner of the screen, so some additional math is needed (specifically, subtracting - * the position from the center of the screen, i.e. half the resolution of the canvas). - */ - - v_eyeVector = (u_resolution * 0.5) - v_position; - - /** - * Transforming the position (currently represented in dom space) into view space (with our dom space view transform) - * and then projecting the point into raster both by applying a perspective transformation and converting to clip space - * (the perspective matrix is a combination of both transformations, therefore it's probably more apt to refer to it as a - * projection transform). - */ - - pos = u_perspective * MVMatrix * pos; - return pos; } -/** - * Placeholder for positionOffset chunks to be templated in. - * Used for mesh deformation. - * - * @method calculateOffset - * @private - * - * - */ -#vert_definitions -vec3 calculateOffset(vec3 ID) { - #vert_applications - return vec3(0.0); -} - /** * Writes the position of the vertex onto the screen. * Passes texture coordinate and normal attributes as varyings @@ -165,10 +96,22 @@ vec3 calculateOffset(vec3 ID) { * */ void main() { - v_textureCoordinate = a_texCoord; - vec3 invertedNormals = a_normals + (u_normals.x < 0.0 ? calculateOffset(u_normals) * 2.0 - 1.0 : vec3(0.0)); + vec4 mvPos; + vec3 offsetPos, + invertedNormals; + + invertedNormals = a_normals; invertedNormals.y *= -1.0; - v_normal = transpose(mat3(inverse(u_transform))) * invertedNormals; - vec3 offsetPos = a_pos + calculateOffset(u_positionOffset); - gl_Position = applyTransform(vec4(offsetPos, 1.0)); + + v_normal = u_normalMatrix * invertedNormals; + v_tangent = u_normalMatrix * a_tangent; + v_textureCoordinate = a_texCoord; + + offsetPos = (u_positionOffset.x < 0.0) ? a_pos + calculateOffset(u_positionOffset) : a_pos; + offsetPos = clipSpacePos(offsetPos); + mvPos = u_mvMatrix * vec4(offsetPos, 1.0); + v_position = mvPos.xyz; + v_eyeVector = (u_resolution * 0.5) - v_position; + + gl_Position = u_perspective * mvPos; } diff --git a/webgl-shaders/chunks/applyLight.glsl b/webgl-shaders/chunks/applyLight.glsl index 00c742bc..330703d2 100644 --- a/webgl-shaders/chunks/applyLight.glsl +++ b/webgl-shaders/chunks/applyLight.glsl @@ -1,18 +1,18 @@ /** * The MIT License (MIT) - * + * * Copyright (c) 2015 Famous Industries Inc. - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -29,12 +29,13 @@ * @private * */ -vec4 applyLight(in vec4 baseColor, in vec3 normal, in vec4 glossiness, int numLights, vec3 ambientColor, vec3 eyeVector, mat4 lightPosition, mat4 lightColor, vec3 v_position) { +vec4 applyLight(vec4 baseColor, vec3 normal, vec4 glossiness, int numLights, vec3 ambience, vec3 eyeVector, mat4 lightPosition, mat4 lightColor, vec3 v_position) { vec3 diffuse = vec3(0.0); bool hasGlossiness = glossiness.a > 0.0; bool hasSpecularColor = length(glossiness.rgb) > 0.0; for(int i = 0; i < 4; i++) { + if (i >= numLights) break; vec3 lightDirection = normalize(lightPosition[i].xyz - v_position); float lambertian = max(dot(lightDirection, normal), 0.0); @@ -48,10 +49,9 @@ vec4 applyLight(in vec4 baseColor, in vec3 normal, in vec4 glossiness, int numLi diffuse += specularColor * specularWeight * lambertian; } } - } - return vec4(ambientColor + diffuse, baseColor.a); + return vec4(ambience + diffuse, baseColor.a); } #pragma glslify: export(applyLight) diff --git a/webgl-shaders/chunks/getNormalMatrix.glsl b/webgl-shaders/chunks/getNormalMatrix.glsl deleted file mode 100644 index eada8f9e..00000000 --- a/webgl-shaders/chunks/getNormalMatrix.glsl +++ /dev/null @@ -1,74 +0,0 @@ -/** - * The MIT License (MIT) - * - * Copyright (c) 2015 Famous Industries Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -/** - * Calculates transpose inverse matrix from transform - * - * @method random - * @private - * - * - */ - - -mat3 getNormalMatrix(in mat4 t) { - mat3 matNorm; - mat4 a = t; - - float a00 = a[0][0], a01 = a[0][1], a02 = a[0][2], a03 = a[0][3], - a10 = a[1][0], a11 = a[1][1], a12 = a[1][2], a13 = a[1][3], - a20 = a[2][0], a21 = a[2][1], a22 = a[2][2], a23 = a[2][3], - a30 = a[3][0], a31 = a[3][1], a32 = a[3][2], a33 = a[3][3], - b00 = a00 * a11 - a01 * a10, - b01 = a00 * a12 - a02 * a10, - b02 = a00 * a13 - a03 * a10, - b03 = a01 * a12 - a02 * a11, - b04 = a01 * a13 - a03 * a11, - b05 = a02 * a13 - a03 * a12, - b06 = a20 * a31 - a21 * a30, - b07 = a20 * a32 - a22 * a30, - b08 = a20 * a33 - a23 * a30, - b09 = a21 * a32 - a22 * a31, - b10 = a21 * a33 - a23 * a31, - b11 = a22 * a33 - a23 * a32, - - det = b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06; - det = 1.0 / det; - - matNorm[0][0] = (a11 * b11 - a12 * b10 + a13 * b09) * det; - matNorm[0][1] = (a12 * b08 - a10 * b11 - a13 * b07) * det; - matNorm[0][2] = (a10 * b10 - a11 * b08 + a13 * b06) * det; - - matNorm[1][0] = (a02 * b10 - a01 * b11 - a03 * b09) * det; - matNorm[1][1] = (a00 * b11 - a02 * b08 + a03 * b07) * det; - matNorm[1][2] = (a01 * b08 - a00 * b10 - a03 * b06) * det; - - matNorm[2][0] = (a31 * b05 - a32 * b04 + a33 * b03) * det; - matNorm[2][1] = (a32 * b02 - a30 * b05 - a33 * b01) * det; - matNorm[2][2] = (a30 * b04 - a31 * b02 + a33 * b00) * det; - - return matNorm; -} - -#pragma glslify: export(getNormalMatrix)