Created
September 17, 2011 22:50
-
-
Save Themaister/1224459 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>XML Shader (1.0) Viewer</title> | |
</head> | |
<body onload="webGLStart();"> | |
<input type="button" onclick="do_resize(0.25)" value="Scale 0.25x"/> | |
<input type="button" onclick="do_resize(0.5)" value="Scale 0.5x"/> | |
<input type="button" onclick="do_resize(1)" value="Scale 1x"/> | |
<input type="button" onclick="do_resize(2)" value="Scale 2x"/> | |
<input type="button" onclick="do_resize(3)" value="Scale 3x"/> | |
<input type="button" onclick="do_resize(4)" value="Scale 4x"/> | |
<input type="button" onclick="do_resize(5)" value="Scale 5x"/><br/> | |
<p>Image: <input type="file" id="image_file" name="files[]"/></p> | |
<p>Shader: <input type="file" id="shader_file" name="files[]"/></p> | |
<canvas id="test_canvas" style="border: none" width="256" height="224"></canvas><br/> | |
<output id="text_output"></output><br/> | |
</body> | |
<script type="text/javascript"> | |
function do_resize(scale) { | |
var canvas = document.getElementById("test_canvas"); | |
canvas.width = texture_.image.width * scale; | |
canvas.height = texture_.image.height * scale; | |
} | |
</script> | |
<script id="vertex_shader" type="x-shader/x-vertex"> | |
attribute vec2 rubyVertex; | |
attribute vec2 rubyTexCoord; | |
varying vec4 rubyTexCoord_[8]; | |
void main() | |
{ | |
gl_Position = vec4(rubyVertex, 0.0, 1.0); | |
rubyTexCoord_[0] = vec4(rubyTexCoord, 0.0, 1.0); | |
} | |
</script> | |
<script id="fragment_shader" type="x-shader/x-fragment"> | |
#ifdef GL_ES | |
precision highp float; | |
#endif | |
uniform sampler2D rubyTexture; | |
varying vec4 rubyTexCoord_[5]; | |
void main() | |
{ | |
gl_FragColor = texture2D(rubyTexture, rubyTexCoord_[0].xy); | |
} | |
</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 set_image(img) { | |
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, img); | |
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, false); | |
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); | |
} | |
function load_image(evt) { | |
if (!(window.File && window.FileReader && window.FileList && window.Blob)) { | |
alert("FileReader API not supported by this browser ..."); | |
return; | |
} | |
var file = evt.target.files[0]; | |
if (!file.type.match("image.*")) { | |
alert("This is not an image file! :("); | |
return; | |
} | |
var reader = new FileReader(); | |
reader.onload = | |
function(e) { | |
texture_.old_img = texture_.image; | |
texture_.image = new Image(); | |
texture_.image.onload = function() { | |
if (texture_.image.width > 0 && texture_.image.height > 0) { | |
try { | |
set_image(texture_.image); | |
do_resize(1); | |
} catch (e) { | |
texture_.image = texture_.old_img; | |
alert(e); | |
} | |
} else { | |
texture_.image = texture_.old_img; | |
} | |
} | |
texture_.image.src = e.target.result; | |
} | |
reader.readAsDataURL(file); | |
} | |
function parse_xml(text) { | |
try { | |
var vert = null; | |
var frag = null; | |
var parser = new DOMParser(); | |
var xmldoc = parser.parseFromString(text, "text/xml"); | |
var elems; | |
elems = xmldoc.getElementsByTagName("vertex"); | |
if (elems.length > 0) { | |
vert = elems[0].childNodes[0].nodeValue; | |
} | |
elems = xmldoc.getElementsByTagName("fragment"); | |
if (elems.length > 0) { | |
frag = elems[0].childNodes[0].nodeValue; | |
} | |
} catch (e) { | |
alert(e); | |
} | |
return { | |
vert: vert, | |
frag: frag | |
}; | |
} | |
function transform_vert(vert_) { | |
var vert = "const mat4 trans_matrix_ = mat4(1.0, 0.0, 0.0, 0.0,\n"; | |
vert += "0.0, 1.0, 0.0, 0.0,\n"; | |
vert += "0.0, 0.0, 1.0, 0.0,\n"; | |
vert += "0.0, 0.0, 0.0, 1.0);\n"; | |
vert += "#define gl_ModelViewProjectionMatrix trans_matrix_\n"; | |
vert += "#define gl_Vertex vec4(rubyVertex, 0.0, 1.0)\n"; | |
vert += "#define gl_MultiTexCoord0 vec4(rubyTexCoord, 0.0, 0.0)\n"; | |
vert += "attribute vec2 rubyVertex;\n"; | |
vert += "attribute vec2 rubyTexCoord;\n"; | |
vert += "varying vec4 rubyTexCoord_[8];\n"; | |
vert += "#define gl_TexCoord rubyTexCoord_\n"; | |
vert += vert_; | |
return vert; | |
} | |
function transform_frag(frag_) { | |
var frag = "precision highp float;\n"; | |
frag += "varying vec4 rubyTexCoord_[8];\n"; | |
frag += "#define gl_TexCoord rubyTexCoord_\n"; | |
frag += frag_; | |
return frag; | |
} | |
function compile_xml_shader(vert, frag) { | |
var vert_s = null; | |
var frag_s = null; | |
if (vert) { | |
vert_s = gl.createShader(gl.VERTEX_SHADER); | |
gl.shaderSource(vert_s, transform_vert(vert)); | |
gl.compileShader(vert_s); | |
if (!gl.getShaderParameter(vert_s, gl.COMPILE_STATUS)) { | |
alert(gl.getShaderInfoLog(vert_s)); | |
return; | |
} | |
} else { | |
vert_s = getShader("vertex_shader"); | |
} | |
if (frag) { | |
frag_s = gl.createShader(gl.FRAGMENT_SHADER); | |
gl.shaderSource(frag_s, transform_frag(frag)); | |
gl.compileShader(frag_s); | |
if (!gl.getShaderParameter(frag_s, gl.COMPILE_STATUS)) { | |
alert(gl.getShaderInfoLog(frag_s)); | |
return; | |
} | |
} else { | |
frag_s = getShader("fragment_shader"); | |
} | |
gl.deleteProgram(prog); | |
prog = gl.createProgram(); | |
gl.attachShader(prog, vert_s); | |
gl.attachShader(prog, frag_s); | |
gl.linkProgram(prog); | |
if (!gl.getProgramParameter(prog, gl.LINK_STATUS)) { | |
alert(gl.getProgramInfoLog(prog)); | |
return; | |
} | |
prog.vert = vert_s; | |
prog.frag = frag_s; | |
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.uniform1i(gl.getUniformLocation(prog, "rubyTexture"), 0); | |
gl.vertexAttribPointer(prog.tex_attr, 2, gl.FLOAT, false, 4 * 4, 0 * 4); | |
gl.vertexAttribPointer(prog.vert_attr, 2, gl.FLOAT, false, 4 * 4, 2 * 4); | |
} | |
function load_text(evt) { | |
if (!(window.File && window.FileReader && window.FileList && window.Blob)) { | |
alert("FileReader API not supported by this browser ..."); | |
return; | |
} | |
if (!window.DOMParser) { | |
alert("No XML parser found :("); | |
return; | |
} | |
var file = evt.target.files[0]; | |
if (!file.name.match("\\.shader$")) { | |
alert("Not an XML shader!"); | |
return; | |
} | |
var reader = new FileReader(); | |
reader.onload = | |
function(e) { | |
var xml = parse_xml(e.target.result); | |
var output = document.getElementById("text_output"); | |
output.innerHTML = ""; | |
if (xml.vert != null) { | |
output.innerHTML += '<textarea cols="50" rows="10" style="font-family:monospace">' | |
+ xml.vert + '</textarea>'; | |
} | |
if (xml.frag != null) { | |
output.innerHTML += '<textarea cols="50" rows="10" style="font-family:monospace">' | |
+ xml.frag + '</textarea>'; | |
} | |
try { | |
compile_xml_shader(xml.vert, xml.frag); | |
} catch (e) { | |
alert(e); | |
} | |
} | |
reader.readAsText(file); | |
} | |
document.getElementById("image_file").addEventListener('change', load_image, false); | |
document.getElementById("shader_file").addEventListener('change', load_text, false); | |
var prog; | |
function initShaders() { | |
prog = gl.createProgram(); | |
prog.frag = getShader("fragment_shader"); | |
prog.vertex = getShader("vertex_shader"); | |
gl.attachShader(prog, prog.frag); | |
gl.attachShader(prog, 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.uniform1i(gl.getUniformLocation(prog, "rubyTexture"), 0); | |
gl.enable(gl.TEXTURE_2D); | |
texture_ = gl.createTexture(); | |
texture_.image = new Image(); | |
texture_.image.width = 0; | |
texture_.image.height = 0; | |
gl.bindTexture(gl.TEXTURE_2D, texture_); | |
} | |
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() { | |
if (texture_.image.width == 0 && texture_.image.height == 0) | |
return; | |
var canvas = document.getElementById("test_canvas"); | |
gl.viewportWidth = canvas.width; | |
gl.viewportHeight = canvas.height; | |
gl.viewport(0, 0, gl.viewportWidth, gl.viewportHeight); | |
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"), | |
gl.viewportWidth, gl.viewportHeight); | |
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