如何在运行期间在WebGl中绘制各种大小的各种形状?

时间:2012-10-13 07:19:03

标签: javascript opengl-es webgl

我正在阅读hereinitBuffers函数用于存储我们需要绘制到缓冲区中的对象的顶点。

var triangleVertexPositionBuffer;
var triangleVertexColorBuffer;
function initBuffers() {
    triangleVertexPositionBuffer = gl.createBuffer();
    gl.bindBuffer(gl.ARRAY_BUFFER, triangleVertexPositionBuffer);
    var vertices = [
         0.0, 1.0, 0.0,
        -1.0, -1.0, 0.0,
         1.0, -1.0, 0.0
    ];
    gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);
    triangleVertexPositionBuffer.itemSize = 3;
    triangleVertexPositionBuffer.numItems = 3;

    triangleVertexColorBuffer = gl.createBuffer();
    gl.bindBuffer(gl.ARRAY_BUFFER, triangleVertexColorBuffer);
    var colors = [
        1.0, 0.0, 0.0, 1.0,
        0.0, 1.0, 0.0, 1.0,
        0.0, 0.0, 1.0, 1.0,
    ];
    gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(colors), gl.STATIC_DRAW);
    triangleVertexColorBuffer.itemSize = 4;
    triangleVertexColorBuffer.numItems = 3;
}

现在这是为三角形定义的某种“形状”。现在,如果我想要所有类型和尺寸的形状我必须为每个形状保留缓冲区,如triangleVertexPositionBuffer,对吗?它必须初始化正确

每个新形状的新缓冲区对象是必须的吗?

我计划创建一个系统,在运行期间可以使用按钮创建各种形状。 那么这个问题有解决方案吗? 如何在运行时创建新的缓冲区?是否有一个共同的现有解决方案?

如果我创建一个缓冲对象数组会阻碍性能吗?

1 个答案:

答案 0 :(得分:2)

WebGl并不关心你是否每帧调用initBuffers。嗯,表现可能会。

由于javascript是解释语言,因此运行时与编译时的概念并不存在。然而,一个高级的事情是webgl所需的着色器可以从“文字”字符串生成,在运行时以及从外部文件和html元素生成。

有webgl-infrastructures可用,例如three.js,但我认为Javascript本身就是答案。

编辑:关于评论中的其他问题。 OpenGL和WebGL的工作方式基本上与您描述的方式相同,但是使用矩阵,这些矩阵比仅仅为对象提供偏移更灵活。还有'index-buffers',它们有助于在三角形之间共享顶点。

CubeCorners = [0,0,0,   0,0,1,  0,1,0,  0,1,1,  1,0,0,  1,0,1,  1,1,0,  1,1,1 ]; 
// There are 8 corners in a cube
//              0----1  <-- vertices (aka corners, with x=0)
//             /|   /|
//            4-+--5 |
//            | 2--|-3
//            |/   |/
//            6----7 
Triangles = [0,1,2, 1,3,2, 6,4,2, 2,4,0, 5,4,7, 4,6,7,  ... + 6 other triangles ];
//
TransScaleMatrix = [X,0,0,0, 0,Y,0,0, 0,0,Z,0, ox,oy,oz,1];
// scales the object and sets an internal origin (around which object is rotated)
RotMatrix = [rx,ry,rz, 0, ux,uy,yz,0, tx,ty,tz, 0, Ox,Oy,Oz,1];
// aligns the objects orthogonal up,right,toward vectors to r,u,t, (i.e. rotates it)
// and translates it to new origin O.
CameraOrientationMatrix = [  ... ... ];
// sets cameras lookat, up and right vector + position
PerspectiveMatrix = [ ... ...];
// transforms viewing frustums 6 planes left,right,top,bottom,near and far planes
// to unit cube. (objects outside this cube are clipped away)

使用这些数组,通常会渲染分层场景,其中顶点和对象可以重复使用。可以立方体放置在两个不同的位置,但不同的比例和不同的方向。然后,在“世界坐标”中建模场景后,将相机放置到某个位置和某个方向,并应用透视矩阵将坐标转换为模拟屏幕坐标x,y和深度z的“剪辑空间”。

这些矩阵的美妙之处在于,人们可以将这些矩阵中的每一个预乘到单个矩阵中,从而执行所提到的所有内容。或者可以将此操作链分成尽可能最佳的操作量,这些操作可以在着色器中实时计算,也可以在顶点缓冲区中预先计算。人们应该仔细考虑重用对象的最佳平衡,因为渲染的瓶颈通常是drawElements / drawArray -calls和状态变化(gl.useProgram)的数量,而不是每个对象的顶点数。