为什么这表明WebGL是2D API而不是3D API? [英] Why does this state that WebGL is a 2D API, not a 3D API?

查看:181
本文介绍了为什么这表明WebGL是2D API而不是3D API?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

根据HTML5 Rocks ,WebGL实际上是一个2D API,而不是3D API。他们为什么这么说,这是什么意思?



我们可以在WebGL顶点着色器和片段着色器中指定X,Y,Z坐标。我无法理解2D和3D图形API之间的区别。你能解释他们为什么说这是一个2D API吗?解析方案

WebGL是一个rasteration API而不是3D api。您必须提供投影坐标。这与Canvas没有什么不同。它只是更快。我们来比较一下。



以下是Canvas中的3D

  window.onload = main; 

function main(){
var cubeVertices = [
-1,-1,-1,
1,-1,-1,
1,-1,
-1,1,-1,
-1,-1,1,
1,-1,1,
1,1, 1,
-1,1,1,
];
var 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,
];

var canvas = document.getElementById(c);
var ctx = canvas.getContext(2d);
var clock = 0;
var then = Date.now()* 0.001;

函数render(){
var now = Date.now()* 0.001;
时钟+ =现在 - 然后;
then = now;

var 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;

var fieldOfView = Math.PI * 0.25;
var aspect = canvas.width / canvas.height;
var projection = m.perspective(fieldOfView,aspect,1,500);
var radius = 5;
var eye = [
Math.sin(clock)* radius,
1,
Math.cos(clock)* radius];
var target = [0,0,0];
var up = [0,1,0];
var view = m.lookAt(eye,target,up);

var worldViewProjection = m.multiplyMatrix(view,projection);

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

函数drawLines(cubeVertices,indices,worldViewProjection){
ctx.beginPath();
//
//将点从3D转换为2D。
//
var points = [];
for(var ii = 0; ii< cubeVertices.length; ii + = 3){
points.push(m.transformPoint(
worldViewProjection,
[cubeVertices [ii + 0],cubeVertices [ii + 1],cubeVertices [ii + 2]])); (var 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();


$ / code $ / pre

这里是WebGL中的同一个3D

 < script> 
window.onload = main;

function main(){
var cubeVertices = [
-1,-1,-1,
1,-1,-1,
1,-1,
-1,1,-1,
-1,-1,1,
1,-1,1,
1,1, 1,
-1,1,1,
];
var 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,
];

var canvas = document.getElementById(c);
var gl = getWebGLContext(c);
var clock = 0;
var then = Date.now()* 0.001;

var program = createProgramFromScripts(
gl,[2d-vertex-shader,2d-fragment-shader]);
gl.useProgram(program);

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

var 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);

var buffer = gl.createBuffer();
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER,buffer);
gl.bufferData(
gl.ELEMENT_ARRAY_BUFFER,
new Uint16Array(indices),
gl.STATIC_DRAW);

函数render(){
var now = Date.now()* 0.001;
时钟+ =现在 - 然后;
then = now;

var scale = 4;

gl.clear(gl.COLOR_BUFFER_BIT);

var fieldOfView = Math.PI * 0.25;
var aspect = canvas.width / canvas.height;
var projection = m.perspective(fieldOfView,aspect,0.0001,500);
var radius = 5;
var eye = [
Math.sin(clock)* radius,
1,
Math.cos(clock)* radius];
var target = [0,0,0];
var up = [0,1,0];
var view = m.lookAt(eye,target,up);

var worldViewProjection = m.multiplyMatrix(view,projection);
gl.uniformMatrix4fv(
worldViewProjectionLoc,false,worldViewProjection);

gl.drawElements(gl.LINES,indices.length,gl.UNSIGNED_SHORT,0);
requestAnimFrame(render);
}
render();
}
< / script>
<! - 顶点着色器 - >
< script id =2d-vertex-shadertype =x-shader / x-vertex>
属性vec4 a_position;
uniform mat4 u_worldViewProjection;

void main(){
//
//将点从3D转换为2D。
//
gl_Position = u_worldViewProjection * a_position;
}
< / script>
<! - 片段着色器 - >
< script id =2d-fragment-shadertype =x-shader / x-fragment>
void main(){
gl_FragColor = vec4(0,0,0,1);
}
< / script>

如果您想要看到它们,请立即这是画布版本这是webgl版本



Canvas和WebGL之间的唯一区别是在Canvas中,我在JavaScript和WebGL中进行了转换投影,我在着色器中进行了投影。在这两种情况下,我写的代码都做了预测。



在Canvas版本中,代码是:

  m.transformPoint (
worldViewProjection,
[cubeVertices [ii + 0],cubeVertices [ii + 1],cubeVertices [ii + 2]);

在WebGL版本中,代码是:

  gl_Position = u_worldViewProjection * a_position 

API本身只能栅格化。无论在哪种情况下,我都必须提供投影。 WebGL中没有任何3D功能。只有一个光栅化api和2个函数,顶点着色器和片段着色器,用GLSL编写,我必须提供非常快速的运行并包含一个数学库。在这两种情况下,我仍然必须将代码提供给API到API。



WebGL是* NOT 3D API



我相信指出这一点很重要。有各种版本的OpenGL。 1993年的原始OpenGL是3D api。你给了它三维数据,你告诉它什么颜色可以制作,你告诉它关于各种灯光。你给了它一个模型矩阵和一个投影矩阵,它为你画了3D。



OpenGL ES 2.0和WebGL摆脱了所有这些。他们提供光栅化API和着色器,并让您编写硬件。但是你要写出所有的预测。您必须从3D计算投影坐标。你有计算光照方程,颜色和所有其他的东西。

这使WebGL和OpenGL ES 2.0可以说比旧的固定函数OpenGL更难,但同时它使他们更加灵活。如果你愿意做所有这些转换和数学工作,或者如果你不介意学习,那么就跳进去做吧。如果你不习惯这样做,那么有很多WebGL 3D库会为你做。



对于声称WebGL是3D库的人,让我们试试一个思想游戏。



这是一个物理图书馆, box2d。 JS 。你给它的形状,质量和力量,它为你计算物理。如果它真的是一个数学库,并且你必须自己提供所有的物理方程,那么你是否仍然称它为物理库?一个叫做物理图书馆的东西必须提供物理知识,否则它不是一个物理图书馆。同样,3D图书馆必须提供3D知识,否则它不是3D图书馆。

OpenGL 1.0是一个3D图书馆。你给了它三维位置,顶点颜色,灯光,它为你画了3D。你不需要3D知识。另一方面,WebGL不提供任何3D知识。你必须知道如何做3D投影,你必须知道如何采样纹理,你必须知道如何进行光照计算。它不再是一个3D库,它只是一个光栅化API。称它为3D库对于那些真正在寻找3D库的人来说是一种谎言和伤害,即提供3D的库。



称它为2D库可能是但称它为3D库是错误的。



这是另一篇关于它的文章


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?

解决方案

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

window.onload = main;

function main() {
  var 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,
  ];
  var 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,
  ];

  var canvas = document.getElementById("c");
  var ctx = canvas.getContext("2d");
  var clock = 0;
  var then = Date.now() * 0.001;

  function render() {
    var now = Date.now() * 0.001;
    clock += now - then;
    then = now;

    var 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";

    var fieldOfView = Math.PI * 0.25;
    var aspect = canvas.width / canvas.height;
    var projection = m.perspective(fieldOfView, aspect, 1, 500);
    var radius = 5;
    var eye = [
        Math.sin(clock) * radius,
        1,
        Math.cos(clock) * radius];
    var target = [0, 0, 0];
    var up = [0, 1, 0];
    var view = m.lookAt(eye, target, up);

    var worldViewProjection = m.multiplyMatrix(view, projection);

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

  function drawLines(cubeVertices, indices, worldViewProjection) {
    ctx.beginPath();
    //
    // transform points from 3D to 2D.
    //
    var points = [];
    for (var ii = 0; ii < cubeVertices.length; ii += 3) {
      points.push(m.transformPoint(
        worldViewProjection,
        [cubeVertices[ii + 0], cubeVertices[ii + 1], cubeVertices[ii + 2]]));
    }
    for (var 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();
  }
}

and here's the same 3D in WebGL

<script>
window.onload = main;

function main() {
  var 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,
  ];
  var 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,
  ];

  var canvas = document.getElementById("c");
  var gl = getWebGLContext(c);
  var clock = 0;
  var then = Date.now() * 0.001;

  var program = createProgramFromScripts(
      gl, ["2d-vertex-shader", "2d-fragment-shader"]);
  gl.useProgram(program);

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

  var 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);

  var buffer = gl.createBuffer();
  gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, buffer);
  gl.bufferData(
      gl.ELEMENT_ARRAY_BUFFER,
      new Uint16Array(indices),
      gl.STATIC_DRAW);

  function render() {
    var now = Date.now() * 0.001;
    clock += now - then;
    then = now;

    var scale = 4;

    gl.clear(gl.COLOR_BUFFER_BIT);

    var fieldOfView = Math.PI * 0.25;
    var aspect = canvas.width / canvas.height;
    var projection = m.perspective(fieldOfView, aspect, 0.0001, 500);
    var radius = 5;
    var eye = [
        Math.sin(clock) * radius,
        1,
        Math.cos(clock) * radius];
    var target = [0, 0, 0];
    var up = [0, 1, 0];
    var view = m.lookAt(eye, target, up);

    var worldViewProjection = m.multiplyMatrix(view, projection);
    gl.uniformMatrix4fv(
        worldViewProjectionLoc, false, worldViewProjection);

    gl.drawElements(gl.LINES, indices.length, gl.UNSIGNED_SHORT, 0);
    requestAnimFrame(render);
  }
  render();
}
</script>
<!-- vertex shader -->
<script id="2d-vertex-shader" type="x-shader/x-vertex">
attribute vec4 a_position;
uniform mat4 u_worldViewProjection;

void main() {
    //
    // transform points from 3D to 2D.
    //
    gl_Position = u_worldViewProjection * a_position;
}
</script>
<!-- fragment shader -->
<script id="2d-fragment-shader" type="x-shader/x-fragment">
void main() {
   gl_FragColor = vec4(0,0,0,1);
}
</script>

If you'd like to see them live here's the canvas version and here's the webgl version.

The only difference between the Canvas one and the WebGL one is in Canvas I did the conversion 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:

m.transformPoint(
    worldViewProjection,
    [cubeVertices[ii + 0], cubeVertices[ii + 1], cubeVertices[ii + 2]);

In the WebGL version that code is:

gl_Position = u_worldViewProjection * a_position

The API itself only rasterizes. I have to supply the projection 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, 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 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.

这篇关于为什么这表明WebGL是2D API而不是3D API?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