Difference between revisions of "WebGL and OpenGL"

From WebGL Public Wiki
Jump to navigation Jump to search
(fixing links)
Line 12: Line 12:
 
[[image:Texturetest.png]]
 
[[image:Texturetest.png]]
 
<p> The <code>loadTexture()</code> function contains all the code necessary to load an image from the Web and add it to a 3D scene:</p>
 
<p> The <code>loadTexture()</code> function contains all the code necessary to load an image from the Web and add it to a 3D scene:</p>
 +
 +
----
 +
 
<source lang="javascript">
 
<source lang="javascript">
 
function loadTexture(src) {
 
function loadTexture(src) {
Line 29: Line 32:
 
}
 
}
 
</source>
 
</source>
 +
 +
----
 +
 
<p>Let's look at the <code>loadTexture()</code> function more closely. First, notice that the WebGL calls are almost identical to their OpenGL counterparts, with a few exceptions. In particular, <code>gl.createTexture()</code> uses the singular form of "Texture" (not "Textures"), and it uses the verb "create" in place of the OpenGL "Gen" (so, <code>glGenTextures()</code> in OpenGL becomes <code>gl.createTexture()</code> in WebGL). The OpenGL call <code>glGenTextures()</code> simply generates a numeric texture id, whereas the WebGL call <code>gl.createTexture()</code> creates a <code>CanvasTexture</code> object to wrap that id.</p>
 
<p>Let's look at the <code>loadTexture()</code> function more closely. First, notice that the WebGL calls are almost identical to their OpenGL counterparts, with a few exceptions. In particular, <code>gl.createTexture()</code> uses the singular form of "Texture" (not "Textures"), and it uses the verb "create" in place of the OpenGL "Gen" (so, <code>glGenTextures()</code> in OpenGL becomes <code>gl.createTexture()</code> in WebGL). The OpenGL call <code>glGenTextures()</code> simply generates a numeric texture id, whereas the WebGL call <code>gl.createTexture()</code> creates a <code>CanvasTexture</code> object to wrap that id.</p>
 
<p>The <code>gl.createTexture()</code> call allocates a texture object but does not initialize it yet. The <code>gl.bindTexture()</code> call binds this texture object to a <code>TEXTURE_2D</code> binding point. (This call is analogous to OpenGL, where a texture object is bound to either a <code>TEXURE_2D</code> or a <code>TEXTURE_CUBE_MAP</code> binding point.) As in OpenGL, the <code>gl.texParameteri()</code> call is used to set the minification and magnification filters (in this case, to <code>gl.LINEAR</code>).</p>
 
<p>The <code>gl.createTexture()</code> call allocates a texture object but does not initialize it yet. The <code>gl.bindTexture()</code> call binds this texture object to a <code>TEXTURE_2D</code> binding point. (This call is analogous to OpenGL, where a texture object is bound to either a <code>TEXURE_2D</code> or a <code>TEXTURE_CUBE_MAP</code> binding point.) As in OpenGL, the <code>gl.texParameteri()</code> call is used to set the minification and magnification filters (in this case, to <code>gl.LINEAR</code>).</p>
 
<p>The following code in <code>loadTexture()</code> starts downloading the image located at <code>src</code>. This image is loaded in the background and, in this case, will be used in the 3D context rather than directly on the Web page. The application uses the browser's <code>image.onload</code> event to do the WebGL-specific work associated with the image loading:</p>
 
<p>The following code in <code>loadTexture()</code> starts downloading the image located at <code>src</code>. This image is loaded in the background and, in this case, will be used in the 3D context rather than directly on the Web page. The application uses the browser's <code>image.onload</code> event to do the WebGL-specific work associated with the image loading:</p>
 +
 +
----
 +
 
<source lang="javascript">
 
<source lang="javascript">
 
