14

According to HTML5 Rocks, WebGL is actually a 2D API, not a 3D API. Why do they say that, and what does it mean?

We can specify X, Y, Z coordinates in WebGL vertex shaders and fragment shaders. I can't understand the difference between a 2D and 3D graphics API. Could you explain why they say this is a 2D API?

Brad Larson
  • 170,088
  • 45
  • 397
  • 571
Saravana Kumar
  • 816
  • 1
  • 12
  • 28
  • 3
    Have you got a link for where you read that? – enhzflep Oct 30 '12 at 08:41
  • Got it from HTML5 rocks http://www.html5rocks.com/en/tutorials/webgl/webgl_fundamentals/ – Saravana Kumar Oct 31 '12 at 07:51
  • 1
    Wow, that _does_ surprise me. Some of the other things I've read there have been pretty good - I still can't work out quite where that author was coming from. Here's a bunch of demos: http://www.awwwards.com/22-experimental-webgl-demo-examples.html – enhzflep Oct 31 '12 at 10:19
  • Check the explanation here: https://webglfundamentals.org/webgl/lessons/webgl-2d-vs-3d-library.html – Meglio Dec 19 '21 at 08:12

6 Answers6

26

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.

cmc
  • 973
  • 8
  • 17
Nicol Bolas
  • 449,505
  • 63
  • 781
  • 982
  • 3
    Wow, Since I'm both the author of that article and one of the major implementors of WebGL, wrote 70% of the conformance tests and am a major contributor to the spec you'd think I'd have a clue but I guess not :-( WebGL is a 2D api. It will no more draw 3D any other 2D api. You want 2D in Canvas? You do some math on 3D data and provide the API with 2D coordinates. You want 3D in WebGL same thing. Unless you provide the conversion from 3D to 2D it won't draw 3D because it's a 2D api. – gman Nov 01 '12 at 07:49
  • 4
    @gman: "*Unless you provide the conversion from 3D to 2D it won't draw 3D because it's a 2D api.*" The output of a vertex shader is a ***4D homogeneous coordinate system***. That's the only "conversion" you provide. So yeah, it's a 3D API. Also, as I pointed out, if you're putting WebGL on the same level as SVG and Canvas, then you're basically saying that "2D API" is a meaningless term and should never be used by anyone as a category for anything. So either you're wrong or you're saying that "2D API" is worthless as a concept. Which is it? – Nicol Bolas Nov 01 '12 at 07:54
  • 5
    @gman: More to the point, telling someone that WebGL is a 2D API is extremely misleading, *especially* in introductory material. It makes them think that WebGL is no different from, for example, Canvas, SVG, or Cairo. And it is *very* different from them. So even if you were technically correct in the sense that it is a triangle rasterizer (again, making a mockery of the term "2D API"), it is still useless information that serves only to confuse the neophyte users who stumble upon your website. Hence the reason why this question exists. – Nicol Bolas Nov 01 '12 at 08:10
  • 4
    @gman: "*You want 2D in Canvas? You do some math on 3D data and provide the API with 2D coordinates.*" Yes, and you immediately lose perspective correct interpolation, as well as all depth buffering information. That's not very good 3D. OpenGL defines clip-space as a 3D space. OpenGL defines normalized-device-coordinate space as a 3D space. OpenGL defines window-space as a 3D space. As far as the OpenGL specification is concerned, it's 3D. – Nicol Bolas Nov 01 '12 at 08:12
  • 2
    I disagree that it's misleading. In fact IMO it's misleading to call WebGL a 3D api. OpenGL 1.0 and all the fixed function versions of OpenGL were 3D apis. 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. That's why it's important to call it a 2D api, To point out that the 3D is up to you. You have to provide that code else it won't do any 3D. That very different than the old fixed function stuff that gave you 3D, lights, etc all for free. Now it's left to the programmer. – gman Nov 01 '12 at 09:13
  • 3
    @gman: You provide the code that generates 4D homogeneous-space positions, not 2D positions. Those are *two very different things*. There can be no real argument about this; the OpenGL specifications are very clear: `gl_Position` has 4 components. All of those 4 components are used by OpenGL in its rasterization computations. None of the post-vertex-shader spaces that OpenGL defines are 2D. So there is no "3D to 2D math" *anywhere in OpenGL*. Or, more to the point, show me the part of the OpenGL specification where it says that the vertex shader outputs 2D positions. – Nicol Bolas Nov 01 '12 at 15:46
  • Show me an WebGL sample that takes 3D data, doesn't do a 3D to 2D conversion step and yet still draws 3D. What do you think multiplying a vec4 by a mat4 projection matrix does? You divide by W and your left with 2D points. A depth buffer doesn't make the API 3D. A 3D api takes 3D data and draws 3D. WebGL doesn't do this. OpenGL 1.0 did. OpenGL ES 2.0 does not. – gman Nov 01 '12 at 17:17
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/18929/discussion-between-nicol-bolas-and-gman) – Nicol Bolas Nov 01 '12 at 17:18
  • @gman: If you won't look at the chat, look at my extensive edits. – Nicol Bolas Nov 01 '12 at 17:50
  • 3
    As a game developer with 15+ years 3D graphics experience, I have to agree with Nicol here. No matter gman's credentials, it seems to me he's clearly wrong here. Triangles rasterized by WebGL use z and w information to perform perspective correct interpolation and depth buffering, those values are essential to correctly render a 2D image that appears to be a projection of a 3D scene. If WebGL did not preserve them and use them in the rasterization process it would produce incorrect output that the user could not fix with anything they did in a shader. – mattnewport Jan 06 '14 at 23:45
  • 3
    To make everyone happy, let say that 2d is a subset of 3d. OpenGL being a 3d api it is also a 2d api! – Loïc Faure-Lacroix Jan 13 '14 at 20:58
  • can only agree with gman here since it's about the API and not about how it's handled within the functions. seems like you're forgetting what an API is. – Robin F. Aug 26 '17 at 12:44
