如何在WebGL的xy平面(z=0)上绘制2D图形?

时间:2022-03-04 13:16:30

I wish to draw 2D shapes on the xy plane (z=0) in WebGL.

我希望在WebGL的xy平面上画2D图形(z=0)。

I'm reading from here.

我从这里阅读。

Here is my drawScene function :

这是我的drawScene功能:

function drawScene() {
    gl.viewport(0, 0, gl.viewportWidth, gl.viewportHeight);
    gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);

    mat4.perspective(45, gl.viewportWidth / gl.viewportHeight, 0.1, 100.0, pMatrix);

    mat4.identity(mvMatrix);
    mat4.translate(mvMatrix, [2.0, 5.0, -1.0]);

    mvPushMatrix();
    gl.bindBuffer(gl.ARRAY_BUFFER, squareVertexPositionBuffer);
    gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, squareVertexPositionBuffer.itemSize, gl.FLOAT, false, 0, 0);

    gl.bindBuffer(gl.ARRAY_BUFFER, squareVertexColorBuffer);
    gl.vertexAttribPointer(shaderProgram.vertexColorAttribute,squareVertexColorBuffer.itemSize, gl.FLOAT, false, 0, 0);

    setMatrixUniforms();
    gl.drawArrays(gl.TRIANGLE_FAN, 0, squareVertexPositionBuffer.numItems);

        mvPopMatrix();
}

squareVertexPositionBuffer and squareVertexColorBuffer are the shape and color buffers of my object.

squareVertexPositionBuffer和squareVertexColorBuffer是我的对象的形状和颜色缓冲。

The issue is here: mat4.perspective(45, gl.viewportWidth / gl.viewportHeight, 0.1, 100.0, pMatrix); and mat4.translate(mvMatrix, [2.0, 5.0, -1.0]);

问题在这里:mat4。透视图(45,gl.viewportWidth / gl.viewportHeight, 0.1, 100.0, pMatrix);和mat4。翻译(mvMatrix[2.0,5.0,-1.0]);

I wish to draw the object on the z=0 plane. So when I change that to mat4.perspective(45, gl.viewportWidth / gl.viewportHeight, 0.0, 100.0, pMatrix); and mat4.translate(mvMatrix, [2.0, 5.0, 0.0]);

我希望在z=0平面上画出这个物体。当我把它换成mat4。透视图(45,gl.viewportWidth / gl.viewportHeight, 0.0, 100.0, pMatrix);和mat4。翻译(mvMatrix[2.0,5.0,0.0]);

nothing gets displayed on the screen. Why is this happening?

没有任何东西显示在屏幕上。为什么会这样?

Also, are the numbers we specify in WebGL to translate and store coordinates of shapes in buffers in screen pixel units?

还有,我们在WebGL中指定的数字是用来翻译和存储屏幕像素单元中缓冲区中形状的坐标吗?

4 个解决方案

#1


1  

If you want to do 2D rendering you should NOT be using 3D math. Get rid of the mat4 library and do 2D math and all your problems with 2D will go away.

如果你想做2D渲染,你不应该使用3D数学。去掉mat4库,做二维数学,你所有的二维问题都会消失。

Using 3D math for 2D in WebGL is arguably old thinking left over from OpenGL 1.0 and is no longer and arguably should be discouraged.

在WebGL中使用3D计算2D的方法,可以说是OpenGL 1.0时代遗留下来的旧思想,现在已经不再有争议了。

Here's a series of articles that go over how to do 2D including 2D math libraries

这里有一系列的文章,讨论如何做2D,包括2D数学库。

http://games.greggman.com/game/webgl-fundamentals/

http://games.greggman.com/game/webgl-fundamentals/

#2


2  

It's because your near clipping plane (third argument in mat4.perspective) is set to 0.1, which means anything in front of that will be culled.

这是因为您的近剪切面(mat4.perspective中的第三个参数)被设置为0.1,这意味着在它前面的任何东西都将被剔除。

#3


1  

Before I get into the main part of my answer, and in an effort to answer the last part of your question, it may help to understand how the numbers received by WebGL actually become colors on your screen. I've already written up a detailed answer on exactly that, if you don't mind clicking through to " How WebGL works? ".

