简体   繁体   English

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

[英]How to draw 2D shapes on the xy plane (z=0) in WebGL?

I wish to draw 2D shapes on the xy plane (z=0) in WebGL. 我希望在WebGL中的xy平面(z = 0)上绘制2D形状。

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); 问题出在这里: mat4.perspective(45, gl.viewportWidth / gl.viewportHeight, 0.1, 100.0, pMatrix); and mat4.translate(mvMatrix, [2.0, 5.0, -1.0]); mat4.translate(mvMatrix, [2.0, 5.0, -1.0]);

I wish to draw the object on the z=0 plane. 我希望在z = 0平面上绘制对象。 So when I change that to mat4.perspective(45, gl.viewportWidth / gl.viewportHeight, 0.0, 100.0, pMatrix); 所以当我把它改为mat4.perspective(45, gl.viewportWidth / gl.viewportHeight, 0.0, 100.0, pMatrix); and mat4.translate(mvMatrix, [2.0, 5.0, 0.0]); mat4.translate(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中指定的数字是否以屏幕像素为单位转换和存储缓冲区中形状的坐标?

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

If you want to do 2D rendering you should NOT be using 3D math. 如果要进行2D渲染,则不应使用3D数学。 Get rid of the mat4 library and do 2D math and all your problems with 2D will go away. 摆脱mat4库并进行2D数学运算,所有2D问题都将消失。

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/

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. 在进入我的答案的主要部分之前,为了回答问题的最后部分,可能有助于理解WebGL收到的数字实际上如何成为屏幕上的颜色。 I've already written up a detailed answer on exactly that, if you don't mind clicking through to " How WebGL works? ". 如果您不介意点击“ 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). 使用正交投影矩阵,无论物体与相机有多近或多远,物体都被绘制成相同的尺寸,这使得它们非常适合各种2D操作,即使在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 : 这是使用gl-matrix实例化正交矩阵的示例:

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. 如果您希望将对象保留在单位空间中,则可以使用范围-1..1 ,如果要将对象缩放到窗口大小,或者可以使用画布的像素坐标(即有时用于布置用户界面等。 (And yes, you can use a near value of 0.) (是的,你可以使用近似值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. 在2D环境中,这可能更少。 Doing this has its uses but is not common. 这样做有其用途,但并不常见。

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. 最后,关于在WebGL中进行2D图形的最后一个注释。 There are some functions you'll want to call: 您需要调用一些函数:

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

Also, if you are doing a 2D renderer, you should probably disable depth buffer tests. 此外,如果您正在进行2D渲染器,则应该禁用深度缓冲测试。 Since you probably want to rely on draw order to determine visibility. 因为您可能希望依靠绘制顺序来确定可见性。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM