CS424 Notes, 10 February 2012
- Texture Transforms (Discussion)
- A pair of (s,t) texture coordinates is just a vec2. You can apply an affine transformation to these coordinates just as easily as you can to vertex coordinates.
- How would you do this? Would it be in the vertex or in the fragment shader?
- What would be the effect? What happens if you apply a rotation, translation, or scaling to the texture coordinates, before using them in a sampler2D?
- A Note on Animation with requestAnimationFrame
- The traditional way to do animation in JavaScript is with the standard function setTimeout(callback,millis). The first parameter to setTimeout is a function, the second is an integer. The result is to schedule a call to the function, callback(), millis milliseconds after the call to setTimeout is executed. To continue the animation, the callback function can include a call to setTimeout to schedule the next frame of the animation. This is the the animation method used in transform-demo.html, for example.
- There are problems with this type of animation: It keeps running and consuming resources even when the browser window is minimized or when it's in a tab that is not currently visible in the window. And it does not fit in well with the way web browsers refresh the page, which happens on a regular schedule.
- There is a proposed standard for a new way to do animation,
a standard function
requestAnimationFrame( callback );
This is similar to setTimeout, but in this case, there is no second parameter to say when the callback function should be called. Instead, it will be called during the next browser page-refresh (and, I presume, will force one if necessary, but only if the page is actually visible). The callback function will be called with one parameter, a timestamp giving the number of milliseconds since some arbitrary point in the past. Generally, you would rather know the number of milliseconds since the animation started. To get that information, you might use a callback function like this doFrame() function:var animationStartTime; function doFrame( timestamp ) { if (!animationStartTime) animationStartTime = timestamp; // Record time of first call. var runTime = timestamp - animationStartTime; // Time since start. . . // Draw the frame, using the value of runTime. . requestAnimationFrame( doFrame ); }
To start this animation, you would just call requestAnimationFrame(doFrame). You might do this, for example, in an init() function that is called in response to the document onload event. - As I write this, requestAnimationFrame doesn't seem to be defined in any
browser, but there are browser-specific experimental versions. The following
statement will define requestAnimationFrame if it is not already defined,
falling back to setTimeout if it can't find anything else:
window.requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame || function (callback) { setTimeout(function() { callback(Date.now()); }, 33); };
Except for the fallback to setTimeout, this follows an example on the WebGL web site. (Note: the use of "window." here avoids undefined variable errors, but "window." is actually the default scope in a browser, so the function can be called as requestAnimationFrame rather than window.requestAnimationFrame.) - This type of animation is used, for example, in hierarchical2d-example.html.
- A note on glutil2d.js
- For Lab 4, I have moved some utility routines, which were previously in the main HTML file, into a JavaScript file, glutil2d.js.
- glutil2d.js contains the functions createProgram(), createWebGLContext(), and checkGLError(). The latter differs from the version in previous labs, since it requires the WebGL context, gl, as a parameter.
- glutil2d.js also includes a copy of the AffineTransform2D class, which was previously defined in its own JavaScript file.
- New in glutil2d.js is a function getElementText() that extracts all the text content of an HTML element. This is used in Lab 4 to get the shader source code text from HTML elements, which makes it easier to edit the shader source. See points.html, from Lab 4, for example.
- glutil2d.js defines requestAnimationFrame(), as discussed above.
- It also
introduces a new Animator class to make it easier to do animations with
requestAnimationFrame().
-
To create an Animator object, just call
animator = new Animator( frameFunc );
where frameFunc is a callback function, similar to the callback function in requestAnimationFrame. (But this frameFunc is not responsible for scheduling the next call to requestAnimationFrame; the animator takes care of that.) - The animation does not start automatically. Call animator.start() to start the animation running. You can call animator.stop() to stop the animation; after calling animator.stop(), you can call animator.start() to restart it.
- The function animator.isAnimating() returns a boolean value that tells whether or not the animation is paused. As an alternative to animator.start and animator.stop, you can call animator.setAnimating(animate), where animate is a boolean.
- In the constructor, the callback function frameFunc is a function that draws a frame of the animation. It should be a function of one or two parameters. It is will be called by the animator with two parameters, but you will probably not use the second, and you can leave it out of the function definition. The first parameter is the time that the animation has been running, in milliseconds, starting from the first time frameFunc is called by the animator. (It's value will be 0 the first time the function is called.) This time does not include time during which the animation was paused; the clock stops during a pause. This makes it possible to start and stop the animation smoothly. The second parameter to frameFunc is the actual elapsed time from the first call to frameFunc, including times when the animation was paused. (If the animation was never paused, the second parameter will be the same as the first.)