image.onload = function() {
 
image.onload = function() {
Line 41: Line 50:
 
image.src = src;
 
image.src = src;
 
</source>
 
</source>
 +
 +
----
 +
 
<p>When the image is finished loading, the <code>onload</code> event handler is called, which inserts the image into the WebGL <code>texture</code> object. Next, the application's <code>draw()</code> function is called, which forces a redraw of the scene and causes this texture image to "pop" into place.</p>
 
<p>When the image is finished loading, the <code>onload</code> event handler is called, which inserts the image into the WebGL <code>texture</code> object. Next, the application's <code>draw()</code> function is called, which forces a redraw of the scene and causes this texture image to "pop" into place.</p>
 
<h2 id="teapot">Handling Events</h2>
 
<h2 id="teapot">Handling Events</h2>
Line 46: Line 58:
 
[[image:Shinyteapot.png]]
 
[[image:Shinyteapot.png]]
 
<p>Here is the <code>CameraController</code> code that receives the standard <code>onmousedown</code>, <code>onmouseup</code>, and <code>onmousemove</code> events and issues callback functions that automatically update the corresponding camera controller variables:</p>
 
<p>Here is the <code>CameraController</code> code that receives the standard <code>onmousedown</code>, <code>onmouseup</code>, and <code>onmousemove</code> events and issues callback functions that automatically update the corresponding camera controller variables:</p>
 +
 +
----
 +
 
<source lang="javascript">
 
<source lang="javascript">
 
function CameraController(element) {
 
function CameraController(element) {
Line 89: Line 104:
 
}
 
}
 
</source>
 
</source>
 +
 +
----
  
 
<p>In WebGL, as in OpenGL, the application must explicitly compute the camera, view, and projection matrices. See the code in [https://cvs.khronos.org/svn/repos/registry/trunk/public/webgl/sdk/demos/google/shiny-teapot/index.html shiny-teapot] as an example. </p>
 
<p>In WebGL, as in OpenGL, the application must explicitly compute the camera, view, and projection matrices. See the code in [https://cvs.khronos.org/svn/repos/registry/trunk/public/webgl/sdk/demos/google/shiny-teapot/index.html shiny-teapot] as an example. </p>

Revision as of 00:13, 9 December 2009

WebGL is a DOM API for creating 3D graphics in a Web browser. Based on OpenGL ES 2.0, WebGL uses the OpenGL shading language, GLSL, and offers the familiarity of the standard OpenGL API. In addition, because it is fully integrated into the browser, a WebGL application can take advantage of the JavaScript infrastructure and Document Object Model (DOM) fundamental to any HTML document. WebGL is essentially another rendering context on the <canvas> element, so it can be cleanly combined with HTML and other web content that is layered on top or underneath the 3D content.

Integrating 3D Graphics with the DOM

The code examples discussed here illustrate some of the basic advantages facilitated by WebGL's integration with the DOM:

  • Image loading. Although numerous image loading facilities have been developed for OpenGL, no current standard exists. A WebGL app can simply use the browser's image loading facilities directly, as shown below in the texture loading example (Loading Images).
  • Event handling. WebGL uses the standard browser event handling mechanism. A WebGL application can set a callback function on any JavaScript event. See Handling Events for code that passes mouse events to a camera controller.
  • Seamless compositing of web content. WebGL uses the standard <canvas> element, which is automatically integrated with the other elements on the web page.
  • Automatic memory management. In OpenGL, memory is explicitly allocated and deallocated. In WebGL, memory management is handled automatically.

Loading Images

The image-texture-test example, shown below, illustrates how simple it is for a WebGL program to use the browser's image loading capabilities:

Texturetest.png

The loadTexture() function contains all the code necessary to load an image from the Web and add it to a 3D scene:


function loadTexture(src) {
  var texture = gl.createTexture();
  gl.bindTexture(gl.TEXTURE_2D, texture);
  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
  var image = new Image();
  image.onload = function() {
    gl.bindTexture(gl.TEXTURE_2D, texture);
    gl.texImage2D(gl.TEXTURE_2D, 0, image, true);
    checkGLError();
    draw();
  }
  image.src = src;
  return texture;
}

Let's look at the loadTexture() function more closely. First, notice that the WebGL calls are almost identical to their OpenGL counterparts, with a few exceptions. In particular, gl.createTexture() uses the singular form of "Texture" (not "Textures"), and it uses the verb "create" in place of the OpenGL "Gen" (so, glGenTextures() in OpenGL becomes gl.createTexture() in WebGL). The OpenGL call glGenTextures() simply generates a numeric texture id, whereas the WebGL call gl.createTexture() creates a CanvasTexture object to wrap that id.

The gl.createTexture() call allocates a texture object but does not initialize it yet. The gl.bindTexture() call binds this texture object to a TEXTURE_2D binding point. (This call is analogous to OpenGL, where a texture object is bound to either a TEXURE_2D or a TEXTURE_CUBE_MAP binding point.) As in OpenGL, the gl.texParameteri() call is used to set the minification and magnification filters (in this case, to gl.LINEAR).

The following code in loadTexture() starts downloading the image located at src. This image is loaded in the background and, in this case, will be used in the 3D context rather than directly on the Web page. The application uses the browser's image.onload event to do the WebGL-specific work associated with the image loading:


image.onload = function() {
  gl.bindTexture(gl.TEXTURE_2D, texture);
  gl.texImage2D(gl.TEXTURE_2D, 0, image, true);
  checkGLError();
  draw();
}
image.src = src;

When the image is finished loading, the onload event handler is called, which inserts the image into the WebGL texture object. Next, the application's draw() function is called, which forces a redraw of the scene and causes this texture image to "pop" into place.

Handling Events

The shiny-teapot example illustrates another benefit of WebGL: the WebGL JavaScript program flow is completely integrated with the browser's event handling system. In this example, the camera controller element uses standard browser events that run in any Web browser on any platform. This example tracks the x and y coordinates of incoming mouse events and updates the current camera coordinates used to render the scene. The shiny-teapot example, shown below, also illustrates compositing 3D graphics over standard HTML content:

Shinyteapot.png

Here is the CameraController code that receives the standard onmousedown, onmouseup, and onmousemove events and issues callback functions that automatically update the corresponding camera controller variables:


function CameraController(element) {
  var controller = this;
  this.onchange = null;
  this.xRot = 0;
  this.yRot = 0;
  this.scaleFactor = 3.0;
  this.dragging = false;
  this.curX = 0;
  this.curY = 0;

  element.onmousedown = function(ev) {
    controller.dragging = true;
    controller.curX = ev.clientX;
    controller.curY = ev.clientY;
  }

  element.onmouseup = function(ev) {
    controller.dragging = false;
  }

  element.onmousemove = function(ev) {
    if (controller.dragging) {
      var curX = ev.clientX;
      var curY = ev.clientY;
      var deltaX = (controller.curX - curX) / controller.scaleFactor;
      var deltaY = (controller.curY - curY) / controller.scaleFactor;
      controller.curX = curX;
      controller.curY = curY;
      controller.yRot = (controller.yRot + deltaX) % 360;
      controller.xRot = (controller.xRot + deltaY);
      if (controller.xRot < -90) {
        controller.xRot = -90;
      } else if (controller.xRot > 90) {
        controller.xRot = 90;
      }
      if (controller.onchange != null) {
        controller.onchange(controller.xRot, controller.yRot);
      }
    }
  }
}

In WebGL, as in OpenGL, the application must explicitly compute the camera, view, and projection matrices. See the code in shiny-teapot as an example.