From ce0aec51636defa1d8e7c3824f4767a69225ebeb Mon Sep 17 00:00:00 2001 From: Farhad Ghayour Date: Thu, 18 Jun 2015 13:41:47 -0700 Subject: [PATCH 01/12] Feat: Add glMatrix for math support --- core/Transform.js | 93 ++--------------------------------------------- package.json | 1 + 2 files changed, 5 insertions(+), 89 deletions(-) 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": { From 0375c2cb788c1f60123fb0c8ace633ef15acf99c Mon Sep 17 00:00:00 2001 From: redwoodfavorite Date: Thu, 18 Jun 2015 15:23:27 -0700 Subject: [PATCH 02/12] feat: coordinates working with mvMatrix uniform --- webgl-renderers/Program.js | 5 +- webgl-renderers/WebGLRenderer.js | 20 ++++-- webgl-shaders/VertexShader.glsl | 102 ++++++++----------------------- 3 files changed, 43 insertions(+), 84 deletions(-) diff --git a/webgl-renderers/Program.js b/webgl-renderers/Program.js index 526f8e64..eb8853d7 100644 --- a/webgl-renderers/Program.js +++ b/webgl-renderers/Program.js @@ -43,6 +43,7 @@ var TYPES = { 2: 'vec2 ', 3: 'vec3 ', 4: 'vec4 ', + 9: 'mat3 ', 16: 'mat4 ' }; @@ -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, diff --git a/webgl-renderers/WebGLRenderer.js b/webgl-renderers/WebGLRenderer.js index da718a16..0d3381d5 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) }); /** @@ -536,7 +543,7 @@ WebGLRenderer.prototype.draw = function draw(renderState) { this.setGlobalUniforms(renderState); this.drawCutouts(); - this.drawMeshes(); + 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,12 @@ WebGLRenderer.prototype.drawMeshes = function drawMeshes() { if (mesh.options) this.handleOptions(mesh.options, mesh); + mat44.multiply(meshTransforms.values[0], renderState.viewTransform, mesh.uniformValues[1]); + 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); diff --git a/webgl-shaders/VertexShader.glsl b/webgl-shaders/VertexShader.glsl index d064b848..c27a455e 100644 --- a/webgl-shaders/VertexShader.glsl +++ b/webgl-shaders/VertexShader.glsl @@ -27,45 +27,21 @@ #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. @@ -110,50 +86,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 +100,21 @@ vec3 calculateOffset(vec3 ID) { * */ void main() { + vec3 offsetPos, + invertedNormals; + + vec4 pos4; + v_textureCoordinate = a_texCoord; - vec3 invertedNormals = a_normals + (u_normals.x < 0.0 ? calculateOffset(u_normals) * 2.0 - 1.0 : vec3(0.0)); + + 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; + + offsetPos = a_pos + calculateOffset(u_positionOffset); + offsetPos = clipSpacePos(offsetPos); + pos4 = vec4(offsetPos, 1.0); + v_position = (u_mvMatrix * pos4).xyz; + v_eyeVector = (u_resolution * 0.5) - v_position; + gl_Position = u_perspective * u_mvMatrix * pos4; } From 038ea6acedc38d71b9486b8df284e605870d22cf Mon Sep 17 00:00:00 2001 From: redwoodfavorite Date: Thu, 18 Jun 2015 20:26:50 -0700 Subject: [PATCH 03/12] feat: cutout mat uniforms --- webgl-renderers/WebGLRenderer.js | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/webgl-renderers/WebGLRenderer.js b/webgl-renderers/WebGLRenderer.js index 0d3381d5..131b266e 100644 --- a/webgl-renderers/WebGLRenderer.js +++ b/webgl-renderers/WebGLRenderer.js @@ -542,7 +542,7 @@ WebGLRenderer.prototype.draw = function draw(renderState) { this.meshRegistryKeys = sorter(this.meshRegistryKeys, this.meshRegistry); this.setGlobalUniforms(renderState); - this.drawCutouts(); + this.drawCutouts(renderState); this.drawMeshes(renderState); }; @@ -602,7 +602,7 @@ WebGLRenderer.prototype.drawMeshes = function drawMeshes(renderState) { * * @return {undefined} undefined */ -WebGLRenderer.prototype.drawCutouts = function drawCutouts() { +WebGLRenderer.prototype.drawCutouts = function drawCutouts(renderState) { var cutout; var buffers; var len = this.cutoutRegistryKeys.length; @@ -616,10 +616,14 @@ WebGLRenderer.prototype.drawCutouts = function drawCutouts() { for (var i = 0; i < len; i++) { cutout = this.cutoutRegistry[this.cutoutRegistryKeys[i]]; buffers = this.bufferRegistry.registry[cutout.geometry]; - + 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); } From 590c29ada2aacf292ac15a263b652e6d9e799598 Mon Sep 17 00:00:00 2001 From: redwoodfavorite Date: Thu, 18 Jun 2015 20:52:48 -0700 Subject: [PATCH 04/12] feat: wip fragment shader refactor and normal applicatoin --- webgl-shaders/FragmentShader.glsl | 26 +++++++++++++++----------- webgl-shaders/chunks/applyLight.glsl | 5 +++-- 2 files changed, 18 insertions(+), 13 deletions(-) diff --git a/webgl-shaders/FragmentShader.glsl b/webgl-shaders/FragmentShader.glsl index b440695b..5698f32a 100644 --- a/webgl-shaders/FragmentShader.glsl +++ b/webgl-shaders/FragmentShader.glsl @@ -36,25 +36,29 @@ */ void main() { vec4 material = u_baseColor.r >= 0.0 ? u_baseColor : applyMaterial(u_baseColor); - + vec4 color; /** * Apply lights only if flat shading is false * and at least one light is added to the scene */ bool lightsEnabled = (u_flatShading == 0.0) && (u_numLights > 0.0 || length(u_ambientLight) > 0.0); - vec3 normal = normalize(v_normal); + vec3 normalOffset = u_normals.x < 0.0 ? applyMaterial(u_normals) * 2.0 - 1.0 : vec3(0.0); + vec3 normal = normalize(u_normalMatrix * (v_normal + normalOffset)); + normal.y *= -1.0; + vec4 glossiness = u_glossiness.x < 0.0 ? applyMaterial(u_glossiness) : u_glossiness; + int numLights = int(u_numLights); + vec3 ambience = u_ambientLight * u_baseColor.rgb; + vec3 eyeVector = normalize(v_eyeVector); - 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; + if (lightsEnabled) { + color = applyLight(material, normal, glossiness, numLights, ambience, + eyeVector, u_lightPosition, u_lightColor, v_position); + } + else { + color = material; + } gl_FragColor = color; gl_FragColor.a *= u_opacity; diff --git a/webgl-shaders/chunks/applyLight.glsl b/webgl-shaders/chunks/applyLight.glsl index 00c742bc..fee6ff45 100644 --- a/webgl-shaders/chunks/applyLight.glsl +++ b/webgl-shaders/chunks/applyLight.glsl @@ -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); @@ -51,7 +52,7 @@ vec4 applyLight(in vec4 baseColor, in vec3 normal, in vec4 glossiness, int numLi } - return vec4(ambientColor + diffuse, baseColor.a); + return vec4(ambience + diffuse, baseColor.a); } #pragma glslify: export(applyLight) From 29f8a4964d92bb2d2a6a8b79757ea8df5c46748b Mon Sep 17 00:00:00 2001 From: redwoodfavorite Date: Thu, 18 Jun 2015 21:12:32 -0700 Subject: [PATCH 05/12] feat: moving normal offset to shader, refactor vertex shader --- webgl-renderers/Program.js | 2 +- webgl-shaders/FragmentShader.glsl | 3 ++- webgl-shaders/VertexShader.glsl | 11 +++++------ 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/webgl-renderers/Program.js b/webgl-renderers/Program.js index eb8853d7..c5e545d9 100644 --- a/webgl-renderers/Program.js +++ b/webgl-renderers/Program.js @@ -49,7 +49,7 @@ var TYPES = { var inputTypes = { u_baseColor: 'vec4', - u_normals: 'vert', + u_normals: 'vec3', u_glossiness: 'vec4', u_positionOffset: 'vert' }; diff --git a/webgl-shaders/FragmentShader.glsl b/webgl-shaders/FragmentShader.glsl index 5698f32a..a8a6a448 100644 --- a/webgl-shaders/FragmentShader.glsl +++ b/webgl-shaders/FragmentShader.glsl @@ -36,7 +36,7 @@ */ void main() { vec4 material = u_baseColor.r >= 0.0 ? u_baseColor : applyMaterial(u_baseColor); - vec4 color; + /** * Apply lights only if flat shading is false * and at least one light is added to the scene @@ -51,6 +51,7 @@ void main() { int numLights = int(u_numLights); vec3 ambience = u_ambientLight * u_baseColor.rgb; vec3 eyeVector = normalize(v_eyeVector); + vec4 color; if (lightsEnabled) { color = applyLight(material, normal, glossiness, numLights, ambience, diff --git a/webgl-shaders/VertexShader.glsl b/webgl-shaders/VertexShader.glsl index c27a455e..276cea31 100644 --- a/webgl-shaders/VertexShader.glsl +++ b/webgl-shaders/VertexShader.glsl @@ -100,21 +100,20 @@ vec3 clipSpacePos(in vec3 pos) { * */ void main() { + vec4 mvPos; vec3 offsetPos, invertedNormals; - vec4 pos4; - v_textureCoordinate = a_texCoord; invertedNormals = a_normals; invertedNormals.y *= -1.0; v_normal = u_normalMatrix * invertedNormals; - offsetPos = a_pos + calculateOffset(u_positionOffset); + offsetPos = (u_positionOffset.x < 0.0) ? a_pos + calculateOffset(u_positionOffset) : a_pos; offsetPos = clipSpacePos(offsetPos); - pos4 = vec4(offsetPos, 1.0); - v_position = (u_mvMatrix * pos4).xyz; + mvPos = u_mvMatrix * vec4(offsetPos, 1.0); + v_position = mvPos.xyz; v_eyeVector = (u_resolution * 0.5) - v_position; - gl_Position = u_perspective * u_mvMatrix * pos4; + gl_Position = u_perspective * mvPos; } From 206d398f301381571c9919a62d5857b6f61b1c62 Mon Sep 17 00:00:00 2001 From: redwoodfavorite Date: Thu, 18 Jun 2015 21:15:57 -0700 Subject: [PATCH 06/12] breaks: removing unnecessary shader dependencies, removing getNormalMatrix --- webgl-shaders/VertexShader.glsl | 4 -- webgl-shaders/chunks/getNormalMatrix.glsl | 74 ----------------------- 2 files changed, 78 deletions(-) delete mode 100644 webgl-shaders/chunks/getNormalMatrix.glsl diff --git a/webgl-shaders/VertexShader.glsl b/webgl-shaders/VertexShader.glsl index 276cea31..8b3f1c42 100644 --- a/webgl-shaders/VertexShader.glsl +++ b/webgl-shaders/VertexShader.glsl @@ -22,10 +22,6 @@ * THE SOFTWARE. */ -#pragma glslify: getNormalMatrix = require(./chunks/getNormalMatrix) -#pragma glslify: inverse = require(./chunks/inverse) -#pragma glslify: transpose = require(./chunks/transpose) - /** * Placeholder for positionOffset chunks to be templated in. * Used for mesh deformation. 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) From 0e9eea719e623c7277dc979ee2d3f637d7199f66 Mon Sep 17 00:00:00 2001 From: Farhad Ghayour Date: Thu, 18 Jun 2015 22:39:15 -0700 Subject: [PATCH 07/12] Fix: Update normal matrix math --- webgl-renderers/WebGLRenderer.js | 2 +- webgl-shaders/FragmentShader.glsl | 26 +++++++++++--------------- webgl-shaders/VertexShader.glsl | 24 ++++++++++-------------- webgl-shaders/chunks/applyLight.glsl | 11 +++++------ 4 files changed, 27 insertions(+), 36 deletions(-) diff --git a/webgl-renderers/WebGLRenderer.js b/webgl-renderers/WebGLRenderer.js index 131b266e..79e28170 100644 --- a/webgl-renderers/WebGLRenderer.js +++ b/webgl-renderers/WebGLRenderer.js @@ -616,7 +616,7 @@ WebGLRenderer.prototype.drawCutouts = function drawCutouts(renderState) { for (var i = 0; i < len; i++) { cutout = this.cutoutRegistry[this.cutoutRegistryKeys[i]]; buffers = this.bufferRegistry.registry[cutout.geometry]; - + if (!cutout.visible) continue; mat44.multiply(meshTransforms.values[0], renderState.viewTransform, cutout.uniformValues[1]); diff --git a/webgl-shaders/FragmentShader.glsl b/webgl-shaders/FragmentShader.glsl index a8a6a448..50d8a3b5 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,23 +44,19 @@ void main() { bool lightsEnabled = (u_flatShading == 0.0) && (u_numLights > 0.0 || length(u_ambientLight) > 0.0); vec3 normalOffset = u_normals.x < 0.0 ? applyMaterial(u_normals) * 2.0 - 1.0 : vec3(0.0); - vec3 normal = normalize(u_normalMatrix * (v_normal + normalOffset)); + vec3 normal = (v_normal + normalOffset); normal.y *= -1.0; + normal = normalize(u_normalMatrix * (normal + normalOffset)); vec4 glossiness = u_glossiness.x < 0.0 ? applyMaterial(u_glossiness) : u_glossiness; int numLights = int(u_numLights); - vec3 ambience = u_ambientLight * u_baseColor.rgb; vec3 eyeVector = normalize(v_eyeVector); - vec4 color; + vec3 ambience = u_ambientLight * u_baseColor.rgb; - if (lightsEnabled) { - color = applyLight(material, normal, glossiness, numLights, ambience, - eyeVector, u_lightPosition, u_lightColor, v_position); - } - else { - color = 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 8b3f1c42..815a4857 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 @@ -43,7 +43,7 @@ vec3 clipSpacePos(in vec3 pos) { * 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 @@ -59,7 +59,7 @@ vec3 clipSpacePos(in vec3 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 @@ -69,11 +69,11 @@ vec3 clipSpacePos(in vec3 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 @@ -98,14 +98,10 @@ vec3 clipSpacePos(in vec3 pos) { void main() { vec4 mvPos; vec3 offsetPos, - invertedNormals; + invertedNormals; v_textureCoordinate = a_texCoord; - - invertedNormals = a_normals; - invertedNormals.y *= -1.0; - v_normal = u_normalMatrix * invertedNormals; - + v_normal = a_normals; offsetPos = (u_positionOffset.x < 0.0) ? a_pos + calculateOffset(u_positionOffset) : a_pos; offsetPos = clipSpacePos(offsetPos); mvPos = u_mvMatrix * vec4(offsetPos, 1.0); diff --git a/webgl-shaders/chunks/applyLight.glsl b/webgl-shaders/chunks/applyLight.glsl index fee6ff45..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 @@ -35,7 +35,7 @@ vec4 applyLight(vec4 baseColor, vec3 normal, vec4 glossiness, int numLights, vec 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); @@ -49,7 +49,6 @@ vec4 applyLight(vec4 baseColor, vec3 normal, vec4 glossiness, int numLights, vec diffuse += specularColor * specularWeight * lambertian; } } - } return vec4(ambience + diffuse, baseColor.a); From 19ed4632f59ce9062d92a72ac6b5836a93b81d7d Mon Sep 17 00:00:00 2001 From: Farhad Ghayour Date: Thu, 18 Jun 2015 22:42:25 -0700 Subject: [PATCH 08/12] Chore: Add docs for MV matrix updates --- webgl-renderers/WebGLRenderer.js | 3 +++ webgl-shaders/VertexShader.glsl | 4 +++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/webgl-renderers/WebGLRenderer.js b/webgl-renderers/WebGLRenderer.js index 79e28170..204aa4cc 100644 --- a/webgl-renderers/WebGLRenderer.js +++ b/webgl-renderers/WebGLRenderer.js @@ -582,7 +582,10 @@ WebGLRenderer.prototype.drawMeshes = function drawMeshes(renderState) { 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); diff --git a/webgl-shaders/VertexShader.glsl b/webgl-shaders/VertexShader.glsl index 815a4857..23fc892c 100644 --- a/webgl-shaders/VertexShader.glsl +++ b/webgl-shaders/VertexShader.glsl @@ -100,12 +100,14 @@ void main() { vec3 offsetPos, invertedNormals; - v_textureCoordinate = a_texCoord; v_normal = a_normals; + 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; } From 72890aecd0a7c4d39f0ee7e52cba93534ac0308d Mon Sep 17 00:00:00 2001 From: redwoodfavorite Date: Thu, 18 Jun 2015 22:51:19 -0700 Subject: [PATCH 09/12] fix: normal offset fix --- webgl-shaders/FragmentShader.glsl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/webgl-shaders/FragmentShader.glsl b/webgl-shaders/FragmentShader.glsl index 50d8a3b5..4e7c90b4 100644 --- a/webgl-shaders/FragmentShader.glsl +++ b/webgl-shaders/FragmentShader.glsl @@ -46,7 +46,7 @@ void main() { vec3 normalOffset = u_normals.x < 0.0 ? applyMaterial(u_normals) * 2.0 - 1.0 : vec3(0.0); vec3 normal = (v_normal + normalOffset); normal.y *= -1.0; - normal = normalize(u_normalMatrix * (normal + normalOffset)); + normal = normalize(u_normalMatrix * normal); vec4 glossiness = u_glossiness.x < 0.0 ? applyMaterial(u_glossiness) : u_glossiness; int numLights = int(u_numLights); From 7de926479e46f89c6ae3a5f2696f3b619c96ba8d Mon Sep 17 00:00:00 2001 From: redwoodfavorite Date: Thu, 25 Jun 2015 00:24:55 -0700 Subject: [PATCH 10/12] Feat: wip tangent calculation for accurate normal maps --- webgl-geometries/GeometryHelper.js | 102 +++++++++++++++++++++++++++++ webgl-geometries/primitives/Box.js | 24 +++++-- webgl-renderers/Program.js | 6 +- webgl-shaders/FragmentShader.glsl | 18 +++-- webgl-shaders/VertexShader.glsl | 6 +- 5 files changed, 142 insertions(+), 14 deletions(-) diff --git a/webgl-geometries/GeometryHelper.js b/webgl-geometries/GeometryHelper.js index c9c75d7e..19daa18d 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,104 @@ 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]; + + console.log(t) + } + + 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-renderers/Program.js b/webgl-renderers/Program.js index c5e545d9..5696ea1b 100644 --- a/webgl-renderers/Program.js +++ b/webgl-renderers/Program.js @@ -90,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] }); /** @@ -100,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-shaders/FragmentShader.glsl b/webgl-shaders/FragmentShader.glsl index 4e7c90b4..87d9138d 100644 --- a/webgl-shaders/FragmentShader.glsl +++ b/webgl-shaders/FragmentShader.glsl @@ -43,10 +43,18 @@ void main() { */ bool lightsEnabled = (u_flatShading == 0.0) && (u_numLights > 0.0 || length(u_ambientLight) > 0.0); + vec3 normal = normalize(v_normal); + vec3 tangent = normalize(v_tangent); + + tangent = normalize(tangent - dot(tangent, normal) * normal); + vec3 bitangent = cross(tangent, normal); vec3 normalOffset = u_normals.x < 0.0 ? applyMaterial(u_normals) * 2.0 - 1.0 : vec3(0.0); - vec3 normal = (v_normal + normalOffset); - normal.y *= -1.0; - normal = normalize(u_normalMatrix * normal); + normalOffset.y *= 1.0; + + mat3 TBNMatrix = mat3(tangent, bitangent, normal); + vec3 newNormal = 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); @@ -54,9 +62,9 @@ void main() { vec3 ambience = u_ambientLight * u_baseColor.rgb; vec4 color = !lightsEnabled ? material : - applyLight(material, normal, glossiness, numLights, ambience, + applyLight(material, newNormal, glossiness, numLights, ambience, eyeVector, u_lightPosition, u_lightColor, v_position); - gl_FragColor = color; + gl_FragColor = vec4((v_tangent + 1.0) * 0.5, 1.0); gl_FragColor.a *= u_opacity; } diff --git a/webgl-shaders/VertexShader.glsl b/webgl-shaders/VertexShader.glsl index 23fc892c..271660d2 100644 --- a/webgl-shaders/VertexShader.glsl +++ b/webgl-shaders/VertexShader.glsl @@ -100,7 +100,11 @@ void main() { vec3 offsetPos, invertedNormals; - v_normal = a_normals; + invertedNormals = a_normals; + invertedNormals.y *= -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; From 3c8ad44cacbcec455622342bc214ba41f6d4925e Mon Sep 17 00:00:00 2001 From: redwoodfavorite Date: Thu, 25 Jun 2015 13:15:40 -0700 Subject: [PATCH 11/12] Feat: tangent functionality for sphere --- webgl-geometries/GeometryHelper.js | 3 --- webgl-geometries/primitives/Sphere.js | 25 +++++++++++++++++++------ webgl-shaders/FragmentShader.glsl | 2 +- 3 files changed, 20 insertions(+), 10 deletions(-) diff --git a/webgl-geometries/GeometryHelper.js b/webgl-geometries/GeometryHelper.js index 19daa18d..9281d464 100644 --- a/webgl-geometries/GeometryHelper.js +++ b/webgl-geometries/GeometryHelper.js @@ -615,7 +615,6 @@ GeometryHelper.computeTangents = function computeTangents(vertices, indices, nor (t2 * z1 - t1 * z2) * r ); - vec3.set(tdir, (s1 * x2 - s2 * x1) * r, (s1 * y2 - s2 * y1) * r, @@ -658,8 +657,6 @@ GeometryHelper.computeTangents = function computeTangents(vertices, indices, nor out[i * 3] = t[0]; out[i * 3 + 1] = t[1]; out[i * 3 + 2] = t[2]; - - console.log(t) } return out; 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-shaders/FragmentShader.glsl b/webgl-shaders/FragmentShader.glsl index 87d9138d..48ebb919 100644 --- a/webgl-shaders/FragmentShader.glsl +++ b/webgl-shaders/FragmentShader.glsl @@ -65,6 +65,6 @@ void main() { applyLight(material, newNormal, glossiness, numLights, ambience, eyeVector, u_lightPosition, u_lightColor, v_position); - gl_FragColor = vec4((v_tangent + 1.0) * 0.5, 1.0); + gl_FragColor = color; gl_FragColor.a *= u_opacity; } From f9a1859e62035f3ce89f5188a744dd1e8cb30bf3 Mon Sep 17 00:00:00 2001 From: redwoodfavorite Date: Thu, 25 Jun 2015 19:46:24 -0700 Subject: [PATCH 12/12] Feat: disabling normalOffset calculation when not necessary --- webgl-shaders/FragmentShader.glsl | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/webgl-shaders/FragmentShader.glsl b/webgl-shaders/FragmentShader.glsl index 48ebb919..d4b89f5e 100644 --- a/webgl-shaders/FragmentShader.glsl +++ b/webgl-shaders/FragmentShader.glsl @@ -44,16 +44,17 @@ void main() { bool lightsEnabled = (u_flatShading == 0.0) && (u_numLights > 0.0 || length(u_ambientLight) > 0.0); vec3 normal = normalize(v_normal); - vec3 tangent = normalize(v_tangent); - - tangent = normalize(tangent - dot(tangent, normal) * normal); - vec3 bitangent = cross(tangent, normal); - vec3 normalOffset = u_normals.x < 0.0 ? applyMaterial(u_normals) * 2.0 - 1.0 : vec3(0.0); - normalOffset.y *= 1.0; - - mat3 TBNMatrix = mat3(tangent, bitangent, normal); - vec3 newNormal = normalize(TBNMatrix * normalOffset); + 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; @@ -62,7 +63,7 @@ void main() { vec3 ambience = u_ambientLight * u_baseColor.rgb; vec4 color = !lightsEnabled ? material : - applyLight(material, newNormal, glossiness, numLights, ambience, + applyLight(material, normal, glossiness, numLights, ambience, eyeVector, u_lightPosition, u_lightColor, v_position); gl_FragColor = color;