WebGL编程中的平滑边缘

时间:2016-05-31 10:33:54

标签: javascript webgl

当您在WebGL原生API中创建一个球体(实际上,它也是apolyhedron)或其他多面体时,您将得到一个具有平面样式的多面体,并为多面体指定纹理,它看起来很难看在多面体表面上的两个小面之间的角度。实际上,您可以细分曲面以获得光滑的曲面。还有其他任何方法来对多面体的smooth the surface进行分析。看下来就像下面两张图片一样。(这两张照片是从搅拌机软件中捕获的)

polyhedron with flat style

polyhedron with smooth style

这是我生成球体的代码

 function getSphere(r,segment_lat,segment_lon){
      var normalData = [];
      var vertexData = [];
      var textureCoord = [];
      var vertexIndex = [],
      for (var latNum = 0; latNum <= segment_lat; latNum++) {
            var theta = latNum * Math.PI / segment_lat;
            var sinTheta = Math.sin(theta);
            var cosTheta = Math.cos(theta);
        for (var lonNum = 0; lonNum <= segment_lon; lonNum++) {
              var phi = lonNum * 2 * Math.PI / segment_lon;
              var sinPhi = Math.sin(phi);
              var cosPhi = Math.cos(phi);
              var x = cosPhi * sinTheta;
              var y = cosTheta;
              var z = sinPhi * sinTheta;
              var u = 1 - (lonNum / segment_lon);
              var v = 1 - (latNum / segment_lat);
              textureCoord.push(u);
              textureCoord.push(v);
              vertexData.push(r * x);
              vertexData.push(r * y);
              vertexData.push(r * z);
          }
      }
      for (var latNum=0; latNum < segment_lat;latNum++) {
          for (var lonNum=0; lonNum < segment_lon; lonNum++) {
            var first = (latNum * (segment_lon + 1)) + lonNum;
            var second = first + segment_lon + 1;
            vertexIndex .push(first);
            vertexIndex .push(second);
            vertexIndex .push(first + 1);
            vertexIndex .push(second);
            vertexIndex .push(second + 1);
            vertexIndex .push(first + 1);
        }
      }
        return {'vertexData':vertexData,'vertexIndex':vertexIndex,'textureCoord':textureCoord,'normalDatas':normalData};
    },

片段着色器:           

        precision mediump float;
        varying vec2 vTextureCoord;
        uniform sampler2D uSampler;

        void main(void) {
            vec3 light = vec3(1,1,1);
            vec4 textureColor = texture2D(uSampler, vec2(vTextureCoord.s, vTextureCoord.t));
            gl_FragColor = vec4(textureColor.rgb*light,textureColor.a);
            // gl_FragColor = vec4 (1,0,0,.8);
        }

顶点着色器:         

        attribute vec2 aTextureCoord;
        attribute vec3 aVertexPosition;
        // uniform mediump mat4 proj_inv;
        uniform mediump mat4 modelViewMatrix;
        uniform mediump mat4 projectMatrix;
        varying highp vec2 vTextureCoord;

        void main(void) {
            //projectMatrix multi modelViewMatrix must be in vertex shader,or it will be wrong;
            gl_Position = projectMatrix*modelViewMatrix*vec4(aVertexPosition, 1.0);
            vTextureCoord = aTextureCoord;
        }

1 个答案:

答案 0 :(得分:-1)

如果我猜测你的渲染结果与你展示的图片有所不同。你看到的是一个统一颜色的“扁平”球体,你想要一个阴影球体,这是正确的吗?

如果是这样,您需要阅读有关照明工作原理的教程。基本上,观察矢量和片段法线之间的角度用于确定每个片段的亮度。您直接盯着球体上的一个片段在视图矢量与其法线之间的角度非常小,因此它的亮度非常小。球体几乎看不见的边缘上的碎片在法线和视图之间有一个很大的角度,因此看起来很暗。

在球体生成代码中,您还需要计算法线并将该信息与其余信息一起传递给gpu。幸运的是,对于球体,法线很容易计算:normal = normalize(position - center);如果假设中心位于(0,0,0),则只需normalize(position)