在我回答问题的主要部分之前,为了回答你问题的最后一部分,它可能有助于理解WebGL接收的数字是如何在屏幕上变成颜色的。我已经写了详细的答案,如果你不介意点击“WebGL如何工作?””。

You can't use a near plane depth of 0 for perspective matrices because doing so produces a division by 0, which leads to NaN values in the matrix:

对于透视矩阵,你不能使用*面深度0,因为这样做会产生一个0的除法,这会导致矩阵中的NaN值:

                     // fovy, aspect, znear, zfar
m = mat4.perspective(     45,      1,     0, 100);
//=> [NaN, 0, 0, 0, 0, NaN, 0, 0, NaN, NaN, -1, -1, 0, 0, 0, 0]

Think of the near plane as the eyepiece of a camera lens. It's very close to your eye, but it's not actually in your eye, which is what a near plane of 0 would imply.

把*面看成是照相机镜头的目镜。它离你的眼睛很近,但实际上并不是你的眼睛,这是一个接近0的平面所暗示的。

However, using a nonzero near value is only half of the answer. You should become familiar with orthographic projection, which is sort of the opposite of perspective.

然而,使用非零的接近值只是答案的一半。你应该熟悉正字法投影,这是一种相反的观点。

Perspective means that as objects become more distant, they appear to grow smaller. This is what gives you a sense of depth. With orthographic projection matrices, objects are drawn the same size no matter how close or far they are to the camera, which makes them perfect for all sorts of 2D operations, even in 3D engines (such as drawing a scope lens or HUD).

透视意味着随着物体变得越来越远,它们看起来会变得更小。这给了你一种深度感。在正投影矩阵中,物体的大小是相同的,无论它们离相机有多近,都是完美的,即使是在3D引擎上(比如画幅透镜或HUD)。

It's worth noting that even with orthographic projections, there must still be a near and far plane, and objects must still lie between them to be visible.

值得注意的是,即使有正投影,也必须有一个近距离远的平面,物体必须仍然在它们之间以可见。

Most matrix libraries have a function for producing an orthographic projection, and actually making use of the ortho matrix once created is identical to making use of a perspective matrix. Here's an example of instantiating an ortho matrix using gl-matrix:

大多数矩阵库都有一个用于生成正投影的函数,而实际上,一旦创建了一个正投影矩阵,就可以使用一个透视矩阵。这是一个使用gll -矩阵来实例化一个正交矩阵的例子:

m = mat4.ortho(left, right, bottom, top, near, far);

Most people get hung up on exactly what the values should be. Truth is, you can use whatever values you want. You can use the range -1..1 if you prefer to keep things in unit space, which is useful if you want to scale your objects to the size of the window, or you can use the pixel coordinates of the canvas, which is sometimes useful for laying out user interfaces and the like. (And yes, you can use a near value of 0.)

大多数人都被挂在了正确的价值观上。事实是,你可以使用任何你想要的值。你可以使用范围-1..如果你喜欢把东西放在单位空间里,如果你想把你的对象缩放到窗口的大小,或者你可以使用画布的像素坐标,这是很有用的,因为它有时可以用来布置用户界面等等。(是的,你可以用接近0的值。)

Using a negative near plane value works, but can be a bit unwieldy since it technically means to allow objects behind the camera to be drawn. In a 2D environment, this may matter less. Doing this has its uses but is not common.

使用一个负的*面值的工作,但是可能有点笨拙,因为它在技术上意味着允许在相机后面绘制物体。在2D环境中,这可能更重要。这样做有其用途,但并不常见。

I'm not entirely sure whether objects will start getting culled out at the near plane or past it, so you should be cautious about using values directly on the near plane. To be safe, I try to always set the near plane at least 0.01 closer than the closest object will be.

我不完全确定物体是否会在附近的飞机上被剔除,或者是过去,所以你应该谨慎地使用*面上的值。为了安全起见,我试着始终把*面设置在比最接近的物体近0.01处。

