WebGL编程指南--入门

一、前言

        自从入坑了CesiumJS,一直对一些特效感兴趣。奈何三维方面基础太薄弱,每次看别人写的glsl特效都有点力不从心。更不要说实现自己想要的特效。终于最近抽空入手了一本《WebGL编程指南》,强烈推荐像我一样的小白去看。这本书的原版是日文,后来被翻译为中文和英文。非常感谢本书的翻译者,用平实的语言让我读懂了WebGL的特性,并让我非常自然的接受了后面比较难以理解的矩阵变换。

        我写WebGL编程指南系列,也是跟着这本书的脉络,整理一下我的学习心得,并分享出来。

二、WebGL概述

        WebGL是一项用来在网页上绘制和渲染复杂三维图形,并允许用户与之进行交互的技术。传统的三维渲染,需要C或C++语言开发,并利用OpenGL(开源)或Direct3D(微软提供)这些三维图形库开开发独立应用程序。WebGL的出现,改变了桌面端应用程序垄断三维技术的情况。WebGL内嵌在浏览器中,不需要安装软件和3D环境,直接打开网页即可浏览。

WebGL技术规范继承自免费和开源的OpenGL标准,因此WebGL就是Web版的OpenGL(实际上,WebGL继承自OpenGL的一个特殊版本---OpenGL  ES 2.0)。OpenGL 2.0版本开始,支持了可编程着色器方法(programmable shader functions),这个特性被OpenGL ES 2.0继承,并成为了WebGL 1.0标准的核心部分。

因此也可以说,OpenGL ES 着色器语言(GLSL  ES),是WebGL的核心。WebGL需要两种着色器:

顶点着色器(Vertex shader):顶点着色器用来描述顶点特性(位置、大小、颜色等)。顶点是指二维或三维空间中的一个点,比如二维或三维图形的端点或交点。

片源着色器(Fragment shader):进行逐片源处理过程,如颜色、光照、阴影。片源也可以理解为像素。

这两个概念第一次结束会比较抽象,这里先有一个印象即可。后面随着案例的深入,会慢慢变得很形象。

三、WebGL入门

1、绘制一个点

熟悉web编程的朋友们应该都知道,在html中绘制二维元素,需要在<canvas>元素中实现。同理,利用WebGL绘制三维元素,也需要在<canvas>中绘制。

我写案例使用的是Vue3+typeScript。

<template>
  <canvas id='webgl' width='400' height='400'></canvas>
</template>

<script lang='ts'>
import { defineComponent, onMounted } from 'vue'

export default defineComponent({
  name: 'webgl1',
  setup() {
    // 着色器程序是以字符串形式嵌入进js代码中的
    // WebGL因为继承自OpenGL,而OpenGL支持C、C++语言
    // 所以着色器程序的编程风格与C相同,是强类型编程语言
    // 关于C、C++的编程规范,这里不展开说,需自行了解。
    // 顶点着色器程序
    const v_shader_source = `
       void main()
       {
          // 顶点着色器的内置变量
          // gl_Position 表示顶点位置
          // gl_pointSize 表示点的尺寸
          gl_Position = vec4(0.0,0.0,0.0,1.0);
          // gl_PointSize若不赋值,默认为1.0
          gl_PointSize = 10.0;
       }
    `;
    // 片元着色器程序
    const f_shader_source = `
       void main()
       {
          // gl_FragColor是片元着色器的唯一内置变量,
          // 这里用来为这个点赋值颜色
          // vec4()是一个四维向量,在颜色方面,分别代表 r g b a
          gl_FragColor = vec4(1.0,0.0,0.0,1.0);
       }
    `;

    /**
     * 初始化着色器,将提前写好的glsl代码赋值给着色器
     * */
    const initShaders=(gl:WebGLRenderingContext,v_shader_source:string,f_shader_source:string)=>{
      const vertexShader = gl.createShader(gl.VERTEX_SHADER)
      gl.shaderSource(vertexShader!, v_shader_source)
      gl.compileShader(vertexShader!)

      const fragmentShader = gl.createShader(gl.FRAGMENT_SHADER)
      gl.shaderSource(fragmentShader!, f_shader_source)
      gl.compileShader(fragmentShader!)

      const shaderProgram = gl.createProgram()
      gl.attachShader(shaderProgram!, vertexShader!)
      gl.attachShader(shaderProgram!, fragmentShader!)
      gl.linkProgram(shaderProgram!)
      gl.useProgram(shaderProgram!)
    }

    onMounted(()=>{
      // 从<canvas>标签中获取webgl绘图上下文
      const canvas = document.getElementById('webgl') as HTMLCanvasElement;
      const gl = canvas.getContext('webgl') as WebGLRenderingContext;

      //初始化着色器
      initShaders(gl, v_shader_source, f_shader_source)

      gl.clearColor(1.0, 1.0, 0.0, 1.0)
      gl.clear(gl.COLOR_BUFFER_BIT)

      gl.drawArrays(gl.POINTS, 0, 1)
    })
  }
})
</script>

<style scoped>

</style>

程序执行后的效果:

2、WebGL坐标系统

gl_Position = vec4(0.0,0.0,0.0,1.0);

