WebGL学习

WebGL+three.js

4.4

1、canvas 和 webgl 的区别
1.1 画布

image-20240413162741970

1.2 Canvas API

image-20240413173052139

1.3 WebGL API

image-20240413173110928

image-20240413173129557

2、WebGL 简介
2.1 什么是 webgl

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

2.2 为什么学 webgl
  • 数据可视化
  • 图形/游戏引擎
  • 交互演示、图形渲染
  • 地图
  • VR
  • 物品展示
  • 室内设计
  • 城市规划
2.3 webgl 的优势

image-20240413173142525

2.4 webgl 开源框架

image-20240413173157165

image-20240413173219515

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>

image-20240413173500873

image-20240413173540242

3.2 通过 webgl 绘制一个点
什么是着色器

image-20240413173556231

image-20240413173601506

着色器的工作流程

image-20240413173638692

<!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>

image-20240413173704997

3.3 webgl 坐标系

image-20240413173717729

image-20240413173752281

<!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>

image-20240413173846404

3.4 学习使用 attribute 变量

image-20240413173911902

attribute变量只能在顶点着色器中使用不能在片元着色器中使用!

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

image-20240413174120305

image-20240413174210792

image-20240413174215962

<!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>

image-20240413174235897

4.5

1、通过鼠标控制绘制

image-20240413174419192

<!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变量,设置到颜色

image-20240413174540453

const _FRAGMENT_SHADER_SOURCE _= `
    void main(){
        uniform vec4 uColor;
        gl_FragColor = uColor;
    }
`;//片元着色器

image-20240413174555996

设置完发现有编译错误,片元着色器需要设置精度

const _FRAGMENT_SHADER_SOURCE _= `
    void main(){
        precision mediump float;
        uniform vec4 uColor;
        gl_FragColor = uColor;
    }
`;//片元着色器

image-20240413174622523

注意:片元着色器类型要与方法对应 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>

image-20240413174644189

4.6

1、使用缓冲区对象——绘制多个点

image-20240413174710655

image-20240413174720009

image-20240413174729263

image-20240413174743695

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 精度限定

4.11

1、3D 基础

2、正射投影

3、透视投影

…未完待续

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值