阅读 245

webgl学习笔记

缓冲区类型 1、顶点缓冲区(ARRAY_BUFFER) 2、索引缓冲区(ELEMENT_ARRAY_BUFFER) 3、纹理 4、帧缓冲(可能包含深度缓冲区) 5、深度缓冲区 6、颜色缓冲区 7、模板缓冲区

矩阵 1、模型矩阵 2、观察矩阵 3、投影矩阵 4、视口

opengl 纯可编程式管线技术 创建main 往main插入代码 然后 编译代码 创建进程 把编译好的main放入进程 链接进程 使用进程

创建一个缓冲区

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body onload="initLoad()">
    <canvas id="myCanvas"></canvas>
</body>
<script id="vertexShader" type="x-shader/x_vertex">
    attribute vec3 v3Position;
    void main(void)
    {
        gl_Position = vec4(v3Position,1.0);
    }
</script>
<script id="fragmentShader" type="x-shader/x_fragment">
    void main(void)
    {
        gl_FragColor = vec4(0.0,1.0,1.0,1.0);
    }
</script>

<script>
    var VSHADER_SOURCE =
        "attribute vec4 v3Position;" +
        "void main() {" +
        //设置坐标
        "gl_Position = v3Position; " +
        "} ";
    var FSHADER_SOURCE =
        "void main() {" +
        //设置颜色
        "gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);" +
        "}";
    var webgl
    var programObject
    function initLoad() {
        var v3PositionIndex = 0;

        var canvas = document.getElementById('myCanvas');
        webgl = canvas.getContext('webgl');
        webgl.viewport(0, 0, canvas.clientWidth, canvas.clientHeight);
        // 向显卡传递要执行的代码
        // 初始化类似创建了一个main
        // 创建顶点着色器对象
        var vertexShaderObject = webgl.createShader(webgl.VERTEX_SHADER);
        // 创建片元着色器对象
        var fragmentShaderObject = webgl.createShader(webgl.FRAGMENT_SHADER);
        // 像main函数里插入代码
        webgl.shaderSource(vertexShaderObject, VSHADER_SOURCE)
        webgl.shaderSource(fragmentShaderObject, FSHADER_SOURCE)
        // 编译代码
        webgl.compileShader(vertexShaderObject);
        webgl.compileShader(fragmentShaderObject);
        if (!webgl.getShaderParameter(vertexShaderObject, webgl.COMPILE_STATUS)) {
            // 获取vertexShaderObject的编译状态
            alert("error:vertexShaderObject");
        }
        if (!webgl.getShaderParameter(fragmentShaderObject, webgl.COMPILE_STATUS)) {
            // 获取fragmentShaderObject的编译状态
            alert("error:fragmentShaderObject");
        }
        // 创建一个进程类似exe
        programObject = webgl.createProgram();
        // 向进程里传入编译好的程序
        webgl.attachShader(programObject, vertexShaderObject);
        webgl.attachShader(programObject, fragmentShaderObject);
        // 输入值
        webgl.bindAttribLocation(programObject, v3PositionIndex, "v3Position");
        // 链接生成一个真正的可执行程序
        webgl.linkProgram(programObject)
        if (!webgl.getProgramParameter(programObject, webgl.LINK_STATUS)) {
            // 获取fragmentShaderObject的编译状态
            alert("error:programObject");
        }
        console.log(webgl.getAttribLocation(programObject, 'v3Position'))
        // glsl
        // 使用这个可执行程序
        webgl.useProgram(programObject);
        // 坐标
        var jsArrayData = [
            0.0, 1.0, 0.0,
            -1.0, -1.0, 0.0,
            1.0, -1.0, 0.0
        ]
        var triangleBuffer = webgl.createBuffer(); // 创建一个缓冲区
        // 绑定
        webgl.bindBuffer(webgl.ARRAY_BUFFER, triangleBuffer);
        // 给缓冲区绑定值和类型 第三个参数标识静态类型 
        webgl.bufferData(webgl.ARRAY_BUFFER, new Float32Array(jsArrayData), webgl.STATIC_DRAW); // 如果经常要变化的话使用 DYNAMIC_DRAW
        // 偶尔变STREAM_DRAW 顶点缓冲区的三种类型
        // webgl.bindBuffer(webgl.ARRAY_BUFFER, triangleBuffer);
        //将缓冲区对象分配给v3PositionIndex变量
        webgl.vertexAttribPointer(v3PositionIndex, 3, webgl.FLOAT, false, 0, 0);
        //连接v3PositionIndex变量与分配给它的缓冲区对象
        webgl.enableVertexAttribArray(v3PositionIndex);
        // 清除指定<画布>的颜色
        webgl.clearColor(0.0, 0.0, 0.0, 1.0);

        // 清空 <canvas>
        webgl.clear(webgl.COLOR_BUFFER_BIT);



        // 要赋值的名称    类型就是几维度 变量的类型 是否规格化
        webgl.drawArrays(webgl.TRIANGLES, 0, 3);
    }


