Why does this state that WebGL is a 2D API, not a 3D API?

In my opinion (as a game developer with 15+ years 3D graphics experience), gman's characterization of WebGL as a 2D API is highly misleading at best and I'd be inclined to argue is just flat out wrong. Nicol Bolas points out most of the reasons why in his answer but for me the key point is that it would simply not be possible to get a correctly rendered 3D scene once you move from the wireframe graphics gman uses in his canvas / WebGL examples to textured triangles if WebGL was not supplied with z and w information in the output of the vertex shader and if it did not use them during rasterization to get perspective correct interpolation and to perform hidden surface removal using a z-buffer.

The point gman really seems to be trying to make is that WebGL is not a fixed function 3D graphics API like the ancient 3D graphics APIs of old but has a programmable pipeline. This is true of all modern 3D graphics APIs however (Direct3D 8, 9, 10, 11; OpenGL 2.0 and up; proprietary APIs you'll find on consoles like the PS3, PS4, Wii U...). They all work in essentially the same way: vertex shaders output homogeneous coordinates and the rasterizer uses z and w information to correctly interpolate 3D triangles projected to a 2D image and to perform hidden surface removal using a z-buffer. This is very different from 2D APIs that have no z and w coordinates, no concept of perspective correct interpolation and no z-buffer for hidden surface removal. To render a 3D scene of textured triangles correctly in a 2D API like canvas you would need to implement all of that in software yourself.

[Updated] In one of his articles gman uses 'API' and 'Library' more or less interchangeably. I don't think there's a clear and well established definition of the two terms but I think different understandings of the terms may be contributing to some of the disagreement here.

Khronos describes WebGL:

WebGL™ is an immediate mode 3D rendering API designed for the web.

and I think that is an accurate description. One commonly used meaning of 'API' is a defined software interface to access underlying hardware or OS services and refers to the public facing software interface rather than any specific implementation. In this sense all mainstream modern APIs intended to access 3D graphics hardware can be considered low-level 'immediate mode 3D rendering APIs'. I'd include OpenGL, OpenGL ES, WebGL, Direct3D and the proprietary APIs found on consoles in this category.

It is normal in the industry to refer to all of these as '3D APIs' because they are designed to provide access to GPUs whose primary function is rendering 3D graphics and they expose the low level functionality that supports that function (perspective correct interpolation and z-buffer based hidden surface removal during rasterization, anisotropic texture filtering, in some instances tesselation hardware, etc.) as well as a means to program the programmable parts of the 3D pipeline (vertex, pixel, geometry shaders, hull and domain shaders etc.).

I tend to think of 'library' as having a slightly different meaning to 'API'. Something like three.js describes itself as a 'library' rather than an 'API':

Three.js is a library that makes WebGL - 3D in the browser - very easy. While a simple cube in raw WebGL would turn out hundreds of lines of Javascript and shader code, a Three.js equivalent is only a fraction of that.

and while there are no hard and fast definitions of the two terms I tend to think of a library as referring more to a specific implementation of functionality and implying perhaps more high level helper functionality than a straight API.

Other higher level 3D 'libraries' might describe themselves as 'engines' or 'frameworks', e.g.

OGRE (Object-Oriented Graphics Rendering Engine) is a scene-oriented, flexible 3D engine written in C++ designed to make it easier and more intuitive for developers to produce applications utilising hardware-accelerated 3D graphics.

There's a whole bunch of functionality that isn't part of old style fixed function 'APIs' like pre 2.0 OpenGL or pre DX8 DirectX but is very useful if you just want to render some 3D objects without needing detailed understanding of 3D graphics - things like a scene graph, functions to load and render models with attached materials, high level support for lights and shadows, etc. but that is not what the low level 3D 'APIs' like Direct3D or WebGL are aimed at. It's not the problem they are trying to solve. I can see how it might be useful to try and convey that to novices who just want to render some 3D objects in a browser but I don't think claiming WebGL is a '2D API' is a helpful or accurate way to get that across.


It's a point of view.

Nothing mandates in WebGL to model the world in 3d, to create a camera, set lights etc. At the end the renderer is only concerned of points, lines and triangles, whose 4 coordinates relate to |w*x|<w, |w*y|<w, |w*z|<w. Also by default one can pass to a shader only two coordinates, x and y, while the framework sets z=0 and w=1.

One can as well use opengl es to draw 2d sprites without any concern of setting up some projection matrix. One can omit z-buffer and handling of the z-coordinate all together up to the point, where it's necessary to hold: |z*w| <= w for anything to be rendered.

But also it's quite clear that it's no coincidence that the API is well suited to rendering 3D-models.


WebGL is actually a 2D API, not a 3D API. What does it mean?

It means you should stop listening to whatever website or person told you that. When people say idiotic things like that, it's best to ignore them and move on to more reasonable tutorials/information/discussions.

You can certainly work with WebGL in purely 2D terms. You can pass 2D positions to vertex shaders. You can turn off depth testing entirely. And so forth. But the output from your vertex shader is a 4D homogeneous coordinate, even if your W is 1 and your Z is 0. So the rendering system is going to do all of the 3D math that it would normally do for a 3D scene.

Yes, rasterization is basically a 2D process, with depth testing as a "hack" to allow for hidden surface removal. But this has been true of all rasterization-based renders. D3D, OpenGL, GLIDE, and every software rasterizer would also be "2D API"s by this logic.

And if all of them are 2D APIs, then the statement is pointless. It puts OpenGL/D3D on the same level as actual "2D API"s like SDL and Direct2D. Yet those "2D API"s can't do 3D rendering at all (or not without substantial pain).

So the statement is both factually incorrect and incredibly misleading. Whoever said it is not worth your time or attention.

from comments:

The person who originally wrote this "WebGL is 2D" stuff has deigned to explain his reasoning, so I'll address those points here.

Let's use his definition of API dimensionality. His exact quote is:

You gave them 3D data and nothing else and they gave you a 3D display. OpenGL ES 2.0 is a 2D api. You have to supply all of the 3D to 2D math conversion yourself.

From this, we can deduce that a "3D API" means "an API which 'you' feed 3D values into to cause 3D rendering to happen." Similarly, a "2D API" means "an API which 'you' feed 2D values into to cause 2D rendering to happen."

Let's assume that 'you' doesn't simply mean the dimensionality of the values fetched from a buffer object. 'You' means every piece of code you have direct control over, which includes your shader. OK, fine. So 'you', for WebGL, stops at the end of the vertex shader. Therefore, WebGL starts doing its stuff with the vertex shader outputs.

The output from a vertex shader is a 4D homogeneous coordinate. I'm guessing that the argument is that a 4D homogeneous coordinate is somehow identical to a 2D coordinate. Even though it's obviously not, since it has 2 more components, and the various math operations you do with them are very different.

I'll let you decide whether you want to consider a 4D homogeneous coordinate to be identical to a 2D coordinate.

Instead, I'll look at how WebGL treats the 4D output. Does it convert it into a 2D coordinate? The OpenGL specification says no.

From the OpenGL ES 2.0, section 2.12, folio page 44:

Vertex shader execution yields a vertex coordinate gl_Position which is assumed to be in clip coordinates. Perspective division is carried out on clip coordinates to yield normalized device coordinates, followed by a viewport transformation to convert these coordinates into window coordinates (see figure 2.4).

Clip coordinates are four-dimensional homogeneous vectors consisting of x, y, z, and w coordinates (in that order). If a vertex’s clip coordinates are:

(xc, yc, zc, wc)

then the vertex’s normalized device coordinates are

(xd, yd, zd) = (xc/wc, yc/wc, zc/wc)

Normalized device coordinate space has 3 components. It is therefore not a 2D space. But what about later transformations?

Well, from section 2.12.1 of the same specification (folio pages 44-45):

The viewport transformation is determined by the viewport’s width and height in pixels, px and py, respectively, and its center (ox, oy) (also in pixels). The vertex’s window coordinates, (xw, yw, zw), are given by

xw = (px/2)xd + ox

yw = (py/2)yd + oy

zw = ((f - n)/2)zd + (n + f)/2

So yes, even window space is a 3D coordinate system. Window space is the final space that OpenGL uses in its computation; window space goes straight to the rasterizer. That's what gets rendered.

Therefore, by the OpenGL ES 2.0 specification, there is no point in the entire rendering pipeline where anything get converted into a purely 2D space.

WebGL is an API that you feed 4D homogeneous coordinates into. At no point does WebGL perform any "3D to 2D math conversion", nor does the user. Nobody converts anything into 2D coordinates at any point in WebGL. 2D values are not fed through a 2D pipeline; 4D values are fed through a 3D pipeline.

Therefore, by his own definition, WebGL is not a 2D API.

QED.


Well, I dunno about everybody else - I'd be inclined to go with whatever what Khronos said on their website. Seems perfectly clear to me. :shrugs:

WebGL™ is an immediate mode 3D rendering API designed for the web. It is derived from OpenGL® ES 2.0, and provides similar rendering functionality, but in an HTML context. WebGL is designed as a rendering context for the HTML Canvas element. The HTML Canvas provides a destination for programmatic rendering in web pages, and allows for performing that rendering using different rendering APIs. The only such interface described as part of the Canvas specification is the 2D canvas rendering context, CanvasRenderingContext2D. This document describes another such interface, WebGLRenderingContext, which presents the WebGL API.

https://www.khronos.org/registry/webgl/specs/1.0/