十五、视点和视线

339 阅读2分钟

一、介绍

1、二维图形与三维图形的区别是,三维图形有深度,即z轴

2、 确定观察者状态的三要素

要素 格式 类型 默认值
视点 (eyeX, eyeY, eyeZ) 坐标 (0, 0, 0)原点
视察目标点 (atX, atY, atZ) 坐标 (0, 0, -1)z轴负方向
上方向 (upX, upY, upZ) 矢量 (0, 1, 0)Y轴负方向

3、 根据矢量创建视图矩阵(使用前文提到的库函数cuon-matrix.js的setLookAt()方法)\

Matrix4.setLookAt(eyeX, eyeY, eyeZ, atX, atY, atZ, upX, upY, upZ)

创建默认矩阵

var initViewMatrix = new Matrix4();
initViewMatrix.setLookAt(0,0,0, 0,0,-1, 0,1,0)

二、关键代码

var VSHADER_SOURCE =
    'attribute vec4 a_Position;\n' +
    'attribute vec4 a_Color;\n' +
    'uniform mat4 u_ViewMatrix;\n' +
    'varying vec4 v_Color;\n' +
    'void main() {\n' +
    '  gl_Position = u_ViewMatrix * a_Position;\n' +
    '  v_Color = a_Color;\n' +
    '}\n';

var FSHADER_SOURCE =
    'varying vec4 v_Color;\n' +
    'void main() {\n' +
    '  gl_FragColor = v_Color;\n' +
    '}\n';

function main() {
    ···
    var n = initVertexBuffers(gl);
    gl.clearColor(0, 0, 0, 1);

    var u_ViewMatrix = gl.getUniformLocation(gl.program, 'u_ViewMatrix');

    var viewMatrix = new Matrix4();
    #设置视点、视线、上方向
    viewMatrix.setLookAt(0.20, 0.25, 0.25, 0, 0, 0, 0, 1, 0);
    #设置视图矩阵
    gl.uniformMatrix4fv(u_ViewMatrix, false, viewMatrix.elements);

    gl.clear(gl.COLOR_BUFFER_BIT);
    gl.drawArrays(gl.TRIANGLES, 0, n);
}

function initVertexBuffers(gl) {
    var verticesColors = new Float32Array([
        #顶点坐标和颜色
         0.0,  0.5,  -0.4,  0.4,  1.0,  0.4, 
        -0.5, -0.5,  -0.4,  0.4,  1.0,  0.4,
         0.5, -0.5,  -0.4,  1.0,  0.4,  0.4, 

         0.5,  0.4,  -0.2,  1.0,  0.4,  0.4, 
        -0.5,  0.4,  -0.2,  1.0,  1.0,  0.4,
         0.0, -0.6,  -0.2,  1.0,  1.0,  0.4, 

         0.0,  0.5,   0.0,  0.4,  0.4,  1.0, 
        -0.5, -0.5,   0.0,  0.4,  0.4,  1.0,
         0.5, -0.5,   0.0,  1.0,  0.4,  0.4, 
    ]);
    var n = 9;
    #(1)
    var vertexColorbuffer = gl.createBuffer();  
    #(2)
    gl.bindBuffer(gl.ARRAY_BUFFER, vertexColorbuffer);
    #(3)
    gl.bufferData(gl.ARRAY_BUFFER, verticesColors, gl.STATIC_DRAW);
    
    var FSIZE = verticesColors.BYTES_PER_ELEMENT;
    var a_Position = gl.getAttribLocation(gl.program, 'a_Position');
    #(4)
    gl.vertexAttribPointer(a_Position, 3, gl.FLOAT, false, FSIZE * 6, 0);
    #(5)
    gl.enableVertexAttribArray(a_Position);


    var a_Color = gl.getAttribLocation(gl.program, 'a_Color');
    #(4)
    gl.vertexAttribPointer(a_Color, 3, gl.FLOAT, false, FSIZE * 6, FSIZE * 3);
    #(5)
    gl.enableVertexAttribArray(a_Color);
    
    gl.bindBuffer(gl.ARRAY_BUFFER, null);
    return n;
}

注:
(1)
实际上,“根据自定义的观察者状态,绘制观察者看到的景象”与“使用默认的观察状态,但是对三维对象进行评议、旋转等变换,再绘制观察者看到的景象”,这两种行为是等价的。 即,“改变观察者的状态”与“对整个世界进行平移和旋转变换”,本质上是一样的。
(2)
<旋转后顶点坐标> = <旋转矩阵> * <原始顶点坐标>
<从视点看上去的旋转后顶点坐标> = <视图矩阵> * <旋转后顶点坐标>
以上两个公式可得
<从视点看上去的旋转后顶点坐标> = <视图矩阵> * <旋转矩阵> * <原始顶点坐标>