计算机图形学——实验一 WebGL基本图形绘制

实验内容

  1. 修改程序HelloPoint2,使用uniform变量来获取颜色值。
  2. 绘制曲线。参考程序MultiPoint。
  3. 通过点击鼠标选取点绘制三角形,添加菜单改变三角形的颜色。

参考程序ClickedPoints和rotatingSquare2。

实验设计思路

      注:由于只有实验相关的文档,给我提供文档的人没有给我相关的示例代码,因此所有的程序都是自己编写,非常可能与示例程序有较大出入,但是实现的原理基本一致。后面的几篇实验也是如此。实验中要求使用cuon-matrix.js作为矩阵操作函数库,而这里是用glMatrix.js作为矩阵操作函数库。

      任务1:最基本的webgl在canvas上进行图形绘制操作。以下是需要实现的步骤

             ①获取webgl上下文

             ②编写顶点着色器和片元着色器

             ③创建和编译着色器

             ④创建着色器程序并链接

             ⑤准备顶点数据并创建缓冲区

             ⑥向着色器程序传入所需的数据

             ⑦进行绘图操作

     任务2:将曲线细分为大量的点,再将这些点用直线连起来,能够得到非常接近该曲线的图形

     任务3:对canvas画布进行onclick事件绑定,发生点击事件后,通过点击事件的坐标,计算出点击的点在画布中的坐标{ (x,y)|x∈[-1,1],y∈[-1,1] },并将该点记录到indices数组中。当indices数组满足绘制三角形所需的顶点个数时,进行绘制操作。设置三个改变颜色的button,点击后会向着色器程序传入对应的颜色数据,并进行重新绘制。

  

实验结果

任务1

任务2

任务3

实验代码

任务1

 //获取上下文
    const canvas = document.getElementById("my_Canvas");
    gl = canvas.getContext("experimental-webgl");

    //编写Shader代码,并编译
    const vertCode =
      'attribute vec3 coordinates;' +
      'void main(void){' +
      'gl_Position = vec4(coordinates,1.0);' +
      '}';

    const vertShader = gl.createShader(gl.VERTEX_SHADER);
    gl.shaderSource(vertShader, vertCode);
    gl.compileShader(vertShader);

    const fragCode =
      'precision mediump float;' +
      'uniform vec3 u_Color;' +
      'void main(void){' +
      'gl_FragColor = vec4(u_Color, 1.0);' +
      '}';

    const fragShader = gl.createShader(gl.FRAGMENT_SHADER);
    gl.shaderSource(fragShader, fragCode);
    gl.compileShader(fragShader);

    //创建并设置着色器程序
    const shaderProgram = gl.createProgram();
    gl.attachShader(shaderProgram, vertShader);
    gl.attachShader(shaderProgram, fragShader);
    gl.linkProgram(shaderProgram);
    gl.useProgram(shaderProgram);

    //定义顶点,索引
    const vertices = new Float32Array([
      -0.5, 0.5, 0.0,
      -0.5, -0.5, 0.0,
      1, -1, 0.0,
    ]);

    const indices = new Uint16Array([
      0, 1, 2
    ]);

    //创建缓冲区并向缓冲区传入数据
    const vertex_buffer = gl.createBuffer();
    gl.bindBuffer(gl.ARRAY_BUFFER, vertex_buffer);
    gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);

    const index_Buffer = gl.createBuffer();
    gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, index_Buffer);
    gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, indices, gl.STATIC_DRAW);

    //利用缓冲区向attribute变量传入数据
    const coord = gl.getAttribLocation(shaderProgram, "coordinates");
    gl.vertexAttribPointer(coord, 3, gl.FLOAT, false, 0, 0);
    gl.enableVertexAttribArray(coord);

    //向uniform变量传入数据
    const u_ColorLocation = gl.getUniformLocation(shaderProgram, 'u_Color');
    gl.uniform3f(u_ColorLocation, 1.0, 0.0, 0.0);

    //进行绘制
    gl.clearColor(0.5, 0.5, 0.5, 1.0);
    gl.enable(gl.DEPTH_TEST);
    gl.clear(gl.COLOR_BUFFER_BIT);
    gl.drawElements(gl.TRIANGLES, indices.length, gl.UNSIGNED_SHORT, 0);

