diff --git a/src/accessibility/outputs.js b/src/accessibility/outputs.js index 8d1f399969..97b38712f4 100644 --- a/src/accessibility/outputs.js +++ b/src/accessibility/outputs.js @@ -543,7 +543,7 @@ function outputs(p5, fn){ fn._getPos = function (x, y) { const untransformedPosition = new DOMPointReadOnly(x, y); const currentTransform = this._renderer.isP3D ? - new DOMMatrix(this._renderer.states.uMVMatrix.mat4) : + new DOMMatrix(this._renderer.calculateCombinedMatrix()) : this.drawingContext.getTransform(); const { x: transformedX, y: transformedY } = untransformedPosition .matrixTransform(currentTransform); diff --git a/src/webgl/GeometryBuilder.js b/src/webgl/GeometryBuilder.js index 9d5783dbf9..5cb4862168 100644 --- a/src/webgl/GeometryBuilder.js +++ b/src/webgl/GeometryBuilder.js @@ -37,7 +37,7 @@ class GeometryBuilder { if (!this.hasTransform) return normals; return normals.map( - v => this.renderer.states.uNMatrix.multiplyVec(v) // this is a vec3 + v => this.renderer.scratchMat3.multiplyVec(v) // this is a vec3 ); } @@ -51,7 +51,7 @@ class GeometryBuilder { .every((v, i) => v === this.identityMatrix.mat4[i]); if (this.hasTransform) { - this.renderer.states.uNMatrix.inverseTranspose4x4(this.renderer.states.uModelMatrix); + this.renderer.scratchMat3.inverseTranspose4x4(this.renderer.states.uModelMatrix); } let startIdx = this.geometry.vertices.length; diff --git a/src/webgl/material.js b/src/webgl/material.js index d63b9a6b69..3fdb3733cd 100644 --- a/src/webgl/material.js +++ b/src/webgl/material.js @@ -1195,56 +1195,34 @@ function material(p5, fn){ * * * - * `vec3 getLocalPosition` + * `Vertex getObjectInputs` * * * - * Update the position of vertices before transforms are applied. It takes in `vec3 position` and must return a modified version. - * - * - * - * - * `vec3 getWorldPosition` - * - * - * - * Update the position of vertices after transforms are applied. It takes in `vec3 position` and pust return a modified version. - * - * - * - * - * `vec3 getLocalNormal` - * - * - * - * Update the normal before transforms are applied. It takes in `vec3 normal` and must return a modified version. - * - * - * - * - * `vec3 getWorldNormal` - * - * - * - * Update the normal after transforms are applied. It takes in `vec3 normal` and must return a modified version. + * Update the vertex data of the model being drawn before any positioning has been applied. It takes in a `Vertex` struct, which includes: + * - `vec3 position`, the position of the vertex + * - `vec3 normal`, the direction facing out of the surface + * - `vec2 uv`, the texture coordinates associeted with the vertex + * - `vec4 color`, the per-vertex color + * The struct can be modified and returned. * * * * - * `vec2 getUV` + * `Vertex getWorldInputs` * * * - * Update the texture coordinates. It takes in `vec2 uv` and must return a modified version. + * Update the vertex data of the model being drawn after transformations such as `translate()` and `scale()` have been applied, but before the camera has been applied. It takes in a `Vertex` struct like, in the `getObjectInputs` hook above, that can be modified and returned. * * * * - * `vec4 getVertexColor` + * `Vertex getCameraInputs` * * * - * Update the color of each vertex. It takes in a `vec4 color` and must return a modified version. + * Update the vertex data of the model being drawn as they appear relative to the camera. It takes in a `Vertex` struct like, in the `getObjectInputs` hook above, that can be modified and returned. * * * @@ -1342,9 +1320,10 @@ function material(p5, fn){ * uniforms: { * 'float time': () => millis() * }, - * 'vec3 getWorldPosition': `(vec3 pos) { - * pos.y += 20.0 * sin(time * 0.001 + pos.x * 0.05); - * return pos; + * 'Vertex getWorldInputs': `(Vertex inputs) { + * inputs.position.y += + * 20.0 * sin(time * 0.001 + inputs.position.x * 0.05); + * return inputs; * }` * }); * } @@ -1492,19 +1471,86 @@ function material(p5, fn){ * You can call `baseNormalShader().modify()` * and change any of the following hooks: * - * Hook | Description - * -----|------------ - * `void beforeVertex` | Called at the start of the vertex shader. - * `vec3 getLocalPosition` | Update the position of vertices before transforms are applied. It takes in `vec3 position` and must return a modified version. - * `vec3 getWorldPosition` | Update the position of vertices after transforms are applied. It takes in `vec3 position` and pust return a modified version. - * `vec3 getLocalNormal` | Update the normal before transforms are applied. It takes in `vec3 normal` and must return a modified version. - * `vec3 getWorldNormal` | Update the normal after transforms are applied. It takes in `vec3 normal` and must return a modified version. - * `vec2 getUV` | Update the texture coordinates. It takes in `vec2 uv` and must return a modified version. - * `vec4 getVertexColor` | Update the color of each vertex. It takes in a `vec4 color` and must return a modified version. - * `void afterVertex` | Called at the end of the vertex shader. - * `void beforeFragment` | Called at the start of the fragment shader. - * `vec4 getFinalColor` | Update the final color after mixing. It takes in a `vec4 color` and must return a modified version. - * `void afterFragment` | Called at the end of the fragment shader. + * + * + * + * + * + * + * + * + * + * + *
HookDescription
+ * + * `void beforeVertex` + * + * + * + * Called at the start of the vertex shader. + * + *
+ * + * `Vertex getObjectInputs` + * + * + * + * Update the vertex data of the model being drawn before any positioning has been applied. It takes in a `Vertex` struct, which includes: + * - `vec3 position`, the position of the vertex + * - `vec3 normal`, the direction facing out of the surface + * - `vec2 uv`, the texture coordinates associeted with the vertex + * - `vec4 color`, the per-vertex color + * The struct can be modified and returned. + * + *
+ * + * `Vertex getWorldInputs` + * + * + * + * Update the vertex data of the model being drawn after transformations such as `translate()` and `scale()` have been applied, but before the camera has been applied. It takes in a `Vertex` struct like, in the `getObjectInputs` hook above, that can be modified and returned. + * + *
+ * + * `Vertex getCameraInputs` + * + * + * + * Update the vertex data of the model being drawn as they appear relative to the camera. It takes in a `Vertex` struct like, in the `getObjectInputs` hook above, that can be modified and returned. + * + *
+ * + * `void afterVertex` + * + * + * + * Called at the end of the vertex shader. + * + *
+ * + * `void beforeFragment` + * + * + * + * Called at the start of the fragment shader. + * + *
+ * + * `vec4 getFinalColor` + * + * + * + * Update the final color after mixing. It takes in a `vec4 color` and must return a modified version. + * + *
+ * + * `void afterFragment` + * + * + * + * Called at the end of the fragment shader. + * + *
* * Most of the time, you will need to write your hooks in GLSL ES version 300. If you * are using WebGL 1 instead of 2, write your hooks in GLSL ES 100 instead. @@ -1527,9 +1573,10 @@ function material(p5, fn){ * uniforms: { * 'float time': () => millis() * }, - * 'vec3 getWorldPosition': `(vec3 pos) { - * pos.y += 20. * sin(time * 0.001 + pos.x * 0.05); - * return pos; + * 'Vertex getWorldInputs': `(Vertex inputs) { + * inputs.position.y += + * 20. * sin(time * 0.001 + inputs.position.x * 0.05); + * return inputs; * }` * }); * } @@ -1551,7 +1598,10 @@ function material(p5, fn){ * function setup() { * createCanvas(200, 200, WEBGL); * myShader = baseNormalShader().modify({ - * 'vec3 getWorldNormal': '(vec3 normal) { return abs(normal); }', + * 'Vertex getCameraInputs': `(Vertex inputs) { + * inputs.normal = abs(inputs.normal); + * return inputs; + * }`, * 'vec4 getFinalColor': `(vec4 color) { * // Map the r, g, and b values of the old normal to new colors * // instead of just red, green, and blue: @@ -1587,19 +1637,86 @@ function material(p5, fn){ * You can call `baseColorShader().modify()` * and change any of the following hooks: * - * Hook | Description - * -------|------------- - * `void beforeVertex` | Called at the start of the vertex shader. - * `vec3 getLocalPosition` | Update the position of vertices before transforms are applied. It takes in `vec3 position` and must return a modified version. - * `vec3 getWorldPosition` | Update the position of vertices after transforms are applied. It takes in `vec3 position` and pust return a modified version. - * `vec3 getLocalNormal` | Update the normal before transforms are applied. It takes in `vec3 normal` and must return a modified version. - * `vec3 getWorldNormal` | Update the normal after transforms are applied. It takes in `vec3 normal` and must return a modified version. - * `vec2 getUV` | Update the texture coordinates. It takes in `vec2 uv` and must return a modified version. - * `vec4 getVertexColor` | Update the color of each vertex. It takes in a `vec4 color` and must return a modified version. - * `void afterVertex` | Called at the end of the vertex shader. - * `void beforeFragment` | Called at the start of the fragment shader. - * `vec4 getFinalColor` | Update the final color after mixing. It takes in a `vec4 color` and must return a modified version. - * `void afterFragment` | Called at the end of the fragment shader. + * + * + * + * + * + * + * + * + * + * + *
HookDescription
+ * + * `void beforeVertex` + * + * + * + * Called at the start of the vertex shader. + * + *
+ * + * `Vertex getObjectInputs` + * + * + * + * Update the vertex data of the model being drawn before any positioning has been applied. It takes in a `Vertex` struct, which includes: + * - `vec3 position`, the position of the vertex + * - `vec3 normal`, the direction facing out of the surface + * - `vec2 uv`, the texture coordinates associeted with the vertex + * - `vec4 color`, the per-vertex color + * The struct can be modified and returned. + * + *
+ * + * `Vertex getWorldInputs` + * + * + * + * Update the vertex data of the model being drawn after transformations such as `translate()` and `scale()` have been applied, but before the camera has been applied. It takes in a `Vertex` struct like, in the `getObjectInputs` hook above, that can be modified and returned. + * + *
+ * + * `Vertex getCameraInputs` + * + * + * + * Update the vertex data of the model being drawn as they appear relative to the camera. It takes in a `Vertex` struct like, in the `getObjectInputs` hook above, that can be modified and returned. + * + *
+ * + * `void afterVertex` + * + * + * + * Called at the end of the vertex shader. + * + *
+ * + * `void beforeFragment` + * + * + * + * Called at the start of the fragment shader. + * + *
+ * + * `vec4 getFinalColor` + * + * + * + * Update the final color after mixing. It takes in a `vec4 color` and must return a modified version. + * + *
+ * + * `void afterFragment` + * + * + * + * Called at the end of the fragment shader. + * + *
* * Most of the time, you will need to write your hooks in GLSL ES version 300. If you * are using WebGL 1 instead of 2, write your hooks in GLSL ES 100 instead. @@ -1622,9 +1739,10 @@ function material(p5, fn){ * uniforms: { * 'float time': () => millis() * }, - * 'vec3 getWorldPosition': `(vec3 pos) { - * pos.y += 20. * sin(time * 0.001 + pos.x * 0.05); - * return pos; + * 'Vertex getWorldInputs': `(Vertex inputs) { + * inputs.position.y += + * 20. * sin(time * 0.001 + inputs.position.x * 0.05); + * return inputs; * }` * }); * } @@ -1663,56 +1781,35 @@ function material(p5, fn){ * * * - * `vec3 getLocalPosition` - * - * - * - * Update the position of vertices before transforms are applied. It takes in `vec3 position` and must return a modified version. - * - * - * - * - * `vec3 getWorldPosition` - * - * - * - * Update the position of vertices after transforms are applied. It takes in `vec3 position` and pust return a modified version. - * - * - * - * - * `float getStrokeWeight` - * - * - * - * Update the stroke weight. It takes in `float weight` and pust return a modified version. - * - * - * - * - * `vec2 getLineCenter` + * `StrokeVertex getObjectInputs` * * * - * Update the center of the line. It takes in `vec2 center` and must return a modified version. + * Update the vertex data of the stroke being drawn before any positioning has been applied. It takes in a `StrokeVertex` struct, which includes: + * - `vec3 position`, the position of the vertex + * - `vec3 tangentIn`, the tangent coming in to the vertex + * - `vec3 tangentOut`, the tangent coming out of the vertex. In straight segments, this will be the same as `tangentIn`. In joins, it will be different. In caps, one of the tangents will be 0. + * - `vec4 color`, the per-vertex color + * - `float weight`, the stroke weight + * The struct can be modified and returned. * * * * - * `vec2 getLinePosition` + * `StrokeVertex getWorldInputs` * * * - * Update the position of each vertex on the edge of the line. It takes in `vec2 position` and must return a modified version. + * Update the vertex data of the model being drawn after transformations such as `translate()` and `scale()` have been applied, but before the camera has been applied. It takes in a `StrokeVertex` struct like, in the `getObjectInputs` hook above, that can be modified and returned. * * * * - * `vec4 getVertexColor` + * `StrokeVertex getCameraInputs` * * * - * Update the color of each vertex. It takes in a `vec4 color` and must return a modified version. + * Update the vertex data of the model being drawn as they appear relative to the camera. It takes in a `StrokeVertex` struct like, in the `getObjectInputs` hook above, that can be modified and returned. * * * @@ -1831,20 +1928,16 @@ function material(p5, fn){ * uniforms: { * 'float time': () => millis() * }, - * declarations: 'vec3 myPosition;', - * 'vec3 getWorldPosition': `(vec3 pos) { - * myPosition = pos; - * return pos; - * }`, - * 'float getStrokeWeight': `(float w) { + * 'StrokeVertex getWorldInputs': `(StrokeVertex inputs) { * // Add a somewhat random offset to the weight * // that varies based on position and time * float scale = 0.8 + 0.2*sin(10.0 * sin( * floor(time/250.) + - * myPosition.x*0.01 + - * myPosition.y*0.01 + * inputs.position.x*0.01 + + * inputs.position.y*0.01 * )); - * return w * scale; + * inputs.weight *= scale; + * return inputs; * }` * }); * } @@ -1852,7 +1945,6 @@ function material(p5, fn){ * function draw() { * background(255); * strokeShader(myShader); - * noStroke(); * myShader.setUniform('time', millis()); * strokeWeight(10); * beginShape(); diff --git a/src/webgl/p5.RendererGL.js b/src/webgl/p5.RendererGL.js index c2d97f1a01..b6b90984af 100644 --- a/src/webgl/p5.RendererGL.js +++ b/src/webgl/p5.RendererGL.js @@ -177,10 +177,7 @@ class RendererGL extends Renderer { // Push/pop state this.states.uModelMatrix = new Matrix(4); this.states.uViewMatrix = new Matrix(4); - this.states.uMVMatrix = new Matrix(4); this.states.uPMatrix = new Matrix(4); - this.states.uNMatrix = new Matrix(3); - this.states.curMatrix = new Matrix(3); this.states.curCamera = new Camera(this); @@ -416,6 +413,8 @@ class RendererGL extends Renderer { this._curShader = undefined; this.drawShapeCount = 1; + + this.scratchMat3 = new Matrix(3); } ////////////////////////////////////////////// @@ -1739,11 +1738,11 @@ class RendererGL extends Renderer { if (!this.sphereMapping) { this.sphereMapping = this._pInst.createFilterShader(sphereMapping); } - this.states.uNMatrix.inverseTranspose4x4(this.states.uViewMatrix); - this.states.uNMatrix.invert(this.states.uNMatrix); // uNMMatrix is 3x3 + this.scratchMat3.inverseTranspose4x4(this.states.uViewMatrix); + this.scratchMat3.invert(this.scratchMat3); // uNMMatrix is 3x3 this.sphereMapping.setUniform("uFovY", this.states.curCamera.cameraFOV); this.sphereMapping.setUniform("uAspect", this.states.curCamera.aspectRatio); - this.sphereMapping.setUniform("uNewNormalMatrix", this.states.uNMatrix.mat3); + this.sphereMapping.setUniform("uNewNormalMatrix", this.scratchMat3.mat3); this.sphereMapping.setUniform("uSampler", img); return this.sphereMapping; } @@ -1809,12 +1808,9 @@ class RendererGL extends Renderer { { vertex: { "void beforeVertex": "() {}", - "vec3 getLocalPosition": "(vec3 position) { return position; }", - "vec3 getWorldPosition": "(vec3 position) { return position; }", - "vec3 getLocalNormal": "(vec3 normal) { return normal; }", - "vec3 getWorldNormal": "(vec3 normal) { return normal; }", - "vec2 getUV": "(vec2 uv) { return uv; }", - "vec4 getVertexColor": "(vec4 color) { return color; }", + "Vertex getObjectInputs": "(Vertex inputs) { return inputs; }", + "Vertex getWorldInputs": "(Vertex inputs) { return inputs; }", + "Vertex getCameraInputs": "(Vertex inputs) { return inputs; }", "void afterVertex": "() {}", }, fragment: { @@ -1863,12 +1859,9 @@ class RendererGL extends Renderer { { vertex: { "void beforeVertex": "() {}", - "vec3 getLocalPosition": "(vec3 position) { return position; }", - "vec3 getWorldPosition": "(vec3 position) { return position; }", - "vec3 getLocalNormal": "(vec3 normal) { return normal; }", - "vec3 getWorldNormal": "(vec3 normal) { return normal; }", - "vec2 getUV": "(vec2 uv) { return uv; }", - "vec4 getVertexColor": "(vec4 color) { return color; }", + "Vertex getObjectInputs": "(Vertex inputs) { return inputs; }", + "Vertex getWorldInputs": "(Vertex inputs) { return inputs; }", + "Vertex getCameraInputs": "(Vertex inputs) { return inputs; }", "void afterVertex": "() {}", }, fragment: { @@ -1898,12 +1891,9 @@ class RendererGL extends Renderer { { vertex: { "void beforeVertex": "() {}", - "vec3 getLocalPosition": "(vec3 position) { return position; }", - "vec3 getWorldPosition": "(vec3 position) { return position; }", - "vec3 getLocalNormal": "(vec3 normal) { return normal; }", - "vec3 getWorldNormal": "(vec3 normal) { return normal; }", - "vec2 getUV": "(vec2 uv) { return uv; }", - "vec4 getVertexColor": "(vec4 color) { return color; }", + "Vertex getObjectInputs": "(Vertex inputs) { return inputs; }", + "Vertex getWorldInputs": "(Vertex inputs) { return inputs; }", + "Vertex getCameraInputs": "(Vertex inputs) { return inputs; }", "void afterVertex": "() {}", }, fragment: { @@ -1989,12 +1979,9 @@ class RendererGL extends Renderer { { vertex: { "void beforeVertex": "() {}", - "vec3 getLocalPosition": "(vec3 position) { return position; }", - "vec3 getWorldPosition": "(vec3 position) { return position; }", - "float getStrokeWeight": "(float weight) { return weight; }", - "vec2 getLineCenter": "(vec2 center) { return center; }", - "vec2 getLinePosition": "(vec2 position) { return position; }", - "vec4 getVertexColor": "(vec4 color) { return color; }", + "StrokeVertex getObjectInputs": "(StrokeVertex inputs) { return inputs; }", + "StrokeVertex getWorldInputs": "(StrokeVertex inputs) { return inputs; }", + "StrokeVertex getCameraInputs": "(StrokeVertex inputs) { return inputs; }", "void afterVertex": "() {}", }, fragment: { @@ -2191,11 +2178,7 @@ class RendererGL extends Renderer { const modelMatrix = this.states.uModelMatrix; const viewMatrix = this.states.uViewMatrix; const projectionMatrix = this.states.uPMatrix; - const modelViewMatrix = modelMatrix.copy().mult(viewMatrix); - this.states.uMVMatrix = this.calculateCombinedMatrix(); - - const modelViewProjectionMatrix = modelViewMatrix.copy(); - modelViewProjectionMatrix.mult(projectionMatrix); + const modelViewMatrix = this.calculateCombinedMatrix(); shader.setUniform( "uPerspective", @@ -2205,17 +2188,29 @@ class RendererGL extends Renderer { shader.setUniform("uProjectionMatrix", projectionMatrix.mat4); shader.setUniform("uModelMatrix", modelMatrix.mat4); shader.setUniform("uModelViewMatrix", modelViewMatrix.mat4); - shader.setUniform( - "uModelViewProjectionMatrix", - modelViewProjectionMatrix.mat4, - ); + if (shader.uniforms.uModelViewProjectionMatrix) { + const modelViewProjectionMatrix = modelViewMatrix.copy(); + modelViewProjectionMatrix.mult(projectionMatrix); + shader.setUniform( + "uModelViewProjectionMatrix", + modelViewProjectionMatrix.mat4, + ); + } if (shader.uniforms.uNormalMatrix) { - this.states.uNMatrix.inverseTranspose4x4(this.states.uMVMatrix); - shader.setUniform("uNormalMatrix", this.states.uNMatrix.mat3); + this.scratchMat3.inverseTranspose4x4(modelViewMatrix); + shader.setUniform("uNormalMatrix", this.scratchMat3.mat3); + } + if (shader.uniforms.uModelNormalMatrix) { + this.scratchMat3.inverseTranspose4x4(this.states.uModelMatrix); + shader.setUniform("uModelNormalMatrix", this.scratchMat3.mat3); + } + if (shader.uniforms.uCameraNormalMatrix) { + this.scratchMat3.inverseTranspose4x4(this.states.uViewMatrix); + shader.setUniform("uCameraNormalMatrix", this.scratchMat3.mat3); } if (shader.uniforms.uCameraRotation) { - this.states.curMatrix.inverseTranspose4x4(this.states.uViewMatrix); - shader.setUniform("uCameraRotation", this.states.curMatrix.mat3); + this.scratchMat3.inverseTranspose4x4(this.states.uViewMatrix); + shader.setUniform("uCameraRotation", this.scratchMat3.mat3); } shader.setUniform("uViewport", this._viewport); } diff --git a/src/webgl/p5.Shader.js b/src/webgl/p5.Shader.js index 01256011df..8d885c7c53 100644 --- a/src/webgl/p5.Shader.js +++ b/src/webgl/p5.Shader.js @@ -54,9 +54,10 @@ class Shader { shaderSrc(src, shaderType) { const main = 'void main'; - const [preMain, postMain] = src.split(main); + let [preMain, postMain] = src.split(main); let hooks = ''; + let defines = ''; for (const key in this.hooks.uniforms) { hooks += `uniform ${key};\n`; } @@ -76,14 +77,22 @@ class Shader { // Add a #define so that if the shader wants to use preprocessor directives to // optimize away the extra function calls in main, it can do so if (this.hooks.modified[shaderType][hookDef]) { - hooks += '#define AUGMENTED_HOOK_' + hookName + '\n'; + defines += '#define AUGMENTED_HOOK_' + hookName + '\n'; } hooks += hookType + ' HOOK_' + hookName + this.hooks[shaderType][hookDef] + '\n'; } - return preMain + hooks + main + postMain; + // Allow shaders to specify the location of hook #define statements. Normally these + // go after function definitions, but one might want to have them defined earlier + // in order to only conditionally make uniforms. + if (preMain.indexOf('#define HOOK_DEFINES') !== -1) { + preMain = preMain.replace('#define HOOK_DEFINES', '\n' + defines + '\n'); + defines = ''; + } + + return preMain + '\n' + defines + hooks + main + postMain; } /** @@ -365,6 +374,7 @@ class Shader { if (typeof IS_MINIFIED !== 'undefined') { console.error(glError); } else { + throw glError; p5._friendlyError( `Yikes! An error occurred compiling the vertex shader:${glError}` ); @@ -382,6 +392,7 @@ class Shader { if (typeof IS_MINIFIED !== 'undefined') { console.error(glError); } else { + throw glError; p5._friendlyError( `Darn! An error occurred compiling the fragment shader:${glError}` ); @@ -629,8 +640,8 @@ class Shader { this.init(); } } - - + + /** * Queries the active attributes for this shader and loads * their names and locations into the attributes array. diff --git a/src/webgl/shaders/line.vert b/src/webgl/shaders/line.vert index 9609fc38d4..de422ad6b6 100644 --- a/src/webgl/shaders/line.vert +++ b/src/webgl/shaders/line.vert @@ -18,10 +18,18 @@ #define PROCESSING_LINE_SHADER +#define HOOK_DEFINES + precision highp int; precision highp float; +#ifdef AUGMENTED_HOOK_getWorldInputs +uniform mat4 uModelMatrix; +uniform mat4 uViewMatrix; +#else uniform mat4 uModelViewMatrix; +#endif + uniform mat4 uProjectionMatrix; uniform float uStrokeWeight; @@ -33,7 +41,7 @@ uniform vec4 uViewport; uniform int uPerspective; uniform int uStrokeJoin; -IN vec4 aPosition; +IN vec3 aPosition; IN vec3 aTangentIn; IN vec3 aTangentOut; IN float aSide; @@ -66,6 +74,14 @@ vec2 lineIntersection(vec2 aPoint, vec2 aDir, vec2 bPoint, vec2 bDir) { return aPoint + aDir * intersectionDistance; } +struct StrokeVertex { + vec3 position; + vec3 tangentIn; + vec3 tangentOut; + vec4 color; + float weight; +}; + void main() { HOOK_beforeVertex(); @@ -81,12 +97,43 @@ void main() { ) ? 1. : 0.; } - vec4 localPosition = vec4(HOOK_getLocalPosition(aPosition.xyz), 1.); - vec4 posp = vec4(HOOK_getWorldPosition((uModelViewMatrix * localPosition).xyz), 1.); - vec4 posqIn = posp + uModelViewMatrix * vec4(aTangentIn, 0); - vec4 posqOut = posp + uModelViewMatrix * vec4(aTangentOut, 0); - float strokeWeight = HOOK_getStrokeWeight(uStrokeWeight); - vStrokeWeight = strokeWeight; + StrokeVertex inputs; + inputs.position = aPosition.xyz; + inputs.color = uUseLineColor ? aVertexColor : uMaterialColor; + inputs.weight = uStrokeWeight; + inputs.tangentIn = aTangentIn; + inputs.tangentOut = aTangentOut; + +#ifdef AUGMENTED_HOOK_getObjectInputs + inputs = HOOK_getObjectInputs(inputs); +#endif + +#ifdef AUGMENTED_HOOK_getWorldInputs + inputs.position = (uModelMatrix * vec4(inputs.position, 1.)).xyz; + inputs.tangentIn = (uModelMatrix * vec4(aTangentIn, 0.)).xyz; + inputs.tangentOut = (uModelMatrix * vec4(aTangentOut, 0.)).xyz; + inputs = HOOK_getWorldInputs(inputs); +#endif + +#ifdef AUGMENTED_HOOK_getWorldInputs + // Already multiplied by the model matrix, just apply view + inputs.position = (uViewMatrix * vec4(inputs.position, 1.)).xyz; + inputs.tangentIn = (uViewMatrix * vec4(aTangentIn, 0.)).xyz; + inputs.tangentOut = (uViewMatrix * vec4(aTangentOut, 0.)).xyz; +#else + // Apply both at once + inputs.position = (uModelViewMatrix * vec4(inputs.position, 1.)).xyz; + inputs.tangentIn = (uModelViewMatrix * vec4(aTangentIn, 0.)).xyz; + inputs.tangentOut = (uModelViewMatrix * vec4(aTangentOut, 0.)).xyz; +#endif +#ifdef AUGMENTED_HOOK_getCameraInputs + inputs = hook_getCameraInputs(inputs); +#endif + + vec4 posp = vec4(inputs.position, 1.); + vec4 posqIn = vec4(inputs.position + inputs.tangentIn, 1.); + vec4 posqOut = vec4(inputs.position + inputs.tangentOut, 1.); + vStrokeWeight = inputs.weight; float facingCamera = pow( // The word space tangent's z value is 0 if it's facing the camera @@ -130,7 +177,6 @@ void main() { vec4 p = uProjectionMatrix * posp; vec4 qIn = uProjectionMatrix * posqIn; vec4 qOut = uProjectionMatrix * posqOut; - vCenter = HOOK_getLineCenter(p.xy); // formula to convert from clip space (range -1..1) to screen space (range 0..[width or height]) // screen_p = (p.xy/p.w + <1,1>) * 0.5 * uViewport.zw @@ -195,9 +241,9 @@ void main() { // find where the lines intersect to find the elbow of the join vec2 c = (posp.xy/posp.w + vec2(1.,1.)) * 0.5 * uViewport.zw; vec2 intersection = lineIntersection( - c + (side * normalIn * strokeWeight / 2.), + c + (side * normalIn * inputs.weight / 2.), tangentIn, - c + (side * normalOut * strokeWeight / 2.), + c + (side * normalOut * inputs.weight / 2.), tangentOut ); offset = (intersection - c); @@ -207,21 +253,21 @@ void main() { // the magnitude to avoid lines going across the whole screen when this // happens. float mag = length(offset); - float maxMag = 3. * strokeWeight; + float maxMag = 3. * inputs.weight; if (mag > maxMag) { offset *= maxMag / mag; } } else if (sideEnum == 1.) { - offset = side * normalIn * strokeWeight / 2.; + offset = side * normalIn * inputs.weight / 2.; } else if (sideEnum == 3.) { - offset = side * normalOut * strokeWeight / 2.; + offset = side * normalOut * inputs.weight / 2.; } } if (uStrokeJoin == STROKE_JOIN_BEVEL) { vec2 avgNormal = vec2(-vTangent.y, vTangent.x); - vMaxDist = abs(dot(avgNormal, normalIn * strokeWeight / 2.)); + vMaxDist = abs(dot(avgNormal, normalIn * inputs.weight / 2.)); } else { - vMaxDist = strokeWeight / 2.; + vMaxDist = inputs.weight / 2.; } } else { vec2 tangent = aTangentIn == vec3(0.) ? tangentOut : tangentIn; @@ -233,14 +279,16 @@ void main() { // extends out from the line float tangentOffset = abs(aSide) - 1.; offset = (normal * normalOffset + tangent * tangentOffset) * - strokeWeight * 0.5; - vMaxDist = strokeWeight / 2.; + inputs.weight * 0.5; + vMaxDist = inputs.weight / 2.; } - vPosition = HOOK_getLinePosition(vCenter + offset); + + vCenter = p.xy; + vPosition = vCenter + offset; + vColor = inputs.color; gl_Position.xy = p.xy + offset.xy * curPerspScale; gl_Position.zw = p.zw; - vColor = HOOK_getVertexColor(uUseLineColor ? aVertexColor : uMaterialColor); HOOK_afterVertex(); } diff --git a/src/webgl/shaders/normal.vert b/src/webgl/shaders/normal.vert index 63922714b4..9b466b54c6 100644 --- a/src/webgl/shaders/normal.vert +++ b/src/webgl/shaders/normal.vert @@ -3,9 +3,18 @@ IN vec3 aNormal; IN vec2 aTexCoord; IN vec4 aVertexColor; +#define HOOK_DEFINES + +#ifdef AUGMENTED_HOOK_getWorldInputs +uniform mat4 uModelMatrix; +uniform mat4 uViewMatrix; +uniform mat3 uModelNormalMatrix; +uniform mat3 uCameraNormalMatrix; +#else uniform mat4 uModelViewMatrix; -uniform mat4 uProjectionMatrix; uniform mat3 uNormalMatrix; +#endif +uniform mat4 uProjectionMatrix; uniform vec4 uMaterialColor; uniform bool uUseVertexColor; @@ -14,16 +23,50 @@ OUT vec3 vVertexNormal; OUT highp vec2 vVertTexCoord; OUT vec4 vColor; +struct Vertex { + vec3 position; + vec3 normal; + vec2 uv; + vec4 color; +}; + void main(void) { HOOK_beforeVertex(); - vec4 positionVec4 = vec4(HOOK_getWorldPosition( - (uModelViewMatrix * vec4(HOOK_getLocalPosition(aPosition), 1.0)).xyz - ), 1.); - gl_Position = uProjectionMatrix * positionVec4; + Vertex inputs; + inputs.position = aPosition; + inputs.normal = aNormal; + inputs.uv = aTexCoord; + inputs.color = (uUseVertexColor && aVertexColor.x >= 0.0) ? aVertexColor : uMaterialColor; +#ifdef AUGMENTED_HOOK_getObjectInputs + inputs = HOOK_getObjectInputs(inputs); +#endif + +#ifdef AUGMENTED_HOOK_getWorldInputs + inputs.position = (uModelMatrix * vec4(inputs.position, 1.)).xyz; + inputs.normal = uModelNormalMatrix * inputs.normal; + inputs = HOOK_getWorldInputs(inputs); +#endif + +#ifdef AUGMENTED_HOOK_getWorldInputs + // Already multiplied by the model matrix, just apply view + inputs.position = (uViewMatrix * vec4(inputs.position, 1.)).xyz; + inputs.normal = uCameraNormalMatrix * inputs.normal; +#else + // Apply both at once + inputs.position = (uModelViewMatrix * vec4(inputs.position, 1.)).xyz; + inputs.normal = uNormalMatrix * inputs.normal; +#endif +#ifdef AUGMENTED_HOOK_getCameraInputs + inputs = HOOK_getCameraInputs(inputs); +#endif + + // Pass varyings to fragment shader + vVertTexCoord = inputs.uv; + vVertexNormal = normalize(inputs.normal); + vColor = inputs.color; + + gl_Position = uProjectionMatrix * vec4(inputs.position, 1.); - vVertexNormal = HOOK_getWorldNormal(normalize(uNormalMatrix * HOOK_getLocalNormal(aNormal))); - vVertTexCoord = HOOK_getUV(aTexCoord); - vColor = HOOK_getVertexColor((uUseVertexColor && aVertexColor.x >= 0.0) ? aVertexColor : uMaterialColor); HOOK_afterVertex(); } diff --git a/src/webgl/shaders/phong.frag b/src/webgl/shaders/phong.frag index e141f62f1f..74c5206d95 100644 --- a/src/webgl/shaders/phong.frag +++ b/src/webgl/shaders/phong.frag @@ -47,13 +47,13 @@ void main(void) { inputs.texCoord = vTexCoord; inputs.ambientLight = vAmbientColor; inputs.color = isTexture - // Textures come in with premultiplied alpha. To apply tint and still have - // premultiplied alpha output, we need to multiply the RGB channels by the - // tint RGB, and all channels by the tint alpha. - ? TEXTURE(uSampler, vTexCoord) * vec4(uTint.rgb/255., 1.) * (uTint.a/255.) - // Colors come in with unmultiplied alpha, so we need to multiply the RGB - // channels by alpha to convert it to premultiplied alpha. - : vec4(vColor.rgb * vColor.a, vColor.a); + ? TEXTURE(uSampler, vTexCoord) * uTint/255. + : vColor; + if (isTexture) { + // Textures come in with premultiplied alpha. Temporarily unpremultiply it + // so hooks users don't have to think about premultiplied alpha. + inputs.color.rgb /= inputs.color.a; + } inputs.shininess = uShininess; inputs.metalness = uMetallic; inputs.ambientMaterial = uHasSetAmbient ? uAmbientMatColor.rgb : inputs.color.rgb; @@ -79,5 +79,6 @@ void main(void) { c.specular = specular; c.emissive = inputs.emissiveMaterial; OUT_COLOR = HOOK_getFinalColor(HOOK_combineColors(c)); + OUT_COLOR.rgb *= OUT_COLOR.a; // Premultiply alpha before rendering HOOK_afterFragment(); } diff --git a/src/webgl/shaders/phong.vert b/src/webgl/shaders/phong.vert index 0576ccd304..f59c09744a 100644 --- a/src/webgl/shaders/phong.vert +++ b/src/webgl/shaders/phong.vert @@ -1,5 +1,7 @@ precision highp int; +#define HOOK_DEFINES + IN vec3 aPosition; IN vec3 aNormal; IN vec2 aTexCoord; @@ -7,9 +9,16 @@ IN vec4 aVertexColor; uniform vec3 uAmbientColor[5]; +#ifdef AUGMENTED_HOOK_getWorldInputs +uniform mat4 uModelMatrix; +uniform mat4 uViewMatrix; +uniform mat3 uModelNormalMatrix; +uniform mat3 uCameraNormalMatrix; +#else uniform mat4 uModelViewMatrix; -uniform mat4 uProjectionMatrix; uniform mat3 uNormalMatrix; +#endif +uniform mat4 uProjectionMatrix; uniform int uAmbientLightCount; uniform bool uUseVertexColor; @@ -21,18 +30,49 @@ OUT vec3 vViewPosition; OUT vec3 vAmbientColor; OUT vec4 vColor; +struct Vertex { + vec3 position; + vec3 normal; + vec2 uv; + vec4 color; +}; + void main(void) { HOOK_beforeVertex(); - vec4 viewModelPosition = vec4(HOOK_getWorldPosition( - (uModelViewMatrix * vec4(HOOK_getLocalPosition(aPosition), 1.0)).xyz - ), 1.); - // Pass varyings to fragment shader - vViewPosition = viewModelPosition.xyz; - gl_Position = uProjectionMatrix * viewModelPosition; + Vertex inputs; + inputs.position = aPosition; + inputs.normal = aNormal; + inputs.uv = aTexCoord; + inputs.color = (uUseVertexColor && aVertexColor.x >= 0.0) ? aVertexColor : uMaterialColor; +#ifdef AUGMENTED_HOOK_getObjectInputs + inputs = HOOK_getObjectInputs(inputs); +#endif - vNormal = HOOK_getWorldNormal(uNormalMatrix * HOOK_getLocalNormal(aNormal)); - vTexCoord = HOOK_getUV(aTexCoord); +#ifdef AUGMENTED_HOOK_getWorldInputs + inputs.position = (uModelMatrix * vec4(inputs.position, 1.)).xyz; + inputs.normal = uModelNormalMatrix * inputs.normal; + inputs = HOOK_getWorldInputs(inputs); +#endif + +#ifdef AUGMENTED_HOOK_getWorldInputs + // Already multiplied by the model matrix, just apply view + inputs.position = (uViewMatrix * vec4(inputs.position, 1.)).xyz; + inputs.normal = uCameraNormalMatrix * inputs.normal; +#else + // Apply both at once + inputs.position = (uModelViewMatrix * vec4(inputs.position, 1.)).xyz; + inputs.normal = uNormalMatrix * inputs.normal; +#endif +#ifdef AUGMENTED_HOOK_getCameraInputs + inputs = HOOK_getCameraInputs(inputs); +#endif + + // Pass varyings to fragment shader + vViewPosition = inputs.position; + vTexCoord = inputs.uv; + vNormal = inputs.normal; + vColor = inputs.color; // TODO: this should be a uniform vAmbientColor = vec3(0.0); @@ -41,7 +81,7 @@ void main(void) { vAmbientColor += uAmbientColor[i]; } } - - vColor = HOOK_getVertexColor(((uUseVertexColor && aVertexColor.x >= 0.0) ? aVertexColor : uMaterialColor)); + + gl_Position = uProjectionMatrix * vec4(inputs.position, 1.); HOOK_afterVertex(); } diff --git a/test/unit/visual/cases/webgl.js b/test/unit/visual/cases/webgl.js index fe676a0e8c..f32f9c2f31 100644 --- a/test/unit/visual/cases/webgl.js +++ b/test/unit/visual/cases/webgl.js @@ -345,4 +345,151 @@ visualSuite('WebGL', function() { screenshot(); }) }) + + visualSuite('Opacity', function() { + visualTest('Basic colors have opacity applied correctly', (p5, screenshot) => { + p5.createCanvas(50, 50, p5.WEBGL); + p5.background(255); + p5.fill(255, 0, 0, 100); + p5.circle(0, 0, 50); + screenshot(); + }); + + visualTest('Colors have opacity applied correctly when lights are used', (p5, screenshot) => { + p5.createCanvas(50, 50, p5.WEBGL); + p5.background(255); + p5.ambientLight(255); + p5.fill(255, 0, 0, 100); + p5.circle(0, 0, 50); + screenshot(); + }); + + visualTest('Colors in shader hooks have opacity applied correctly', (p5, screenshot) => { + p5.createCanvas(50, 50, p5.WEBGL); + const myShader = p5.baseMaterialShader().modify({ + 'Inputs getPixelInputs': `(Inputs inputs) { + inputs.color = vec4(1., 0., 0., 100./255.); + return inputs; + }` + }) + p5.background(255); + p5.shader(myShader); + p5.circle(0, 0, 50); + screenshot(); + }); + + visualTest('Colors in textures have opacity applied correctly', (p5, screenshot) => { + p5.createCanvas(50, 50, p5.WEBGL); + const tex = p5.createFramebuffer(); + tex.draw(() => p5.background(255, 0, 0, 100)); + p5.background(255); + p5.texture(tex); + p5.circle(0, 0, 50); + screenshot(); + }); + + visualTest('Colors in tinted textures have opacity applied correctly', (p5, screenshot) => { + p5.createCanvas(50, 50, p5.WEBGL); + const tex = p5.createFramebuffer(); + tex.draw(() => p5.background(255, 0, 0, 255)); + p5.background(255); + p5.texture(tex); + p5.tint(255, 100); + p5.circle(0, 0, 50); + screenshot(); + }); + }); + + visualSuite('Hooks coordinate spaces', () => { + for (const base of ['baseMaterialShader', 'baseColorShader', 'baseNormalShader']) { + visualSuite(base, () => { + visualTest('Object space', (p5, screenshot) => { + p5.createCanvas(50, 50, p5.WEBGL); + const myShader = p5[base]().modify({ + 'Vertex getObjectInputs': `(Vertex inputs) { + inputs.position.x += 0.25; + inputs.normal.x += 0.5 * sin(inputs.position.y * 2.); + inputs.normal = normalize(inputs.normal); + return inputs; + }` + }); + p5.background(255); + p5.lights(); + p5.fill('red'); + p5.noStroke(); + p5.rotateY(p5.PI/2); + p5.camera(-800, 0, 0, 0, 0, 0); + p5.shader(myShader); + p5.sphere(20); + screenshot(); + }); + + visualTest('World space', (p5, screenshot) => { + p5.createCanvas(50, 50, p5.WEBGL); + const myShader = p5[base]().modify({ + 'Vertex getWorldInputs': `(Vertex inputs) { + inputs.position.x += 10.; + inputs.normal.x += 0.5 * sin(inputs.position.y * 2.); + inputs.normal = normalize(inputs.normal); + return inputs; + }` + }); + p5.background(255); + p5.lights(); + p5.fill('red'); + p5.noStroke(); + p5.rotateY(p5.PI/2); + p5.camera(-800, 0, 0, 0, 0, 0); + p5.shader(myShader); + p5.sphere(20); + screenshot(); + }); + + visualTest('Camera space', (p5, screenshot) => { + p5.createCanvas(50, 50, p5.WEBGL); + const myShader = p5[base]().modify({ + 'Vertex getCameraInputs': `(Vertex inputs) { + inputs.position.x += 10.; + inputs.normal.x += 0.5 * sin(inputs.position.y * 2.); + inputs.normal = normalize(inputs.normal); + return inputs; + }` + }); + p5.background(255); + p5.lights(); + p5.fill('red'); + p5.noStroke(); + p5.rotateY(p5.PI/2); + p5.camera(-800, 0, 0, 0, 0, 0); + p5.shader(myShader); + p5.sphere(20); + screenshot(); + }); + + visualTest('Combined vs split matrices', (p5, screenshot) => { + p5.createCanvas(50, 50, p5.WEBGL); + for (const space of ['Object', 'World', 'Camera']) { + const myShader = p5[base]().modify({ + [`Vertex get${space}Inputs`]: `(Vertex inputs) { + // No-op + return inputs; + }` + }); + p5.background(255); + p5.push(); + p5.lights(); + p5.fill('red'); + p5.noStroke(); + p5.translate(20, -10, 5); + p5.rotate(p5.PI * 0.1); + p5.camera(-800, 0, 0, 0, 0, 0); + p5.shader(myShader); + p5.box(30); + p5.pop(); + screenshot(); + } + }); + }); + } + }); }); diff --git a/test/unit/visual/screenshots/WebGL/Hooks coordinate spaces/baseColorShader/Camera space/000.png b/test/unit/visual/screenshots/WebGL/Hooks coordinate spaces/baseColorShader/Camera space/000.png new file mode 100644 index 0000000000..5878075344 Binary files /dev/null and b/test/unit/visual/screenshots/WebGL/Hooks coordinate spaces/baseColorShader/Camera space/000.png differ diff --git a/test/unit/visual/screenshots/WebGL/Hooks coordinate spaces/baseColorShader/Camera space/metadata.json b/test/unit/visual/screenshots/WebGL/Hooks coordinate spaces/baseColorShader/Camera space/metadata.json new file mode 100644 index 0000000000..2d4bfe30da --- /dev/null +++ b/test/unit/visual/screenshots/WebGL/Hooks coordinate spaces/baseColorShader/Camera space/metadata.json @@ -0,0 +1,3 @@ +{ + "numScreenshots": 1 +} \ No newline at end of file diff --git a/test/unit/visual/screenshots/WebGL/Hooks coordinate spaces/baseColorShader/Combined vs split matrices/000.png b/test/unit/visual/screenshots/WebGL/Hooks coordinate spaces/baseColorShader/Combined vs split matrices/000.png new file mode 100644 index 0000000000..ee9d8c2748 Binary files /dev/null and b/test/unit/visual/screenshots/WebGL/Hooks coordinate spaces/baseColorShader/Combined vs split matrices/000.png differ diff --git a/test/unit/visual/screenshots/WebGL/Hooks coordinate spaces/baseColorShader/Combined vs split matrices/001.png b/test/unit/visual/screenshots/WebGL/Hooks coordinate spaces/baseColorShader/Combined vs split matrices/001.png new file mode 100644 index 0000000000..ee9d8c2748 Binary files /dev/null and b/test/unit/visual/screenshots/WebGL/Hooks coordinate spaces/baseColorShader/Combined vs split matrices/001.png differ diff --git a/test/unit/visual/screenshots/WebGL/Hooks coordinate spaces/baseColorShader/Combined vs split matrices/002.png b/test/unit/visual/screenshots/WebGL/Hooks coordinate spaces/baseColorShader/Combined vs split matrices/002.png new file mode 100644 index 0000000000..ee9d8c2748 Binary files /dev/null and b/test/unit/visual/screenshots/WebGL/Hooks coordinate spaces/baseColorShader/Combined vs split matrices/002.png differ diff --git a/test/unit/visual/screenshots/WebGL/Hooks coordinate spaces/baseColorShader/Combined vs split matrices/metadata.json b/test/unit/visual/screenshots/WebGL/Hooks coordinate spaces/baseColorShader/Combined vs split matrices/metadata.json new file mode 100644 index 0000000000..0c316a63ab --- /dev/null +++ b/test/unit/visual/screenshots/WebGL/Hooks coordinate spaces/baseColorShader/Combined vs split matrices/metadata.json @@ -0,0 +1,3 @@ +{ + "numScreenshots": 3 +} \ No newline at end of file diff --git a/test/unit/visual/screenshots/WebGL/Hooks coordinate spaces/baseColorShader/Object space/000.png b/test/unit/visual/screenshots/WebGL/Hooks coordinate spaces/baseColorShader/Object space/000.png new file mode 100644 index 0000000000..9692230099 Binary files /dev/null and b/test/unit/visual/screenshots/WebGL/Hooks coordinate spaces/baseColorShader/Object space/000.png differ diff --git a/test/unit/visual/screenshots/WebGL/Hooks coordinate spaces/baseColorShader/Object space/metadata.json b/test/unit/visual/screenshots/WebGL/Hooks coordinate spaces/baseColorShader/Object space/metadata.json new file mode 100644 index 0000000000..2d4bfe30da --- /dev/null +++ b/test/unit/visual/screenshots/WebGL/Hooks coordinate spaces/baseColorShader/Object space/metadata.json @@ -0,0 +1,3 @@ +{ + "numScreenshots": 1 +} \ No newline at end of file diff --git a/test/unit/visual/screenshots/WebGL/Hooks coordinate spaces/baseColorShader/World space/000.png b/test/unit/visual/screenshots/WebGL/Hooks coordinate spaces/baseColorShader/World space/000.png new file mode 100644 index 0000000000..075543a498 Binary files /dev/null and b/test/unit/visual/screenshots/WebGL/Hooks coordinate spaces/baseColorShader/World space/000.png differ diff --git a/test/unit/visual/screenshots/WebGL/Hooks coordinate spaces/baseColorShader/World space/metadata.json b/test/unit/visual/screenshots/WebGL/Hooks coordinate spaces/baseColorShader/World space/metadata.json new file mode 100644 index 0000000000..2d4bfe30da --- /dev/null +++ b/test/unit/visual/screenshots/WebGL/Hooks coordinate spaces/baseColorShader/World space/metadata.json @@ -0,0 +1,3 @@ +{ + "numScreenshots": 1 +} \ No newline at end of file diff --git a/test/unit/visual/screenshots/WebGL/Hooks coordinate spaces/baseMaterialShader/Camera space/000.png b/test/unit/visual/screenshots/WebGL/Hooks coordinate spaces/baseMaterialShader/Camera space/000.png new file mode 100644 index 0000000000..41f35381dd Binary files /dev/null and b/test/unit/visual/screenshots/WebGL/Hooks coordinate spaces/baseMaterialShader/Camera space/000.png differ diff --git a/test/unit/visual/screenshots/WebGL/Hooks coordinate spaces/baseMaterialShader/Camera space/metadata.json b/test/unit/visual/screenshots/WebGL/Hooks coordinate spaces/baseMaterialShader/Camera space/metadata.json new file mode 100644 index 0000000000..2d4bfe30da --- /dev/null +++ b/test/unit/visual/screenshots/WebGL/Hooks coordinate spaces/baseMaterialShader/Camera space/metadata.json @@ -0,0 +1,3 @@ +{ + "numScreenshots": 1 +} \ No newline at end of file diff --git a/test/unit/visual/screenshots/WebGL/Hooks coordinate spaces/baseMaterialShader/Combined vs split matrices/000.png b/test/unit/visual/screenshots/WebGL/Hooks coordinate spaces/baseMaterialShader/Combined vs split matrices/000.png new file mode 100644 index 0000000000..1b77843e48 Binary files /dev/null and b/test/unit/visual/screenshots/WebGL/Hooks coordinate spaces/baseMaterialShader/Combined vs split matrices/000.png differ diff --git a/test/unit/visual/screenshots/WebGL/Hooks coordinate spaces/baseMaterialShader/Combined vs split matrices/001.png b/test/unit/visual/screenshots/WebGL/Hooks coordinate spaces/baseMaterialShader/Combined vs split matrices/001.png new file mode 100644 index 0000000000..1b77843e48 Binary files /dev/null and b/test/unit/visual/screenshots/WebGL/Hooks coordinate spaces/baseMaterialShader/Combined vs split matrices/001.png differ diff --git a/test/unit/visual/screenshots/WebGL/Hooks coordinate spaces/baseMaterialShader/Combined vs split matrices/002.png b/test/unit/visual/screenshots/WebGL/Hooks coordinate spaces/baseMaterialShader/Combined vs split matrices/002.png new file mode 100644 index 0000000000..1b77843e48 Binary files /dev/null and b/test/unit/visual/screenshots/WebGL/Hooks coordinate spaces/baseMaterialShader/Combined vs split matrices/002.png differ diff --git a/test/unit/visual/screenshots/WebGL/Hooks coordinate spaces/baseMaterialShader/Combined vs split matrices/metadata.json b/test/unit/visual/screenshots/WebGL/Hooks coordinate spaces/baseMaterialShader/Combined vs split matrices/metadata.json new file mode 100644 index 0000000000..0c316a63ab --- /dev/null +++ b/test/unit/visual/screenshots/WebGL/Hooks coordinate spaces/baseMaterialShader/Combined vs split matrices/metadata.json @@ -0,0 +1,3 @@ +{ + "numScreenshots": 3 +} \ No newline at end of file diff --git a/test/unit/visual/screenshots/WebGL/Hooks coordinate spaces/baseMaterialShader/Object space/000.png b/test/unit/visual/screenshots/WebGL/Hooks coordinate spaces/baseMaterialShader/Object space/000.png new file mode 100644 index 0000000000..f6fab1658c Binary files /dev/null and b/test/unit/visual/screenshots/WebGL/Hooks coordinate spaces/baseMaterialShader/Object space/000.png differ diff --git a/test/unit/visual/screenshots/WebGL/Hooks coordinate spaces/baseMaterialShader/Object space/metadata.json b/test/unit/visual/screenshots/WebGL/Hooks coordinate spaces/baseMaterialShader/Object space/metadata.json new file mode 100644 index 0000000000..2d4bfe30da --- /dev/null +++ b/test/unit/visual/screenshots/WebGL/Hooks coordinate spaces/baseMaterialShader/Object space/metadata.json @@ -0,0 +1,3 @@ +{ + "numScreenshots": 1 +} \ No newline at end of file diff --git a/test/unit/visual/screenshots/WebGL/Hooks coordinate spaces/baseMaterialShader/World space/000.png b/test/unit/visual/screenshots/WebGL/Hooks coordinate spaces/baseMaterialShader/World space/000.png new file mode 100644 index 0000000000..f545c7da45 Binary files /dev/null and b/test/unit/visual/screenshots/WebGL/Hooks coordinate spaces/baseMaterialShader/World space/000.png differ diff --git a/test/unit/visual/screenshots/WebGL/Hooks coordinate spaces/baseMaterialShader/World space/metadata.json b/test/unit/visual/screenshots/WebGL/Hooks coordinate spaces/baseMaterialShader/World space/metadata.json new file mode 100644 index 0000000000..2d4bfe30da --- /dev/null +++ b/test/unit/visual/screenshots/WebGL/Hooks coordinate spaces/baseMaterialShader/World space/metadata.json @@ -0,0 +1,3 @@ +{ + "numScreenshots": 1 +} \ No newline at end of file diff --git a/test/unit/visual/screenshots/WebGL/Hooks coordinate spaces/baseNormalShader/Camera space/000.png b/test/unit/visual/screenshots/WebGL/Hooks coordinate spaces/baseNormalShader/Camera space/000.png new file mode 100644 index 0000000000..1a5e70fea6 Binary files /dev/null and b/test/unit/visual/screenshots/WebGL/Hooks coordinate spaces/baseNormalShader/Camera space/000.png differ diff --git a/test/unit/visual/screenshots/WebGL/Hooks coordinate spaces/baseNormalShader/Camera space/metadata.json b/test/unit/visual/screenshots/WebGL/Hooks coordinate spaces/baseNormalShader/Camera space/metadata.json new file mode 100644 index 0000000000..2d4bfe30da --- /dev/null +++ b/test/unit/visual/screenshots/WebGL/Hooks coordinate spaces/baseNormalShader/Camera space/metadata.json @@ -0,0 +1,3 @@ +{ + "numScreenshots": 1 +} \ No newline at end of file diff --git a/test/unit/visual/screenshots/WebGL/Hooks coordinate spaces/baseNormalShader/Combined vs split matrices/000.png b/test/unit/visual/screenshots/WebGL/Hooks coordinate spaces/baseNormalShader/Combined vs split matrices/000.png new file mode 100644 index 0000000000..62eb6320b8 Binary files /dev/null and b/test/unit/visual/screenshots/WebGL/Hooks coordinate spaces/baseNormalShader/Combined vs split matrices/000.png differ diff --git a/test/unit/visual/screenshots/WebGL/Hooks coordinate spaces/baseNormalShader/Combined vs split matrices/001.png b/test/unit/visual/screenshots/WebGL/Hooks coordinate spaces/baseNormalShader/Combined vs split matrices/001.png new file mode 100644 index 0000000000..62eb6320b8 Binary files /dev/null and b/test/unit/visual/screenshots/WebGL/Hooks coordinate spaces/baseNormalShader/Combined vs split matrices/001.png differ diff --git a/test/unit/visual/screenshots/WebGL/Hooks coordinate spaces/baseNormalShader/Combined vs split matrices/002.png b/test/unit/visual/screenshots/WebGL/Hooks coordinate spaces/baseNormalShader/Combined vs split matrices/002.png new file mode 100644 index 0000000000..62eb6320b8 Binary files /dev/null and b/test/unit/visual/screenshots/WebGL/Hooks coordinate spaces/baseNormalShader/Combined vs split matrices/002.png differ diff --git a/test/unit/visual/screenshots/WebGL/Hooks coordinate spaces/baseNormalShader/Combined vs split matrices/metadata.json b/test/unit/visual/screenshots/WebGL/Hooks coordinate spaces/baseNormalShader/Combined vs split matrices/metadata.json new file mode 100644 index 0000000000..0c316a63ab --- /dev/null +++ b/test/unit/visual/screenshots/WebGL/Hooks coordinate spaces/baseNormalShader/Combined vs split matrices/metadata.json @@ -0,0 +1,3 @@ +{ + "numScreenshots": 3 +} \ No newline at end of file diff --git a/test/unit/visual/screenshots/WebGL/Hooks coordinate spaces/baseNormalShader/Object space/000.png b/test/unit/visual/screenshots/WebGL/Hooks coordinate spaces/baseNormalShader/Object space/000.png new file mode 100644 index 0000000000..2f428f5f74 Binary files /dev/null and b/test/unit/visual/screenshots/WebGL/Hooks coordinate spaces/baseNormalShader/Object space/000.png differ diff --git a/test/unit/visual/screenshots/WebGL/Hooks coordinate spaces/baseNormalShader/Object space/metadata.json b/test/unit/visual/screenshots/WebGL/Hooks coordinate spaces/baseNormalShader/Object space/metadata.json new file mode 100644 index 0000000000..2d4bfe30da --- /dev/null +++ b/test/unit/visual/screenshots/WebGL/Hooks coordinate spaces/baseNormalShader/Object space/metadata.json @@ -0,0 +1,3 @@ +{ + "numScreenshots": 1 +} \ No newline at end of file diff --git a/test/unit/visual/screenshots/WebGL/Hooks coordinate spaces/baseNormalShader/World space/000.png b/test/unit/visual/screenshots/WebGL/Hooks coordinate spaces/baseNormalShader/World space/000.png new file mode 100644 index 0000000000..3e03667ebb Binary files /dev/null and b/test/unit/visual/screenshots/WebGL/Hooks coordinate spaces/baseNormalShader/World space/000.png differ diff --git a/test/unit/visual/screenshots/WebGL/Hooks coordinate spaces/baseNormalShader/World space/metadata.json b/test/unit/visual/screenshots/WebGL/Hooks coordinate spaces/baseNormalShader/World space/metadata.json new file mode 100644 index 0000000000..2d4bfe30da --- /dev/null +++ b/test/unit/visual/screenshots/WebGL/Hooks coordinate spaces/baseNormalShader/World space/metadata.json @@ -0,0 +1,3 @@ +{ + "numScreenshots": 1 +} \ No newline at end of file diff --git a/test/unit/visual/screenshots/WebGL/Opacity/Basic colors have opacity applied correctly/000.png b/test/unit/visual/screenshots/WebGL/Opacity/Basic colors have opacity applied correctly/000.png new file mode 100644 index 0000000000..b885704e16 Binary files /dev/null and b/test/unit/visual/screenshots/WebGL/Opacity/Basic colors have opacity applied correctly/000.png differ diff --git a/test/unit/visual/screenshots/WebGL/Opacity/Basic colors have opacity applied correctly/metadata.json b/test/unit/visual/screenshots/WebGL/Opacity/Basic colors have opacity applied correctly/metadata.json new file mode 100644 index 0000000000..2d4bfe30da --- /dev/null +++ b/test/unit/visual/screenshots/WebGL/Opacity/Basic colors have opacity applied correctly/metadata.json @@ -0,0 +1,3 @@ +{ + "numScreenshots": 1 +} \ No newline at end of file diff --git a/test/unit/visual/screenshots/WebGL/Opacity/Colors have opacity applied correctly when lights are used/000.png b/test/unit/visual/screenshots/WebGL/Opacity/Colors have opacity applied correctly when lights are used/000.png new file mode 100644 index 0000000000..b885704e16 Binary files /dev/null and b/test/unit/visual/screenshots/WebGL/Opacity/Colors have opacity applied correctly when lights are used/000.png differ diff --git a/test/unit/visual/screenshots/WebGL/Opacity/Colors have opacity applied correctly when lights are used/metadata.json b/test/unit/visual/screenshots/WebGL/Opacity/Colors have opacity applied correctly when lights are used/metadata.json new file mode 100644 index 0000000000..2d4bfe30da --- /dev/null +++ b/test/unit/visual/screenshots/WebGL/Opacity/Colors have opacity applied correctly when lights are used/metadata.json @@ -0,0 +1,3 @@ +{ + "numScreenshots": 1 +} \ No newline at end of file diff --git a/test/unit/visual/screenshots/WebGL/Opacity/Colors in shader hooks have opacity applied correctly/000.png b/test/unit/visual/screenshots/WebGL/Opacity/Colors in shader hooks have opacity applied correctly/000.png new file mode 100644 index 0000000000..b885704e16 Binary files /dev/null and b/test/unit/visual/screenshots/WebGL/Opacity/Colors in shader hooks have opacity applied correctly/000.png differ diff --git a/test/unit/visual/screenshots/WebGL/Opacity/Colors in shader hooks have opacity applied correctly/metadata.json b/test/unit/visual/screenshots/WebGL/Opacity/Colors in shader hooks have opacity applied correctly/metadata.json new file mode 100644 index 0000000000..2d4bfe30da --- /dev/null +++ b/test/unit/visual/screenshots/WebGL/Opacity/Colors in shader hooks have opacity applied correctly/metadata.json @@ -0,0 +1,3 @@ +{ + "numScreenshots": 1 +} \ No newline at end of file diff --git a/test/unit/visual/screenshots/WebGL/Opacity/Colors in textures have opacity applied correctly/000.png b/test/unit/visual/screenshots/WebGL/Opacity/Colors in textures have opacity applied correctly/000.png new file mode 100644 index 0000000000..b885704e16 Binary files /dev/null and b/test/unit/visual/screenshots/WebGL/Opacity/Colors in textures have opacity applied correctly/000.png differ diff --git a/test/unit/visual/screenshots/WebGL/Opacity/Colors in textures have opacity applied correctly/metadata.json b/test/unit/visual/screenshots/WebGL/Opacity/Colors in textures have opacity applied correctly/metadata.json new file mode 100644 index 0000000000..2d4bfe30da --- /dev/null +++ b/test/unit/visual/screenshots/WebGL/Opacity/Colors in textures have opacity applied correctly/metadata.json @@ -0,0 +1,3 @@ +{ + "numScreenshots": 1 +} \ No newline at end of file diff --git a/test/unit/visual/screenshots/WebGL/Opacity/Colors in tinted textures have opacity applied correctly/000.png b/test/unit/visual/screenshots/WebGL/Opacity/Colors in tinted textures have opacity applied correctly/000.png new file mode 100644 index 0000000000..b885704e16 Binary files /dev/null and b/test/unit/visual/screenshots/WebGL/Opacity/Colors in tinted textures have opacity applied correctly/000.png differ diff --git a/test/unit/visual/screenshots/WebGL/Opacity/Colors in tinted textures have opacity applied correctly/metadata.json b/test/unit/visual/screenshots/WebGL/Opacity/Colors in tinted textures have opacity applied correctly/metadata.json new file mode 100644 index 0000000000..2d4bfe30da --- /dev/null +++ b/test/unit/visual/screenshots/WebGL/Opacity/Colors in tinted textures have opacity applied correctly/metadata.json @@ -0,0 +1,3 @@ +{ + "numScreenshots": 1 +} \ No newline at end of file