在顶点着色器中,我们定义了一个四维变量作为点的位置,但实际上我们只需要x、y、z三个纬度的坐标即可。这是为什么呢?

这涉及到线性代数的知识。由4个分量组成的矢量被称为其次坐标,因为它能够提高处理三维数据的效率,所以在三维图形系统重被大量使用。事实上,齐次坐标(x,y,z,w)等价于(x/w,y/w.z/w)。所以(0.0,0.0,0.0,1.0)等价于(0.0,0.0,0.0)。

根据上面的执行结果,可知点绘制在了canvas的中间,但熟悉屏幕坐标的同学都知道,canvas的(0,0)点应该是左上角,为什么会将点绘制在中间呢?

那是因为gl_Position表示的是webgl的坐标系中的位置,canvas的坐标需转换为webgl中的坐标系统。二者的坐标系统关系,见下图:

以上就是我对WebGL的初步认识,总结一下:

WebGL继承自OpenGL ES 2.0实现,glsl着色器编程是它的核心。

着色器又分为:顶点着色器和片元着色器。顶点着色器用来定义图形的交点、顶点的位置、大小。片源着色器用来基于顶点的颜色渲染其余片元的颜色、光照和阴影效果。

着色器语言规范与C语言相同。

顶点着色器中内置两个变量:gl_Position,gl_PointSize。

片源着色器中内置一个变量:gl_FragColor。

WebGL坐标系统,是归一化的坐标系统,其x轴、y轴的坐标范围是[-1,1]。且(0,0)位置位于中心处。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
基本信息 原书名:WebGL Programming Guide: Interactive 3D Graphics Programming with WebGL (OpenGL) 原出版社: Addison-Wesley Professional 作者: (美)Kouichi Matsuda Rodger Lea(松田浩一,罗杰.李) 译者: 谢光磊 出版社:电子工业出版社 ISBN:9787121229428 上架时间:2014-6-11 出版日期:2014 年6月 开本:16开 页码:470 版次:1-1 ---------------------------------------- 目录 《WebGL编程指南》 第1 章 WebGL 概述 1 WebGL 的优势 3 使用文本编辑器开发三维应用 3 轻松发布三维图形程序 4 充分利用浏览器的功能 5 学习和使用WebGL 很简单 5 WebGL 的起源 5 WebGL 程序的结构 6 总结 7 第2 章 WebGL 入门 9 Canvas 是什么? 10 使用[canvas] 标签 11 DrawRectangle.js 13 最短的WebGL 程序:清空绘图区 16 HTML 文件(HelloCanvas.html) 16 JavaScript 程序(HelloCanvas.js) 17 用示例程序做实验 22 绘制一个点(版本1) 22 HelloPoint1.html 24 HelloPoint1.js 24 着色器是什么? 25 使用着色器的WebGL 程序的结构 27 初始化着色器 29 顶点着色器 31 片元着色器 33 绘制操作 34 WebGL 坐标系统 35 用示例程序做实验 37 绘制一个点(版本2) 38 使用attribute 变量 38 示例程序(HelloPoint2.js) 39 获取attribute 变量的存储位置 41 向attribute 变量赋值 42 gl.vertexAttrib3f() 的同族函数 44 用示例程序做实验 45 通过鼠标点击绘点 46 示例程序(ClickedPoints.js) 47 注册事件响应函数 48 响应鼠标点击事件 50 用示例程序做实验 53 改变点的颜色 55 示例程序(ColoredPoints.js) 56 uniform 变量 58 获取uniform 变量的存储地址 59 向uniform 变量赋值 60 gl.uniform4f() 的同族函数 61 总结 62 第3 章 绘制和变换三角形 63 绘制多个点 64 示例程序(MultiPoint.js) 66 使用缓冲区对象 69 创建缓冲区对象(gl.createBuffer()) 70 绑定缓冲区(gl.bindBuffer()) 71 向缓冲区对象中写入数据(gl.bufferData()) 72 类型化数组 74 将缓冲区对象分配给attribute 变量(gl.vertexAttribPointer()) 75 开启attribute 变量(gl.enableVertexAttribArray()) 77 gl.drawArrays() 的第2 个和第3 个参数 78 用示例程序做实验 79 Hello Triangle 80 示例程序(HelloTriangle.js) 80 基本图形 82 用示例程序做实验 83 Hello Rectangle(HelloQuad) 84 用示例程序做实验 85 移动、旋转和缩放 86 平移 87 示例程序(TranslatedTriangle.js) 88 旋转 91 示例程序(RotatedTriangle.js) 93 变换矩阵:旋转 97 变换矩阵:平移 100 4×4 的旋转矩阵 101 示例程序(RotatedTriangle_Matrix.js) 102 平移:相同的策略 105 变换矩阵:缩放 106 总结 108 第4 章 高级变换与动画基础 109 平移,然后旋转 109 矩阵变换库:cuon-matrix.js 110 示例程序(RotatedTriangle_Matrix4.js) 111 复合变换 113 示例程序(RotatedTranslatedTriangle.js) 115 用示例程序做实验 117 动画 118 动画基础 119 示例程序(RotatingTriangle.js) 119 反复调用绘制函数(tick()) 123 按照指定的旋转角度绘制三角形(dr
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值