快速导航(持续更新中)
WebGL系列教程一(开篇)
WebGL系列教程二(环境搭建及着色器初始化)
WebGL系列教程三(使用缓冲区绘制三角形)
WebGL系列教程四(绘制彩色三角形)
WebGL系列教程五(使用索引绘制彩色立方体)
WebGL系列教程六(纹理映射与立方体贴图)
WebGL系列教程七(二维及三维旋转、平移、缩放)
WebGL系列教程八(GLSL着色器基础语法)
WebGL系列教程九(动画)
WebGL系列教程十(模型Model、视图View、投影Projection变换)
WebGL系列教程十一(光照原理及Blinn Phong着色模型)
目录
1 前言
上一篇中我们对
WebGL
进行了简单的介绍,从本篇开始,正式进入实战。那么我们第一步需要做什么呢?当然是环境的搭建,以及
Shader
的初始化。废话不多说,咱们直接开整。
2 新建html页面
其实搭建
WebGL
的环境十分简单,因为
WebGL
在在浏览里运行的,因此只需要新建一个
html
页面就行了。
3 着色器介绍
3.1 顶点着色器、片元着色器与光栅化的概念
那么什么是顶点着色器?什么是片元着色器?什么叫做光栅化?这三个概念对我们学习
WebGL
还是很重要的,在学习
WebGL
的过程中,我曾经常困惑于片元、光栅化的概念,现在我们就用一张图来解释下。假设我们要在屏幕上画一个三角形。
如图所示,
v1 v2 v3
就叫做顶点,三角形内部的一个个红色的点,就叫做片元,也叫片段,其实它的意思就是一个个像素。注意像素应该是密密麻麻占满了整个三角形,这里为了示意只画出来了少部分。屏幕是什么?屏幕是一种光栅设备,因此把任何一种图形,不论是二维三维的,画在屏幕上,就叫做光栅化。光栅化的概念就这么简单。看过很多其他教程,只说光栅化,不说光栅化是什么意思,很令人困惑。
3.2 声明顶点着色器
声明顶点着色器很简单,只需要写一个
script
标签,注意
type
<script id="vertex-shader" type="x-shader/x-vertex"></script>
3.3 声明片元着色器
声明片元着色器也很简单,只需要写一个
script
标签,同样注意
type
<script id="vertex-shader" type="x-shader/x-fragment"></script>
4 坐标系(右手系)介绍
现在我们来做一个最简单的例子,画一个点,这个点的坐标分别是
x=0.5,y=0.5,z=0
。在此之前我们先明确一下
WebGL
中的坐标系:
X轴向右,Y轴向上,Z轴向外
。右手握拳,四指从
X
到
Y
转动,大拇指的方向就是
Z
轴的方向。很明显,
WebGL
中默认是右手系。因为
z=0
,因此这个点在
xy
所形成的平面内。
5 着色器初始化
初始化着色也很简单,我们先给出步骤,然后一步步来说明
- 创建着色器对象
- 获取着色器对象的源代码
- 绑定着色器的源
- 编译着色器
- 创建并关联项目
5.1 给一个画布canvas
<canvasid="canvas"width="1080"height="720"></canvas>
5.2 获取WebGL对象
const canvas = document.getElementById("canvas");const gl = canvas.getContext("webgl");
5.3 创建着色器对象
//创建着色器对象let vertexShader = gl.createShader(gl.VERTEX_SHADER);let fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
5.4 获取着色器对象的源
//获取着色器对象的源let vertexSource = document.getElementById("vertex-shader").innerText;let fragmentSource = document.getElementById("fragment-shader").innerText;
因为这里我们要用的innerText,也就是script标签里的文本,因此也可以不把文本写在script标签里,而是直接手写字符串,这样的不好处就是没有智能提示,比如:
let vertexSource = “…”
let fragmentSource = “…”
5.5 绑定着色器的源
//绑定着色器的源
gl.shaderSource(vertexShader,vertexSource);
gl.shaderSource(fragmentShader,fragmentSource);
5.6 编译着色器
//编译着色器
gl.compileShader(vertexShader);
gl.compileShader(fragmentShader);
5.7 创建并关联项目
//创建并关联项目let program = gl.createProgram();
gl.attachShader(program,vertexShader);
gl.attachShader(program,fragmentShader);
gl.linkProgram(program);
gl.useProgram(program);
6 绘制
现在我们的准备工作已经完事了,可以开始绘制了。首先需要补齐
script
标签的内容
6.1 声明点的位置、大小和颜色
<scriptid="vertex-shader"type="x-shader/x-vertex">//声明一个点,vec2表示2维向量
attribute vec2 aPos;voidmain(){//点的大小10像素
gl_PointSize =10.0;//点的位置,将vec2补齐为vec4
gl_Position =vec4(aPos,0.0,1.0);}</script><scriptid="fragment-shader"type="x-shader/x-fragment">voidmain(){//点的颜色,rgba形式,红色
gl_FragColor =vec4(1.0,0.0,0.0,1.0);}</script>
6.2 绘制
//绘制let aPos = gl.getAttribLocation(program,"aPos");//设置顶点的值,该顶点是用二维坐标表示的,vertexAttrib2f表示vertex中的attribute属性,2个float值
gl.vertexAttrib2f(aPos,0.5,0.5);//绘制点,从第0个点开始,绘制两个
gl.drawArrays(gl.POINTS,0,2);
改为x=0,y=0看看效果,点回到了正中间。
6.3 完整代码
<!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"><metaname="viewport"content="width=device-width, initial-scale=1.0"><title>Document</title><style>#canvas{border: 1px solid #ccc;}</style></head><body><canvasid="canvas"width="1080"height="720"></canvas><scriptid="vertex-shader"type="x-shader/x-vertex">
attribute vec2 aPos;voidmain(){
gl_PointSize =10.0;
gl_Position =vec4(aPos,0.0,1.0);//gl_Position = aPos; }</script><scriptid="fragment-shader"type="x-shader/x-fragment">voidmain(){
gl_FragColor =vec4(1.0,0.0,0.0,1.0);}</script><script>const canvas = document.getElementById("canvas");const gl = canvas.getContext("webgl");//创建着色器对象let vertexShader = gl.createShader(gl.VERTEX_SHADER);let fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);//获取着色器对象的源let vertexSource = document.getElementById("vertex-shader").innerText;let fragmentSource = document.getElementById("fragment-shader").innerText;//绑定着色器的源
gl.shaderSource(vertexShader,vertexSource);
gl.shaderSource(fragmentShader,fragmentSource);//编译着色器
gl.compileShader(vertexShader);
gl.compileShader(fragmentShader);
console.log(gl.getShaderInfoLog(vertexShader));//创建并关联项目let program = gl.createProgram();
gl.attachShader(program,vertexShader);
gl.attachShader(program,fragmentShader);
gl.linkProgram(program);
gl.useProgram(program);//绘制let aPos = gl.getAttribLocation(program,"aPos");//设置顶点的值,该顶点是用二维坐标表示的
gl.vertexAttrib2f(aPos,0.0,0.0);
gl.drawArrays(gl.POINTS,0,2);</script></body></html>
7 总结
本篇博文中我们梳理了WebGL中整个的绘制流程,右手坐标系的指向,顶点着色器、片元着色器、光栅化等概念的含义,并以一个最简单的示例,点绘制来演示
Shader
的初始化过程,代码并不复杂,希望读者仔细体会,回见~
版权归原作者 AIGIS. 所有, 如有侵权,请联系我们删除。