Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/PenSkin.js
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ class PenSkin extends Skin {
this._lineShader = this._renderer._shaderManager.getShader(ShaderManager.DRAW_MODE.line, NO_EFFECTS);

/** @type {twgl.ProgramInfo} */
this._triangleShader = this._renderer._shaderManager.getShader(ShaderManager.DRAW_MODE.triangle, NO_EFFECTS);
this._triangleShader = this._renderer._shaderManager.getTriangleShader();
this._triangle_glbuffer = gl.createBuffer();
this._triangle_position_loc = gl.getAttribLocation(this._triangleShader.program, 'a_position');
this._triangle_color_loc = gl.getAttribLocation(this._triangleShader.program, 'a_triangleColor');
Expand Down
47 changes: 40 additions & 7 deletions src/ShaderManager.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,13 @@ class ShaderManager {
this._shaderCache[modeName] = [];
}
}

/**
* The pen triangle shader, built on first use.
* @type {?ProgramInfo}
* @private
*/
this._triangleShader = null;
}

/**
Expand Down Expand Up @@ -68,6 +75,37 @@ class ShaderManager {
const fsFullText = definesText + require('raw-loader!./shaders/sprite.frag');
/* eslint-enable global-require */

return this._compileProgram(vsFullText, fsFullText, `mode ${drawMode}, effects ${effectBits}`);
}

/**
* Fetch the shader that draws batched pen triangles with a color per vertex.
* It is built from its own source and kept out of the sprite shader cache because extensions
* rewrite the sprite shader text inside _buildShader and delete every cached sprite program.
* @returns {ProgramInfo} The shader's program info.
*/
getTriangleShader () {
if (!this._triangleShader) {
/* eslint-disable global-require */
this._triangleShader = this._compileProgram(
require('raw-loader!./shaders/triangle.vert'),
require('raw-loader!./shaders/triangle.frag'),
'pen triangles'
);
/* eslint-enable global-require */
}
return this._triangleShader;
}

/**
* Compile and link a vertex and fragment shader.
* @param {string} vsFullText The vertex shader source.
* @param {string} fsFullText The fragment shader source.
* @param {string} description What the shader is for, used in the error message.
* @returns {ProgramInfo} The new shader's program info.
* @private
*/
_compileProgram (vsFullText, fsFullText, description) {
let errorMessage = null;
const onError = newError => {
// twgl won't log the error when we provide a custom error callback, so log it ourselves
Expand All @@ -87,7 +125,7 @@ class ShaderManager {
const preview = `vertex starts "${vsFullText.slice(0, 80)}", ` +
`fragment starts "${fsFullText.slice(0, 80)}"`;
throw new Error(
`Failed to compile shader (mode ${drawMode}, effects ${effectBits}): ${reason} (${preview})`
`Failed to compile shader (${description}): ${reason} (${preview})`
);
}
return program;
Expand Down Expand Up @@ -203,12 +241,7 @@ ShaderManager.DRAW_MODE = {
/**
* Draw the background in a certain color. Must sometimes be used instead of gl.clear.
*/
background: 'background',

/**
* Draw batched pen triangles with a color per vertex.
*/
triangle: 'triangle'
background: 'background'
};

module.exports = ShaderManager;
12 changes: 2 additions & 10 deletions src/shaders/sprite.frag
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,6 @@ varying float v_lineLength;
uniform vec4 u_backgroundColor;
#endif // DRAW_MODE_background

#ifdef DRAW_MODE_triangle
varying vec4 v_triangleColor;
#endif // DRAW_MODE_triangle

uniform sampler2D u_skin;

#ifndef DRAW_MODE_background
Expand Down Expand Up @@ -119,7 +115,7 @@ const vec2 kCenter = vec2(0.5, 0.5);

void main()
{
#if !(defined(DRAW_MODE_line) || defined(DRAW_MODE_background) || defined(DRAW_MODE_triangle))
#if !(defined(DRAW_MODE_line) || defined(DRAW_MODE_background))
vec2 texcoord0 = v_texCoord;

#ifdef ENABLE_mosaic
Expand Down Expand Up @@ -225,7 +221,7 @@ void main()
gl_FragColor.rgb /= gl_FragColor.a + epsilon;
#endif

#endif // !(defined(DRAW_MODE_line) || defined(DRAW_MODE_background) || defined(DRAW_MODE_triangle))
#endif // !(defined(DRAW_MODE_line) || defined(DRAW_MODE_background))

#ifdef DRAW_MODE_line
// Maaaaagic antialiased-line-with-round-caps shader.
Expand All @@ -247,10 +243,6 @@ void main()
gl_FragColor = v_lineColor * clamp(1.0 - line, 0.0, 1.0);
#endif // DRAW_MODE_line

#ifdef DRAW_MODE_triangle
gl_FragColor = v_triangleColor;
#endif // DRAW_MODE_triangle

#ifdef DRAW_MODE_background
gl_FragColor = u_backgroundColor;
#endif
Expand Down
10 changes: 1 addition & 9 deletions src/shaders/sprite.vert
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,7 @@ varying vec4 v_penPoints;
const float epsilon = 1e-3;
#endif

#ifdef DRAW_MODE_triangle
attribute vec4 a_triangleColor;
varying vec4 v_triangleColor;
#endif

#if !(defined(DRAW_MODE_line) || defined(DRAW_MODE_background) || defined(DRAW_MODE_triangle))
#if !(defined(DRAW_MODE_line) || defined(DRAW_MODE_background))
uniform mat4 u_projectionMatrix;
uniform mat4 u_modelMatrix;
attribute vec2 a_texCoord;
Expand Down Expand Up @@ -80,9 +75,6 @@ void main() {
v_penPoints = a_penPoints;
#elif defined(DRAW_MODE_background)
gl_Position = vec4(a_position * 2.0, 0, 1);
#elif defined(DRAW_MODE_triangle)
gl_Position = vec4(a_position * 2.0, 0, 1);
v_triangleColor = a_triangleColor;
#else
gl_Position = u_projectionMatrix * u_modelMatrix * vec4(a_position, 0, 1);
v_texCoord = a_texCoord;
Expand Down
8 changes: 8 additions & 0 deletions src/shaders/triangle.frag
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
precision mediump float;

varying vec4 v_triangleColor;

void main()
{
gl_FragColor = v_triangleColor;
}
11 changes: 11 additions & 0 deletions src/shaders/triangle.vert
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
precision mediump float;

attribute vec2 a_position;
attribute vec4 a_triangleColor;

varying vec4 v_triangleColor;

void main() {
gl_Position = vec4(a_position * 2.0, 0, 1);
v_triangleColor = a_triangleColor;
}
27 changes: 27 additions & 0 deletions test/unit/ShaderSourceTests.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
const test = require('tap').test;
const fs = require('fs');
const path = require('path');

const readShader = name => fs.readFileSync(path.join(__dirname, '../../src/shaders', name), 'utf8');

// Extensions such as SharkPool's Looks Expanded patch the sprite shaders with find-and-replace,
// so these lines have to stay exactly as they are in TurboWarp.
test('sprite shaders keep the lines extensions patch', t => {
const vert = readShader('sprite.vert');
t.ok(vert.includes('#if !(defined(DRAW_MODE_line) || defined(DRAW_MODE_background))\n'));
t.ok(vert.includes('void main() {'));
t.ok(vert.includes('v_texCoord = a_texCoord;'));
t.ok(vert.includes('vec4(a_position, 0, 1)'));

const frag = readShader('sprite.frag');
t.ok(frag.includes('uniform sampler2D u_skin;'));
t.ok(frag.includes('#if defined(ENABLE_color) || defined(ENABLE_brightness)'));
t.ok(frag.includes('gl_FragColor.rgb = clamp(gl_FragColor.rgb / (gl_FragColor.a + epsilon), 0.0, 1.0);'));
t.end();
});

test('pen triangles are not drawn with the sprite shaders', t => {
t.notOk(readShader('sprite.vert').includes('DRAW_MODE_triangle'));
t.notOk(readShader('sprite.frag').includes('DRAW_MODE_triangle'));
t.end();
});
Loading