17

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.

mattnewport
  • 13,728
  • 2
  • 35
  • 39
  • 1
    Would you call a math API a physics API if you had the supply all the physics? Do you call C++ a Word Processor because one can be written with it? An API supplies a solution so you don't have personally have that knowledge. Example: Lots of programmers use a physics API so they don't have to know physics. They just supply shapes/mass/friction and the library handles the physics. Similarly a 3D API you'd provide verts/materials/lights/camera and it would render. OpenGL's fixed function pipeline provided that solution. WebGL does not. It can't be called a 3D API as it supplies no 3D knowledge – gman Jan 12 '14 at 14:34
  • 4
    If WebGL is not a 3D API then neither are Direct3D 10/11 (no fixed function pipeline), recent versions of OpenGL ES (fixed function pipeline mostly removed) or even arguably recent versions of OpenGL (it may still support a fixed function pipeline but it is deprecated). Neither are the proprietary APIs on the PS3, PS4 or Wii U. All of them support perspective correct interpolation and a z-buffer for hidden surface removal however and I've never heard anyone else suggest they should be called 2D APIs. – mattnewport Jan 13 '14 at 08:07
6

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/

Nicol Bolas
  • 449,505
  • 63
  • 781
  • 982
enhzflep
  • 12,927
  • 2
  • 32
  • 51
  • 1
    It's marketing. I'd argue a library's purpose is to do stuff for you so you don't have to learn how to do it. A sorting library sorts. You don't have to know how it does it. A physics library does physics. You don't have to know physics math to use it. A 3D library does 3D, you don't have to know 3D math to use it. OpenGL, Three.JS, Unity3D all fit that description. OpenGL ES 2.0 and WebGL do not. You have to provide all the 3D knowledge as they have none built in. – gman May 06 '13 at 08:09
  • 1
    You can say that all you like, but the documentation is the documentation; if it says it's 3D, it's 3D. You might disagree with their usage of terminology, but how it ought to be does not dictate what it is. – Alice Jan 07 '14 at 01:51
  • So by your argument if I label an apple an orange it's an orange? Interesting logic there. – gman Jan 13 '14 at 12:42
  • 1
    @gman (I dont know if your comment was addressed to me or Alice) By my argument - if a large, well-known entity labelled an object as being something, I'd be more inclined to believe their assertion than that made by someone of whom I've no experience. Furthermore, native methods _are_ provided for 3d work. Nicolas Bolas & mattnewport have each articulated much more clearly than I could, all of the counter arguments I'd make in the matter. Though, these 2 points seem particularly pertinent: No 3d = no perspective correct texturing, No 3d = no need(or use) for a depth buffer. – enhzflep Jan 13 '14 at 13:47
5

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.

Aki Suihkonen
  • 19,144
  • 1
  • 36
  • 57
  • 1
    You can't omit the Z. `gl_Position` is a `vec4`; you aren't allowed to just ignore that component. Even a Z of 0 is *still* a Z value, and all of the computations are still valid. – Nicol Bolas Oct 30 '12 at 16:19
  • One can make / copy a vertex shader from a tutorial that's essentially void main(){ gl_Position=aVertexCoordinates; vTexCoords = aTexCoords;} and be totally ignorant of the z and w. – Aki Suihkonen Oct 30 '12 at 16:28
  • 4
    Being ignorant of data does not mean that the data stops *existing*. It's *there*, whether you know about it or not. Just like those texture coordinates are there, whether you know what they are or not. You can *think* of it as a 2D API all you want; that doesn't make it true. – Nicol Bolas Oct 30 '12 at 16:30
  • 1
    I certainly didn't imply that wishes change reality. I just happen to understand a bit of the claim, although it seems to have certain characteristics of a flame bait. – Aki Suihkonen Oct 30 '12 at 16:34
  • Who created `gl_Position`? – Davit Jan 12 '14 at 23:29
  • OpenGL is more like a square being a rectangle. But a rectangle not necessarly a square. – Loïc Faure-Lacroix Jan 13 '14 at 20:56
4

WebGL is a rasteration API not a 3D api. You have to provide it with projected coordinates. This many ways it is no different than Canvas. It's just faster. Let's compare.

Here's 3D in Canvas

const cubeVertices = [
  -1, -1, -1,
   1, -1, -1,
   1,  1, -1,
  -1,  1, -1,
  -1, -1,  1,
   1, -1,  1,
   1,  1,  1,
  -1,  1,  1,
];
const indices = [
  0, 1,
  1, 2,
  2, 3,
  3, 0,
  4, 5,
  5, 6,
  6, 7,
  7, 4,
  0, 4,
  1, 5,
  2, 6,
  3, 7,
];

const canvas = document.querySelector("#c");
const ctx = canvas.getContext("2d");

function render(time) {
  time *= 0.001;

  const scale = 2;

  ctx.clearRect(0, 0, canvas.width, canvas.height);
  ctx.save();
  ctx.translate(canvas.width / 2, canvas.height / 2);
  ctx.scale(canvas.width / scale, -canvas.height / scale);
  ctx.lineWidth = scale / canvas.width;
  ctx.strokeStyle = "black";

  const fieldOfView = Math.PI * 0.25;
  const aspect = canvas.width / canvas.height;
  const projection = m4.perspective(fieldOfView, aspect, 1, 500);
  const radius = 5;
  const eye = [
      Math.sin(time) * radius,
      2,
      Math.cos(time) * radius];
  const target = [0, 0, 0];
  const up = [0, 1, 0];
  const camera = m4.lookAt(eye, target, up);
  const view = m4.inverse(camera);

  const worldViewProjection = m4.multiply(projection, view);

  drawLines(cubeVertices, indices, worldViewProjection);
  ctx.restore();
  requestAnimationFrame(render);
}
requestAnimationFrame(render);

function drawLines(cubeVertices, indices, worldViewProjection) {
  ctx.beginPath();
  //
  // transform points from 3D to 2D.
  //
  const points = [];
  for (let ii = 0; ii < cubeVertices.length; ii += 3) {
    points.push(m4.transformPoint(
      worldViewProjection,
      cubeVertices.slice(ii, ii + 3)));
  }
  for (let ii = 0; ii < indices.length; ii += 2) {
    var p0 = points[indices[ii + 0]];
    var p1 = points[indices[ii + 1]];
    ctx.moveTo(p0[0], p0[1]);
    ctx.lineTo(p1[0], p1[1]);
  }
  ctx.stroke();
}
canvas { border: 1px solid red; }
<!-- just a math lib -->
<script src="https://webglfundamentals.org/webgl/resources/m4.js"></script>
<canvas id="c"></canvas>

and here's the same 3D in WebGL

const cubeVertices = [
  -1, -1, -1,
   1, -1, -1,
   1,  1, -1,
  -1,  1, -1,
  -1, -1,  1,
   1, -1,  1,
   1,  1,  1,
  -1,  1,  1,
];
const indices = [
  0, 1,
  1, 2,
  2, 3,
  3, 0,
  4, 5,
  5, 6,
  6, 7,
  7, 4,
  0, 4,
  1, 5,
  2, 6,
  3, 7,
];

const canvas = document.querySelector('#c');
const gl = canvas.getContext('webgl');

const vs = `
attribute vec4 a_position;
uniform mat4 u_worldViewProjection;

void main() {
    //
    // transform points from 3D to 2D.
    //
    gl_Position = u_worldViewProjection * a_position;
}
`;

