该系列仅为记录自己的学习相关知识。
以 2d 的顶点着色器为例
<script id="vertex-shader-2d" type="notjs">
// an attribute will receive data from a buffer
attribute vec4 a_position;
// all shaders have a main function
void main() {
// gl_Position is a special variable a vertex shader
// is responsible for setting
gl_Position = a_position;
}
</script>
我们知道,定义一个定点着色器,我们为了能够让我们定义的数据能够渲染到屏幕上,我们需要将屏幕中的点转化到裁剪空间中,以下是对应关系。
裁剪空间 屏幕空间
0, 0 -> 200, 150
0, 0.5 -> 200, 225
0.7, 0 -> 340, 150
会渲染出以下的图形
我们会发现这个三角形是从中间开始,并且是朝向右上方的,是因为裁剪空间的x
坐标范围是 -1 到 +1,而 (0,0) 在中心。
对于二维空间中的物体,我们更希望得到的是屏幕像素坐标而不是裁剪空间坐标。
<script id="vertex-shader-2d" type="x-shader/x-vertex">
attribute vec2 a_position;
uniform vec2 u_resolution;
uniform mat3 u_matrix;
void main() {
// 从像素坐标转换到 0.0 到 1.0
vec2 zeroToOne = position / u_resolution;
// 再把 0->1 转换 0->2
vec2 zeroToTwo = zeroToOne * 2.0;
// 把 0->2 转换到 -1->+1 (裁剪空间)
vec2 clipSpace = zeroToTwo - 1.0;
gl_Position = vec4(clipSpace, 0, 1);
}
</script>
因此对于输入的坐标点 (200, 150)( 200, 225)( 340, 150),我们可以渲染成
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PnvdtZU3-1633759639041)(/Users/huayifeng/Downloads/image-20211009010603385.png)]
而WebGL默认为左下角为 (0,0)想要像传统 API 一样右上角为 (0,0),我们只需要将 Y 轴反转gl_Position = vec4(clipSpace * vec2(1, -1), 0, 1);
<script id="vertex-shader-2d" type="notjs">
// an attribute will receive data from a buffer
attribute vec2 a_position;
uniform vec2 u_resolution;
// all shaders have a main function
void main() {
// 从像素坐标转换到 0.0 到 1.0
vec2 zeroToOne = a_position / u_resolution;
// 再把 0->1 转换 0->2
vec2 zeroToTwo = zeroToOne * 2.0;
// 把 0->2 转换到 -1->+1 (裁剪空间)
vec2 clipSpace = zeroToTwo - 1.0;
gl_Position = vec4(clipSpace * vec2(1, -1), 0, 1);
}
</script>
扫描二维码关注公众号,回复:
14652048 查看本文章
而为了能够更加简洁地描述,我们可以使用矩阵来进行描述
<script id="vertex-shader-2d" type="x-shader/x-vertex">
attribute vec2 a_position;
uniform mat3 u_matrix;
void main() {
// 使位置和矩阵相乘
gl_Position = vec4((u_matrix * vec3(a_position, 1)).xy, 0, 1);
}
</script>
var matrixLocation = gl.getUniformLocation(program, "u_matrix");
var m3 = {
projection: function (width, height) {
return [
2 / width, 0, 0,
0, -2 / height, 0,
-1, 1, 1
];
},
}
var matrix = m3.projection(gl.canvas.clientWidth, gl.canvas.clientHeight);
gl.uniformMatrix3fv(matrixLocation, false, matrix);
下面谈谈,关于以下式子的推导:
等价于以下式子,由于矩阵变化为从右到左。依次为
1.缩放到 [-1, 1]范围
2.放大2倍
3.x,y平移 -1
4.y轴反转
参考资料:GAMES101-现代计算机图形学入门-闫令琪