</script>

</html>


</script>

</html>

</script>

</html>
复制代码
顶点缓冲区
webgl.bufferData(webgl.ARRAY_BUFFER, new Float32Array(jsArrayData), webgl.STATIC_DRAW);
webgl.bufferData(webgl.ARRAY_BUFFER,4 * 9, webgl.STATIC_DRAW); // 字节
// 更新部分缓冲区 
webgl.bufferSubData(webgl.ARRAY_BUFFER,2,new Float32Array([]))
// 修改从第二个字节开始修改成后面的内容

复制代码
索引缓冲区

假如要绘制一个矩形的话 可以通过两个三角形拼接起来

	var v3PositionIndex = 0;
   var VSHADER_SOURCE =
        "attribute vec3 v3Position;" +
        "void main() {" +
        //设置坐标
        "gl_Position = vec4(v3Position,1.0); " +
        "} ";
    var FSHADER_SOURCE =
        "void main() {" +
        //设置颜色
        "gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);" +
        "}";
let webgl = null;
let programObject  = null;
var canvas = document.getElementById('myCanvas');
webgl = canvas.getContext('webgl');
webgl.viewport(0, 0, canvas.clientWidth, canvas.clientHeight);
var vertexShaderObject = webgl.createShader(webgl.VERTEX_SHADER);
var fragmentShaderObject = webgl.createShader(webgl.FRAGMENT_SHADER);
webgl.shaderSource(vertexShaderObject, VSHADER_SOURCE)
webgl.shaderSource(fragmentShaderObject, FSHADER_SOURCE)
webgl.compileShader(vertexShaderObject);
webgl.compileShader(fragmentShaderObject);
programObject = webgl.createProgram();
webgl.attachShader(programObject, vertexShaderObject);
webgl.attachShader(programObject, fragmentShaderObject);
webgl.linkProgram(programObject);
webgl.useProgram(programObject);
webgl.bindAttribLocation(programObject, v3PositionIndex, "v3Position");
var triangleBuffer = webgl.createBuffer();
var jsArrayData2 = [
	  -0.5, 0.5, 0.0,
      0.5, 0.5, 0.0,
      0.5, -0.5, 0.0,
       -0.5, 0.5, 0.0,
       0.5, -0.5, 0.0,
      -0.5, -0.5, 0.0
]
webgl.bindBuffer(webgl.ARRAY_BUFFER, triangleBuffer);
webgl.bufferData(webgl.ARRAY_BUFFER, new Float32Array(jsArrayData2), webgl.STATIC_DRAW);
webgl.vertexAttribPointer(v3PositionIndex, 3, webgl.FLOAT, false, 0, 0);
webgl.enableVertexAttribArray(v3PositionIndex);
webgl.clearColor(0.0, 0.0, 0.0, 1.0);
webgl.clear(webgl.COLOR_BUFFER_BIT);
webgl.drawArrays(webgl.TRIANGLES, 0, 6);
复制代码

在这里插入图片描述 然后矩形就画好了 但是 下面的那个用来绘图的float数组一个是4个字节 所有画矩形时需要向显卡传输4*3*6字节的内容(72字节)可以发现有些坐标是重复的 可以少写两个点可以节省4*3*2个字节(24字节)可以用到索引缓冲区

var jsArrayData2 = [
	  -0.5, 0.5, 0.0,
      0.5, 0.5, 0.0,
      0.5, -0.5, 0.0,
       -0.5, 0.5, 0.0,
       0.5, -0.5, 0.0,
      -0.5, -0.5, 0.0
]
复制代码

用法 在这里插入图片描述 可以看出这个矩形是由两个三角形012和023构成的

var v3PositionIndex = 0;
   var VSHADER_SOURCE =
        "attribute vec3 v3Position;" +
        "void main() {" +
        //设置坐标
        "gl_Position = vec4(v3Position,1.0); " +
        "} ";
    var FSHADER_SOURCE =
        "void main() {" +
        //设置颜色
        "gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);" +
        "}";
let webgl = null;
let programObject  = null;
var canvas = document.getElementById('myCanvas');
webgl = canvas.getContext('webgl');
webgl.viewport(0, 0, canvas.clientWidth, canvas.clientHeight);
var vertexShaderObject = webgl.createShader(webgl.VERTEX_SHADER);
var fragmentShaderObject = webgl.createShader(webgl.FRAGMENT_SHADER);
webgl.shaderSource(vertexShaderObject, VSHADER_SOURCE)
webgl.shaderSource(fragmentShaderObject, FSHADER_SOURCE)
webgl.compileShader(vertexShaderObject);
webgl.compileShader(fragmentShaderObject);
programObject = webgl.createProgram();
webgl.attachShader(programObject, vertexShaderObject);
webgl.attachShader(programObject, fragmentShaderObject);
webgl.linkProgram(programObject);
webgl.useProgram(programObject);
webgl.bindAttribLocation(programObject, v3PositionIndex, "v3Position");

// 修改的内容------
// 这里是矩形的四个点
var jsArrayData2 = [
	  -0.5, 0.5, 0.0,
      0.5, 0.5, 0.0,
      0.5, -0.5, 0.0,
      -0.5, -0.5, 0.0
]
// 索引数组
var indexArray = [
	  0,1,2,
	  0,2,3
]
// ------
var triangleBuffer = webgl.createBuffer();
// 创建一个索引缓冲区
var indexBuffer = webgl.createBuffer();
webgl.bindBuffer(webgl.ARRAY_BUFFER, triangleBuffer);
webgl.bufferData(webgl.ARRAY_BUFFER, new Float32Array(jsArrayData2), webgl.STATIC_DRAW);
// 操作索引缓冲区
// 把当前操作的缓冲区换成indexBuffer
webgl.bindBuffer(webgl.ELEMENT_ARRAY_BUFFER, indexBuffer);
// 赋值 注意这里只能使用无符号的短整型
webgl.bufferData(webgl.ELEMENT_ARRAY_BUFFER, new Uint16Array(indexArray), webgl.STATIC_DRAW);
webgl.vertexAttribPointer(v3PositionIndex, 3, webgl.FLOAT, false, 0, 0);
webgl.enableVertexAttribArray(v3PositionIndex);
webgl.clearColor(0.0, 0.0, 0.0, 1.0);
webgl.clear(webgl.COLOR_BUFFER_BIT);
// 这里调用绘画的方法就要变了
// webgl.drawArrays(webgl.TRIANGLES, 0, 6);
// 第一个参数绘画的类型 ,第二个参数要话几个点 几个索引就一般就几个点 第三个索引值的类型 ,第四个参数是偏移值offset 从几个索引开始绘制
webgl.drawElements(webgl.TRIANGLES, 6, webgl.UNSIGNED_SHORT, 0)
复制代码

运行效果和上面一样 在这里插入图片描述 渐变的矩形

var v3PositionIndex = 0;
var inColor = 1;
var VSHADER_SOURCE =
   "precision lowp float;" +
   "attribute vec3 v3Position;" +
   "attribute vec4 inColor;" +
   "varying vec4 outColor;" +
   "void main() {" +
   //设置坐标
   "outColor= inColor;" +
   "gl_Position = vec4(v3Position,1.0); " +
   "} ";
var FSHADER_SOURCE =
   "precision lowp float;" +
   "varying vec4 outColor;" +
   "void main() {" +
   //设置颜色
   "gl_FragColor = outColor;" +
   "}";
let webgl = null;
let programObject  = null;
var canvas = document.getElementById('myCanvas');
webgl = canvas.getContext('webgl');
webgl.viewport(0, 0, canvas.clientWidth, canvas.clientHeight);
var vertexShaderObject = webgl.createShader(webgl.VERTEX_SHADER);
var fragmentShaderObject = webgl.createShader(webgl.FRAGMENT_SHADER);
webgl.shaderSource(vertexShaderObject, VSHADER_SOURCE)
webgl.shaderSource(fragmentShaderObject, FSHADER_SOURCE)
webgl.compileShader(vertexShaderObject);
webgl.compileShader(fragmentShaderObject);
programObject = webgl.createProgram();
webgl.attachShader(programObject, vertexShaderObject);
webgl.attachShader(programObject, fragmentShaderObject);
webgl.linkProgram(programObject);
webgl.useProgram(programObject);
webgl.bindAttribLocation(programObject, v3PositionIndex, "v3Position");

// 修改的内容------
// 这里是矩形的四个点
   var jsArrayData2 = [
            // x,y,z,r,g,b,a
            -0.5, 0.5, 0.0, 1.0, 0.0, 0.0, 1.0,
            0.5, 0.5, 0.0, 1.0, 1.0, 0.0, 1.0,
            0.5, -0.5, 0.0, 1.0, 0.0, 1.0, 1.0,
            -0.5, -0.5, 0.0, 1.0, 0.0, 1.0, 1.0,
        ]
// 索引数组
var indexArray = [
	  0,1,2,
	  0,2,3
]
// ------
var triangleBuffer = webgl.createBuffer();
// 创建一个索引缓冲区
var indexBuffer = webgl.createBuffer();
webgl.bindBuffer(webgl.ARRAY_BUFFER, triangleBuffer);
webgl.bufferData(webgl.ARRAY_BUFFER, new Float32Array(jsArrayData2), webgl.STATIC_DRAW);
// 操作索引缓冲区
// 把当前操作的缓冲区换成indexBuffer
webgl.bindBuffer(webgl.ELEMENT_ARRAY_BUFFER, indexBuffer);
// 赋值 注意这里只能使用无符号的短整型
webgl.bufferData(webgl.ELEMENT_ARRAY_BUFFER, new Uint16Array(indexArray), webgl.STATIC_DRAW);
webgl.vertexAttribPointer(v3PositionIndex, 3, webgl.FLOAT, false, 4 * 7, 0);
webgl.vertexAttribPointer(inColor, 4, webgl.FLOAT, false, 4 * 7, 3 * 4);
webgl.enableVertexAttribArray(v3PositionIndex);
webgl.enableVertexAttribArray(inColor);
webgl.clearColor(0.0, 0.0, 0.0, 1.0);
webgl.clear(webgl.COLOR_BUFFER_BIT);
// 这里调用绘画的方法就要变了
// webgl.drawArrays(webgl.TRIANGLES, 0, 6);
// 第一个参数绘画的类型 ,第二个参数要话几个点 几个索引就一般就几个点 第三个索引值的类型 ,第四个参数是偏移值offset 从几个索引开始绘制
webgl.drawElements(webgl.TRIANGLES, 6, webgl.UNSIGNED_SHORT, 0)
复制代码

在这里插入图片描述

查看顶点着色器对象和片元着色器对象编译后的错误信息

     var canvas = document.getElementById('myCanvas');
        webgl = canvas.getContext('webgl');
 if (!webgl.getShaderParameter(vertexShaderObject, webgl.COMPILE_STATUS)) {
            // 获取vertexShaderObject的编译状态
            var err = webgl.getShaderInfoLog(vertexShaderObject)
            console.log(err)
            alert("error:vertexShaderObject");
        }
        if (!webgl.getShaderParameter(fragmentShaderObject, webgl.COMPILE_STATUS)) {
            // 获取fragmentShaderObject的编译状态
            var err = webgl.getShaderInfoLog(fragmentShaderObject)
            console.log(err)
            alert("error:fragmentShaderObject");
        }
复制代码
文章分类
前端
文章标签