WebGL入门课程04-颜色与纹理

[TOC]

十三、WebGL颜色与纹理

关键:创建多个缓冲区对象

<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>将非顶点信息传入顶点</title>
    <style>
        #web12 {
            width: 750px;
            height: 500px;
        }
    </style>
    <script src="matrix.js"></script>
    <script src="lib.js"></script>
</head>
<body>
<canvas id="web12"></canvas>
<script>
    let canvas = document.querySelector("#web12");
    let gl = canvas.getContext('webgl');
    let VERTEX_SHADER = '' +
        'attribute vec4 a_pos;' +
        'attribute float a_size;' +
        'void main(){' +
        'gl_Position=a_pos;' +
        'gl_PointSize=a_size;' +
        '}';
    let FRAG_SHADER = '' +
        'void main(){' +
        'gl_FragColor=vec4(1.0,0.5,0.0,1.0);' +
        '}';
    let program = initShader(gl, VERTEX_SHADER, FRAG_SHADER);
    let dataVertices = new Float32Array([
        -0.3, 0.0,
        0.0, 0.3,
        0.3, 0.0
    ]);
    bufferInit(gl, dataVertices, "a_pos", program);
    let dataSize = new Float32Array([
        10.0, 20.0, 30.0
    ]);
    let bufferSize = gl.createBuffer();
    gl.bindBuffer(gl.ARRAY_BUFFER, bufferSize);
    gl.bufferData(gl.ARRAY_BUFFER, dataSize, gl.STATIC_DRAW);

    let a_size = gl.getAttribLocation(program, 'a_size');
    gl.vertexAttribPointer(a_size, 1, gl.FLOAT, false, 0, 0);
    gl.enableVertexAttribArray(a_size);

    gl.drawArrays(gl.POINTS, 0, 3);

</script>
</body>
</html>

十四、vertexAttriPointer()的步进和偏移参数

可以将顶点的坐标和大小数据按照某种方式交错组织:

1582539933174

十五、varying变量、绘制彩色三角形

varying变量的作用是从顶点着色器向片元着色器中传递数据。

怎么传?

顶点着色器与片元着色器中有类型和命名都相同的varying变量,顶点着色器赋给变量的值就会被自动传入片元着色器

顶点着色器:varying vec4 v_color;

片元着色器:varying vec4 v_color;

<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>将非顶点信息传入顶点</title>
    <style>
        #web12 {
            width: 750px;
            height: 500px;
        }
    </style>
    <script src="matrix.js"></script>
    <script src="lib.js"></script>
</head>
<body>
<canvas id="web12"></canvas>
<script>
    let canvas = document.querySelector("#web12");
    let gl = canvas.getContext('webgl');
    let VERTEX_SHADER = '' +
        'attribute vec4 a_pos;' +
        'attribute vec4 a_color;' +
        'varying vec4 v_color;' +
        'void main(){' +
        'gl_Position=a_pos;' +
        'v_color=a_color;' +
        'gl_PointSize=20.0;' +
        '}';
    let FRAG_SHADER = '' +
        'precision lowp float;' +
        'varying vec4 v_color;' +
        'void main(){' +
        'gl_FragColor=v_color;' +
        '}';
    let program = initShader(gl, VERTEX_SHADER, FRAG_SHADER);
    let dataVertices = new Float32Array([
        -0.3, -0.4, 1.0, 0.0, 0.0,
        0.0, 0.3, 0.0, 1.0, 0.0,
        0.3, -0.4, 0.0, 0.0, 1.0,
    ]);
    let buffer = gl.createBuffer();
    gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
    gl.bufferData(gl.ARRAY_BUFFER, dataVertices, gl.STATIC_DRAW);

    let a_pos = gl.getAttribLocation(program, "a_pos");
    let a_color = gl.getAttribLocation(program, "a_color");

    let FSIZE = dataVertices.BYTES_PER_ELEMENT;
    gl.vertexAttribPointer(a_pos, 2, gl.FLOAT, false, FSIZE * 5, 0);
    gl.vertexAttribPointer(a_color, 3, gl.FLOAT, false, FSIZE * 5, FSIZE * 2);

    gl.enableVertexAttribArray(a_pos);
    gl.enableVertexAttribArray(a_color);

    gl.drawArrays(gl.TRIANGLES, 0, 3);

