WebGL着色器使用

WebGL着色器使用

1.编译 2.链接 3.使用 4.绘图

第 ① 步:编译着色器

1.1着色器源码:

let vShader_source = `

    attribute vec4 aPosition;

     uniform mat4 uModelViewMatrix;
     uniform mat4 uProjectionMatrix;

     attribute float size; //每个顶点的大小
     void main(){
         // gl_Position =  uModelViewMatrix * aPosition;
         gl_Position = uProjectionMatrix * uModelViewMatrix * aPosition;
         gl_PointSize = size;

     }`;

let fShader_source = `

     precision mediump float;
     uniform bool uBoolFrame;
     uniform vec4 vColor;
     void main(){
         if(uBoolFrame){
             gl_FragColor = vec4(1.0,0.0,0.0,1.0);
         }
         else{
             gl_FragColor = vColor;
         }
         
     }`;

1.2编译着色器:

 //------>>>第1步:编译着色器
 //顶点着色器
  let vShader = gl.createShader(gl.VERTEX_SHADER);
  gl.shaderSource(vShader, vShader_source);
  gl.compileShader(vShader);

  if (!gl.getShaderParameter(vShader, gl.COMPILE_STATUS)) {
      console.error('----->>>vShader 编译错误:', gl.getShaderInfoLog(vShader));
  }



  //片元着色器
  let fShader = gl.createShader(gl.FRAGMENT_SHADER);
  gl.shaderSource(fShader, fShader_source);
  gl.compileShader(fShader);

  if (!gl.getShaderParameter(fShader, gl.COMPILE_STATUS)) {
      console.error('----->>>fShader 编译错误:', gl.getShaderInfoLog(fShader));
  }

第 ② 步:链接着色器程序

//------>>>第2步:链接着色器程序
 const shaderProgram = gl.createProgram();
  gl.attachShader(shaderProgram, vShader);
  gl.attachShader(shaderProgram, fShader);
  gl.linkProgram(shaderProgram);

  if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) {
      console.error('------>>>着色器链接失败: ' + gl.getProgramInfoLog(program));
  }

第 ③ 步:使用着色器程序

 //------>>>第3步:使用着色器程序
  gl.useProgram(shaderProgram);

第 ④ 步:绘图

  gl.drawElements(gl.TRIANGLES, 36, gl.UNSIGNED_SHORT, 0);

附:使用着色器的简单案例

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

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>WebGL</title>
    <style>
        table {
            position: absolute;
            right: 0;
        }
    </style>
    <!-- <script src="./gl-matrix.js"></script> -->
    <script src="./gl-matrix-min.js"></script>  //从http://glmatrix.net/获取 v2.6.1
</head>