Another thing regarding near and far values: they directly and drastically affect the accuracy of your depth buffer. Keep them as close together as possible. Obviously, this matters a whole lot more in 3D, but can come into play if you're doing a pseudo-2D scene, such as offsetting sprites from one another in layers.

关于近距离和远值的另一件事:它们直接影响到你的深度缓冲的准确性。尽量让他们保持在一起。显然,这在3D上更重要,但如果你在做一个伪2d场景,比如在图层中相互抵消,就可以发挥作用。

Finally, one last note about doing 2D graphics in WebGL. There are some functions you'll want to call:

最后,关于在WebGL中做2D图形的最后一个注意事项。有一些函数你需要调用:

// Disable depth testing. This way, the last object drawn is always in "front".
// WebGL will not attempt to determine whether one object lies behind another.
gl.disable(gl.DEPTH_TEST);

// Alternatively, keep depth testing, but allow objects that share a plane with
// one another to overwrite each other. Your mileage may vary but the idea here
// is to be able to draw the scene in distinct layers, where objects in a given
// layer share the same plane but objects from one layer to the next can still
// take advantage of depth testing.
gl.depthFunc(gl.LEQUAL);

#4


0  

Also, if you are doing a 2D renderer, you should probably disable depth buffer tests. Since you probably want to rely on draw order to determine visibility.

另外,如果您正在执行2D渲染器,您可能应该禁用深度缓冲测试。因为您可能希望依赖于绘制顺序来确定可见性。

#1


1  

If you want to do 2D rendering you should NOT be using 3D math. Get rid of the mat4 library and do 2D math and all your problems with 2D will go away.

如果你想做2D渲染,你不应该使用3D数学。去掉mat4库,做二维数学,你所有的二维问题都会消失。

Using 3D math for 2D in WebGL is arguably old thinking left over from OpenGL 1.0 and is no longer and arguably should be discouraged.

在WebGL中使用3D计算2D的方法,可以说是OpenGL 1.0时代遗留下来的旧思想,现在已经不再有争议了。

Here's a series of articles that go over how to do 2D including 2D math libraries

这里有一系列的文章,讨论如何做2D,包括2D数学库。

http://games.greggman.com/game/webgl-fundamentals/

http://games.greggman.com/game/webgl-fundamentals/

#2


2  

It's because your near clipping plane (third argument in mat4.perspective) is set to 0.1, which means anything in front of that will be culled.

这是因为您的近剪切面(mat4.perspective中的第三个参数)被设置为0.1,这意味着在它前面的任何东西都将被剔除。

#3


1  

Before I get into the main part of my answer, and in an effort to answer the last part of your question, it may help to understand how the numbers received by WebGL actually become colors on your screen. I've already written up a detailed answer on exactly that, if you don't mind clicking through to " How WebGL works? ".

在我回答问题的主要部分之前,为了回答你问题的最后一部分,它可能有助于理解WebGL接收的数字是如何在屏幕上变成颜色的。我已经写了详细的答案,如果你不介意点击“WebGL如何工作?””。

You can't use a near plane depth of 0 for perspective matrices because doing so produces a division by 0, which leads to NaN values in the matrix:

对于透视矩阵,你不能使用*面深度0,因为这样做会产生一个0的除法,这会导致矩阵中的NaN值:

                     // fovy, aspect, znear, zfar
m = mat4.perspective(     45,      1,     0, 100);
//=> [NaN, 0, 0, 0, 0, NaN, 0, 0, NaN, NaN, -1, -1, 0, 0, 0, 0]

Think of the near plane as the eyepiece of a camera lens. It's very close to your eye, but it's not actually in your eye, which is what a near plane of 0 would imply.

把*面看成是照相机镜头的目镜。它离你的眼睛很近,但实际上并不是你的眼睛,这是一个接近0的平面所暗示的。

However, using a nonzero near value is only half of the answer. You should become familiar with orthographic projection, which is sort of the opposite of perspective.

然而,使用非零的接近值只是答案的一半。你应该熟悉正字法投影,这是一种相反的观点。

