open_canvas(); set_color();
What has to happen to draw points?
mouse_click_eventhandler() { get_mouse_location(); draw_point(mouse_location); }
javascript?
interact_with_video_card() transfer_data() tell_video_card_to_draw()
Hide-then-expose browser window
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8" /> <title>Draw a point with a mouse click</title> </head> <body onload="main()"> <canvas id="webgl" width="400" height="400"> Please use a browser that supports "canvas" </canvas> <script src="lib/webgl-utils.js"></script> <script src="lib/webgl-debug.js"></script> <script src="lib/cuon-utils.js"></script> <script src="ClickedPoints.js"></script> </body> </html>
<body onload="main()">
When is main()
executed?
Where is main()
found?
<canvas id="webgl" width="400" height="400"> Please use a browser that supports "canvas" </canvas>
Name? Multiple canvases?
Supports display image in web page, but
<img>
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8" /> <title>Draw a blue rectangle (canvas version)</title> </head> <body onload="main()"> <canvas id="webgl" width="400" height="400"> Please use a browser that supports "canvas" </canvas> <script src="DrawRectangle.js"></script> </body> </html>
// DrawTriangle.js (c) 2012 matsuda function main() { // Retrieve <canvas> element <- (1) var canvas = document.getElementById('webgl'); if (!canvas) { console.log('Failed to retrieve the <canvas> element'); return false; } // Get the rendering context for 2DCG <- (2) var ctx = canvas.getContext('2d'); // Draw a blue rectangle <- (3) // Set color to blue ctx.fillStyle = 'rgba(32, 32, 255, 1.0)'; // Fill a rectangle with the color ctx.fillRect(120, 10, 150, 150); // Draw the corners of the rectangle ctx.fillStyle = 'rgba(255, 32, 32, 1.0)'; ctx.fillRect(118, 8, 5, 5); ctx.fillStyle = 'rgba(32, 255, 32, 1.0)'; ctx.fillRect(267, 157, 5, 5); }
var canvas = document.getElementByID('webgl');
Reference to canvas element
Context
var ctx = canvas.getContext('2d');
Set state
ctx.fillStyle = 'rgba(0, 0, 255, 1.0)';
Draw
ctx.fillRect(120, 10, 150, 150);
DrawRectangle
uses HTML5 and canvas elements to draw simple 2D box in a window
WebGL - more complex
// retrieve canvas elements // get rendering context // initialize shaders // get location of variables shared between main and shaders // register event handler // clear canvas
So, what code draws the boxes?
var canvas = document.getElementById('webgl'); var gl = getWebGLContext(canvas);
Note: this is different (not canvas.xxxxx()
)
Wrapper around setupWebGL(canvas)
that allows debugging
setupWebGL
is a function in webgl-utils.js, a standard library from Google
Text files (or strings) as in OpenGL
OpenGL compiles
Embed as string in code
or
Read from file
Functions provided to handle details
if(!initShaders(gl, VSHADER_SOURCE, FSHADER_SOURCE)) { console.log('Failed to initialize shaders.'); return; }
Data transmitted to GPU
How can main()
and shader code share data?
Cannot use global variables in shared memory
Cannot pass variables
So, transfer to GPU memory but must be able to connect
var a_Position = gl.getAttribLocation(gl.program, 'a_position'); // name in shader programs -^
canvas.onmousedown = function(ev) { click(ev, gl, canvas, a_Position); };
Note: Anonymous function. Why?
Function must deal with location, what to do, etc. Should not rely on global variables.
But event handlers must have fixed signature (single parameter)
gl.clearColor(0.0, 0.0, 0.0, 1.0); // set state of how to clear gl.clear(gl.COLOR_BUFFER_BIT); // do clearing!
Where are the points drawn in response to mouse click?
var g_points = [];
Then, define click()
which is called by mouse click
function click(ev, gl, canvas, a_Position) { // NOTE: a_Position is target for data on GPU var x = ev.clientX; var y = ev.clientY; // ... }
Convert mouse locations to coordinates in window
var rect = ev.target.getBoundingClientRect(); x = ((x - rect.left) - canvas.width/2) / (canvas.width/2); y = (canvas.height/2 - (y - rect.top)) / (canvas.height/2);
g_points.push(x); g_points.push(y);
What happens to data structure?
Looks like an array, treat as stack
var len = g_points.length; for(var i = 0; i < len; i += 2) { gl.vertexAttrib3f(a_Position, g_points[i], g_points[i+1], 0.0); // functionName3f // 3 parameters type float gl.drawArrays(gl.Points, 0, 1); // ^ ^ ^- draw 1 point // | \--- begin at 0 // \------------- what to draw }
Transfer 1 point, draw
Lots of communication
Data collection is handled in main()
but passed to video card 1 at a time
var VSHADER_SOURCE = 'attribute vec4 a_Position;\n' + 'void main() {\n' + ' gl_Position = a_Position;\n' + ' gl_PointSize = 10.0;\n' + '}\n';
Set position of vertex to be passed through system
var FSHADER_SOURCE = 'void main() {\n' + ' gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);\n' + '}\n';
Single string, function main()
gl_FragColor
fragment color set to red