зеркало из https://github.com/mozilla/shumway.git
Put shaders in their own separate files, implement glow and drop shadow in webgl.
This commit is contained in:
Родитель
f564b7ca36
Коммит
1fe394805a
|
@ -4,8 +4,12 @@
|
||||||
<title></title>
|
<title></title>
|
||||||
</head>
|
</head>
|
||||||
<body style="background-color: #2c2c2c">
|
<body style="background-color: #2c2c2c">
|
||||||
|
<script>
|
||||||
|
SHUMWAY_ROOT = "../../src/";
|
||||||
|
</script>
|
||||||
<script src="../../src/avm2/util.js"></script>
|
<script src="../../src/avm2/util.js"></script>
|
||||||
<script src="../../src/swf/filter.js"></script>
|
<script src="../../src/swf/filters/gl.js"></script>
|
||||||
|
<script src="../../src/swf/filters/filter.js"></script>
|
||||||
<style TYPE="text/css">
|
<style TYPE="text/css">
|
||||||
body {
|
body {
|
||||||
color: white;
|
color: white;
|
||||||
|
@ -65,6 +69,9 @@
|
||||||
<td>
|
<td>
|
||||||
GL Glow
|
GL Glow
|
||||||
</td>
|
</td>
|
||||||
|
<td>
|
||||||
|
GL Shadow
|
||||||
|
</td>
|
||||||
<td>
|
<td>
|
||||||
GL Color
|
GL Color
|
||||||
</td>
|
</td>
|
||||||
|
@ -79,6 +86,9 @@
|
||||||
<td>
|
<td>
|
||||||
<canvas width="256" height="256" id="glow-canvas-gl"></canvas>
|
<canvas width="256" height="256" id="glow-canvas-gl"></canvas>
|
||||||
</td>
|
</td>
|
||||||
|
<td>
|
||||||
|
<canvas width="256" height="256" id="shadow-canvas-gl"></canvas>
|
||||||
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<canvas width="256" height="256" id="color-canvas-gl"></canvas>
|
<canvas width="256" height="256" id="color-canvas-gl"></canvas>
|
||||||
</td>
|
</td>
|
||||||
|
@ -86,65 +96,6 @@
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
<img src="firefox.png" id="firefox" style="visibility: hidden;">
|
<img src="firefox.png" id="firefox" style="visibility: hidden;">
|
||||||
<script id="2d-vertex-shader" type="x-shader/x-vertex">
|
|
||||||
attribute vec2 a_position;
|
|
||||||
uniform vec2 u_resolution;
|
|
||||||
uniform float u_flipY;
|
|
||||||
attribute vec2 a_textureCoordinate;
|
|
||||||
varying vec2 v_texCoord;
|
|
||||||
void main() {
|
|
||||||
vec2 p = (a_position / u_resolution) * 2.0 - 1.0;
|
|
||||||
gl_Position = vec4(p * vec2(1, u_flipY), 0, 1);
|
|
||||||
v_texCoord = a_textureCoordinate;
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<script id="2d-blur-fragment-shader-h" type="x-shader/x-fragment">
|
|
||||||
precision mediump float;
|
|
||||||
uniform sampler2D u_image;
|
|
||||||
uniform vec2 u_textureSize;
|
|
||||||
varying vec2 v_texCoord;
|
|
||||||
void main() {
|
|
||||||
const int sampleRadius = 9;
|
|
||||||
const int samples = sampleRadius * 2 + 1;
|
|
||||||
vec2 one = vec2(1.0, 1.0) / u_textureSize;
|
|
||||||
vec4 color = vec4(0, 0, 0, 0);
|
|
||||||
for (int i = -sampleRadius; i <= sampleRadius; i++) {
|
|
||||||
color += texture2D(u_image, v_texCoord + vec2(float(i) * one.x, 0));
|
|
||||||
}
|
|
||||||
color /= float(samples);
|
|
||||||
gl_FragColor = color;
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<script id="2d-blur-fragment-shader-v" type="x-shader/x-fragment">
|
|
||||||
precision mediump float;
|
|
||||||
uniform sampler2D u_image;
|
|
||||||
uniform vec2 u_textureSize;
|
|
||||||
varying vec2 v_texCoord;
|
|
||||||
void main() {
|
|
||||||
const int sampleRadius = 9;
|
|
||||||
const int samples = sampleRadius * 2 + 1;
|
|
||||||
vec2 one = vec2(1.0, 1.0) / u_textureSize;
|
|
||||||
vec4 color = vec4(0, 0, 0, 0);
|
|
||||||
for (int i = -sampleRadius; i <= sampleRadius; i++) {
|
|
||||||
color += texture2D(u_image, v_texCoord + vec2(0, float(i) * one.y));
|
|
||||||
}
|
|
||||||
color /= float(samples);
|
|
||||||
gl_FragColor = color;
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<script id="2d-color-fragment-shader" type="x-shader/x-fragment">
|
|
||||||
precision mediump float;
|
|
||||||
uniform sampler2D u_image;
|
|
||||||
uniform mat4 u_matrix;
|
|
||||||
uniform vec4 u_vector;
|
|
||||||
varying vec2 v_texCoord;
|
|
||||||
void main() {
|
|
||||||
gl_FragColor = u_matrix * texture2D(u_image, v_texCoord) + u_vector;
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<script src="filter_driver.js"></script>
|
<script src="filter_driver.js"></script>
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,7 @@ function drawShape(ctx, length, x, y) {
|
||||||
ctx.fillStyle = '#ff0000';
|
ctx.fillStyle = '#ff0000';
|
||||||
ctx.strokeStyle = 'green';
|
ctx.strokeStyle = 'green';
|
||||||
ctx.translate(x, y);
|
ctx.translate(x, y);
|
||||||
ctx.rotate(r += 0.01);
|
ctx.rotate(r += 0.02);
|
||||||
ctx.rotate((Math.PI * 1 / 10));
|
ctx.rotate((Math.PI * 1 / 10));
|
||||||
ctx.beginPath();
|
ctx.beginPath();
|
||||||
for (var i = 5; i--;) {
|
for (var i = 5; i--;) {
|
||||||
|
@ -28,20 +28,6 @@ function drawShape(ctx, length, x, y) {
|
||||||
|
|
||||||
var colorMatrix4x5 = new Float32Array([0.748939, 1.044984, -0.793923, 0.000000, 0.000000, -0.008795, 0.713845, 0.294950, 0.000000, 0.000000, 0.827417, -0.240804, 0.413387, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 1.000000, 0.000000]);
|
var colorMatrix4x5 = new Float32Array([0.748939, 1.044984, -0.793923, 0.000000, 0.000000, -0.008795, 0.713845, 0.294950, 0.000000, 0.000000, 0.827417, -0.240804, 0.413387, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 1.000000, 0.000000]);
|
||||||
|
|
||||||
function transpose(r, c, m) {
|
|
||||||
var result = new Float32Array(16);
|
|
||||||
for (var i = 0; i < r; i++) {
|
|
||||||
for (var j = 0; j < c; j++) {
|
|
||||||
result[j * r + i] = m[i * c + j];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
var colorMatrix5x4 = transpose(4, 5, colorMatrix4x5);
|
|
||||||
var colorMatrix4x4 = colorMatrix5x4.subarray(0, 16);
|
|
||||||
var colorMatrixVector = colorMatrix5x4.subarray(16, 20);
|
|
||||||
|
|
||||||
var blurCanvasJS = document.getElementById("blur-canvas-js");
|
var blurCanvasJS = document.getElementById("blur-canvas-js");
|
||||||
var blurCanvasGL = document.getElementById("blur-canvas-gl");
|
var blurCanvasGL = document.getElementById("blur-canvas-gl");
|
||||||
|
|
||||||
|
@ -55,73 +41,14 @@ var colorCanvasJS = document.getElementById("color-canvas-js");
|
||||||
var colorCanvasGL = document.getElementById("color-canvas-gl");
|
var colorCanvasGL = document.getElementById("color-canvas-gl");
|
||||||
|
|
||||||
var glCanvas = document.getElementById("canvas-gl");
|
var glCanvas = document.getElementById("canvas-gl");
|
||||||
|
|
||||||
|
var glFilters = new WebGLFilters(glCanvas);
|
||||||
|
|
||||||
var gl = new WebGLCanvas(glCanvas);
|
var gl = new WebGLCanvas(glCanvas);
|
||||||
|
|
||||||
var vShader = gl.createShaderFromElement("2d-vertex-shader");
|
|
||||||
var blurFragmentShaderH = gl.createShaderFromElement("2d-blur-fragment-shader-h");
|
|
||||||
var blurFragmentShaderV = gl.createShaderFromElement("2d-blur-fragment-shader-v");
|
|
||||||
var colorFragmentShader = gl.createShaderFromElement("2d-color-fragment-shader");
|
|
||||||
|
|
||||||
var blurProgramH = gl.createProgram([vShader, blurFragmentShaderH]);
|
|
||||||
var blurProgramV = gl.createProgram([vShader, blurFragmentShaderV]);
|
|
||||||
var colorProgram = gl.createProgram([vShader, colorFragmentShader]);
|
|
||||||
|
|
||||||
var texture = gl.createTexture();
|
|
||||||
var vertices = gl.createVertexBuffer(gl.rectangleVertices(width, height));
|
|
||||||
var textureCoordinates = gl.createVertexBuffer(gl.rectangleTextureCoordinates());
|
|
||||||
|
|
||||||
gl.useProgram(blurProgramH);
|
|
||||||
gl.setUniform2f(blurProgramH, "u_resolution", width, height);
|
|
||||||
gl.setUniform2f(blurProgramH, "u_textureSize", width, height);
|
|
||||||
gl.setUniform1f(blurProgramH, "u_flipY", 1);
|
|
||||||
gl.setVertexAttribute(blurProgramH, "a_position", vertices);
|
|
||||||
gl.setVertexAttribute(blurProgramH, "a_textureCoordinate", textureCoordinates);
|
|
||||||
|
|
||||||
gl.useProgram(blurProgramV);
|
|
||||||
gl.setUniform2f(blurProgramV, "u_resolution", width, height);
|
|
||||||
gl.setUniform2f(blurProgramV, "u_textureSize", width, height);
|
|
||||||
gl.setUniform1f(blurProgramV, "u_flipY", -1);
|
|
||||||
gl.setVertexAttribute(blurProgramV, "a_textureCoordinate", textureCoordinates);
|
|
||||||
gl.setVertexAttribute(blurProgramV, "a_position", vertices);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
gl.useProgram(colorProgram);
|
|
||||||
gl.setUniform2f(colorProgram, "u_resolution", width, height);
|
|
||||||
gl.setUniformMatrix4fv(colorProgram, "u_matrix", colorMatrix4x4);
|
|
||||||
gl.setUniform4fv(colorProgram, "u_vector", colorMatrixVector);
|
|
||||||
// gl.setUniform2f(colorProgram, "u_textureSize", canvas.width, canvas.height);
|
|
||||||
|
|
||||||
gl.setUniform1f(colorProgram, "u_flipY", -1);
|
|
||||||
gl.setVertexAttribute(colorProgram, "a_textureCoordinate", textureCoordinates);
|
|
||||||
gl.setVertexAttribute(colorProgram, "a_position", vertices);
|
|
||||||
|
|
||||||
var framebuffer = gl.createFramebuffer();
|
|
||||||
|
|
||||||
var firefoxImage = document.getElementById("firefox");
|
var firefoxImage = document.getElementById("firefox");
|
||||||
|
|
||||||
|
|
||||||
function blurGL(data, width, height) {
|
|
||||||
gl.initializeTexture(texture, width, height, new Uint8Array(data.buffer));
|
|
||||||
gl.useProgram(blurProgramH);
|
|
||||||
gl.bindTexture(texture);
|
|
||||||
gl.bindFramebuffer(framebuffer);
|
|
||||||
gl.drawTriangles(0, 6);
|
|
||||||
|
|
||||||
gl.useProgram(blurProgramV);
|
|
||||||
gl.bindTexture(framebuffer.texture);
|
|
||||||
gl.bindFramebuffer(null);
|
|
||||||
gl.drawTriangles(0, 6);
|
|
||||||
}
|
|
||||||
|
|
||||||
function colorGL(data, width, height) {
|
|
||||||
gl.initializeTexture(texture, width, height, new Uint8Array(data.buffer));
|
|
||||||
gl.useProgram(colorProgram);
|
|
||||||
gl.bindTexture(texture);
|
|
||||||
gl.bindFramebuffer(null);
|
|
||||||
gl.drawTriangles(0, 6);
|
|
||||||
}
|
|
||||||
|
|
||||||
function getImageData(straightAlpha) {
|
function getImageData(straightAlpha) {
|
||||||
var imageData = context.getImageData(0, 0, width, height);
|
var imageData = context.getImageData(0, 0, width, height);
|
||||||
if (!straightAlpha) {
|
if (!straightAlpha) {
|
||||||
|
@ -137,26 +64,29 @@ function putImageData(imageData, context, straightAlpha) {
|
||||||
context.putImageData(imageData, 0, 0);
|
context.putImageData(imageData, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var runJS = true;
|
||||||
|
var runGL = true;
|
||||||
|
|
||||||
var run = {
|
var run = {
|
||||||
blur: {
|
blur: {
|
||||||
js: false,
|
js: runJS && true,
|
||||||
gl: false
|
gl: runGL && true
|
||||||
},
|
},
|
||||||
glow: {
|
glow: {
|
||||||
js: false,
|
js: runJS && true,
|
||||||
gl: false
|
gl: runGL && true
|
||||||
},
|
},
|
||||||
shadow: {
|
shadow: {
|
||||||
js: true,
|
js: runJS && true,
|
||||||
gl: false
|
gl: runGL && true
|
||||||
},
|
},
|
||||||
color: {
|
color: {
|
||||||
js: false,
|
js: runJS && true,
|
||||||
gl: false
|
gl: runGL && true
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
var k = 0;
|
var frameCount = 0;
|
||||||
|
|
||||||
setInterval(function () {
|
setInterval(function () {
|
||||||
|
|
||||||
|
@ -164,37 +94,54 @@ setInterval(function () {
|
||||||
context.fillStyle = "white";
|
context.fillStyle = "white";
|
||||||
// context.fillRect(0, 0, 256, 256);
|
// context.fillRect(0, 0, 256, 256);
|
||||||
context.clearRect(0, 0, 256, 256);
|
context.clearRect(0, 0, 256, 256);
|
||||||
drawShape(context, 50, 120, 120);
|
drawShape(context, 50, 140, 140);
|
||||||
context.drawImage(firefoxImage, 40, 40);
|
context.drawImage(firefoxImage, 40, 40);
|
||||||
|
|
||||||
var imageData;
|
var imageData;
|
||||||
|
|
||||||
|
var blurX = 10, blurY = 10;
|
||||||
|
|
||||||
if (run.blur.js) {
|
if (run.blur.js) {
|
||||||
// Run JS Blur Filter
|
// Run JS Blur Filter
|
||||||
imageData = getImageData();
|
imageData = getImageData();
|
||||||
blurFilter(imageData.data, width, height, 10, 10);
|
blurFilter(imageData.data, width, height, blurX, blurY);
|
||||||
putImageData(imageData, blurCanvasJS.getContext('2d'));
|
putImageData(imageData, blurCanvasJS.getContext('2d'));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (run.blur.gl) {
|
if (run.blur.gl) {
|
||||||
// Run WebGL Blur Filter
|
// Run WebGL Blur Filter
|
||||||
imageData = getImageData(true);
|
imageData = getImageData(true);
|
||||||
blurGL(imageData.data, width, height);
|
glFilters.blurFilter(imageData.data, width, height);
|
||||||
drawImage(glCanvas, blurCanvasGL);
|
drawImage(glCanvas, blurCanvasGL);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (run.glow.js) {
|
if (run.glow.js) {
|
||||||
imageData = getImageData();
|
imageData = getImageData();
|
||||||
glowFilter(imageData.data, width, height, [0, 0, 255, 0], 20, 20, 1);
|
glowFilter(imageData.data, width, height, [0, 0, 255, 0], blurX, blurY, 1);
|
||||||
putImageData(imageData, glowCanvasJS.getContext('2d'));
|
putImageData(imageData, glowCanvasJS.getContext('2d'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (run.glow.gl) {
|
||||||
|
imageData = getImageData(true);
|
||||||
|
glFilters.glowFilter(imageData.data, width, height, [0, 0, 255, 255], blurX, blurY, 1);
|
||||||
|
drawImage(glCanvas, glowCanvasGL);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
if (run.shadow.js) {
|
if (run.shadow.js) {
|
||||||
imageData = getImageData();
|
imageData = getImageData();
|
||||||
dropShadowFilter(imageData.data, width, height, [0, 0, 0, 0], 5, 5, Math.PI / 4, 10, 0.5);
|
dropShadowFilter(imageData.data, width, height, [0, 0, 255, 0], blurX, blurY, Math.PI / 4, 20, 0.5);
|
||||||
putImageData(imageData, shadowCanvasJS.getContext('2d'));
|
putImageData(imageData, shadowCanvasJS.getContext('2d'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (run.shadow.gl) {
|
||||||
|
imageData = getImageData();
|
||||||
|
glFilters.dropShadowFilter(imageData.data, width, height, [0, 0, 255, 255], blurX, blurY, Math.PI / 4, 20, 0.5);
|
||||||
|
drawImage(glCanvas, shadowCanvasGL);
|
||||||
|
}
|
||||||
|
|
||||||
|
colorMatrix4x5[0] = Math.sin(frameCount / 100);
|
||||||
|
|
||||||
if (run.color.js) {
|
if (run.color.js) {
|
||||||
// Run JS Color Filter
|
// Run JS Color Filter
|
||||||
imageData = getImageData();
|
imageData = getImageData();
|
||||||
|
@ -205,10 +152,12 @@ setInterval(function () {
|
||||||
if (run.color.gl) {
|
if (run.color.gl) {
|
||||||
// Run WebGL Color Filter
|
// Run WebGL Color Filter
|
||||||
imageData = getImageData();
|
imageData = getImageData();
|
||||||
colorGL(imageData.data, width, height);
|
glFilters.colorFilter(imageData.data, width, height, colorMatrix4x5);
|
||||||
drawImage(glCanvas, colorCanvasGL);
|
drawImage(glCanvas, colorCanvasGL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
frameCount ++;
|
||||||
|
|
||||||
}, 1000 / 60);
|
}, 1000 / 60);
|
||||||
|
|
||||||
function drawImage(src, dst) {
|
function drawImage(src, dst) {
|
||||||
|
|
|
@ -5,6 +5,17 @@
|
||||||
* Resources: http://www.m2osw.com/swf_struct_any_filter#swf_filter_colormatrix
|
* Resources: http://www.m2osw.com/swf_struct_any_filter#swf_filter_colormatrix
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
function transpose(r, c, m) {
|
||||||
|
assert (r * c === m.length);
|
||||||
|
var result = new Float32Array(m.length);
|
||||||
|
for (var i = 0; i < r; i++) {
|
||||||
|
for (var j = 0; j < c; j++) {
|
||||||
|
result[j * r + i] = m[i * c + j];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Applies a blur box-filter, averaging pixel values in a box with radius (blurX x blurY).
|
* Applies a blur box-filter, averaging pixel values in a box with radius (blurX x blurY).
|
||||||
*
|
*
|
||||||
|
@ -148,7 +159,7 @@ function blurFilterV(buffer, w, h, blurY) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function getAlphaChannel(buffer, color) {
|
function alphaFilter(buffer, color) {
|
||||||
if (!color) {
|
if (!color) {
|
||||||
color = [0, 0, 0, 0];
|
color = [0, 0, 0, 0];
|
||||||
}
|
}
|
||||||
|
@ -232,7 +243,7 @@ function panFilter(buffer, w, h, angle, distance) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function dropShadowFilter(buffer, w, h, color, blurX, blurY, angle, distance, strength) {
|
function dropShadowFilter(buffer, w, h, color, blurX, blurY, angle, distance, strength) {
|
||||||
var tmp = getAlphaChannel(buffer, color);
|
var tmp = alphaFilter(buffer, color);
|
||||||
panFilter(tmp, w, h, angle, distance);
|
panFilter(tmp, w, h, angle, distance);
|
||||||
blurFilter(tmp, w, h, blurX, blurY);
|
blurFilter(tmp, w, h, blurX, blurY);
|
||||||
scaleAlphaChannel(tmp, strength);
|
scaleAlphaChannel(tmp, strength);
|
||||||
|
@ -240,6 +251,10 @@ function dropShadowFilter(buffer, w, h, color, blurX, blurY, angle, distance, st
|
||||||
buffer.set(tmp);
|
buffer.set(tmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function clamp(n) {
|
||||||
|
return (((255 - n) >> 31) | n) & 0xFF;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Applies a color transformation. The |matrix| is a 5x5 matrix whose
|
* Applies a color transformation. The |matrix| is a 5x5 matrix whose
|
||||||
* last row is always [0, 0, 0, 0, 1]. The |matrix| is specified in row-major order;
|
* last row is always [0, 0, 0, 0, 1]. The |matrix| is specified in row-major order;
|
||||||
|
@ -252,10 +267,6 @@ function dropShadowFilter(buffer, w, h, color, blurX, blurY, angle, distance, st
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
function clamp(n) {
|
|
||||||
return (((255 - n) >> 31) | n) & 0xFF;
|
|
||||||
}
|
|
||||||
|
|
||||||
function colorFilter(buffer, w, h, matrix) {
|
function colorFilter(buffer, w, h, matrix) {
|
||||||
var r0 = matrix[0], r1 = matrix[1], r2 = matrix[2], r3 = matrix[3], r4 = matrix[4];
|
var r0 = matrix[0], r1 = matrix[1], r2 = matrix[2], r3 = matrix[3], r4 = matrix[4];
|
||||||
var g0 = matrix[5], g1 = matrix[6], g2 = matrix[7], g3 = matrix[8], g4 = matrix[9];
|
var g0 = matrix[5], g1 = matrix[6], g2 = matrix[7], g3 = matrix[8], g4 = matrix[9];
|
||||||
|
@ -273,157 +284,188 @@ function colorFilter(buffer, w, h, matrix) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
var WebGLFilters = (function () {
|
||||||
* Yet another abstraction over WebGL APIs.
|
var shaderRoot = SHUMWAY_ROOT + "/swf/filters/shaders/";
|
||||||
*/
|
|
||||||
var WebGLCanvas = (function () {
|
function colorVector(color) {
|
||||||
|
return [color[0] / 255, color[1] / 255, color[2] / 255, color[3] / 255];
|
||||||
|
}
|
||||||
|
|
||||||
|
function makeTranslation(tx, ty) {
|
||||||
|
return transpose(3, 3, [
|
||||||
|
1, 0, tx,
|
||||||
|
0, 1, ty,
|
||||||
|
0, 0, 1
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
var counter = 0;
|
||||||
|
|
||||||
function constructor(canvas) {
|
function constructor(canvas) {
|
||||||
this.canvas = canvas;
|
assert (canvas);
|
||||||
var w = this.width = canvas.width;
|
var gl = this.gl = new WebGLCanvas(canvas);
|
||||||
var h = this.height = canvas.height;
|
var width = canvas.width;
|
||||||
assert (w && h && isPowerOfTwo(w) && isPowerOfTwo(h));
|
var height = canvas.height;
|
||||||
this.gl = this.canvas.getContext("experimental-webgl");
|
function loadShader(name) {
|
||||||
assert (this.gl);
|
return gl.createShaderFromFile(shaderRoot + name);
|
||||||
|
}
|
||||||
|
// Create shader programs.
|
||||||
|
var canvasVert = loadShader("canvas.vert");
|
||||||
|
this.blurHProgram = gl.createProgram([canvasVert, loadShader("blurh.frag")]);
|
||||||
|
this.blurVProgram = gl.createProgram([canvasVert, loadShader("blurv.frag")]);
|
||||||
|
this.colorProgram = gl.createProgram([canvasVert, loadShader("color.frag")]);
|
||||||
|
this.alphaProgram = gl.createProgram([canvasVert, loadShader("alpha.frag")]);
|
||||||
|
this.multiplyProgram = gl.createProgram([canvasVert, loadShader("multiply.frag")]);
|
||||||
|
this.identityProgram = gl.createProgram([canvasVert, loadShader("identity.frag")]);
|
||||||
|
|
||||||
|
this.programs = [
|
||||||
|
this.blurHProgram,
|
||||||
|
this.blurVProgram,
|
||||||
|
this.colorProgram,
|
||||||
|
this.alphaProgram,
|
||||||
|
this.multiplyProgram,
|
||||||
|
this.identityProgram
|
||||||
|
];
|
||||||
|
|
||||||
|
this.texture = gl.createTexture();
|
||||||
|
this.framebufferA = gl.createFramebuffer();
|
||||||
|
this.framebufferB = gl.createFramebuffer();
|
||||||
|
|
||||||
|
var vertices = gl.createVertexBuffer(gl.rectangleVertices(width, height));
|
||||||
|
var textureCoordinates = gl.createVertexBuffer(gl.rectangleTextureCoordinates());
|
||||||
|
var matrix = makeTranslation(0, 0);
|
||||||
|
|
||||||
|
this.programs.forEach(setDefaultAttributesAndUniforms);
|
||||||
|
|
||||||
|
function setDefaultAttributesAndUniforms(program) {
|
||||||
|
gl.useProgram(program);
|
||||||
|
if (gl.hasUniform(program, "u_time")) {
|
||||||
|
gl.setUniform1f(program, "u_time", 0.0);
|
||||||
|
}
|
||||||
|
gl.setUniformMatrix3fv(program, "u_transformMatrix", matrix);
|
||||||
|
gl.setUniform2f(program, "u_resolution", width, height);
|
||||||
|
gl.setUniform1f(program, "u_flipY", 1);
|
||||||
|
|
||||||
|
gl.setVertexAttribute(program, "a_textureCoordinate", textureCoordinates);
|
||||||
|
gl.setVertexAttribute(program, "a_position", vertices);
|
||||||
|
}
|
||||||
|
|
||||||
|
gl.useProgram(this.blurHProgram);
|
||||||
|
gl.setUniform2f(this.blurHProgram, "u_textureSize", width, height);
|
||||||
|
|
||||||
|
gl.useProgram(this.blurVProgram);
|
||||||
|
gl.setUniform2f(this.blurVProgram, "u_textureSize", width, height);
|
||||||
|
|
||||||
|
this.startTime = new Date();
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor.prototype = {
|
constructor.prototype = {
|
||||||
rectangleVertices: function rectangleVertices(w, h) {
|
getElapsedTime: function getElapsedTime() {
|
||||||
return new Float32Array([0, 0, w, 0, 0, h, 0, h, w, 0, w, h]);
|
return new Date() - this.startTime;
|
||||||
},
|
},
|
||||||
rectangleTextureCoordinates: function rectangleTextureCoordinates() {
|
blurFilter: function blurFilterGL(buffer, w, h, blurX, blurY) {
|
||||||
return new Float32Array([0, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 1]);
|
|
||||||
},
|
|
||||||
useProgram: function (program) {
|
|
||||||
this.gl.useProgram(program);
|
|
||||||
},
|
|
||||||
setVertexAttribute: function setVertexAttribute(program, name, buffer) {
|
|
||||||
var gl = this.gl;
|
var gl = this.gl;
|
||||||
var location = gl.getAttribLocation(program, name);
|
|
||||||
assert (location >= 0, "Attribute " + name + " not found.");
|
gl.bindFramebuffer(null);
|
||||||
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
|
gl.clear([0, 0, 0, 0]);
|
||||||
gl.enableVertexAttribArray(location);
|
|
||||||
gl.vertexAttribPointer(location, 2, gl.FLOAT, false, 0, 0);
|
gl.initializeTexture(this.texture, w, h, new Uint8Array(buffer.buffer));
|
||||||
|
gl.bindTexture(this.texture);
|
||||||
|
gl.useProgram(this.blurHProgram);
|
||||||
|
gl.bindFramebuffer(this.framebufferA);
|
||||||
|
gl.clear([0, 0, 0, 0]);
|
||||||
|
gl.drawTriangles(0, 6);
|
||||||
|
|
||||||
|
gl.useProgram(this.blurVProgram);
|
||||||
|
gl.setUniform1f(this.blurVProgram, "u_flipY", -1);
|
||||||
|
gl.bindTexture(this.framebufferA.texture);
|
||||||
|
gl.bindFramebuffer(null);
|
||||||
|
gl.drawTriangles(0, 6);
|
||||||
|
gl.setUniform1f(this.blurVProgram, "u_flipY", 1);
|
||||||
},
|
},
|
||||||
setUniform4fv: function setUniform2f(program, name, vector) {
|
colorFilter: function colorFilter(buffer, w, h, matrix) {
|
||||||
var gl = this.gl
|
var colorMatrix5x4 = transpose(4, 5, matrix);
|
||||||
var location = gl.getUniformLocation(program, name);
|
var colorMatrix4x4 = colorMatrix5x4.subarray(0, 16);
|
||||||
assert (location, "Uniform " + name + " not found.");
|
var colorMatrixVector = colorMatrix5x4.subarray(16, 20);
|
||||||
gl.uniform4fv(location, vector);
|
gl.initializeTexture(this.texture, w, h, new Uint8Array(buffer.buffer));
|
||||||
|
gl.useProgram(this.colorProgram);
|
||||||
|
gl.setUniformMatrix4fv(this.colorProgram, "u_colorMatrix", colorMatrix4x4);
|
||||||
|
gl.setUniform4fv(this.colorProgram, "u_vector", colorMatrixVector);
|
||||||
|
gl.setUniform1f(this.colorProgram, "u_flipY", -1);
|
||||||
|
gl.bindTexture(this.texture);
|
||||||
|
gl.bindFramebuffer(null);
|
||||||
|
gl.clear([0, 0, 0, 0]);
|
||||||
|
gl.drawTriangles(0, 6);
|
||||||
|
gl.setUniform1f(this.colorProgram, "u_flipY", 1);
|
||||||
},
|
},
|
||||||
setUniform2f: function setUniform2f(program, name, x, y) {
|
alphaFilter: function alphaFilter(buffer, w, h, color) {
|
||||||
var gl = this.gl
|
gl.initializeTexture(this.texture, w, h, new Uint8Array(buffer.buffer));
|
||||||
var location = gl.getUniformLocation(program, name);
|
gl.useProgram(this.alphaProgram);
|
||||||
assert (location, "Uniform " + name + " not found.");
|
gl.setUniform4fv(this.alphaProgram, "u_color", colorVector(color));
|
||||||
gl.uniform2f(location, x, y);
|
gl.bindTexture(this.texture);
|
||||||
|
gl.bindFramebuffer(null);
|
||||||
|
gl.drawTriangles(0, 6);
|
||||||
},
|
},
|
||||||
setUniform1f: function setUniform2f(program, name, x) {
|
glowFilter: function dropShadowFilter(buffer, w, h, color, blurX, blurY, strength) {
|
||||||
var gl = this.gl
|
this.dropShadowFilter(buffer, w, h, color, blurX, blurY, 0, 0, strength);
|
||||||
var location = gl.getUniformLocation(program, name);
|
|
||||||
assert (location, "Uniform " + name + " not found.");
|
|
||||||
gl.uniform1f(location, x);
|
|
||||||
},
|
},
|
||||||
setUniformMatrix4fv: function setUniform(program, name, matrix) {
|
dropShadowFilter: function dropShadowFilter(buffer, w, h, color, blurX, blurY, angle, distance, strength) {
|
||||||
var gl = this.gl
|
|
||||||
var location = gl.getUniformLocation(program, name);
|
gl.bindFramebuffer(this.framebufferA);
|
||||||
assert (location, "Uniform " + name + " not found.");
|
gl.clear([0, 0, 0, 0]);
|
||||||
assert (matrix.length === 16, "Invalid matrix size.");
|
gl.bindFramebuffer(this.framebufferB);
|
||||||
gl.uniformMatrix4fv(location, false, matrix);
|
gl.clear([0, 0, 0, 0]);
|
||||||
},
|
gl.bindFramebuffer(null);
|
||||||
createVertexBuffer: function createBuffer(vertices) {
|
gl.clear([0, 0, 0, 0]);
|
||||||
var gl = this.gl;
|
|
||||||
var buffer = gl.createBuffer();
|
// Alpha
|
||||||
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
|
gl.initializeTexture(this.texture, w, h, new Uint8Array(buffer.buffer));
|
||||||
gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);
|
gl.useProgram(this.alphaProgram);
|
||||||
return buffer;
|
gl.setUniform4fv(this.alphaProgram, "u_color", colorVector(color));
|
||||||
},
|
gl.bindTexture(this.texture);
|
||||||
createFramebuffer: function createFramebuffer() {
|
gl.bindFramebuffer(this.framebufferA);
|
||||||
var gl = this.gl;
|
gl.drawTriangles(0, 6);
|
||||||
var texture = this.createTexture();
|
|
||||||
this.initializeTexture(texture, this.width, this.height, null);
|
// Blur H
|
||||||
var framebuffer = gl.createFramebuffer();
|
gl.bindTexture(this.framebufferA.texture);
|
||||||
gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer);
|
gl.useProgram(this.blurHProgram);
|
||||||
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0);
|
gl.bindFramebuffer(this.framebufferB);
|
||||||
framebuffer.texture = texture;
|
gl.drawTriangles(0, 6);
|
||||||
return framebuffer;
|
|
||||||
},
|
// Blur V
|
||||||
createTexture: function createAndBindTexture() {
|
gl.useProgram(this.blurVProgram);
|
||||||
var gl = this.gl;
|
gl.bindTexture(this.framebufferB.texture);
|
||||||
var texture = gl.createTexture();
|
gl.bindFramebuffer(this.framebufferA);
|
||||||
this.bindTexture(texture);
|
gl.drawTriangles(0, 6);
|
||||||
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
|
|
||||||
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
|
// Multiply Alpha
|
||||||
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
|
gl.bindTexture(this.framebufferA.texture);
|
||||||
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
|
gl.useProgram(this.multiplyProgram);
|
||||||
return texture;
|
var dy = (Math.sin(angle) * distance) | 0;
|
||||||
},
|
var dx = (Math.cos(angle) * distance) | 0;
|
||||||
initializeTexture: function initializeTexture(texture, width, height, data) {
|
gl.setUniformMatrix3fv(this.multiplyProgram, "u_transformMatrix", makeTranslation(dx, dy));
|
||||||
var gl = this.gl;
|
gl.setUniform4fv(this.multiplyProgram, "u_color", [strength, strength, strength, strength]);
|
||||||
this.bindTexture(texture);
|
gl.bindFramebuffer(this.framebufferB);
|
||||||
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, width, height, 0, gl.RGBA, gl.UNSIGNED_BYTE, data);
|
gl.drawTriangles(0, 6);
|
||||||
},
|
|
||||||
bindTexture: function bindTexture(texture) {
|
gl.bindTexture(this.texture);
|
||||||
var gl = this.gl;
|
gl.useProgram(this.identityProgram);
|
||||||
gl.bindTexture(gl.TEXTURE_2D, texture);
|
gl.enableBlend();
|
||||||
},
|
gl.gl.blendFunc(gl.gl.ONE, gl.gl.ONE_MINUS_SRC_ALPHA);
|
||||||
bindFramebuffer: function bindFramebuffer(framebuffer) {
|
gl.bindFramebuffer(this.framebufferB);
|
||||||
var gl = this.gl;
|
gl.drawTriangles(0, 6);
|
||||||
gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer);
|
gl.disableBlend();
|
||||||
},
|
|
||||||
createShader: function createShader(gl, shaderType, shaderSource) {
|
gl.bindTexture(this.framebufferB.texture);
|
||||||
var gl = this.gl;
|
gl.useProgram(this.identityProgram);
|
||||||
var shader = gl.createShader(shaderType);
|
gl.setUniform1f(this.identityProgram, "u_flipY", -1);
|
||||||
gl.shaderSource(shader, shaderSource);
|
gl.bindFramebuffer(null);
|
||||||
gl.compileShader(shader);
|
gl.clear([0, 0, 0, 0]);
|
||||||
if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
|
gl.drawTriangles(0, 6);
|
||||||
var lastError = gl.getShaderInfoLog(shader);
|
gl.setUniform1f(this.identityProgram, "u_flipY", 1);
|
||||||
unexpected("Cannot compile shader: " + lastError);
|
|
||||||
gl.deleteShader(shader);
|
return;
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return shader;
|
|
||||||
},
|
|
||||||
createShaderFromElement: function createShaderFromElement(id) {
|
|
||||||
var gl = this.gl;
|
|
||||||
var shaderScript = document.getElementById(id);
|
|
||||||
if (!shaderScript) {
|
|
||||||
unexpected("Shader Script Element: " + id + " not found.");
|
|
||||||
}
|
|
||||||
var shaderType;
|
|
||||||
switch (shaderScript.type) {
|
|
||||||
case "x-shader/x-vertex":
|
|
||||||
shaderType = gl.VERTEX_SHADER;
|
|
||||||
break;
|
|
||||||
case "x-shader/x-fragment":
|
|
||||||
shaderType = gl.FRAGMENT_SHADER;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
throw "Shader Type: " + shaderScript.type + " not supported.";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return this.createShader(gl, shaderType, shaderScript.text);
|
|
||||||
},
|
|
||||||
createProgram: function createProgram(shaders) {
|
|
||||||
var gl = this.gl;
|
|
||||||
var program = gl.createProgram();
|
|
||||||
shaders.forEach(function (shader) {
|
|
||||||
gl.attachShader(program, shader);
|
|
||||||
});
|
|
||||||
gl.linkProgram(program);
|
|
||||||
if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
|
|
||||||
var lastError = gl.getProgramInfoLog(program);
|
|
||||||
unexpected("Cannot link program: " + lastError);
|
|
||||||
gl.deleteProgram(program);
|
|
||||||
}
|
|
||||||
return program;
|
|
||||||
},
|
|
||||||
drawTriangles: function drawArrays(first, count) {
|
|
||||||
var gl = this.gl;
|
|
||||||
gl.drawArrays(gl.TRIANGLES, first, count);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
return constructor;
|
return constructor;
|
||||||
})();
|
})();
|
||||||
|
|
||||||
function trace(s) {
|
|
||||||
console.info(s);
|
|
||||||
}
|
|
|
@ -0,0 +1,189 @@
|
||||||
|
/**
|
||||||
|
* Yet another abstraction over WebGL APIs.
|
||||||
|
*/
|
||||||
|
var WebGLCanvas = (function () {
|
||||||
|
function constructor(canvas) {
|
||||||
|
this.canvas = canvas;
|
||||||
|
var w = this.width = canvas.width;
|
||||||
|
var h = this.height = canvas.height;
|
||||||
|
assert (w && h && isPowerOfTwo(w) && isPowerOfTwo(h));
|
||||||
|
this.gl = this.canvas.getContext("experimental-webgl");
|
||||||
|
assert (this.gl);
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor.prototype = {
|
||||||
|
rectangleVertices: function rectangleVertices(w, h) {
|
||||||
|
return new Float32Array([0, 0, w, 0, 0, h, 0, h, w, 0, w, h]);
|
||||||
|
},
|
||||||
|
rectangleTextureCoordinates: function rectangleTextureCoordinates() {
|
||||||
|
return new Float32Array([0, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 1]);
|
||||||
|
},
|
||||||
|
useProgram: function (program) {
|
||||||
|
this.gl.useProgram(program);
|
||||||
|
},
|
||||||
|
hasUniform: function hasUniform(program, name) {
|
||||||
|
return !!this.gl.getUniformLocation(program, name);
|
||||||
|
},
|
||||||
|
setVertexAttribute: function setVertexAttribute(program, name, buffer) {
|
||||||
|
var gl = this.gl;
|
||||||
|
var location = gl.getAttribLocation(program, name);
|
||||||
|
assert (location >= 0, "Attribute " + name + " not found.");
|
||||||
|
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
|
||||||
|
gl.enableVertexAttribArray(location);
|
||||||
|
gl.vertexAttribPointer(location, 2, gl.FLOAT, false, 0, 0);
|
||||||
|
},
|
||||||
|
setUniform4fv: function setUniform2f(program, name, vector) {
|
||||||
|
var gl = this.gl;
|
||||||
|
var location = gl.getUniformLocation(program, name);
|
||||||
|
assert (location, "Uniform " + name + " not found.");
|
||||||
|
gl.uniform4fv(location, vector);
|
||||||
|
},
|
||||||
|
setUniform2f: function setUniform2f(program, name, x, y) {
|
||||||
|
var gl = this.gl;
|
||||||
|
var location = gl.getUniformLocation(program, name);
|
||||||
|
assert (location, "Uniform " + name + " not found.");
|
||||||
|
gl.uniform2f(location, x, y);
|
||||||
|
},
|
||||||
|
setUniform1f: function setUniform2f(program, name, value) {
|
||||||
|
var gl = this.gl;
|
||||||
|
var location = gl.getUniformLocation(program, name);
|
||||||
|
assert (location, "Uniform " + name + " not found.");
|
||||||
|
gl.uniform1f(location, value);
|
||||||
|
},
|
||||||
|
setUniformMatrix4fv: function setUniform(program, name, matrix) {
|
||||||
|
var gl = this.gl;
|
||||||
|
var location = gl.getUniformLocation(program, name);
|
||||||
|
assert (location, "Uniform " + name + " not found.");
|
||||||
|
assert (matrix.length === 16, "Invalid matrix size.");
|
||||||
|
gl.uniformMatrix4fv(location, false, matrix);
|
||||||
|
},
|
||||||
|
setUniformMatrix3fv: function setUniformMatrix3fv(program, name, matrix) {
|
||||||
|
var gl = this.gl;
|
||||||
|
var location = gl.getUniformLocation(program, name);
|
||||||
|
assert (location, "Uniform " + name + " not found.");
|
||||||
|
assert (matrix.length === 9, "Invalid matrix size.");
|
||||||
|
gl.uniformMatrix3fv(location, false, matrix);
|
||||||
|
},
|
||||||
|
createVertexBuffer: function createBuffer(vertices) {
|
||||||
|
var gl = this.gl;
|
||||||
|
var buffer = gl.createBuffer();
|
||||||
|
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
|
||||||
|
gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);
|
||||||
|
return buffer;
|
||||||
|
},
|
||||||
|
createFramebuffer: function createFramebuffer() {
|
||||||
|
var gl = this.gl;
|
||||||
|
var texture = this.createTexture();
|
||||||
|
this.initializeTexture(texture, this.width, this.height, null);
|
||||||
|
var framebuffer = gl.createFramebuffer();
|
||||||
|
gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer);
|
||||||
|
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0);
|
||||||
|
framebuffer.texture = texture;
|
||||||
|
return framebuffer;
|
||||||
|
},
|
||||||
|
createTexture: function createAndBindTexture() {
|
||||||
|
var gl = this.gl;
|
||||||
|
var texture = gl.createTexture();
|
||||||
|
this.bindTexture(texture);
|
||||||
|
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
|
||||||
|
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
|
||||||
|
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
|
||||||
|
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
|
||||||
|
return texture;
|
||||||
|
},
|
||||||
|
initializeTexture: function initializeTexture(texture, width, height, data) {
|
||||||
|
var gl = this.gl;
|
||||||
|
this.bindTexture(texture);
|
||||||
|
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, width, height, 0, gl.RGBA, gl.UNSIGNED_BYTE, data);
|
||||||
|
},
|
||||||
|
bindTexture: function bindTexture(texture) {
|
||||||
|
var gl = this.gl;
|
||||||
|
gl.bindTexture(gl.TEXTURE_2D, texture);
|
||||||
|
},
|
||||||
|
bindFramebuffer: function bindFramebuffer(framebuffer) {
|
||||||
|
var gl = this.gl;
|
||||||
|
gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer);
|
||||||
|
},
|
||||||
|
createShader: function createShader(gl, shaderType, shaderSource) {
|
||||||
|
var gl = this.gl;
|
||||||
|
var shader = gl.createShader(shaderType);
|
||||||
|
gl.shaderSource(shader, shaderSource);
|
||||||
|
gl.compileShader(shader);
|
||||||
|
if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
|
||||||
|
var lastError = gl.getShaderInfoLog(shader);
|
||||||
|
unexpected("Cannot compile shader: " + lastError);
|
||||||
|
gl.deleteShader(shader);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return shader;
|
||||||
|
},
|
||||||
|
createShaderFromFile: function createShaderFromFile(file) {
|
||||||
|
var gl = this.gl;
|
||||||
|
var request = new XMLHttpRequest();
|
||||||
|
request.open("GET", file, false);
|
||||||
|
request.send();
|
||||||
|
assert (request.status === 200, "File : " + file + " not found.");
|
||||||
|
var shaderType;
|
||||||
|
if (file.endsWith(".vert")) {
|
||||||
|
shaderType = gl.VERTEX_SHADER;
|
||||||
|
} else if (file.endsWith(".frag")) {
|
||||||
|
shaderType = gl.FRAGMENT_SHADER;
|
||||||
|
} else {
|
||||||
|
throw "Shader Type: not supported.";
|
||||||
|
}
|
||||||
|
return this.createShader(gl, shaderType, request.responseText);
|
||||||
|
},
|
||||||
|
createShaderFromElement: function createShaderFromElement(id) {
|
||||||
|
var gl = this.gl;
|
||||||
|
var shaderScript = document.getElementById(id);
|
||||||
|
if (!shaderScript) {
|
||||||
|
unexpected("Shader Script Element: " + id + " not found.");
|
||||||
|
}
|
||||||
|
var shaderType;
|
||||||
|
switch (shaderScript.type) {
|
||||||
|
case "x-shader/x-vertex":
|
||||||
|
shaderType = gl.VERTEX_SHADER;
|
||||||
|
break;
|
||||||
|
case "x-shader/x-fragment":
|
||||||
|
shaderType = gl.FRAGMENT_SHADER;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw "Shader Type: " + shaderScript.type + " not supported.";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return this.createShader(gl, shaderType, shaderScript.text);
|
||||||
|
},
|
||||||
|
createProgram: function createProgram(shaders) {
|
||||||
|
var gl = this.gl;
|
||||||
|
var program = gl.createProgram();
|
||||||
|
shaders.forEach(function (shader) {
|
||||||
|
gl.attachShader(program, shader);
|
||||||
|
});
|
||||||
|
gl.linkProgram(program);
|
||||||
|
if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
|
||||||
|
var lastError = gl.getProgramInfoLog(program);
|
||||||
|
unexpected("Cannot link program: " + lastError);
|
||||||
|
gl.deleteProgram(program);
|
||||||
|
}
|
||||||
|
return program;
|
||||||
|
},
|
||||||
|
drawTriangles: function drawArrays(first, count) {
|
||||||
|
var gl = this.gl;
|
||||||
|
gl.drawArrays(gl.TRIANGLES, first, count);
|
||||||
|
},
|
||||||
|
clear: function clear(color) {
|
||||||
|
var gl = this.gl;
|
||||||
|
gl.clearColor(color[0], color[1], color[2], color[3]);
|
||||||
|
gl.clear(gl.COLOR_BUFFER_BIT);
|
||||||
|
},
|
||||||
|
enableBlend: function enableBlend() {
|
||||||
|
var gl = this.gl;
|
||||||
|
gl.enable(gl.BLEND);
|
||||||
|
},
|
||||||
|
disableBlend: function disableBlend() {
|
||||||
|
var gl = this.gl;
|
||||||
|
gl.disable(gl.BLEND);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return constructor;
|
||||||
|
})();
|
|
@ -0,0 +1,8 @@
|
||||||
|
precision mediump float;
|
||||||
|
uniform sampler2D u_image;
|
||||||
|
uniform vec4 u_color;
|
||||||
|
varying vec2 v_texCoord;
|
||||||
|
void main() {
|
||||||
|
// gl_FragColor = u_matrix * texture2D(u_image, v_texCoord) + u_vector;
|
||||||
|
gl_FragColor = u_color * texture2D(u_image, v_texCoord).a;
|
||||||
|
}
|
|
@ -0,0 +1,15 @@
|
||||||
|
precision mediump float;
|
||||||
|
uniform sampler2D u_image;
|
||||||
|
uniform vec2 u_textureSize;
|
||||||
|
varying vec2 v_texCoord;
|
||||||
|
void main() {
|
||||||
|
const int sampleRadius = 10;
|
||||||
|
const int samples = sampleRadius * 2 + 1;
|
||||||
|
vec2 one = vec2(1.0, 1.0) / u_textureSize;
|
||||||
|
vec4 color = vec4(0, 0, 0, 0);
|
||||||
|
for (int i = -sampleRadius; i <= sampleRadius; i++) {
|
||||||
|
color += texture2D(u_image, v_texCoord + vec2(float(i) * one.x, 0));
|
||||||
|
}
|
||||||
|
color /= float(samples);
|
||||||
|
gl_FragColor = color;
|
||||||
|
}
|
|
@ -0,0 +1,15 @@
|
||||||
|
precision mediump float;
|
||||||
|
uniform sampler2D u_image;
|
||||||
|
uniform vec2 u_textureSize;
|
||||||
|
varying vec2 v_texCoord;
|
||||||
|
void main() {
|
||||||
|
const int sampleRadius = 10;
|
||||||
|
const int samples = sampleRadius * 2 + 1;
|
||||||
|
vec2 one = vec2(1.0, 1.0) / u_textureSize;
|
||||||
|
vec4 color = vec4(0, 0, 0, 0);
|
||||||
|
for (int i = -sampleRadius; i <= sampleRadius; i++) {
|
||||||
|
color += texture2D(u_image, v_texCoord + vec2(0, float(i) * one.y));
|
||||||
|
}
|
||||||
|
color /= float(samples);
|
||||||
|
gl_FragColor = color;
|
||||||
|
}
|
|
@ -0,0 +1,14 @@
|
||||||
|
attribute vec2 a_position;
|
||||||
|
uniform vec2 u_resolution;
|
||||||
|
uniform float u_flipY;
|
||||||
|
uniform float u_time;
|
||||||
|
attribute vec2 a_textureCoordinate;
|
||||||
|
uniform mat3 u_transformMatrix;
|
||||||
|
varying vec2 v_texCoord;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
vec2 position = ((u_transformMatrix * vec3(a_position, 1.0)).xy / u_resolution) * 2.0 - 1.0;
|
||||||
|
position *= vec2(1.0, u_flipY);
|
||||||
|
gl_Position = vec4(vec3(position, 1.0), 1.0);
|
||||||
|
v_texCoord = a_textureCoordinate;
|
||||||
|
}
|
|
@ -0,0 +1,8 @@
|
||||||
|
precision mediump float;
|
||||||
|
uniform sampler2D u_image;
|
||||||
|
uniform mat4 u_colorMatrix;
|
||||||
|
uniform vec4 u_vector;
|
||||||
|
varying vec2 v_texCoord;
|
||||||
|
void main() {
|
||||||
|
gl_FragColor = u_colorMatrix * texture2D(u_image, v_texCoord) + u_vector;
|
||||||
|
}
|
|
@ -0,0 +1,6 @@
|
||||||
|
precision mediump float;
|
||||||
|
uniform sampler2D u_image;
|
||||||
|
varying vec2 v_texCoord;
|
||||||
|
void main() {
|
||||||
|
gl_FragColor = texture2D(u_image, v_texCoord);
|
||||||
|
}
|
|
@ -0,0 +1,8 @@
|
||||||
|
precision mediump float;
|
||||||
|
uniform sampler2D u_image;
|
||||||
|
uniform vec4 u_color;
|
||||||
|
varying vec2 v_texCoord;
|
||||||
|
void main() {
|
||||||
|
gl_FragColor = texture2D(u_image, v_texCoord) * vec4(1.9, 1.0, 1.0, 1.0);
|
||||||
|
gl_FragColor = texture2D(u_image, v_texCoord) * u_color;
|
||||||
|
}
|
Загрузка…
Ссылка в новой задаче