WebGL+three.js
4.4
1、canvas 和 webgl 的区别
1.1 画布
1.2 Canvas API
1.3 WebGL API
2、WebGL 简介
2.1 什么是 webgl
2.2 为什么学 webgl
- 数据可视化
- 图形/游戏引擎
- 交互演示、图形渲染
- 地图
- VR
- 物品展示
- 室内设计
- 城市规划
2.3 webgl 的优势
2.4 webgl 开源框架
3、webgl 入门
3.1 最短的 webgl 程序
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<canvas id="carvas" width="400" height="400">
此浏览器不支持carvas
</canvas>
</body>
</html>
<script>
const _ctx _= _document_.getElementById("carvas")
const _gl _= _ctx_.getContext("webgl")
_gl_.clearColor(1.0, 0.0, 0.0, 1.0)
_gl_.clear(_gl_._COLOR_BUFFER_BIT_)
</script>
3.2 通过 webgl 绘制一个点
什么是着色器
着色器的工作流程
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<canvas id="canvas" width="400" height="400">
此浏览器不支持carvas
</canvas>
</body>
</html>
<script>
const _ctx _= _document_.getElementById("canvas")
const _gl _= _ctx_.getContext("webgl")
//着色器
//创建着色器源码
const _VERTEX_SHADER_SOURCE _= `
void main() {
//点的坐标
gl_Position = vec4(0.0,0.0,0.0,1.0);
//点的大小
gl_PointSize = 100.0;
}
`;//顶点着色器
const _FRAGMENT_SHADER_SOURCE _= `
void main(){
gl_FragColor = vec4(1.0,0.0,0.0,1.0);
}
`;//片元着色器
//创建着色器
const _vertexShader _= _gl_.createShader(_gl_._VERTEX_SHADER_);
const _fragmentShader _= _gl_.createShader(_gl_._FRAGMENT_SHADER_);
_gl_.shaderSource(_vertexShader_, _VERTEX_SHADER_SOURCE_);//指定顶点着色器的源码
_gl_.shaderSource(_fragmentShader_, _FRAGMENT_SHADER_SOURCE_);//指定片元着色器的源码
//编译着色器
_gl_.compileShader(_vertexShader_);
_gl_.compileShader(_fragmentShader_);
//创建一个程序对象
const _program _= _gl_.createProgram();
_gl_.attachShader(_program_, _vertexShader_);
_gl_.attachShader(_program_, _fragmentShader_);
_gl_.linkProgram(_program_);
_gl_.useProgram(_program_);
//执行绘制
//要绘制的图形是什么, 从哪个开始,使用几个顶点
_gl_.drawArrays(_gl_._POINTS_, 0, 1);
</script>
将创建着色器封装
function initShader(gl, VERTEX_SHADER_SOURCE, FRAGMENT_SHADER_SOURCE) {
const vertexShader = gl.createShader(gl._VERTEX_SHADER_);
const fragmentShader = gl.createShader(gl._FRAGMENT_SHADER_);
gl.shaderSource(vertexShader, VERTEX_SHADER_SOURCE);//指定顶点着色器的源码
gl.shaderSource(fragmentShader, FRAGMENT_SHADER_SOURCE);//指定片元着色器的源码
//编译着色器
gl.compileShader(vertexShader);
gl.compileShader(fragmentShader);
//创建一个程序对象
const program = gl.createProgram();
gl.attachShader(program, vertexShader);
gl.attachShader(program, fragmentShader);
gl.linkProgram(program);
gl.useProgram(program);
return program;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="./lib/index.js"></script>
</head>
<body>
<canvas id="canvas" width="400" height="400">
此浏览器不支持carvas
</canvas>
</body>
</html>
<script>
const _ctx _= _document_.getElementById("canvas")
const _gl _= _ctx_.getContext("webgl")
//着色器
//创建着色器源码
const _VERTEX_SHADER_SOURCE _= `
void main() {
//点的坐标
gl_Position = vec4(0.0,0.0,0.0,1.0);
//点的大小
gl_PointSize = 10.0;
}
`;//顶点着色器
const _FRAGMENT_SHADER_SOURCE _= `
void main(){
gl_FragColor = vec4(1.0,0.0,0.0,1.0);
}
`;//片元着色器
// //创建着色器
// const vertexShader = gl.createShader(gl.VERTEX_SHADER);
// const fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
//
// gl.shaderSource(vertexShader, VERTEX_SHADER_SOURCE);//指定顶点着色器的源码
// gl.shaderSource(fragmentShader, FRAGMENT_SHADER_SOURCE);//指定片元着色器的源码
//
// //编译着色器
// gl.compileShader(vertexShader);
// gl.compileShader(fragmentShader);
//
// //创建一个程序对象
// const program = gl.createProgram();
//
// gl.attachShader(program, vertexShader);
// gl.attachShader(program, fragmentShader);
//
// gl.linkProgram(program);
//
// gl.useProgram(program);
const _program _= initShader(_gl_, _VERTEX_SHADER_SOURCE_, _FRAGMENT_SHADER_SOURCE_);
//执行绘制
//要绘制的图形是什么, 从哪个开始,使用几个顶点
_gl_.drawArrays(_gl_._POINTS_, 0, 1);
</script>
3.3 webgl 坐标系
<!DOCTYPE html
<html lang="en"
<head>
<meta charset="UTF-8"
<title>Title</title>
<script src="./lib/index.js"</script>
<style>
* {
margin: 0;
padding: 0;
}
#canvas{
background: grey;
}
body::after{
content: ' ';
display: block;
width: 1px;
height: 400px;
background: red;
position: absolute;
top: 0;
left: 200px;
}
body::before{
content: ' ';
display: block;
width: 400px;
height: 1px;
background: red;
position: absolute;
top: 200px;
left: 0;
}
</style>
</head>
<body>
<canvas id="canvas" width="400" height="400"
此浏览器不支持carvas
</canvas>
</body>
</html>
<script>
const _ctx _= _document_.getElementById("canvas")
const _gl _= _ctx_.getContext("webgl")
//着色器
//创建着色器源码
const _VERTEX_SHADER_SOURCE _= `
void main() {
//点的坐标
gl_Position = vec4(0.5,0.5,0.5,1.0);
//点的大小
gl_PointSize = 30.0;
}
`;//顶点着色器
const _FRAGMENT_SHADER_SOURCE _= `
void main(){
gl_FragColor = vec4(1.0,0.0,0.0,1.0);
}
`;//片元着色器
const _program _= initShader(_gl_, _VERTEX_SHADER_SOURCE_, _FRAGMENT_SHADER_SOURCE_);
//执行绘制
//要绘制的图形是什么, 从哪个开始,使用几个顶点
_gl_.drawArrays(_gl_._POINTS_, 0, 1);
</script>
3.4 学习使用 attribute 变量
attribute变量只能在顶点着色器中使用不能在片元着色器中使用!
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="./lib/index.js"></script>
</head>
<body>
<canvas id="canvas" width="400" height="400">
此浏览器不支持carvas
</canvas>
</body>
</html>
<script>
const _ctx _= _document_.getElementById("canvas")
const _gl _= _ctx_.getContext("webgl")
//着色器
//创建着色器源码
const _VERTEX_SHADER_SOURCE _= `
attribute vec4 aPosition; //默认为vec4(1.0,0.0,0.0,1.0)
void main() {
gl_Position = aPosition;
gl_PointSize = 30.0;
}
`;//顶点着色器
const _FRAGMENT_SHADER_SOURCE _= `
void main(){
gl_FragColor = vec4(1.0,0.0,0.0,1.0);
}
`;//片元着色器
const _program _= initShader(_gl_, _VERTEX_SHADER_SOURCE_, _FRAGMENT_SHADER_SOURCE_);
const _aPosition _= _gl_.getAttribLocation(_program_, "aPosition");
_gl_.vertexAttrib4f(_aPosition_, 1.0, 0.0, 0.0, 1.0)
// gl.vertexAttrib3f(aPosition, 0.0, 0.0, 0.0)
//执行绘制
//要绘制的图形是什么, 从哪个开始,使用几个顶点
let _x _= 0;
setInterval(() =>{
_x _+= 0.1;
if(_x _> 1.0){
_x _= 0.0;
}
_gl_.vertexAttrib1f(_aPosition_, _x_);
_gl_.drawArrays(_gl_._POINTS_, 0, 1);
})
</script>
4.5
1、通过鼠标控制绘制
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="./lib/index.js"></script>
<style>
* {
margin: 0;
padding: 0;
}
canvas{
margin: 50px auto 0;
display: block;
background: yellow;
}
</style>
</head>
<body>
<canvas id="canvas" width="400" height="400">
此浏览器不支持carvas
</canvas>
</body>
</html>
<script>
const _ctx _= _document_.getElementById("canvas")
const _gl _= _ctx_.getContext("webgl")
//着色器
//创建着色器源码
const _VERTEX_SHADER_SOURCE _= `
attribute vec4 aPosition; //默认为vec4(1.0,0.0,0.0,1.0)
void main() {
gl_Position = aPosition;
gl_PointSize = 10.0;
}
`;//顶点着色器
const _FRAGMENT_SHADER_SOURCE _= `
void main(){
gl_FragColor = vec4(1.0,0.0,0.0,1.0);
}
`;//片元着色器
const _program _= initShader(_gl_, _VERTEX_SHADER_SOURCE_, _FRAGMENT_SHADER_SOURCE_);
const _aPosition _= _gl_.getAttribLocation(_program_, "aPosition");
const _point _= [];
_ctx_.onmousemove = function (ev) {
//鼠标坐标
const x = ev.clientX;
const y = ev.clientY;
const domPosition = ev.target.getBoundingClientRect();
const domx = x - domPosition.left;
const domy = y - domPosition.top;
const halfWidth = _ctx_.offsetWidth / 2;
const halfHeight = _ctx_.offsetHeight / 2;
const clickX = (domx - halfWidth) / halfWidth;
const clickY = (halfHeight - domy) / halfHeight;
_point_.push({clickX, clickY});
for(let i = 0; i < _point_.length; i ++){
_gl_.vertexAttrib2f(_aPosition_, _point_[i].clickX, _point_[i].clickY);
_gl_.drawArrays(_gl_._POINTS_, 0 , 1);
}
}
</script>
2、使用 uniform 绘制不同颜色的点
添加uniform变量,设置到颜色
const _FRAGMENT_SHADER_SOURCE _= `
void main(){
uniform vec4 uColor;
gl_FragColor = uColor;
}
`;//片元着色器
设置完发现有编译错误,片元着色器需要设置精度
const _FRAGMENT_SHADER_SOURCE _= `
void main(){
precision mediump float;
uniform vec4 uColor;
gl_FragColor = uColor;
}
`;//片元着色器
注意:片元着色器类型要与方法对应 vec4 --> uniform4f
vec3 --> uniform3f
float --> uniform1f
uniform 也可以在顶点着色器使用,但不能传递位置信息
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="./lib/index.js"></script>
<style>
* {
margin: 0;
padding: 0;
}
canvas{
margin: 50px auto 0;
display: block;
background: yellow;
}
</style>
</head>
<body>
<canvas id="canvas" width="400" height="400">
此浏览器不支持carvas
</canvas>
</body>
</html>
<script>
const _ctx _= _document_.getElementById("canvas")
const _gl _= _ctx_.getContext("webgl")
//着色器
//创建着色器源码
const _VERTEX_SHADER_SOURCE _= `
attribute vec4 aPosition; //默认为vec4(1.0,0.0,0.0,1.0)
void main() {
gl_Position = aPosition;
gl_PointSize = 10.0;
}
`;//顶点着色器
const _FRAGMENT_SHADER_SOURCE _= `
precision mediump float;
uniform vec2 uColor;
void main(){
gl_FragColor = vec4(uColor.r, uColor.g, 0.0, 1.0);
}
`;//片元着色器
const _program _= initShader(_gl_, _VERTEX_SHADER_SOURCE_, _FRAGMENT_SHADER_SOURCE_);
const _aPosition _= _gl_.getAttribLocation(_program_, "aPosition");
const _uColor _= _gl_.getUniformLocation(_program_, "uColor");
const _point _= [];
_ctx_.onmousemove = function (ev) {
//鼠标坐标
const x = ev.clientX;
const y = ev.clientY;
const domPosition = ev.target.getBoundingClientRect();
const domx = x - domPosition.left;
const domy = y - domPosition.top;
const halfWidth = _ctx_.offsetWidth / 2;
const halfHeight = _ctx_.offsetHeight / 2;
const clickX = (domx - halfWidth) / halfWidth;
const clickY = (halfHeight - domy) / halfHeight;
_point_.push({clickX, clickY});
for(let i = 0; i < _point_.length; i ++){
_gl_.vertexAttrib2f(_aPosition_, _point_[i].clickX, _point_[i].clickY);
_gl_.uniform2f(_uColor_, _point_[i].clickX, _point_[i].clickY);
_gl_.drawArrays(_gl_._POINTS_, 0 , 1);
}
}
</script>
4.6
1、使用缓冲区对象——绘制多个点
2、多缓冲区和数据偏移
比如指定顶点的大小
弊端:如果多个属性,要创建多个缓冲区
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="../lib/index.js"></script>
<style>
* {
margin: 0;
padding: 0;
}
canvas{
margin: 50px auto 0;
display: block;
background: yellow;
}
</style>
</head>
<body>
<canvas id="canvas" width="400" height="400">
此浏览器不支持carvas
</canvas>
</body>
</html>
<script>
const _ctx _= _document_.getElementById("canvas")
const _gl _= _ctx_.getContext("webgl")
//着色器
//创建着色器源码
const _VERTEX_SHADER_SOURCE _= `
attribute vec4 aPosition; //默认为vec4(1.0,0.0,0.0,1.0)
attribute float aPointSize;
void main() {
gl_Position = aPosition;
gl_PointSize = aPointSize;
}
`;//顶点着色器
const _FRAGMENT_SHADER_SOURCE _= `
void main(){
gl_FragColor = vec4(1.0,0.0,0.0,1.0);
}
`;//片元着色器
const _program _= initShader(_gl_, _VERTEX_SHADER_SOURCE_, _FRAGMENT_SHADER_SOURCE_);
const _aPosition _= _gl_.getAttribLocation(_program_, "aPosition");
const _aPointSize _= _gl_.getAttribLocation(_program_, "aPointSize");
const _points _= new _Float32Array_([
-0.5, -0.5, 10,
0.5, -0.5, 20,
0.5, 0.5, 30
]);
const _buffer _= _gl_.createBuffer();
_gl_.bindBuffer(_gl_._ARRAY_BUFFER_, _buffer_);
_gl_.bufferData(_gl_._ARRAY_BUFFER_, _points_, _gl_._STATIC_DRAW_);
//多缓冲区绑定数据
const _BYTES _= _points_.BYTES_PER_ELEMENT;
_gl_.vertexAttribPointer(_aPosition_, 2, _gl_._FLOAT_, false, _BYTES _* 3, 0);
_gl_.enableVertexAttribArray(_aPosition_);
_gl_.vertexAttribPointer(_aPointSize_, 1, _gl_._FLOAT_, false, _BYTES _* 3, _BYTES _* 2);
_gl_.enableVertexAttribArray(_aPointSize_);
_gl_.drawArrays(_gl_._POINTS_, 0 , 3);
</script>
3、绘制多种图形
3.1 绘制连续的线段
_gl_.drawArrays(_gl_._LINE_STRIP_, 0 , 3);
3.2 绘制三角形
gl.TRIANGLES
要绘制多个三角形,点数必须是 3 的倍数
4、图形平移——着色器
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="../lib/index.js"></script>
<style>
* {
margin: 0;
padding: 0;
}
canvas{
margin: 50px auto 0;
display: block;
background: yellow;
}
</style>
</head>
<body>
<canvas id="canvas" width="400" height="400">
此浏览器不支持carvas
</canvas>
</body>
</html>
<script>
const _ctx _= _document_.getElementById("canvas")
const _gl _= _ctx_.getContext("webgl")
//着色器
//创建着色器源码
const _VERTEX_SHADER_SOURCE _= `
attribute vec4 aPosition; //默认为vec4(1.0,0.0,0.0,1.0)
attribute float aPointSize;
attribute float aTranslate;
void main() {
gl_Position = vec4(aPosition.x + aTranslate, aPosition.y, aPosition.z, 1.0);
gl_PointSize = 10.0;
}
`;//顶点着色器
const _FRAGMENT_SHADER_SOURCE _= `
void main(){
gl_FragColor = vec4(1.0,0.0,0.0,1.0);
}
`;//片元着色器
const _program _= initShader(_gl_, _VERTEX_SHADER_SOURCE_, _FRAGMENT_SHADER_SOURCE_);
const _aPosition _= _gl_.getAttribLocation(_program_, "aPosition");
const _aTranslate _= _gl_.getAttribLocation(_program_, "aTranslate");
const _points _= new _Float32Array_([
-0.5, -0.5,
0.5, -0.5,
0.5, 0.5,
]);
const _buffer _= _gl_.createBuffer();
_gl_.bindBuffer(_gl_._ARRAY_BUFFER_, _buffer_);
_gl_.bufferData(_gl_._ARRAY_BUFFER_, _points_, _gl_._STATIC_DRAW_);
//多缓冲区绑定数据
const _BYTES _= _points_.BYTES_PER_ELEMENT;
_gl_.vertexAttribPointer(_aPosition_, 2, _gl_._FLOAT_, false, _BYTES _* 2, 0);
_gl_.enableVertexAttribArray(_aPosition_);
let _x _= -1;
setInterval(() => {
_x _+= 0.1;
if(_x _> 1) _x _= -1;
_gl_.vertexAttrib1f(_aTranslate_, _x_);
_gl_.drawArrays(_gl_._TRIANGLES_, 0 , 3);
}, 60)
</script>
5、图形缩放——着色器
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="../lib/index.js"></script>
<style>
* {
margin: 0;
padding: 0;
}
canvas{
margin: 50px auto 0;
display: block;
background: yellow;
}
</style>
</head>
<body>
<canvas id="canvas" width="400" height="400">
此浏览器不支持carvas
</canvas>
</body>
</html>
<script>
const _ctx _= _document_.getElementById("canvas")
const _gl _= _ctx_.getContext("webgl")
//着色器
//创建着色器源码
const _VERTEX_SHADER_SOURCE _= `
attribute vec4 aPosition; //默认为vec4(1.0,0.0,0.0,1.0)
attribute float aScale;
void main() {
gl_Position = vec4(aPosition.x * aScale, aPosition.y, aPosition.z, 1.0);
gl_PointSize = 10.0;
}
`;//顶点着色器
const _FRAGMENT_SHADER_SOURCE _= `
void main(){
gl_FragColor = vec4(1.0,0.0,0.0,1.0);
}
`;//片元着色器
const _program _= initShader(_gl_, _VERTEX_SHADER_SOURCE_, _FRAGMENT_SHADER_SOURCE_);
const _aPosition _= _gl_.getAttribLocation(_program_, "aPosition");
const _aScale _= _gl_.getAttribLocation(_program_, "aScale");
const _points _= new _Float32Array_([
-0.5, -0.5,
0.5, -0.5,
0.5, 0.5,
]);
const _buffer _= _gl_.createBuffer();
_gl_.bindBuffer(_gl_._ARRAY_BUFFER_, _buffer_);
_gl_.bufferData(_gl_._ARRAY_BUFFER_, _points_, _gl_._STATIC_DRAW_);
//多缓冲区绑定数据
const _BYTES _= _points_.BYTES_PER_ELEMENT;
_gl_.vertexAttribPointer(_aPosition_, 2, _gl_._FLOAT_, false, _BYTES _* 2, 0);
_gl_.enableVertexAttribArray(_aPosition_);
let _x _= 1;
setInterval(() => {
_x _+= 0.1;
if(_x _> 2) _x _= 1;
_gl_.vertexAttrib1f(_aScale_, _x_);
_gl_.drawArrays(_gl_._TRIANGLES_, 0 , 3);
}, 60)
</script>
6、图形旋转——着色器
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="../lib/index.js"></script>
<style>
* {
margin: 0;
padding: 0;
}
canvas{
margin: 50px auto 0;
display: block;
background: yellow;
}
</style>
</head>
<body>
<canvas id="canvas" width="400" height="400">
此浏览器不支持carvas
</canvas>
</body>
</html>
<script>
const _ctx _= _document_.getElementById("canvas")
const _gl _= _ctx_.getContext("webgl")
//着色器
//创建着色器源码
const _VERTEX_SHADER_SOURCE _= `
attribute vec4 aPosition; //默认为vec4(1.0,0.0,0.0,1.0)
attribute float deg; //选转角度
void main() {
gl_Position.x = aPosition.x * cos(deg) - aPosition.y * sin(deg);
gl_Position.y = aPosition.x * sin(deg) + aPosition.y * cos(deg);
gl_Position.z = aPosition.z;
gl_Position.w = aPosition.w;
}
`;//顶点着色器
const _FRAGMENT_SHADER_SOURCE _= `
void main(){
gl_FragColor = vec4(1.0,0.0,0.0,1.0);
}
`;//片元着色器
const _program _= initShader(_gl_, _VERTEX_SHADER_SOURCE_, _FRAGMENT_SHADER_SOURCE_);
const _aPosition _= _gl_.getAttribLocation(_program_, "aPosition");
const _deg _= _gl_.getAttribLocation(_program_, "deg");
const _points _= new _Float32Array_([
-0.5, -0.5,
0.5, -0.5,
0.0, 0.5,
]);
const _buffer _= _gl_.createBuffer();
_gl_.bindBuffer(_gl_._ARRAY_BUFFER_, _buffer_);
_gl_.bufferData(_gl_._ARRAY_BUFFER_, _points_, _gl_._STATIC_DRAW_);
//多缓冲区绑定数据
const _BYTES _= _points_.BYTES_PER_ELEMENT;
_gl_.vertexAttribPointer(_aPosition_, 2, _gl_._FLOAT_, false, 0, 0);
_gl_.enableVertexAttribArray(_aPosition_);
let _x _= 1;
function animation() {
_x _+= 0.1;
_gl_.vertexAttrib1f(_deg_, _x_);
_gl_.drawArrays(_gl_._TRIANGLES_, 0 , 3);
requestAnimationFrame(animation)
}
animation()
</script>
7、图形平移——平移矩阵
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="../lib/index.js"></script>
<style>
* {
margin: 0;
padding: 0;
}
canvas{
margin: 50px auto 0;
display: block;
background: yellow;
}
</style>
</head>
<body>
<canvas id="canvas" width="400" height="400">
此浏览器不支持carvas
</canvas>
</body>
</html>
<script>
const _ctx _= _document_.getElementById("canvas")
const _gl _= _ctx_.getContext("webgl")
//着色器
//创建着色器源码
const _VERTEX_SHADER_SOURCE _= `
attribute vec4 aPosition; //默认为vec4(1.0,0.0,0.0,1.0)
uniform mat4 mat;
void main() {
gl_Position = mat * aPosition;
gl_PointSize = 10.0;
}
`;//顶点着色器
const _FRAGMENT_SHADER_SOURCE _= `
void main(){
gl_FragColor = vec4(1.0,0.0,0.0,1.0);
}
`;//片元着色器
const _program _= initShader(_gl_, _VERTEX_SHADER_SOURCE_, _FRAGMENT_SHADER_SOURCE_);
const _aPosition _= _gl_.getAttribLocation(_program_, "aPosition");
const _mat _= _gl_.getUniformLocation(_program_, "mat");
function getTranslateMatrix(x = 0, y = 0, z = 0) {
return new _Float32Array_([
1.0, 0.0, 0.0, 0.0,
0.0, 1.0, 0.0, 0.0,
0.0, 0.0, 1.0, 0.0,
x, y, z, 1.0,
])
}
const _points _= new _Float32Array_([
-0.5, -0.5,
0.5, -0.5,
0.5, 0.5,
]);
const _buffer _= _gl_.createBuffer();
_gl_.bindBuffer(_gl_._ARRAY_BUFFER_, _buffer_);
_gl_.bufferData(_gl_._ARRAY_BUFFER_, _points_, _gl_._STATIC_DRAW_);
//多缓冲区绑定数据
const _BYTES _= _points_.BYTES_PER_ELEMENT;
_gl_.vertexAttribPointer(_aPosition_, 2, _gl_._FLOAT_, false, 0, 0);
_gl_.enableVertexAttribArray(_aPosition_);
let _x _= -1;
function animation() {
_x _+= 0.1;
if(_x _> 1){
_x _= -1;
}
const matrix = getTranslateMatrix(_x_);
_gl_.uniformMatrix4fv(_mat_, false, matrix);
_gl_.drawArrays(_gl_._TRIANGLES_, 0 , 3);
requestAnimationFrame(animation);
}
animation();
</script>
8、图形缩放——缩放矩阵
缩放矩阵
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="../lib/index.js"></script>
<style>
* {
margin: 0;
padding: 0;
}
canvas{
margin: 50px auto 0;
display: block;
background: yellow;
}
</style>
</head>
<body>
<canvas id="canvas" width="400" height="400">
此浏览器不支持carvas
</canvas>
</body>
</html>
<script>
const _ctx _= _document_.getElementById("canvas")
const _gl _= _ctx_.getContext("webgl")
//着色器
//创建着色器源码
const _VERTEX_SHADER_SOURCE _= `
attribute vec4 aPosition; //默认为vec4(1.0,0.0,0.0,1.0)
uniform mat4 mat;
void main() {
gl_Position = mat * aPosition;
gl_PointSize = 10.0;
}
`;//顶点着色器
const _FRAGMENT_SHADER_SOURCE _= `
void main(){
gl_FragColor = vec4(1.0,0.0,0.0,1.0);
}
`;//片元着色器
const _program _= initShader(_gl_, _VERTEX_SHADER_SOURCE_, _FRAGMENT_SHADER_SOURCE_);
const _aPosition _= _gl_.getAttribLocation(_program_, "aPosition");
const _mat _= _gl_.getUniformLocation(_program_, "mat");
function getTranslateMatrix(x = 0, y = 0, z = 0) {
return new _Float32Array_([
1.0, 0.0, 0.0, 0.0,
0.0, 1.0, 0.0, 0.0,
0.0, 0.0, 1.0, 0.0,
x, y, z, 1.0,
])
}
const _points _= new _Float32Array_([
-0.5, -0.5,
0.5, -0.5,
0.5, 0.5,
]);
const _buffer _= _gl_.createBuffer();
_gl_.bindBuffer(_gl_._ARRAY_BUFFER_, _buffer_);
_gl_.bufferData(_gl_._ARRAY_BUFFER_, _points_, _gl_._STATIC_DRAW_);
//多缓冲区绑定数据
const _BYTES _= _points_.BYTES_PER_ELEMENT;
_gl_.vertexAttribPointer(_aPosition_, 2, _gl_._FLOAT_, false, 0, 0);
_gl_.enableVertexAttribArray(_aPosition_);
let _x _= -1;
function animation() {
_x _+= 0.1;
if(_x _> 1){
_x _= -1;
}
const matrix = getTranslateMatrix(_x_);
// gl.vertexAttrib1f(aTranslate, x);
_gl_.uniformMatrix4fv(_mat_, false, matrix);
_gl_.drawArrays(_gl_._TRIANGLES_, 0 , 3);
requestAnimationFrame(animation);
}
animation();
</script>
9、图形旋转——旋转矩阵
绕 z 轴旋转矩阵
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="../lib/index.js"></script>
<style>
* {
margin: 0;
padding: 0;
}
canvas{
margin: 50px auto 0;
display: block;
background: yellow;
}
</style>
</head>
<body>
<canvas id="canvas" width="400" height="400">
此浏览器不支持carvas
</canvas>
</body>
</html>
<script>
const _ctx _= _document_.getElementById("canvas")
const _gl _= _ctx_.getContext("webgl")
//着色器
//创建着色器源码
const _VERTEX_SHADER_SOURCE _= `
attribute vec4 aPosition; //默认为vec4(1.0,0.0,0.0,1.0)
uniform mat4 mat;
void main() {
gl_Position = mat * aPosition;
gl_PointSize = 10.0;
}
`;//顶点着色器
const _FRAGMENT_SHADER_SOURCE _= `
void main(){
gl_FragColor = vec4(1.0,0.0,0.0,1.0);
}
`;//片元着色器
const _program _= initShader(_gl_, _VERTEX_SHADER_SOURCE_, _FRAGMENT_SHADER_SOURCE_);
const _aPosition _= _gl_.getAttribLocation(_program_, "aPosition");
const _mat _= _gl_.getUniformLocation(_program_, "mat");
function getRotateMatrix(deg) {
return new _Float32Array_([
_Math_.cos(deg), _Math_.sin(deg), 0.0, 0.0,
-_Math_.sin(deg), _Math_.cos(deg), 0.0, 0.0,
0.0, 0.0, 1.0, 0.0,
0.0, 0.0, 0.0, 1.0,
])
}
const _points _= new _Float32Array_([
-0.5, -0.5,
0.5, -0.5,
0.5, 0.5,
]);
const _buffer _= _gl_.createBuffer();
_gl_.bindBuffer(_gl_._ARRAY_BUFFER_, _buffer_);
_gl_.bufferData(_gl_._ARRAY_BUFFER_, _points_, _gl_._STATIC_DRAW_);
//多缓冲区绑定数据
const _BYTES _= _points_.BYTES_PER_ELEMENT;
_gl_.vertexAttribPointer(_aPosition_, 2, _gl_._FLOAT_, false, 0, 0);
_gl_.enableVertexAttribArray(_aPosition_);
let _x _= 0;
function animation() {
_x _+= 0.1;
const matrix = getRotateMatrix(_x_);
_gl_.uniformMatrix4fv(_mat_, false, matrix);
_gl_.drawArrays(_gl_._TRIANGLES_, 0 , 3);
requestAnimationFrame(animation);
}
animation();
</script>
10、图形复合变换
因为矩阵是列主序的,所以是列 × 行
getTranslateMatrix、getScaleMatrix、getRotateMatrix 已写入到 lib/index.js 文件中
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="../lib/index.js"></script>
<style>
* {
margin: 0;
padding: 0;
}
canvas{
margin: 50px auto 0;
display: block;
background: yellow;
}
</style>
</head>
<body>
<canvas id="canvas" width="400" height="400">
此浏览器不支持carvas
</canvas>
</body>
</html>
<script>
const _ctx _= _document_.getElementById("canvas")
const _gl _= _ctx_.getContext("webgl")
//着色器
//创建着色器源码
const _VERTEX_SHADER_SOURCE _= `
attribute vec4 aPosition; //默认为vec4(1.0,0.0,0.0,1.0)
uniform mat4 mat;
void main() {
gl_Position = mat * aPosition;
gl_PointSize = 10.0;
}
`;//顶点着色器
const _FRAGMENT_SHADER_SOURCE _= `
void main(){
gl_FragColor = vec4(1.0,0.0,0.0,1.0);
}
`;//片元着色器
const _program _= initShader(_gl_, _VERTEX_SHADER_SOURCE_, _FRAGMENT_SHADER_SOURCE_);
const _aPosition _= _gl_.getAttribLocation(_program_, "aPosition");
const _mat _= _gl_.getUniformLocation(_program_, "mat");
const _points _= new _Float32Array_([
-0.5, -0.5,
0.5, -0.5,
0.5, 0.5,
]);
const _buffer _= _gl_.createBuffer();
_gl_.bindBuffer(_gl_._ARRAY_BUFFER_, _buffer_);
_gl_.bufferData(_gl_._ARRAY_BUFFER_, _points_, _gl_._STATIC_DRAW_);
//多缓冲区绑定数据
const _BYTES _= _points_.BYTES_PER_ELEMENT;
_gl_.vertexAttribPointer(_aPosition_, 2, _gl_._FLOAT_, false, 0, 0);
_gl_.enableVertexAttribArray(_aPosition_);
let _translateX _= -1;
let _scaleX _= 0.1;
let _deg _= 0;
function animation() {
_translateX _+= 0.01;
_scaleX _+= 0.01;
_deg _+= 0.01;
if(_translateX _> 1) _translateX _= -1;
if(_scaleX _> 1.5) _scaleX _= 0.1;
const translateMatrix = getTranslateMatrix(_translateX_);
const scaleMatrix = getScaleMatrix(_scaleX_);
const rotateMatrix = getRotateMatrix(_deg_);
const matrix = getMixMatrix(getMixMatrix(translateMatrix, scaleMatrix), rotateMatrix);
_gl_.uniformMatrix4fv(_mat_, false, matrix);
_gl_.drawArrays(_gl_._TRIANGLES_, 0 , 3);
requestAnimationFrame(animation);
}
animation();
</script>
4.8
1、使用 varying 变量——绘制彩色三角形
2、webgl 渲染流程
2.1 图元装配过程
2.2 光栅化
3、给图形添加背景图
4.9
1、OpenGL 语言基础
2、矢量和举证
3、纹理取样器
4、内置函数的介绍
5、存储限定词
5.1 const
- 声明一个常量,定义之后不能被改变
5.2 attribute
- 只能出现在顶点着色器中,只能声明为全局变量,表示逐顶点信息。单个顶点的信息。
5.3 uniform
- 只读类型,强调一致性
- 可同时出现在顶点着色器和片元着色器中
- 用来存储的是影响所有顶点的数据。如变换矩阵。
5.4 varying
- 从顶点着色器向片元着色器传递数据
5.5 精度限定