【问题标题】:Issue when rendering a torus in webGL在 webGL 中渲染圆环时的问题
【发布时间】:2016-02-24 22:01:00
【问题描述】:

我正在编写一个应该在 webgl 中绘制 3D 参数形状的程序。我目前的代码似乎(大部分)适用于球体,但是当我切换用于查找 x、y 和 z 的方程时,对于环面,只有环面的上半部分被渲染(在 xy飞机)。当仅使用 2d 画布上下文而不使用任何 webgl 时,我拥有的所有参数方程(对于球体、环面和圆柱体)都有效;但是,当使用 webgl 时,似乎出现了问题。除了只渲染一半圆环的问题之外,用于渲染圆柱体的方程不会渲染任何东西。

什么可能导致只有一半的圆环被渲染?渲染参数形状的代码如下:

            var latitudeBands = 30;
            var longitudeBands = 30;
            var radius = 0.5;

            var vertexPositionData = [];
            var normalData = [];
            var textureCoordData = [];
            var indexData = [];

            for (var latNumber = 0; latNumber <= latitudeBands; latNumber++)                     
              {  var theta = latNumber * Math.PI / latitudeBands;
                var sinTheta = Math.sin(theta);
                var cosTheta = Math.cos(theta);

                for (var longNumber = 0; longNumber <= longitudeBands; longNumber++) {
                    var phi = longNumber * 2 * Math.PI / longitudeBands;
                    var sinPhi = Math.sin(phi);
                    var cosPhi = Math.cos(phi);

                    //Equation used for sphere     
                    //var x =  Math.cos(phi) * Math.cos(theta);
                    //var y = Math.cos(phi) * Math.sin(theta);
                    //var z = Math.sin(phi);

                    //Equation used for torus
                    var x = (1 + radius * Math.cos(phi)) * Math.cos(theta);
                    var y = (1 + radius * Math.cos(phi)) * Math.sin(theta);
                    var z = radius * Math.sin(phi);

                  //Equation used for cylinder
                  //var x =  Math.cos(theta);
                  //var y = Math.sin(theta);
                  //var z = 2 * latNumber - 1;


                    var u = 1 - (longNumber / longitudeBands);
                    var v = 1 - (latNumber / latitudeBands);

                    normalData.push(x);
                    normalData.push(y);
                    normalData.push(z);
                    textureCoordData.push(u);
                    textureCoordData.push(v);
                    vertexPositionData.push(radius * x);
                    vertexPositionData.push(radius * y);
                    vertexPositionData.push(radius * z)
                }
            }

            for (var latNumber = 0; latNumber < latitudeBands; latNumber++) {
                for (var longNumber = 0; longNumber < longitudeBands; longNumber++) {
                    var first = (latNumber * (longitudeBands + 1)) + longNumber;
                    var second = first + longitudeBands + 1;
                    indexData.push(first);
                    indexData.push(second);
                    indexData.push(first + 1);
                    indexData.push(second);
                    indexData.push(second + 1);
                    indexData.push(first + 1);
                }
            }

        moonVertexPositionBuffer = gl.createBuffer();
        gl.bindBuffer(gl.ARRAY_BUFFER, moonVertexPositionBuffer);
        gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertexPositionData), gl.STATIC_DRAW);
        moonVertexPositionBuffer.itemSize = 3;
        moonVertexPositionBuffer.numItems = vertexPositionData.length / 3;

        moonVertexIndexBuffer = gl.createBuffer();
        gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, moonVertexIndexBuffer);
        gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(indexData), gl.STATIC_DRAW);
        moonVertexIndexBuffer.itemSize = 1;
        moonVertexIndexBuffer.numItems = indexData.length;

【问题讨论】:

  • 圆环的法线不需要从中心计算,就像球体的法线与 x,y,z 坐标相同。您最好在创建面后计算法线。每个顶点的法线是使用该顶点的所有面的法线的平均值。法线用于剔除背面。将材质设置为双面很可能会显示所有面,但如果法线错误,您的着色将不正确。
  • @Blindman67 我认为只有在使用照明时才需要法线?在这种情况下我没有使用任何东西,所以我不确定法线的计算是否会影响渲染。我刚刚使用要发送到 GPU 的数组更新了代码。

标签: javascript html graphics opengl-es webgl


【解决方案1】:

老实说,对于这些类型的问题,最可能的错误来自几何生成代码。我建议参考优秀的 THREE.js 源代码来检查差异。 Toros 生成代码here.

如果您将来需要它们,您可以找到其他几何生成的代码here

【讨论】:

    【解决方案2】:

    您的球体仰角范围仅为 PI(从极到极),但 环面的范围是 2*PI;因此

    theta = latNumber * Math.PI / latitudeBands
    

    应该是

    theta = latNumber * 2 * Math.PI / latitudeBands
    

    WebGL Torus Example

    【讨论】:

    • 这正是错误,谢谢!你知道学习如何在 WebGL 中绘制高级形状的最佳网络资源是什么吗?
    猜你喜欢
    • 1970-01-01
    • 2018-07-22
    • 2020-05-28
    • 1970-01-01
    • 1970-01-01
    • 2014-10-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多