任务2

    //获取上下文
    const canvas = document.getElementById("my_Canvas");
    const gl = canvas.getContext("experimental-webgl");

    //编写Shader代码,并编译
    const vertCode =
      'attribute vec3 coordinates;' +
      'void main(void){' +
      'gl_Position = vec4(coordinates,1.0);' +
      '}';

    const vertShader = gl.createShader(gl.VERTEX_SHADER);
    gl.shaderSource(vertShader, vertCode);
    gl.compileShader(vertShader);

    const fragCode =
      'precision mediump float;' +
      'void main(void){' +
      'gl_FragColor = vec4(0,0,0, 1);' +
      '}';

    const fragShader = gl.createShader(gl.FRAGMENT_SHADER);
    gl.shaderSource(fragShader, fragCode);
    gl.compileShader(fragShader);

    //创建并设置着色器程序
    const shaderProgram = gl.createProgram();
    gl.attachShader(shaderProgram, vertShader);
    gl.attachShader(shaderProgram, fragShader);
    gl.linkProgram(shaderProgram);
    gl.useProgram(shaderProgram);

    //求出曲线上的点
    var vertices = [];
    const dx = 0.01;
    for (let i = -1; i <= 1; i = i + dx) {
      vertices.push(i);                                             //x轴坐标
      vertices.push((Math.E ** (-i)) * Math.cos(2 * i * Math.PI));  //y轴坐标
      vertices.push(0);                                             //z轴坐标
    }

    //创建缓冲区并向缓冲区传入数据
    const vertex_buffer = gl.createBuffer();
    gl.bindBuffer(gl.ARRAY_BUFFER, vertex_buffer);
    gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);

    //利用缓冲区向attribute变量传入数据
    const coord = gl.getAttribLocation(shaderProgram, "coordinates");
    gl.vertexAttribPointer(coord, 3, gl.FLOAT, false, 0, 0);
    gl.enableVertexAttribArray(coord);

    //绘制
    gl.clearColor(0.5, 0.5, 0.5, 1.0);
    gl.enable(gl.DEPTH_TEST);
    gl.clear(gl.COLOR_BUFFER_BIT);
    gl.drawArrays(gl.LINE_STRIP, 0, vertices.length / 3);

任务3

    //获取上下文
    const canvas = document.getElementById("my_Canvas");
    gl = canvas.getContext("experimental-webgl");

    //编写Shader代码,并编译
    const vertCode =
      'attribute vec3 coordinates;' +
      'void main(void){' +
      'gl_Position = vec4(coordinates,1.0);' +
      '}';

    const vertShader = gl.createShader(gl.VERTEX_SHADER);
    gl.shaderSource(vertShader, vertCode);
    gl.compileShader(vertShader);

    const fragCode =
      'precision mediump float;' +
      'uniform vec4 u_Color;' +
      'void main(void){' +
      'gl_FragColor = vec4(u_Color);' +
      '}';

    var fragShader = gl.createShader(gl.FRAGMENT_SHADER);
    gl.shaderSource(fragShader, fragCode);
    gl.compileShader(fragShader);

    //创建并设置着色器程序
    const shaderProgram = gl.createProgram();
    gl.attachShader(shaderProgram, vertShader);
    gl.attachShader(shaderProgram, fragShader);
    gl.linkProgram(shaderProgram);
    gl.useProgram(shaderProgram);

    //定义顶点,并创建对应的缓冲区
    var vertices = [];

    const vertex_buffer = gl.createBuffer();
    gl.bindBuffer(gl.ARRAY_BUFFER, vertex_buffer);
    gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);

    //传入顶点数据
    const coord = gl.getAttribLocation(shaderProgram, "coordinates");
    gl.vertexAttribPointer(coord, 3, gl.FLOAT, false, 0, 0);
    gl.enableVertexAttribArray(coord);

    //设置默认颜色为黑色
    const color = gl.getUniformLocation(shaderProgram, 'u_Color');
    gl.uniform4f(color, 0.0, 0.0, 0.0, 1.0);

    //初始化画布
    gl.clearColor(0.5, 0.5, 0.5, 0.9);
    gl.enable(gl.DEPTH_TEST);
    gl.clear(gl.COLOR_BUFFER_BIT);

    //对canvas画布绑定点击需要处理的事件
    canvas.addEventListener('click', function (event) {
      const click_x = event.clientX;
      const click_y = event.clientY;
      let x = (click_x / canvas.width) * 2 - 1;
      let y = 1 - (click_y / canvas.height) * 2;

      //z轴坐标默认为0,将顶点数据压入vertices数组,当其满足绘制三角形的条件时进行一次绘制
      vertices.push(x, y, 0);
      if (vertices.length % 9 == 0) {
        draw();
      }
    })

    //以下三个为切换颜色按钮的事件
    function toRed() {
      gl.uniform4f(color, 1.0, 0.0, 0.0, 1.0);
      draw();
    }

    function toGreen() {
      gl.uniform4f(color, 0.0, 1.0, 0.0, 1.0);
      draw();
    }

    function toBlue() {
      gl.uniform4f(color, 0.0, 0.0, 1.0, 1.0);
      draw();
    }

    //绘制操作
    function draw() {
      gl.clearColor(0.5, 0.5, 0.5, 0.9);
      gl.clear(gl.COLOR_BUFFER_BIT);

      gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);
      gl.drawArrays(gl.TRIANGLES, 0, vertices.length);
    }

  • 7
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值