Created
September 17, 2011 15:05
-
-
Save Themaister/1224021 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<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