据HTML5岩石 ,WebGL的实际上是一个2D API,而不是3D API。 为什么他们说,什么意思呢?
我们可以指定X,Y,Z坐标WebGL的顶点着色器和片段着色器。 我无法理解一个2D和3D图形API之间的区别。 你能解释为什么他们说这是一个2D API?
据HTML5岩石 ,WebGL的实际上是一个2D API,而不是3D API。 为什么他们说,什么意思呢?
我们可以指定X,Y,Z坐标WebGL的顶点着色器和片段着色器。 我无法理解一个2D和3D图形API之间的区别。 你能解释为什么他们说这是一个2D API?
WebGL是一个rasteration API不是3D API。 你必须为它提供投影坐标。 这许多方面,它并不比帆布不同。 这只是速度更快。 让我们来比较。
下面是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, 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();
}
}
这里是在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, 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>
如果你想看到他们住这里的帆布版和这里的WebGL的版本 。
画布一个和WebGL的一个之间的唯一区别是在画布我做了转换投影在JavaScript和WebGL的我做着色器中的投影。 在这两种情况下, 我写的代码做了预测。
在画布版本的代码是:
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,我就必须提供一个运行速度非常快,包括数学库。 我还是要提供代码到3D在这两种情况下的API。
WebGL是* 不是 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为您服务。 你不需要3D知识。 在另一方面的WebGL不提供任何3D知识。 你必须知道如何做3D投影,你必须知道如何样的纹理,你必须知道该怎么做照明计算。 它不再是一个3D库,它只是一个光栅化API。 称这是一个3D库是一个谎言和伤害那些真正寻找一个3D库,即库提供3D。
称它是2D库可能是夸张,但称这是一个3D库是错误的。
下面是关于它的另一篇文章 。
WebGL的实际上是一个2D API,而不是3D API。 这是什么意思?
这意味着你应该停止监听任何网站或个人告诉你的。 当人们说这样的愚蠢的事情,这是最好的忽略它们并转移到更合理的教程/信息/讨论。
您可以在纯粹的2D方面支持WebGL肯定工作。 你可以通过2D位置顶点着色器。 您可以完全关闭深度测试。 等等。 但是从你的顶点着色器的输出是一个四维齐次坐标 ,即使你的W是你的Z是0,所以呈现系统会做所有的3D数学,它通常用于3D场景做的。
是的,光栅化基本上是一个二维过程中,随着深度测试为“黑客”,以允许隐面消除。 但是,这一直是所有基于光栅化渲染真实的。 D3D,OpenGL的,GLIDE,每一个软件光栅化也将是“2D API” S这个逻辑。
如果所有的人都是2D的API,那么该语句是没有意义的。 它把的OpenGL / D3D在同一水平上的实际的 “2D API”就像SDL和Direct2D的。 然而,这些“2D API” S无法做到在所有的3D渲染(或不没有实质性疼痛)。
因此,声明是双方事实不正确,令人难以置信的误导。 谁说它不是值得你花时间和注意力。
从评论:
谁最初写这个的人“WebGL是2D”的东西已经屈尊来解释他的理由,所以我会在这里处理这些问题。
让我们用自己的API维度的定义。 他确切的报价是:
你给了他们的3D数据,并没有别的,他们给你的3D显示器。 OpenGL ES 2.0的是2D API。 你必须提供所有的三维到二维数学转换自己。
由此,我们可以推断出一个“3D API”是指“‘你’喂3D值到一个API,使3D渲染的情况发生。” 同样,“2D API”是指“‘你’喂2D值到了一个API,使2D渲染的情况发生。”
让我们假设“你”并不仅仅意味着从一个缓冲区对象获取的值的维度。 “你”是指每一段代码在你有直接的控制,其中包括您的着色器。 好的。 所以,“你”,对WebGL的,停在顶点着色器的结尾。 因此,WebGL的开始尽自己的东西与顶点着色器的输出。
从顶点着色器的输出是一个4D齐次坐标。 我猜测的说法是,一个4D齐次坐标是某种等同于2D坐标。 即使它显然不是,因为它有2个组件,并且你与他们做各种数学运算有很大的不同。
我会让你决定是否要考虑四维齐次坐标是相同的二维坐标。
相反,我会看的WebGL如何对待4D输出。 是否将其转换成二维坐标? OpenGL规范说,没有。
从OpenGL ES的2.0 ,2.12节,对开页面44:
顶点着色器执行产生一个顶点坐标
gl_Position
其被假设为在剪辑坐标。 透视分割剪辑上进行坐标以产生归一化设备坐标,随后视口变换,以这些坐标转换成窗口坐标(参见图2.4)。剪辑坐标是由X,Y,Z的四维向量均一和w的坐标(按该顺序)。 如果一个顶点的剪辑坐标是:
(X C,Y C,Z C,W c)中
那么它的顶点的标准化设备坐标
(X d,Y d,Z d)=(X C / W C,Y C /和z C / W C)
归一化设备坐标空间具有3个分量。 因此,它不是一个二维空间。 但对于后来的转换?
那么,从相同的规格(对开页44-45)第2.12.1:
视口变换由视口的高度和宽度以像素为单位,对X和P Y,分别与它的中心确定(邻X,邻Y)(也以像素为单位)。 顶点的窗口坐标(X W,Y W,Z W),由下式给出
x 宽 =(P X / 2)×d +○×
ÝW =(P Y / 2)Y d + Oÿ
žW =((F - N)/ 2)Z d +(N + F)/ 2
所以,是的,连窗户空间是三维坐标系。 窗口空间是OpenGL的使用其计算最终的空间; 窗口空间去直接光栅化。 这就是获取呈现。
因此, 由OpenGL ES 2.0的说明书中 ,在整个渲染流水线,其中任何被转换成纯粹 2D空间中没有任何意义。
WebGL是你喂4D齐次坐标为API。 在任何时候确实WebGL的执行任何“3D到2D的转换的数学”,也没有用户。 没有人到2D在WebGL的任何点坐标转换任何东西。 2D值没有通过2D管道供给; 4D值是通过一个三维管线送入。
因此, 由他自己的定义 ,WebGL是不是2D API。
QED。
在我看来(作为一个游戏开发者有15年以上的3D图形体验),作为2D API的WebGL的GMAN的特征是极具误导性的,充其量,我会倾向于认为是只是平了错误。 尼科尔流星锤指出,大部分的原因在他的答案,但对我来说,关键的一点是,它仅仅是不可能得到正确的渲染的3D场景,一旦你从线框图形GMAN在他的画布/ WebGL的例子来纹理使用移动三角形的WebGL,如果没有在顶点着色器的输出与Z和W提供的信息,如果没有光栅化过程中使用它们来获得正确的角度插值和使用Z缓冲器进行消隐。
点GMAN似乎真的是想提出的是,WebGL是不喜欢的旧的远古3D图形API固定功能3D图形API,但有一个可编程管线。 但是,这是所有现代的3D图形API的真实(Direct3D的8,9,10,11,OpenGL的2.0及以上;专有的API,你会发现在诸如PS3,PS4,Wii U的......控制台)。 他们都在本质上是相同的方式工作:顶点着色器输出齐次坐标和光栅化使用Z和W信息来正确插值投射到2D图像3D三角形和使用Z缓冲器进行消隐。 这是从那些没有Z和W坐标,没有透视校正插值的概念和隐面消除没有Z缓存2D API的非常不同。 为了使纹理的三角形的3D场景中正确像画布2D API,你需要实现所有的,在软件自己。
[ 更新 ]在他的一个物品 GMAN使用“API”和“库”或多或少可以互换。 我不认为有两个方面的明确和完善的定义,但我觉得条款有不同的理解,可以在这里奉献了一些分歧。
Khronos的WebGL的描述:
WebGL的™是一个立即模式的3D渲染API设计的网页。
我认为这是一个准确的描述。 “API”的一个常用的意思是定义的软件接口来访问底层硬件或操作系统服务,指的是面向公众的软件界面,而不是任何具体实施。 在这个意义上,所有的主流现代的API旨在访问3D图形硬件可以被认为是低层次的“立即模式的3D渲染API”。 我想包括的OpenGL,OpenGL ES的,WebGL的,Direct3D和对这一类游戏机中发现的专有API。
这是正常的行业指的是所有这些为“3D API的”,因为他们的目的是提供给图形处理器,其主要功能是绘制3D图形和它们公开支持该功能(透视校正插值和z低级别的功能访问-buffer光栅化期间,基于隐面消除,各向异性纹理滤波,在一些情况下镶嵌硬件等),以及向三维管线的可编程部分(顶点,像素,几何着色器,船体和域着色器等编程的手段)。
我倾向于认为“图书馆”作为具有略微不同的含义为“API”。 像three.js所描述的东西本身作为一个“图书馆”,而不是“API”:
three.js所是使WebGL的图书馆 - 3D浏览器 - 很容易。 虽然在原料的WebGL一个简单的立方体会变成数百Javascript和着色器代码的行,一个three.js所相当于只是一小部分。
而同时有两个方面,我倾向于认为图书馆作为谈得更多的是一个具体实施的功能性和暗示也许更高层次的辅助功能比直API的没有一成不变的定义。
其他更高级别的3D“图书馆”可能把自己描述成“引擎”或“框架”,如
OGRE(面向对象图形渲染引擎)是用C写的一个场景为导向,灵活的3D引擎++设计,使其更容易,更直观的开发者产生利用硬件加速3D图形应用程序。
还有的功能一大堆,是不是老式的固定功能“的API就像前2.0 OpenGL或预DX8的DirectX的一部分,但是是非常有用的,如果你只是想呈现一些3D对象,而不需要的3D图形详细的了解 - 比如场景图,功能加载和附带材料,灯光和阴影等高层的支持渲染模型,但不是什么低级别的3D“的API”像的Direct3D或WebGL的旨在。 这不是他们想要解决的问题。 我可以看到它可能是有益的尝试,并传达给谁只是想呈现在浏览器中的一些3D对象的新手,但我不认为声称WebGL是一个“2D API”是一个有益的或准确的方式来跨得。
好吧,我不知道说别人 - 我会倾向于去与任何东西在他们的网站克罗诺斯说。 似乎完全清晰。 :耸肩:
WebGL的™是一个立即模式的3D渲染API设计的网页。 它是从的OpenGL ES 2.0导出的,并且提供类似的渲染功能,但在一个HTML上下文。 WebGL是设计作为HTML Canvas元素渲染上下文。 的HTML画布提供了网页编程的渲染目标,并允许使用不同的渲染API执行该呈现。 描述为画布说明书的一部分的唯一这样的接口是2D画布渲染上下文,CanvasRenderingContext2D。 本文介绍了一个这样的接口,WebGLRenderingContext,其中介绍了WebGL的API。
https://www.khronos.org/registry/webgl/specs/1.0/
这是一个观点。
在WebGL的任何任务,以在3D世界模式,打造一个摄像头,设置灯光等在结束渲染器只关心的点,线,三角形,其4坐标涉及到|w*x|<w, |w*y|<w, |w*z|<w.
默认情况下也可以传递给一个仅着色两个坐标,x和y,而框架设置Z = 0且w = 1。
人们可以也使用OpenGL ES的绘制2D精灵,没有设置一些投影矩阵的任何问题。 人们可以省略Z缓冲和处理z坐标一起到的点,其中有必要成立:| Z * W | <= W任何东西将被渲染。
而且它是很清楚,这并非巧合的是,API非常适合于渲染3D模型。
哇,你的问题只是EXCELENT! 你做所有这些大师一样在最后一战打乌
好吧,也许你还想与像1年WebGL的experimence和almoast没有OpenGL的编程技巧,从人读答案,让我们做到这一点! :)
首先,我要说的东西,我没看过到那一步,我觉得很重要。 @gman赛斯说:
所以你没有个人有知识的API提供了一个解决方案。
好了,我真的不同意这种说法。 API提供了一些解决方案,但它并不意味着你不需要这些知识。
现在回到你的问题,正如你所说的:
我们可以指定X,Y,Z坐标在WebGL的顶点着色器和fragement着色器。 我不明白的2D和3D图形API之间的区别。
正如其他人说,你可以指定(我想你甚至必须指定 ) gl_Position
着色器是4D向量。 之前,只是JavaScript和一些分离的GPU。 然后WebGL的出现了新的选择。 WebGL的本身不提供3D行为的任何解决方案,但它带来的对选项来指定gl_Position
着色器。
我数了新的选择,而不是只是整个解决方案。 所以我觉得这个问题也是关于什么API真的是你。 为了我? 在这种情况下,它带来的通过着色,使3D应用的可能性。 因此,它是3D API。
我希望它可以帮助...