我希望在WebGL中的xy平面(z = 0)上绘制2D形状。
我来自here。
这是我的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和squareVertexColorBuffer是我的对象的形状和颜色缓冲区。
问题在于:
mat4.perspective(45, gl.viewportWidth / gl.viewportHeight, 0.1, 100.0, pMatrix);
和
mat4.translate(mvMatrix, [2.0, 5.0, -1.0]);
我希望在z = 0平面上绘制对象。
所以,当我改变它
mat4.perspective(45, gl.viewportWidth / gl.viewportHeight, 0.0, 100.0, pMatrix);
和
mat4.translate(mvMatrix, [2.0, 5.0, 0.0]);
屏幕上没有显示任何内容。 为什么会这样?
另外,我们在WebGL中指定的数字是否以屏幕像素为单位平移和存储缓冲区中形状的坐标?
答案 0 :(得分:2)
这是因为你的近剪裁平面(mat4.perspective
中的第三个参数)设置为0.1,这意味着前面的任何东西都会被剔除。
答案 1 :(得分:1)
如果您想进行2D渲染,则不应使用3D数学。摆脱mat4库并进行2D数学运算,所有2D问题都将消失。
在WebGL中使用3D数学算法可以说是OpenGL 1.0遗留下来的旧思维,已经不再可以说是灰心了。
这是一系列关于如何进行2D包括2D数学库的文章
答案 2 :(得分:1)
在进入我的答案的主要部分之前,为了回答问题的最后部分,可能有助于理解WebGL收到的数字实际上如何成为屏幕上的颜色。如果您不介意点击“How WebGL works?”,我已经准确地写了详细的答案。
对于透视矩阵,不能使用近平面深度为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]
将近平面视为相机镜头的目镜。它非常靠近你的眼睛,但实际上并不是在你的眼睛中,这就是0的近平面意味着什么。
但是,使用非零接近值只是答案的一半。你应该熟悉正交投影,这与透视相反。
透视意味着随着物体变得越来越远,它们似乎变得越来越小。这就是给你一种深度感的东西。使用正交投影矩阵,无论物体与相机有多近或多远,物体都被绘制成相同的尺寸,这使得它们非常适合各种2D操作,即使在3D引擎中(例如绘制示波器镜头或HUD)。 / p>
值得注意的是,即使使用正交投影,仍然必须存在近距离和远距离平面,并且对象必须仍然位于它们之间以便可见。
大多数矩阵库具有用于产生正投影的功能,并且实际上一旦创建就使用正交矩阵与使用透视矩阵相同。以下是使用gl-matrix
实例化正交矩阵的示例:
m = mat4.ortho(left, right, bottom, top, near, far);
大多数人都会对这些价值观产生影响。事实是,你可以使用你想要的任何值。如果您希望将对象保留在单位空间中,则可以使用范围-1..1
,如果要将对象缩放到窗口大小,则可以使用范围// 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);
,或者可以使用画布的像素坐标,即有时用于布置用户界面等。 (是的,您可以使用近似值0。)
使用负近平面值可以工作,但可能有点笨拙,因为它在技术上意味着允许绘制相机后面。在2D环境中,这可能更少。这样做有其用途,但并不常见。
我不完全确定对象是否会在近距离或过去的情况下开始被淘汰,因此您应该谨慎使用近处的值平面。为了安全起见,我尝试始终将近平面设置为比最近的对象更近至少0.01。
关于近端和远端值的另一个问题是:它们直接且极大地影响深度缓冲区的准确性。让它们尽可能靠近。显然,这在3D中更为重要,但如果您正在进行伪2D场景,例如在层中相互抵消精灵,则可以发挥作用。
最后,关于在WebGL中进行2D图形的最后一个注释。您需要调用一些函数:
{{1}}
答案 3 :(得分:0)
此外,如果您正在进行2D渲染器,则应该禁用深度缓冲测试。因为您可能希望依靠绘制顺序来确定可见性。