const fs = `
void main() {
   gl_FragColor = vec4(0,0,0,1);
}
`;

const program = webglUtils.createProgramFromSources(
    gl, [vs, fs]);
gl.useProgram(program);

const positionLoc = gl.getAttribLocation(program, "a_position");
const worldViewProjectionLoc =
    gl.getUniformLocation(program, "u_worldViewProjection");

const buffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
gl.bufferData(
    gl.ARRAY_BUFFER,
    new Float32Array(cubeVertices),
    gl.STATIC_DRAW);
gl.enableVertexAttribArray(positionLoc);
gl.vertexAttribPointer(positionLoc, 3, gl.FLOAT, false, 0, 0);

const buffer2 = gl.createBuffer();
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, buffer2);
gl.bufferData(
    gl.ELEMENT_ARRAY_BUFFER,
    new Uint16Array(indices),
    gl.STATIC_DRAW);

function render(time) {
  time *= 0.001;

  const scale = 4;

  const fieldOfView = Math.PI * 0.25;
  const aspect = canvas.width / canvas.height;
  const projection = m4.perspective(fieldOfView, aspect, 0.0001, 500);
  const radius = 5;
  const eye = [
      Math.sin(time) * radius,
      2,
      Math.cos(time) * radius];
  const target = [0, 0, 0];
  const up = [0, 1, 0];
  const camera = m4.lookAt(eye, target, up);
  const view = m4.inverse(camera);

  const worldViewProjection = m4.multiply(projection, view);
  gl.uniformMatrix4fv(
      worldViewProjectionLoc, false, worldViewProjection);

  gl.drawElements(gl.LINES, indices.length, gl.UNSIGNED_SHORT, 0);
  requestAnimationFrame(render);
}
requestAnimationFrame(render);
canvas { border: 1px solid red; }
<!-- just a math lib -->
<script src="https://webglfundamentals.org/webgl/resources/m4.js"></script>
<script src="https://webglfundamentals.org/webgl/resources/webgl-utils.js"></script>
<canvas id="c"></canvas>

The only difference between the Canvas one and the WebGL one is in Canvas I did the projection in JavaScript and in WebGL I did the projection in the shader. In both cases the code I wrote did the projection.

In the Canvas version that code is:

m4.transformPoint(
    worldViewProjection,
    cubeVertices.slice(ii, ii + 3));

In the WebGL version that code is:

gl_Position = u_worldViewProjection * a_position

The API itself only rasterizes. I have to supply the projection code in either case. There is nothing in WebGL that does 3D. There is just a rasterization api and 2 functions, the vertex shader, and fragment shader, both written in GLSL, that I have to supply that run very fast and include a math library. I still have to provide the code to do the 3D to the API in both cases.

WebGL is **NOT* a 3D API

I believe it's important to point this out. There are various versions of OpenGL. The original OpenGL from 1993 was a 3D api. You gave it 3D data, you told it what colors to make things, you told it about various lights. You gave it a model matrix and a projection matrix and it drew 3D for you.

OpenGL ES 2.0 and WebGL got rid of all of that. They provide a rasterization API and shaders and let you program the hardware. But it's up to you to write all the projections. You have to compute projected coordinates from 3D. You have compute lighting equations, and colors and all the rest.

This makes WebGL and OpenGL ES 2.0 arguably much harder than the old fixed function OpenGL but at the same time it makes them massively more flexible. If you're comfortable doing all those conversions and math or if you don't mind learning it then jump in and do it. If you aren't comfortable doing all then then there are plenty of WebGL 3D libraries that will do it for you.

To you who claim WebGL is a 3D library let's try a thought game.

Here's a physics library, box2d.js. You give it shapes, masses, and forces and it computes physics for you. If all it really was was a math library and you had to supply all the physics equations yourself would you still call it a physics library? Something called a physics library has to supply the physics knowledge or else it's not a physics library. Similarly, something called a 3D library has to supply the 3D knowledge or else it's not a 3D library.

OpenGL 1.0 was a 3D library. You gave it 3D positions, vertex colors, lights and it drew 3D for you. You needed no 3D knowledge. WebGL on the other hand does not provide any 3D knowledge. You have to know how to do 3D projections, you have to know how to sample textures, you have to know how to do lighting calculations. It's no longer a 3D library, it's just a rasterization API. Calling it a 3D library is a lie and a disservice to those actually looking for a 3D library, ie, a library the provides 3D.

Calling it a 2D library might be hyperbole but calling it a 3D library is wrong.