Perspective means that as objects become more distant, they appear to grow smaller. This is what gives you a sense of depth. With orthographic projection matrices, objects are drawn the same size no matter how close or far they are to the camera, which makes them perfect for all sorts of 2D operations, even in 3D engines (such as drawing a scope lens or HUD).

透视意味着随着物体变得越来越远,它们看起来会变得更小。这给了你一种深度感。在正投影矩阵中,物体的大小是相同的,无论它们离相机有多近,都是完美的,即使是在3D引擎上(比如画幅透镜或HUD)。

It's worth noting that even with orthographic projections, there must still be a near and far plane, and objects must still lie between them to be visible.

值得注意的是,即使有正投影,也必须有一个近距离远的平面,物体必须仍然在它们之间以可见。

Most matrix libraries have a function for producing an orthographic projection, and actually making use of the ortho matrix once created is identical to making use of a perspective matrix. Here's an example of instantiating an ortho matrix using gl-matrix:

大多数矩阵库都有一个用于生成正投影的函数,而实际上,一旦创建了一个正投影矩阵,就可以使用一个透视矩阵。这是一个使用gll -矩阵来实例化一个正交矩阵的例子:

m = mat4.ortho(left, right, bottom, top, near, far);

Most people get hung up on exactly what the values should be. Truth is, you can use whatever values you want. You can use the range -1..1 if you prefer to keep things in unit space, which is useful if you want to scale your objects to the size of the window, or you can use the pixel coordinates of the canvas, which is sometimes useful for laying out user interfaces and the like. (And yes, you can use a near value of 0.)

大多数人都被挂在了正确的价值观上。事实是,你可以使用任何你想要的值。你可以使用范围-1..如果你喜欢把东西放在单位空间里,如果你想把你的对象缩放到窗口的大小,或者你可以使用画布的像素坐标,这是很有用的,因为它有时可以用来布置用户界面等等。(是的,你可以用接近0的值。)

Using a negative near plane value works, but can be a bit unwieldy since it technically means to allow objects behind the camera to be drawn. In a 2D environment, this may matter less. Doing this has its uses but is not common.

使用一个负的*面值的工作,但是可能有点笨拙,因为它在技术上意味着允许在相机后面绘制物体。在2D环境中,这可能更重要。这样做有其用途,但并不常见。

I'm not entirely sure whether objects will start getting culled out at the near plane or past it, so you should be cautious about using values directly on the near plane. To be safe, I try to always set the near plane at least 0.01 closer than the closest object will be.

我不完全确定物体是否会在附近的飞机上被剔除,或者是过去,所以你应该谨慎地使用*面上的值。为了安全起见,我试着始终把*面设置在比最接近的物体近0.01处。

Another thing regarding near and far values: they directly and drastically affect the accuracy of your depth buffer. Keep them as close together as possible. Obviously, this matters a whole lot more in 3D, but can come into play if you're doing a pseudo-2D scene, such as offsetting sprites from one another in layers.

关于近距离和远值的另一件事:它们直接影响到你的深度缓冲的准确性。尽量让他们保持在一起。显然,这在3D上更重要,但如果你在做一个伪2d场景,比如在图层中相互抵消,就可以发挥作用。

Finally, one last note about doing 2D graphics in WebGL. There are some functions you'll want to call:

最后,关于在WebGL中做2D图形的最后一个注意事项。有一些函数你需要调用:

// Disable depth testing. This way, the last object drawn is always in "front".
// WebGL will not attempt to determine whether one object lies behind another.
gl.disable(gl.DEPTH_TEST);

// Alternatively, keep depth testing, but allow objects that share a plane with
// one another to overwrite each other. Your mileage may vary but the idea here
// is to be able to draw the scene in distinct layers, where objects in a given
// layer share the same plane but objects from one layer to the next can still
// take advantage of depth testing.
gl.depthFunc(gl.LEQUAL);

#4


0  

Also, if you are doing a 2D renderer, you should probably disable depth buffer tests. Since you probably want to rely on draw order to determine visibility.

另外,如果您正在执行2D渲染器,您可能应该禁用深度缓冲测试。因为您可能希望依赖于绘制顺序来确定可见性。