Three.js教程系列-[系统原理]-顶点变量attribute传值 (21)

68次阅读
没有评论

顶点变量attribute传值

几何体顶点数据的属性名和顶点着色器中attribute变量名一个一样的,这是自动传值的前提。

BufferGeometry

了解BufferGeometry的数据结构,了解顶点数据的属性名。

//创建一个缓冲区类型立方体
var geometry = new THREE.BoxBufferGeometry(100, 100,100);
console.log('几何体所有顶点数据',geometry.attributes);

WebGLProgram.js

查看WebGLProgram.js源码中顶点相关的attribute变量名名称。

// WebGLProgram.js源码
  // 声明顶点着色器代码用到的顶点变量attribute
  'attribute vec3 position;',//顶点位置数据
  'attribute vec3 normal;',//顶点法向量数据
  'attribute vec2 uv;',//顶点UV坐标数据

WebGL API

通过WebGL方法gl.getAttribLocation()可以从程序对象program获得attribute变量的索引地址,用于传值

var aposLocation = gl.getAttribLocation(program,'apos');
var a_color = gl.getAttribLocation(program,'a_color');
var a_normal = gl.getAttribLocation(program,'a_normal');

通过gl.vertexAttribPointer()方法把顶点缓冲区顶点数据传值给变量a_normal

 // 创建缓冲区normalBuffer,传入顶点法向量数据normalData
var normalBuffer=gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER,normalBuffer);
gl.bufferData(gl.ARRAY_BUFFER,normalData,gl.STATIC_DRAW);
// 传值
gl.vertexAttribPointer(a_normal,3,gl.FLOAT,false,0,0);
gl.enableVertexAttribArray(a_normal);

WebGLProgram.js

通过gl.getProgramParameter()计算程序对象对应着色器中uniform变量和attribute变量的个数。

// 表示顶点数据attribute变量数量
var n = gl.getProgramParameter( program, gl.ACTIVE_ATTRIBUTES );
// uniform变量个数
var n = gl.getProgramParameter( program, gl.ACTIVE_UNIFORMS );

通过gl.getActiveAttrib( program, i )获得程序对象着色器第i+1个attribute变量的相关信息,返回值是一个对象,对象.name属性是attribute属性的变量名。

var info = gl.getActiveAttrib( program, i );
var info = gl.getActiveAttrib( program, 0 );
console.log('第1个attribute变量的信息',info);
console.log('attribute变量名字',info.name);

通过gl.getActiveUniform( program, i )获得程序对象着色器第i+1个uniform变量的相关信息,返回值是一个对象,对象.name属性是uniform属性的变量名。

var info = gl.getActiveUniform( program, i );

通过getAttributes方法从程序对象获得attribute变量的索引地址

// 通过该函数获得着色器中所有attribute变量的索引地址
function fetchAttributeLocations( gl, program ) {
    var attributes = {};
  // 获得程序对象attribute变量个数
    var n = gl.getProgramParameter( program, gl.ACTIVE_ATTRIBUTES );

  // 循环遍历获得所有attribute变量
    for ( var i = 0; i < n; i ++ ) {
    // 获得程序对象着色器第i+1个attribute变量的相关信息,返回值是一个对象
        var info = gl.getActiveAttrib( program, i );
    // .name属性是attribute属性的变量名
        var name = info.name;
    // 获得attribute变量索引地址,用于传值
        attributes[ name ] = gl.getAttribLocation( program, name );
    }
  // 返回一个对象,包含了全部attribute变量的索引地址
    return attributes;
}
// 通过WebGLProgram的getAttributes方法调用fetchAttributeLocations函数
this.getAttributes = function () {
  if ( cachedAttributes === undefined ) {
    cachedAttributes = fetchAttributeLocations( gl, program );
  }
  return cachedAttributes;
};

WebGLRenderer.js

setupVertexAttributes函数封装了gl.vertexAttribPointer()用于attribute变量传值。

function setupVertexAttributes(material, program, geometry) {
    // 获得几何体相关顶点数据
    var geometryAttributes = geometry.attributes;
    // 获得着色器中所有attribute变量的索引地址
    var programAttributes = program.getAttributes();

    // 遍历programAttributes对象
    for (var name in programAttributes) {
        // 获得名为name的attribute变量索引地址
        var programAttribute = programAttributes[name];
        // gl.getAttribLocation()本质上的返回值是数字,表示第几个attribute变量
        if (programAttribute >= 0) {
            // 根据name确定对应的包含顶点数据的BufferAttribute对象
            // 比如geometry.attributes.position
            var geometryAttribute = geometryAttributes[name];

            if (geometryAttribute !== undefined) {

                var normalized = geometryAttribute.normalized;
                var size = geometryAttribute.itemSize;
                // WebGLAttributes.js封装的get方法,返回值是对象:
                //  {
                // buffer: buffer,
                // type: type,
                // bytesPerElement: array.BYTES_PER_ELEMENT,
                // version: attribute.version
                // }
                var attribute = attributes.get(geometryAttribute);

                if (attribute === undefined) continue;
                // 获得WebGLAttributes.js创建的顶点缓冲区
                var buffer = attribute.buffer;
                // 顶点缓冲区数据类型
                var type = attribute.type;
                // 类型数组中每个元素所占用的字节数
                var bytesPerElement = attribute.bytesPerElement;
        ...
                // 绑定激活当前顶点缓冲区
                _gl.bindBuffer(_gl.ARRAY_BUFFER, buffer);
                // programAttribute:attribute变量索引地址
                _gl.vertexAttribPointer(programAttribute, size, type, normalized, 0, 0);
                ...
            }
        }
}

this.renderBufferDirect = function(camera, fog, geometry, material, object, group) {
  var program = setProgram(camera, fog, material, object);
    // 调用函数setupVertexAttributes自动传值
  setupVertexAttributes(material, program, geometry);
}