Here's another article about it.

gman
  • 100,619
  • 31
  • 269
  • 393
  • 9
    -1: `gl_Position` is not a 2D vector; it is a 4D vector. The "code you wrote" does *not* perform 3D to 2D conversions. It performs 3D to *4D* conversions. The two pieces of code only appear to look the same, because your Canvas version ditches Z and W coordinates, rather than using them the way the OpenGL post-vertex processing pipeline does. – Nicol Bolas Nov 01 '12 at 15:42
  • I only threw away Z. I divided by W. So what. That doesn't make WebGL a 3D api. In order to be a 3D api you'd have to be able to provide it 3D data AND NO CONVERSION FROM 3D TO 2D and have it draw 3D. It won't do that. Unlike old OpenGL, unlike many of the 3D libraries built on top of WebGL or Canvas or GDI or whatever other 2D library you choose. – gman Nov 01 '12 at 17:03
  • 1
    A 3D api is something you give 3D data and it draws 3D. Calling an API 3D that has some filters or features that help you convert to 2D when you supply it 3D data is like calling Photoshop 3D because you happen to be able to sketch a 3D image and it's got a blur filter to fake DOF. Unless the API is actually doing the conversion for you it's not a 3D API. OpenGL ES 2.0 removed the old built in 3D conversion and left if to the user to provide. Therefore it's not a 3D api. – gman Nov 01 '12 at 17:04
  • 2
    "*I only threw away Z. I divided by W. So what.*" Your "filter" (ie: shader) doesn't throw away the Z or divide by W. So your "filter" doesn't convert anything to 2D. As I stated, `gl_Position` is not 2D. So there is "NO CONVERSION FROM 3D TO 2D". Thus, *by your own definition*, WebGL is a 3D API. – Nicol Bolas Nov 01 '12 at 17:15
  • 1
    We disagree. Multiplying by a projection matrix IS CONVERTING 3D to 2D. I don't understand why you feel compelled to lie to developers about all the 3D code they'll have to write that used to be supplied by OpenGL but was pulled out in OpenGL ES 2.0. That's only a disservice to developers IMO. Rather, be honest about what was removed and how much work it is to supply it yourself. – gman Nov 01 '12 at 17:26
  • 8
    "*Multiplying by a projection matrix IS CONVERTING 3D to 2D.*" Multiplying by a matrix is *multiplying by a matrix*. A 4D homogeneous coordinate is not, by any stretch of the imagination, a 2D coordinate. Also, the only "work" you have to do is the creation of a perspective projection matrix (which you had to do in fixed-function) and using it in a shader. The only difference is that you must explicitly do the multiplication yourself. You still don't end up with 2D coordinates, because WebGL never uses 2D coordinates. – Nicol Bolas Nov 01 '12 at 17:56
  • 1
    I don't understand why you feel compelled to lie to developers and claim that a 4D homogeneous coordinate is really a 2D coordinate. That sounds like a bigger lie than actually talking about the real math that OpenGL does. – Nicol Bolas Nov 01 '12 at 17:57
  • 1
    WebGL or the programmable pipeline of opengl is hardly a 2d api. It's worth saying that Opengl works with 2d buffers such as the depth buffer and stencil buffers. But even those buffers could be intepreted as 3d since the level of greys can be used as a Z parameter. – Loïc Faure-Lacroix Jan 13 '14 at 20:28
0

Wow, your question is just excelent! You made all these guru fight like in the last battle O.o

Well, maybe you would like also read an answer from guy with like 1 year WebGL experimence and almoast no OpenGL programming skill, so let's do that! :)

First, I have to say something that I didn't read there yet and I find it important. @gman sais that:

An API supplies a solution so you don't have personally have that knowledge.

Well, I really don't agree with this statement. API supplies some solution, but it doesn't mean that you don't need that knowledge.

Now back to your question, as you said:

We can specify x,y,z co-ordinates in webGL vertex shader and fragement shader. I couldn't understand difference between 2D and 3D graphics API.

As others say, you can specify (I think you even have to specify) gl_Position in shader which is 4D vector. Before, there was just javascript and some separated gpu. Then WebGL appears with new options. WebGL itself doesn't offer any solutions for 3D behavior, but it brings on that option to specify gl_Position in shader.

And I count new options and not just entire solutions. So I think that this question is also about what API really is for you. For me? In this case, it brings the possibility to make 3D applications via shader. So it is 3D API.

I hope it helps...

Entity Black
  • 3,401
  • 2
  • 23
  • 38