Skip to content

Instantly share code, notes, and snippets.

@Themaister
Created September 17, 2011 15:05
Show Gist options
  • Save Themaister/1224021 to your computer and use it in GitHub Desktop.
Save Themaister/1224021 to your computer and use it in GitHub Desktop.
<html>
<head>
<title>WebGL shader test ...</title>
</head>
<body onload="webGLStart();">
<p>Hai! :D WebGL shader test ...</p>
<canvas id="test_canvas" style="border: none" width="1024" height="896"></canvas>
</body>
<script id="vertex_shader" type="x-shader/x-vertex">
attribute vec2 rubyVertex;
attribute vec2 rubyTexCoord;
varying vec2 c00;
varying vec2 c10;
varying vec2 c20;
varying vec2 c01;
varying vec2 c11;
varying vec2 c21;
varying vec2 c02;
varying vec2 c12;
varying vec2 c22;
varying vec2 pixel_no;
uniform vec2 rubyTextureSize;
uniform vec2 rubyOutputSize;
uniform vec2 rubyInputSize;
void main()
{
gl_Position = vec4(rubyVertex, 0.0, 1.0);
float dx = 1.0 / rubyTextureSize.x;
float dy = 1.0 / rubyTextureSize.y;
vec2 tex = rubyTexCoord;
c00 = tex + vec2(-dx, -dy);
c10 = tex + vec2( 0, -dy);
c20 = tex + vec2( dx, -dy);
c01 = tex + vec2(-dx, 0);
c11 = tex + vec2( 0, 0);
c21 = tex + vec2( dx, 0);
c02 = tex + vec2(-dx, dy);
c12 = tex + vec2( 0, dy);
c22 = tex + vec2( dx, dy);
pixel_no = tex * rubyTextureSize;
}
</script>
<script id="fragment_shader" type="x-shader/x-fragment">
#ifdef GL_ES
precision highp float;
#endif
uniform vec2 rubyTextureSize;
uniform sampler2D rubyTexture;
varying vec2 c00;
varying vec2 c10;
varying vec2 c20;
varying vec2 c01;
varying vec2 c11;
varying vec2 c21;
varying vec2 c02;
varying vec2 c12;
varying vec2 c22;
varying vec2 pixel_no;
const float gamma = 2.4;
const float shine = 0.05;
const float blend = 0.65;
float dist(vec2 coord, vec2 source)
{
vec2 delta = coord - source;
return sqrt(dot(delta, delta));
}
float color_bloom(vec3 color)
{
const vec3 gray_coeff = vec3(0.30, 0.59, 0.11);
float bright = dot(color, gray_coeff);
return mix(1.0 + shine, 1.0 - shine, bright);
}
vec3 lookup(float offset_x, float offset_y, vec2 coord)
{
vec2 offset = vec2(offset_x, offset_y);
vec3 color = texture2D(rubyTexture, coord).rgb;
float delta = dist(fract(pixel_no), offset + vec2(0.5));
return color * exp(-gamma * delta * color_bloom(color));
}
void main()
{
vec3 mid_color = lookup(0.0, 0.0, c11);
vec3 color = vec3(0.0);
color += lookup(-1.0, -1.0, c00);
color += lookup( 0.0, -1.0, c10);
color += lookup( 1.0, -1.0, c20);
color += lookup(-1.0, 0.0, c01);
color += mid_color;
color += lookup( 1.0, 0.0, c21);
color += lookup(-1.0, 1.0, c02);
color += lookup( 0.0, 1.0, c12);
color += lookup( 1.0, 1.0, c22);
vec3 out_color = mix(1.2 * mid_color, color, blend);
gl_FragColor = vec4(out_color, 1.0);
}
</script>
<script type="text/javascript">
var gl;
function initGL(canvas) {
try {
gl = canvas.getContext("experimental-webgl");
gl.viewportWidth = canvas.width;
gl.viewportHeight = canvas.height;
} catch (e) {}
if (!gl) {
alert("Could not init WebGL ... :(");
}
}
function getShader(id) {
var script = document.getElementById(id);
if (!script) { return null; }
var str = "";
var k = script.firstChild;
while (k) {
if (k.nodeType == 3) { // Magic number 3, what :v
str += k.textContent;
}
k = k.nextSibling;
}
var shader;
if (script.type == "x-shader/x-fragment") {
shader = gl.createShader(gl.FRAGMENT_SHADER);
} else if (script.type == "x-shader/x-vertex") {
shader = gl.createShader(gl.VERTEX_SHADER);
} else {
return null;
}
gl.shaderSource(shader, str);
gl.compileShader(shader);
if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
alert(gl.getShaderInfoLog(shader));
return null;
}
return shader;
}
var texture_ = null;
function handleImage(gl, tex) {
try {
gl.bindTexture(gl.TEXTURE_2D, tex);
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, false);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, tex.image);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
// Would prefer clamp to border, but GLES only supports CLAMP_TO_EDGE with NPOT textures.
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);
} catch (e) {
alert(e);
}
}
function initTexture(path) {
var texture = gl.createTexture();
texture.image = new Image();
texture.image.onload = function() {
handleImage(gl, texture);
}
texture.image.src = path;
return texture;
}
var prog;
function initShaders() {
var frag = getShader("fragment_shader");
var vertex = getShader("vertex_shader");
prog = gl.createProgram();
gl.attachShader(prog, frag);
gl.attachShader(prog, vertex);
gl.linkProgram(prog);
if (!gl.getProgramParameter(prog, gl.LINK_STATUS)) {
alert("Failed to init shader!");
}
gl.useProgram(prog);
prog.vert_attr = gl.getAttribLocation(prog, "rubyVertex");
prog.tex_attr = gl.getAttribLocation(prog, "rubyTexCoord");
gl.enableVertexAttribArray(prog.vert_attr);
gl.enableVertexAttribArray(prog.tex_attr);
gl.enable(gl.TEXTURE_2D);
texture_ = initTexture("game.png");
gl.uniform1i(gl.getUniformLocation(prog, "rubyTexture"), 0);
}
var vert_buf;
function initBuffers() {
vert_buf = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, vert_buf);
var coords = [
// TEX // VERT
0.0, 0.0, -1.0, 1.0,
1.0, 0.0, 1.0, 1.0,
0.0, 1.0, -1.0, -1.0,
1.0, 1.0, 1.0, -1.0,
];
coords.size = 4;
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(coords), gl.STATIC_DRAW);
gl.vertexAttribPointer(prog.tex_attr, 2, gl.FLOAT, false, 4 * coords.size, 0 * coords.size);
gl.vertexAttribPointer(prog.vert_attr, 2, gl.FLOAT, false, 4 * coords.size, 2 * coords.size);
}
function do_render() {
gl.uniform2f(gl.getUniformLocation(prog, "rubyTextureSize"),
texture_.image.width, texture_.image.height);
gl.uniform2f(gl.getUniformLocation(prog, "rubyInputSize"),
texture_.image.width, texture_.image.height);
gl.uniform2f(gl.getUniformLocation(prog, "rubyOutputSize"),
1024, 896);
gl.clear(gl.COLOR_BUFFER_BIT);
gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
gl.flush();
}
function webGLStart() {
try {
var canvas = document.getElementById("test_canvas");
initGL(canvas);
initShaders();
initBuffers();
gl.viewport(0, 0, gl.viewportWidth, gl.viewportHeight);
gl.clearColor(0.0, 0.0, 0.0, 1.0);
var f = function() {
window.setTimeout(f, 100);
do_render();
};
f();
} catch (e) {
alert(e);
}
}
</script>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment