webgl学习笔记五-纹理

写在前面

建议先阅读下前面我的三篇文章。

webgl学习笔记一-绘图单点

webgl学习笔记二-绘图多点

webgl学习笔记三-平移旋转缩放

术语 :

  • 纹理 :图像
  • 图形装配区域 :顶点着色器顶点坐标信息
  • 装配图形 : 片元着色器装配
  • 光栅化 :显示在屏幕上的三角形是由片元(像素)组成的,所以还需要将图形转化为片元,这个过程被称为光栅化。
  • 纹理图像:映射的这个图像称为纹理图像
  • 纹素 : 组成纹理图像的像素称为纹素
  • 纹理坐标 : 是纹理图像上的坐标,通过纹理坐标可以在纹理图像上获取纹素颜色;

纹理绘图流程

  重点介绍纹理的流程。

  • 创建纹理对象
  • 加载纹理图像
  • 配置属性

demo

  • html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

<canvas id="canvas" width="200px" height="200px"></canvas>



</body>
</html>
  • JavaScript
<script>

    window.onload = function () {

        //顶点着色器程序
        var VSHADER_SOURCE =
            "attribute vec4 a_Position;" +
            "attribute vec2 a_TextCoord;" + // 接受纹理坐标
            "varying vec2 v_TexCoord;" +    // 传递纹理坐标
            "void main() {" +
            //设置坐标
            "gl_Position = a_Position; " +  // 设置坐标
            //设置纹素
            "v_TexCoord = a_TextCoord; " +  // 设置纹理坐标
            "} ";

        //片元着色器
        var FSHADER_SOURCE =
            "precision mediump float;" +  //需要声明浮点数精度,否则报错No precision specified for (float)
            "uniform sampler2D u_Sampler;" + // 取样器
            "varying vec2 v_TexCoord;" +  // 接受纹理坐标
            "void main() {" +
            //设置颜色
            "gl_FragColor = texture2D(u_Sampler, v_TexCoord);" +  // 设置颜色
            "}";

        //获取canvas元素
        var canvas = document.getElementById('canvas');
        //获取绘制webgl绘图上下文
        var gl = canvas.getContext('webgl');
        if (!gl) {
            console.log("Failed");
            return;
        }
        //编译着色器
//        (1)创建Shader(着色器)对象
//        (2)将着色器程序附加到Shader上
//        (3)编译程序
        var vertShader = gl.createShader(gl.VERTEX_SHADER);
        gl.shaderSource(vertShader, VSHADER_SOURCE);
        gl.compileShader(vertShader);

        var fragShader = gl.createShader(gl.FRAGMENT_SHADER);
        gl.shaderSource(fragShader, FSHADER_SOURCE);
        gl.compileShader(fragShader);
        //合并程序
//        (1)创建一个程序对象
//        (2)附加着色器
//        (3)链接着色器
//        (4)使用程序
        var shaderProgram = gl.createProgram();
        gl.attachShader(shaderProgram, vertShader);
        gl.attachShader(shaderProgram, fragShader);
        gl.linkProgram(shaderProgram);
        gl.useProgram(shaderProgram);


        gl.clearColor(0.0, 0.0, 0.0, 1.0);

        var n = initBuffers(gl, shaderProgram);
        initTexture(gl, shaderProgram, n);

        gl.clear(gl.COLOR_BUFFER_BIT);

        //绘制一个点
        gl.drawArrays(gl.POINTS, 0, 1);
    }


    // 使用缓冲区对象向顶点传入多个顶点数据
    function initBuffers(gl, shaderProgram) {
        //顶点坐标和颜色
        var vertices = new Float32Array([
            -0.5, 0.5, 0.0, 1.0,
            -0.5, -0.5, 0.0, 0.0,
            0.5, 0.5, 1.0, 1.0,
            0.5, -0.5, 1.0, 0.0
        ]);
        var n = 4;//点的个数
        //创建缓冲区对象
        var vertexBuffer = gl.createBuffer();

        //将缓冲区对象绑定到目标
        gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
        //向缓冲区写入数据
        gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);

        var FSIZE = vertices.BYTES_PER_ELEMENT;

        //获取坐标点
        var a_Position = gl.getAttribLocation(shaderProgram, "a_Position");
        //将缓冲区对象分配给a_Position变量
        gl.vertexAttribPointer(a_Position, 2, gl.FLOAT, false, FSIZE * 4, 0);
        //连接a_Position变量与分配给它的缓冲区对象
        gl.enableVertexAttribArray(a_Position);

        //获取Color坐标点
        var a_TextCoord = gl.getAttribLocation(shaderProgram, "a_TextCoord");
        //将缓冲区对象分配给a_Position变量
        gl.vertexAttribPointer(a_TextCoord, 2, gl.FLOAT, false, FSIZE * 4, FSIZE * 2);
        //连接a_Position变量与分配给它的缓冲区对象
        gl.enableVertexAttribArray(a_TextCoord);
        return n;
    }

    // 初始创建纹理,创建image对象
    function initTexture(gl, shaderProgram, n) {
        //创建纹理对象
        var texture = gl.createTexture();
        //获取u_Sampler的存储位置
        var u_Sampler = gl.getUniformLocation(shaderProgram, 'u_Sampler');

        //创建image对象
        var image = new Image();

        //加载纹理
        image.onload = function () {
            loadTexture(gl, n, texture, u_Sampler, image);
        };
        // 浏览器开始加载图片 注意:一定是2^mx2^n尺寸的图片
        image.src = "../../resources/st2_256*128.png";
        return true;

    }

    // 加载纹理图像,配置属性
    function loadTexture(gl, n, texture, u_Sampler, image) {

        //1.对纹理图像进行Y轴反转
        gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, 1);
        //2.开启0号纹理单元
        gl.activeTexture(gl.TEXTURE0);
        //3.向target绑定纹理对象
        gl.bindTexture(gl.TEXTURE_2D, texture);

        //4.配置纹理参数
        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
        //5.配置纹理图像
        gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, gl.RGB, gl.UNSIGNED_BYTE, image);

        //6.将0号纹理图像传递给着色器
        gl.uniform1i(u_Sampler, 0);
        // 清空 <canvas>
        gl.clear(gl.COLOR_BUFFER_BIT);

        //绘制矩形
        gl.drawArrays(gl.TRIANGLE_STRIP, 0, n);

    }

</script>
原文地址:https://www.cnblogs.com/chenmo-xpw/p/7470376.html