Created
September 18, 2011 12:38
-
-
Save Themaister/1225038 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
<!DOCTYPE html> | |
<html lang="en"> | |
<meta charset="utf-8"> | |
<head> | |
<title>XML Shader (1.0) Viewer</title> | |
</head> | |
<style type="text/css"> | |
body { | |
background: #eeeeee; | |
font-family: Verdana, serif; | |
margin: 20px; | |
} | |
</style> | |
<body onload="webGLStart();"> | |
<h1>XML shader viewer</h1> | |
<p>WebGL application to test your shaders against various images from your harddrive.</p> | |
<p>Written in pure HTML5/JavaScript, and can be run locally, just download the page source :)</p> | |
<p>Shaders need to conform to the XML shader specification (supported in | |
<a href="http://byuu.org/bsnes/">bSNES</a>, | |
<a href="https://github.com/Themaister/SSNES">SSNES</a> and | |
<a href="http://snes9x.com">SNES9x-Win32</a>). | |
A draft of this spec can be found | |
<a href="https://gitorious.org/bsnes/pages/XmlShaderFormat">here.</a> | |
Note that only the 1.0 subset is supported. Some example shaders can be found | |
<a href="https://gitorious.org/bsnes/bsnes/trees/patches/snesshader">here.</a></p> | |
<p>Note that it is not limited to emulators, but it's certainly geared for 2D images.</p> | |
<p>Do note that the XML shader is converted internally to be supported by OpenGL ES 2.0. The XML shader spec bases itself on pre-OpenGL 3.x. | |
Some fixed-function components are redefined to properly use varying/attribute components.</p> | |
<p>Total scale: | |
<input type="button" onclick="do_resize(0.25);" value="0.25x"/> | |
<input type="button" onclick="do_resize(0.5);" value="0.5x"/> | |
<input type="button" onclick="do_resize(1);" value="1x"/> | |
<input type="button" onclick="do_resize(2);" value="2x"/> | |
<input type="button" onclick="do_resize(3);" value="3x"/> | |
<input type="button" onclick="do_resize(4);" value="4x"/> | |
<input type="button" onclick="do_resize(5);" value="5x"/> | |
<output id="total_scale_output"><b>1x</b></output></p> | |
<p>Image: <input type="file" id="image_file" name="files[]"/> | |
<input type="button" onclick="reset_image();" value="Reset image"/> | |
<output id="image_output"><b>None</b></output></p> | |
<p>Shader (1. pass): <input type="file" id="shader_file" name="files[]"/> | |
<input type="button" onclick="reset_shader();" value="Reset shader"/> | |
<output id="shader1_output"><b>Default</b></p> | |
<p>FBO scale: | |
<input type="button" onclick="do_fbo_scale(0);" value="Off"/> | |
<input type="button" onclick="do_fbo_scale(1);" value="1x"/> | |
<input type="button" onclick="do_fbo_scale(2);" value="2x"/> | |
<input type="button" onclick="do_fbo_scale(3);" value="3x"/> | |
<input type="button" onclick="do_fbo_scale(4);" value="4x"/> | |
<output id="fbo_scale_output"><b>Off</b></output></p> | |
<p>Shader (2. pass): <input type="file" id="shader_file2" name="files[]"/> | |
<input type="button" onclick="reset_shader2();" value="Reset shader"/> | |
<output id="shader2_output"><b>Default</b></output></p> | |
<canvas id="test_canvas" style="border: none" width="256" height="224"></canvas><br/> | |
<output id="text_output"></output><br/> | |
<output id="text_output2"></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; | |
var output = document.getElementById("total_scale_output"); | |
output.innerHTML = "<b>" + scale + "x</b>"; | |
} | |
var fbo_scale = 1; | |
var fbo_enabled = false; | |
function do_fbo_scale(scale) { | |
fbo_enabled = scale != 0; | |
fbo_scale = scale; | |
var output = document.getElementById("fbo_scale_output"); | |
if (fbo_enabled) { | |
output.innerHTML = "<b>" + fbo_scale + "x</b>"; | |
} else { | |
output.innerHTML = "<b>Off</b>"; | |
} | |
} | |
</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_[8]; | |
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; | |
var texture_fbo = null; | |
var fbo_ = null; | |
function set_image(img) { | |
gl.bindTexture(gl.TEXTURE_2D, texture_); | |
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 | |
}; | |
} | |
// Hacks to conform to GLES 2.0 :) | |
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, index) { | |
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; | |
} | |
var log = gl.getShaderInfoLog(vert_s); | |
if (log.length > 0) { | |
alert(log); | |
} | |
} 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; | |
} | |
var log = gl.getShaderInfoLog(frag_s); | |
if (log.length > 0) { | |
alert(log); | |
} | |
} else { | |
frag_s = getShader("fragment_shader"); | |
} | |
gl.useProgram(null); | |
if (index === 0) { | |
gl.deleteProgram(prog); | |
} else if (index === 1) { | |
gl.deleteProgram(prog2); | |
} | |
var program = gl.createProgram(); | |
gl.attachShader(program, vert_s); | |
gl.attachShader(program, frag_s); | |
gl.linkProgram(program); | |
if (!gl.getProgramParameter(program, gl.LINK_STATUS)) { | |
alert(gl.getProgramInfoLog(program)); | |
return; | |
} | |
program.vert = vert_s; | |
program.frag = frag_s; | |
gl.useProgram(program); | |
program.vert_attr = gl.getAttribLocation(prog, "rubyVertex"); | |
program.tex_attr = gl.getAttribLocation(prog, "rubyTexCoord"); | |
gl.enableVertexAttribArray(program.vert_attr); | |
gl.enableVertexAttribArray(program.tex_attr); | |
gl.uniform1i(gl.getUniformLocation(program, "rubyTexture"), 0); | |
gl.vertexAttribPointer(program.tex_attr, 2, gl.FLOAT, false, 4 * 4, 0 * 4); | |
gl.vertexAttribPointer(program.vert_attr, 2, gl.FLOAT, false, 4 * 4, 2 * 4); | |
if (index === 0) { | |
prog = program; | |
} else if (index === 1) { | |
prog2 = program; | |
} | |
} | |
function reset_shader() { | |
compile_xml_shader(null, null, 0); | |
var output = document.getElementById("text_output"); | |
output.innerHTML = ""; | |
output = document.getElementById("shader1_output"); | |
output.innerHTML = "<b>Default</b>"; | |
} | |
function reset_shader2() { | |
compile_xml_shader(null, null, 1); | |
var output = document.getElementById("text_output2"); | |
output.innerHTML = ""; | |
output = document.getElementById("shader2_output"); | |
output.innerHTML = "<b>Default</b>"; | |
} | |
function reset_image() { | |
texture_.image.width = 0; | |
texture_.image.height = 0; | |
do_resize(1); | |
} | |
function load_text(evt, index) { | |
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, index); | |
var output = null; | |
if (index === 0) { | |
output = document.getElementById("shader1_output"); | |
} else if (index === 1) { | |
output = document.getElementById("shader2_output"); | |
} | |
output.innerHTML = "<b>Enabled</b>"; | |
} catch (e) { | |
alert(e); | |
} | |
} | |
reader.readAsText(file); | |
} | |
function load_text0(evt) { | |
load_text(evt, 0); | |
} | |
function load_text1(evt) { | |
load_text(evt, 1); | |
} | |
document.getElementById("image_file").addEventListener('change', load_image, false); | |
document.getElementById("shader_file").addEventListener('change', load_text0, false); | |
document.getElementById("shader_file2").addEventListener('change', load_text1, false); | |
var prog; | |
var prog2; | |
function initShaders() { | |
prog = gl.createProgram(); | |
prog2 = gl.createProgram(); | |
prog.frag = getShader("fragment_shader"); | |
prog.vertex = getShader("vertex_shader"); | |
prog2.frag = getShader("fragment_shader"); | |
prog2.vertex = getShader("vertex_shader"); | |
gl.attachShader(prog, prog.frag); | |
gl.attachShader(prog, prog.vertex); | |
gl.attachShader(prog2, prog2.frag); | |
gl.attachShader(prog2, prog2.vertex); | |
gl.linkProgram(prog); | |
gl.linkProgram(prog2); | |
if (!gl.getProgramParameter(prog, gl.LINK_STATUS)) { | |
alert("Failed to init shader!"); | |
} | |
if (!gl.getProgramParameter(prog2, gl.LINK_STATUS)) { | |
alert("Failed to init shader!"); | |
} | |
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); | |
texture_ = gl.createTexture(); | |
texture_.image = new Image(); | |
texture_.image.width = 0; | |
texture_.image.height = 0; | |
gl.bindTexture(gl.TEXTURE_2D, texture_); | |
} | |
function initFramebuffer() { | |
texture_fbo = gl.createTexture(); | |
fbo_ = gl.createFramebuffer(); | |
gl.bindFramebuffer(gl.FRAMEBUFFER, fbo_); | |
fbo_.width = 512; | |
fbo_.height = 512; | |
gl.bindTexture(gl.TEXTURE_2D, texture_fbo); | |
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, fbo_.width, fbo_.height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null); | |
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); | |
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.bindTexture(gl.TEXTURE_2D, texture_); | |
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture_fbo, 0); | |
gl.bindFramebuffer(gl.FRAMEBUFFER, null); | |
} | |
var vert_buf; | |
var vert_buf_fbo; | |
function initBuffers() { | |
vert_buf_fbo = gl.createBuffer(); | |
gl.bindBuffer(gl.ARRAY_BUFFER, vert_buf_fbo); | |
var fbo_coords = [ // Non-flipped. | |
// TEX // VERT | |
0.0, 1.0, -1.0, 1.0, | |
1.0, 1.0, 1.0, 1.0, | |
0.0, 0.0, -1.0, -1.0, | |
1.0, 0.0, 1.0, -1.0, | |
]; | |
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(fbo_coords), gl.STATIC_DRAW); | |
vert_buf = gl.createBuffer(); | |
gl.bindBuffer(gl.ARRAY_BUFFER, vert_buf); | |
var coords = [ // Flipped. | |
// 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_regular() { | |
gl.clear(gl.COLOR_BUFFER_BIT); | |
var canvas = document.getElementById("test_canvas"); | |
gl.bindFramebuffer(gl.FRAMEBUFFER, null); | |
gl.viewportWidth = canvas.width; | |
gl.viewportHeight = canvas.height; | |
gl.bindBuffer(gl.ARRAY_BUFFER, vert_buf); | |
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); | |
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.drawArrays(gl.TRIANGLE_STRIP, 0, 4); | |
} | |
function do_render_fbo() { | |
var out_width = texture_.image.width * fbo_scale; | |
var out_height = texture_.image.width * fbo_scale; | |
if ((out_width != fbo_.width) || (out_height != fbo_.height)) { | |
gl.bindTexture(gl.TEXTURE_2D, texture_fbo); | |
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, out_width, out_height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null); | |
fbo_.width = out_width; | |
fbo_.height = out_height; | |
} | |
gl.bindBuffer(gl.ARRAY_BUFFER, vert_buf_fbo); | |
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.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); | |
gl.bindTexture(gl.TEXTURE_2D, texture_); | |
gl.bindFramebuffer(gl.FRAMEBUFFER, fbo_); | |
gl.viewport(0, 0, fbo_.width, fbo_.height); | |
gl.clear(gl.COLOR_BUFFER_BIT); | |
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"), | |
fbo_.width, fbo_.height); | |
gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4); | |
gl.useProgram(prog2); | |
gl.bindFramebuffer(gl.FRAMEBUFFER, null); | |
gl.bindTexture(gl.TEXTURE_2D, texture_fbo); | |
var canvas = document.getElementById("test_canvas"); | |
gl.viewportWidth = canvas.width; | |
gl.viewportHeight = canvas.height; | |
gl.viewport(0, 0, gl.viewportWidth, gl.viewportHeight); | |
gl.clear(gl.COLOR_BUFFER_BIT); | |
gl.bindBuffer(gl.ARRAY_BUFFER, vert_buf); | |
prog2.vert_attr = gl.getAttribLocation(prog2, "rubyVertex"); | |
prog2.tex_attr = gl.getAttribLocation(prog2, "rubyTexCoord"); | |
gl.enableVertexAttribArray(prog2.vert_attr); | |
gl.enableVertexAttribArray(prog2.tex_attr); | |
gl.vertexAttribPointer(prog2.tex_attr, 2, gl.FLOAT, false, 4 * 4, 0 * 4); | |
gl.vertexAttribPointer(prog2.vert_attr, 2, gl.FLOAT, false, 4 * 4, 2 * 4); | |
gl.uniform1i(gl.getUniformLocation(prog2, "rubyTexture"), 0); | |
gl.uniform2f(gl.getUniformLocation(prog2, "rubyTextureSize"), | |
fbo_.width, fbo_.height); | |
gl.uniform2f(gl.getUniformLocation(prog2, "rubyInputSize"), | |
fbo_.width, fbo_.height); | |
gl.uniform2f(gl.getUniformLocation(prog2, "rubyOutputSize"), | |
gl.viewportWidth, gl.viewportHeight); | |
gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4); | |
} | |
function do_render() { | |
try { | |
if (texture_.image.width == 0 && texture_.image.height == 0) | |
return; | |
gl.useProgram(prog); | |
gl.bindTexture(gl.TEXTURE_2D, texture_); | |
if (fbo_enabled) { | |
do_render_fbo(); | |
} else { | |
do_render_regular(); | |
} | |
gl.flush(); | |
} catch (e) { | |
alert(e); | |
} | |
} | |
function webGLStart() { | |
try { | |
var canvas = document.getElementById("test_canvas"); | |
initGL(canvas); | |
gl.enable(gl.TEXTURE_2D); | |
initFramebuffer(); | |
initShaders(); | |
initBuffers(); | |
gl.viewport(0, 0, gl.viewportWidth, gl.viewportHeight); | |
gl.clearColor(0.0, 0.0, 0.0, 0.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