</script>
</body>
</html>

1582540656675

十六、在矩形表面上贴上图像

纹理映射就是将一张图像映射到一个几何图形的便面上去。这张被贴的图称为纹理或者纹理图像。

组成纹理图像的像素又被称为纹素

1582541397778

遵循四步:

纹理坐标在WebGL中是二维的,为了获取纹素的颜色

1582541541471

配置和加载纹理的步骤:

配置和加载纹理的关键函数:

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

<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>纹理</title>
    <style>
        #web12 {
            width: 750px;
            height: 500px;
        }
    </style>
    <script src="lib.js"></script>
</head>

<body>
<canvas id="web12"></canvas>
<script>
    //==========================第一部分==========================
    let canvas = document.querySelector("#web12");
    let gl = canvas.getContext('webgl');
    let VERTEX_SHADER = `
        attribute vec4 a_pos;
        attribute vec2 a_TexCoord;
        varying vec2 v_TexCoord;
        void main(){
            gl_Position=a_pos;
            v_TexCoord=a_TexCoord;
        }`;

    //==========================第二部分==========================
    //片元着色器
    let FRAG_SHADER = `
        precision lowp float;
        uniform sampler2D u_Sampler;
        varying vec2 v_TexCoord;
        void main(){
            gl_FragColor=texture2D(u_Sampler,v_TexCoord);
        }`;
    let program = initShader(gl, VERTEX_SHADER, FRAG_SHADER);
    //==========================第三部分==========================
    //准备顶点信息以及纹理顶点信息
    let dataVertices = 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
    ]);
    let buffer = gl.createBuffer();
    gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
    gl.bufferData(gl.ARRAY_BUFFER, dataVertices, gl.STATIC_DRAW);

    let a_pos = gl.getAttribLocation(program, "a_pos");
    let a_TexCoord = gl.getAttribLocation(program, "a_TexCoord");

    let FSIZE = dataVertices.BYTES_PER_ELEMENT;
    gl.vertexAttribPointer(a_pos, 2, gl.FLOAT, false, FSIZE * 4, 0);
    gl.vertexAttribPointer(a_TexCoord, 2, gl.FLOAT, false, FSIZE * 4, FSIZE * 2);

    gl.enableVertexAttribArray(a_pos);
    gl.enableVertexAttribArray(a_TexCoord);
    //==========================第四部分==========================
    //配置和加载纹理
    initTextures(gl);
    function initTextures(gl) {
        let texture = gl.createTexture(); //创建纹理对象
        let u_Sampler = gl.getUniformLocation(program, 'u_Sampler'); //获取位置
        let image = new Image();
        image.src = 'sky.jpg';//此处图片大小一定要为256*256,
        image.onload = function () {
            loadTexture(gl, texture, u_Sampler, image, 0);
        };
        return true;
    }

    //==========================第五部分==========================
    //为WebGL配置纹理

    function loadTexture(gl, texture, u_Sampler, image, texUnit) {
        gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, 1);//对纹理图像进行Y轴翻转
        gl.activeTexture(gl.TEXTURE0);//开启0号纹理单元
        gl.bindTexture(gl.TEXTURE_2D, texture);//向target绑定纹理对象
        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);//配置纹理参数
        gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, gl.RGB, gl.UNSIGNED_BYTE, image);//配置纹理图像
        gl.uniform1i(u_Sampler, texUnit);
        gl.clear(gl.COLOR_BUFFER_BIT);
        gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);//由于异步加载,所以写在这里
    }
</script>
</body>

</html>