计算机图形学

第二章(3) 图形学编程概述

画一个正方形

完整程序内容

  • 描述性网页(HTML文件),提供对WebGL画板的支持,以实现渲染,同时通过网页获取其它所需文件
  • 定义着色器(HTML文件头),也可以定义在单独的文件中,取决于所采用的浏览器
  • 运算过程描述、数据描述(JavaScript源文件)
  • 将数据送入GPU(JavaScript源文件)
  • 数据渲染(JavaScript文件)

HTML文件


<html>
<head>
  <meta http-equiv="Content-Type" content="text/html;charset=utf-8">
  <title>First WebGL Demo</title>
  <!-- 顶点着色器和片元着色器代码 -->
  <script id="vertex-shader" type="x-shader/x-vertex">
    #version 300 es
    in vec4 vPosition;
    void main(){
        gl_Position = vPosition;
    }
  </script>
  <script id="fragment-shader" type="x-shader/x-fragment">
    #version 300 es	
    precision mediump float;
			
    out vec4 fColor;
    void main(){
        fColor = vec4( 1.0, 1.0, 0.0, 1.0 );
    }
  </script>
  <!-- 一组相关的JS库 -->
  <script type="text/javascript" src="../js/common/webgl-utils.js"></script>
  <script type="text/javascript" src="../js/common/initShaders.js"></script>
  <script type="text/javascript" src="../js/common/glMatrix-0.9.5.min.js"></script>
  <!-- 绘制三角形的JS代码 -->
  <script type="text/javascript" src="../js/ch01/square.js"></script>
</head>

<body>
  <canvas id="square-canvas" style="border:none;" width="500" height="500"></canvas>
</body>

</html>
                    

WebGL程序解析

关于Shader的解释

  • 首先,需要分别为两段Shader程序命名并指明其类型,分别为顶点着色器vertex-shader和面片着色器fragment-shader,该命名用于在JS文件中调用
  • 着色器之间可传递数据,在当前程序中,用于传递的数据变量为gl_Position和fColor,实际上并没有做什么
  • 两段着色器文件都是完整的程序,注意有main
  • 向量类型为vec4,为shader的内建向量类型,着色器中同样可以根据数据精度设置对应的数据类型

WebGL程序解析

包含文件

../js/common/webgl-utils.js
用于设置WebGL环境的工具,对于底层工具进行了封装,便于调用
../js/common/initShaders.js
包含了对Shader程序进行读取、编译、链接的相关工具代码
../js/common/glMatrix-0.9.5.min.js
提供了处理矩阵和向量计算的工具
../js/ch01/square.js
应用程序文件

WebGL程序解析

JavaScript文件


"use strict";

var gl;

window.onload = function init(){
    var canvas = document.getElementById( "square-canvas" );
    gl = canvas.getContext("webgl2");
    if( !gl ){
        alert( "WebGL isn't available" );
    }

    // Four Vertices
    var points = new Float32Array([
        -0.5, -0.5,
         0.5, -0.5,
         0.5,  0.5,
        -0.5,  0.5,
        //-0.5, -0.5,
        // 0.5, 0.5
    ]);

    var colors=new Float32Array([
        0.0, 1.0, 0.0, 1.0,
        //0.0, 1.0, 0.0, 1.0,
        //0.0, 0.0, 1.0, 1.0,
        //1.0, 0.0, 1.0, 1.0
    ]);

    // Configure WebGL
    gl.viewport( 0, 0, canvas.width/2, canvas.height/2 );
    gl.clearColor( 1.0, 0.0, 0.0, 1.0 );

    // Load shaders and initialize attribute buffers
    var program = initShaders( gl, "vertex-shader", "fragment-shader" );
    gl.useProgram( program );

    // Load the data into the GPU
    var bufferId = gl.createBuffer();
    gl.bindBuffer( gl.ARRAY_BUFFER, bufferId );
    gl.bufferData( gl.ARRAY_BUFFER, points, gl.STATIC_DRAW );

    // Associate external shader variables with data buffer
    var vPosition = gl.getAttribLocation( program, "vPosition" );
    gl.vertexAttribPointer( vPosition, 2, gl.FLOAT, false, 0, 0 );
    gl.enableVertexAttribArray( vPosition );

    
    var cBuffer = gl.createBuffer();
    gl.bindBuffer(gl.ARRAY_BUFFER, cBuffer);
    gl.bufferData(gl.ARRAY_BUFFER, colors, gl.STATIC_DRAW);

    var vColor = gl.getAttribLocation(program, "vColor");
    gl.vertexAttribPointer(vColor, 4, gl.FLOAT, false, 0, 0);
    gl.enableVertexAttribArray(vColor);
    
    
    render();
}

function render(){
    gl.clear( gl.COLOR_BUFFER_BIT );
    gl.drawArrays( gl.TRIANGLE_FAN, 0, 4 );
    //gl.drawArrays( gl.TRIANGLES, 0, 6 );
    //gl.drawArrays( gl.TRIANGLE_STRIP, 0, 4 );
}                    
                    

JavaScript文件说明

  • line 6. 当已经载入所有的代码后,就从该位置开始执行代码
  • line 7-8. 从HTML文件中获取WebGL用于渲染的画布环境
  • line 13-20. 定义了正方形的四个顶点,为八个浮点数
  • line 29-31. 定义视口,用于绘制的区域,顶点位置会映射到此区域

JavaScript文件说明(续)

  • line 33-35. initShaders用于载入、编译、链接着色器程序代码,构建程序对象
  • line 37-54. 通过创建Vertex Buffer Object(VBO),将顶点位置数据传递给GPU,这里采用的数据类型为与C中相类似的float32,并将传入的顶点数据与着色器程序中的变量相联系,即顶点着色器中的vPosition,注意在第36行,声明了位置的属性为vec2。将变量值赋给着色器变量,需要声明在缓存中的名字、类型和位置
  • line 61-64. 实际渲染代码,将四个顶点的数组以三角扇的形式绘制出来,可同时尝试参数gl.TRIANGLES, gl.TRIANGLE_STRIP