<body>

    <table>
        <tr>
            <th>
                : <input id='long' onchange="change()" type="number" value="100">
            </th>
        </tr>
        <tr>
            <th>
                : <input id='width' onchange="change()" type="number" value="100">
            </th>
        </tr>
        <tr>
            <th>
                : <input id='height' onchange="change()" type="number" value="100">
            </th>
        </tr>
    </table>



    <canvas id="canvas" width="400" height="400"> </canvas>

    <script>

        let vShader_source = `

            attribute vec4 aPosition;

            uniform mat4 uModelViewMatrix;
            uniform mat4 uProjectionMatrix;

            attribute float size; //每个顶点的大小
            void main(){
                // gl_Position =  uModelViewMatrix * aPosition;
                gl_Position = uProjectionMatrix * uModelViewMatrix * aPosition;
                gl_PointSize = size;

            }`;

        let fShader_source = `

            precision mediump float;
            uniform bool uBoolFrame;
            uniform vec4 vColor;
            void main(){
                if(uBoolFrame){
                    gl_FragColor = vec4(1.0,0.0,0.0,1.0);
                }
                else{
                    gl_FragColor = vColor;
                }
                
            }`;


        const modelViewMatrix = mat4.create();

        window.onload = function main() {

            let canvas = document.getElementById('canvas');
            let gl = canvas.getContext('webgl');

            gl.clearColor(0.5, 1.0, 0.5, 1.0);
            gl.clear(gl.COLOR_BUFFER_BIT);


            //------>>>第1步:编译着色器
            //顶点着色器
            let vShader = gl.createShader(gl.VERTEX_SHADER);
            gl.shaderSource(vShader, vShader_source);
            gl.compileShader(vShader);

            if (!gl.getShaderParameter(vShader, gl.COMPILE_STATUS)) {
                console.error('----->>>vShader 编译错误:', gl.getShaderInfoLog(vShader));
            }



            //片元着色器
            let fShader = gl.createShader(gl.FRAGMENT_SHADER);
            gl.shaderSource(fShader, fShader_source);
            gl.compileShader(fShader);

            if (!gl.getShaderParameter(fShader, gl.COMPILE_STATUS)) {
                console.error('----->>>fShader 编译错误:', gl.getShaderInfoLog(fShader));
            }



            //------>>>第2步:链接着色器程序
            const shaderProgram = gl.createProgram();
            gl.attachShader(shaderProgram, vShader);
            gl.attachShader(shaderProgram, fShader);
            gl.linkProgram(shaderProgram);

            if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) {
                console.error('------>>>着色器链接失败: ' + gl.getProgramInfoLog(program));
            }


            //------>>>第3步:使用着色器程序
            gl.useProgram(shaderProgram);



            //修改size
            gl.vertexAttrib1f(gl.getAttribLocation(shaderProgram, 'size'), 10.0);


            //使用顶点缓冲区上传顶点数据
            //1.创建
            let vertexBuffer = gl.createBuffer();
            //2.绑定
            gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
            //3.写入数据
            let vertices = new Float32Array([
                // 前
                -1.0, -1.0, 1.0,
                1.0, -1.0, 1.0,
                1.0, 1.0, 1.0,
                -1.0, 1.0, 1.0,

                // 后
                -1.0, -1.0, -1.0,
                -1.0, 1.0, -1.0,
                1.0, 1.0, -1.0,
                1.0, -1.0, -1.0,

                // 上
                -1.0, 1.0, -1.0,
                -1.0, 1.0, 1.0,
                1.0, 1.0, 1.0,
                1.0, 1.0, -1.0,

                // 下
                -1.0, -1.0, -1.0,
                1.0, -1.0, -1.0,
                1.0, -1.0, 1.0,
                -1.0, -1.0, 1.0,

                // 右
                1.0, -1.0, -1.0,
                1.0, 1.0, -1.0,
                1.0, 1.0, 1.0,
                1.0, -1.0, 1.0,

                // 左
                -1.0, -1.0, -1.0,
                -1.0, -1.0, 1.0,
                -1.0, 1.0, 1.0,
                -1.0, 1.0, -1.0,
            ]);
            gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);
            //4.分配给变量
            let aPosition_Location = gl.getAttribLocation(shaderProgram, 'aPosition');
            gl.vertexAttribPointer(aPosition_Location, 3, gl.FLOAT, false, 0, 0);
            //5.开启变量
            gl.enableVertexAttribArray(aPosition_Location);




            const indexBuffer = gl.createBuffer();
            gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);

            const indices = new Uint16Array([
                0, 1, 2, 0, 2, 3,    // 前
                4, 5, 6, 4, 6, 7,    // 后
                8, 9, 10, 8, 10, 11,   // 上
                12, 13, 14, 12, 14, 15,   // 下
                16, 17, 18, 16, 18, 19,   // 右
                20, 21, 22, 20, 22, 23,   // 左
            ]);

            gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, indices, gl.STATIC_DRAW);




            mat4.translate(modelViewMatrix, modelViewMatrix, [0.0, 0.0, -8.0]);
            gl.uniformMatrix4fv(gl.getUniformLocation(shaderProgram, 'uModelViewMatrix'), false, modelViewMatrix); //第三个参数指是否转置矩阵,必须为false

            const projectionMatrix = mat4.create();
            mat4.perspective(projectionMatrix, 45 * Math.PI / 180, 1, 0.001, 100.0);
            gl.uniformMatrix4fv(gl.getUniformLocation(shaderProgram, 'uProjectionMatrix'), false, projectionMatrix);




            //------>>>第4步:绘图
            const uModelViewMatrix_Location = gl.getUniformLocation(shaderProgram, 'uModelViewMatrix');
            const uBoolFrame_Location = gl.getUniformLocation(shaderProgram, 'uBoolFrame');



            function render() {
                requestAnimationFrame(render);

                gl.clearDepth(1.0);
                gl.enable(gl.DEPTH_TEST);
                gl.depthFunc(gl.LEQUAL);
                gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);


                mat4.rotate(modelViewMatrix, modelViewMatrix, Math.PI / 200, [0, 1, 0]);
                mat4.rotate(modelViewMatrix, modelViewMatrix, Math.PI / 300, [1, 0, 0]);
                mat4.rotate(modelViewMatrix, modelViewMatrix, Math.PI / 400, [0, 0, 1]);
                gl.uniformMatrix4fv(uModelViewMatrix_Location, false, modelViewMatrix);

                gl.drawElements(gl.TRIANGLES, 36, gl.UNSIGNED_SHORT, 0);

                //绘制线框
                gl.uniform1i(uBoolFrame_Location, 1);
                gl.drawElements(gl.LINE_LOOP, 36, gl.UNSIGNED_SHORT, 0);
                gl.uniform1i(uBoolFrame_Location, 0);


            }
            render();



            // 两秒变色
            let vColor_Location = gl.getUniformLocation(shaderProgram, 'vColor');
            // setInterval(() => {
            //     gl.uniform4f(vColor_Location, Math.random(), Math.random(), Math.random(), 1.0);
            // }, 2000);

            let i = 0;
            setInterval(() => {
                i++;
                if (i >= 200) {
                    i = 0;
                }
                gl.uniform4f(vColor_Location, 1 - i/200, 0.0, i/200, 1.0);
            }, 10);




        }



        //修改长、宽、高
        const initModelViewMatrix = mat4.create();
        mat4.translate(initModelViewMatrix, initModelViewMatrix, [0.0, 0.0, -8.0]);
        function change() {

            let long = document.getElementById('long').value;
            let width = document.getElementById('width').value;
            let height = document.getElementById('height').value;


            mat4.scale(modelViewMatrix, initModelViewMatrix, [long / 100, width / 100, height / 100]);

            console.log(`长:${long},宽:${width},高:${height}`);

        }



    </script>
</body>

</html>
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值