webGL 学习笔记

180 阅读22分钟

CPU 和 GPU

cpu 中央处理器 :控制单元 计算单元 存储单元

gpu 图像处理器

webgl产生背景

WebGL 是一种3D绘图标准,这种绘图技术标准 允许将js和OpenGL结合 (GLSL)

webgl的工作原理

工作方式和流水线类似,将一个绘图过程分为多个步骤,当前步骤只对前一步骤的结果进行处理,然后传递给下一个步骤,最终渲染到2d屏幕上,业界将这种渲染方式称为 图形管线 或者 渲染管线

GPU渲染管线的主要处理过程:

1.首先进入顶点着色器阶段,利用GPU的并行计算优势对顶点逐个进行坐标变换

2.进入图源装配阶段,将顶点按照图源类型组装成图形

3.接下来到光栅化阶段,光栅化阶段图形用不含颜色信息的像素填充

4.片元着色器阶段,该阶段为像素着色器,并最终显示在屏幕上

着色器:顶点着色器 、片元着色器

webgl可绘制的图元

点 线段 三角形

webgl的优点

1.只需要 编辑器 、浏览器 可完成三维图形程序

2.使用通用的web技术发布三维图形程序的显示

3.充分利用率浏览器的功能

4.资料丰富

WebGL之点的绘制

webGL 坐标系统

uniform 赋值

完整的点绘制

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>绘制点</title>
</head>
<body>
    <canvas id="canvas" width="800" height="600"></canvas>
    <script type="notjs" id="vertex" >

        attribute vec2 a_position;
        attribute vec4 a_color;
        uniform vec2 screenSize;
        varying vec4 v_color;
        void main(){
            float x = a_position.x * 2.0 / screenSize.x - 1.0;
            float y = 1.0 - ( a_position.y * 2.0 / screenSize.y);
            gl_Position = vec4(x, y, 0, 1);
            gl_PointSize = 10.0;
            v_color = a_color;
        }
    </script>
    <script type="notjs" id="fragment" >
        precision mediump float;
        varying vec4 v_color;
        void main(){
            gl_FragColor = v_color;
            
        }
    </script>
    <script>
        var canvas = document.getElementById("canvas");
        var gl = canvas.getContext("webgl");
        if(!gl){
            alert('浏览器不支持webgl')
        }
        // var  str = ''
        //创建着色器(两种着色器)
        function createShader(gl,type,source){
            var shader = gl.createShader(type);
            gl.shaderSource(shader,source);
            gl.compileShader(shader);
            var success= gl.getShaderParameter(shader,gl.COMPILE_STATUS);
            if(success){
                return shader;
            }
            console.log(gl.getShaderInfoLog(shader));
            // gl.deleteShader(shader);
        }

        var vetexStr = document.getElementById('vertex').innerText;
        var fragmentStr = document.getElementById('fragment').innerText;
        console.log(vetexStr,fragmentStr)
        //创建着色器程序
        var vertexShader = createShader(gl,gl.VERTEX_SHADER,vetexStr);
        var fragmentShader = createShader(gl,gl.FRAGMENT_SHADER,fragmentStr);

        
        function createProgram(gl,vertexShader,fragmentShader){
            //链接着色器程序
            var program = gl.createProgram();
            gl.attachShader(program,vertexShader);
            gl.attachShader(program,fragmentShader); 
            gl.linkProgram(program);

            var success= gl.getProgramParameter(program,gl.LINK_STATUS);
            if(success){
                return program;
            }
            
            console.log(success);
        }

        var program = createProgram(gl,vertexShader,fragmentShader);
        gl.useProgram(program); //使用着色器程序
        gl.clearColor(0,0,1,1);
        gl.clear(gl.COLOR_BUFFER_BIT); //清空画布
        

        var a_position = gl.getAttribLocation(program,'a_position'); //获取变量存储位置
        var screenSize = gl.getUniformLocation(program,'screenSize'); //获取变量存储位置
        var a_color = gl.getAttribLocation(program,'a_color'); //获取变量存储位置
        gl.uniform2f(screenSize,canvas.width,canvas.height);
        var points = [];
        function bindEvent(){
            
            canvas.onmousedown = function (e){
            //   gl.clearColor(0,0,1,1);
            //   gl.clear(gl.COLOR_BUFFER_BIT); //清空画布
              var x = e.offsetX;
              var y = e.offsetY;
              var color = randomColor();
              points.push({x,y,color}); //记录点击位置
              for(var i = 0;i<points.length;i++){
                gl.vertexAttrib3f(a_position,points[i].x,points[i].y,0.0); //设置变量值
                gl.vertexAttrib4f(a_color,points[i].color.r,points[i].color.g,points[i].color.b,points[i].color.a); //设置变量值
                gl.drawArrays(gl.POINTS,0,1);
              }
              //gl.drawArrays(gl.POINTS,0,1);//放在循环外只能绘制一个点
            }
        };

        function randomColor(){
            var r = Math.random();
            var g = Math.random();
            var b = Math.random();
            var a = 0.5 + Math.random()*0.5;
            return {r,g,b,a};
        }

        bindEvent()

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

WebGL之绘制三角形

缓冲区对象

创建、删除缓冲区对象

绘制三角形

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>绘制三角形</title>
</head>
<body>
    <canvas id="canvas" width="800" height="600"></canvas>
    <script type="notjs" id="vertex" >

        attribute vec2 a_position;
        attribute vec4 a_color;
        attribute float pointsize;
        uniform vec2 screenSize;
        varying vec4 v_color;
        void main(){
            float x = a_position.x * 2.0 / screenSize.x - 1.0;
            float y = 1.0 - ( a_position.y * 2.0 / screenSize.y);
            gl_Position = vec4(x, y, 0, 1);
            gl_PointSize = pointsize;
            v_color = a_color;
        }
    </script>
    <script type="notjs" id="fragment" >
        precision mediump float;
        varying vec4 v_color;
        void main(){
            gl_FragColor = v_color;
            
        }
    </script>
    <script>
        var canvas = document.getElementById("canvas");
        var gl = canvas.getContext("webgl");
        if(!gl){
            alert('浏览器不支持webgl')
        }
        // var  str = ''
        //创建着色器(两种着色器)
        function createShader(gl,type,source){
            var shader = gl.createShader(type);
            gl.shaderSource(shader,source);
            gl.compileShader(shader);
            var success= gl.getShaderParameter(shader,gl.COMPILE_STATUS);
            if(success){
                return shader;
            }
            console.log(gl.getShaderInfoLog(shader));
            // gl.deleteShader(shader);
        }

        var vetexStr = document.getElementById('vertex').innerText;
        var fragmentStr = document.getElementById('fragment').innerText;
        console.log(vetexStr,fragmentStr)
        //创建着色器程序
        var vertexShader = createShader(gl,gl.VERTEX_SHADER,vetexStr);
        var fragmentShader = createShader(gl,gl.FRAGMENT_SHADER,fragmentStr);

        
        function createProgram(gl,vertexShader,fragmentShader){
            //链接着色器程序
            var program = gl.createProgram();
            gl.attachShader(program,vertexShader);
            gl.attachShader(program,fragmentShader); 
            gl.linkProgram(program);

            var success= gl.getProgramParameter(program,gl.LINK_STATUS);
            if(success){
                return program;
            }
            
            console.log(success);
        }

        var program = createProgram(gl,vertexShader,fragmentShader);
        gl.useProgram(program); //使用着色器程序
        // gl.clearColor(0,0,1,1);
        // gl.clear(gl.COLOR_BUFFER_BIT); //清空画布
        

        var a_position = gl.getAttribLocation(program,'a_position'); //获取变量存储位置
        var pointsize = gl.getAttribLocation(program,'pointsize'); //获取变量存储位置
        var screenSize = gl.getUniformLocation(program,'screenSize'); //获取变量存储位置
        var a_color = gl.getAttribLocation(program,'a_color'); //获取变量存储位置
        gl.uniform2f(screenSize,canvas.width,canvas.height);
        gl.vertexAttrib4f(a_color,1,0,0,1);
        
        var positionBuffer = gl.createBuffer();
        gl.bindBuffer(gl.ARRAY_BUFFER,positionBuffer);

        function bindEvent(){
            var points = [];
            canvas.onmousedown = function (e){
            //   gl.clearColor(0,0,1,1);
              gl.clearColor(0,0,0,0);
              gl.clear(gl.COLOR_BUFFER_BIT); //清空画布
              var x = e.offsetX;
              var y = e.offsetY;
              var color = randomColor();
              points.push(x,y,10.0); //记录点击位置
            //   points.push({x,y,
            //     size:10.0
            //   }); //记录点击位置
              if(points.length % 3 == 0){
                gl.bufferData(gl.ARRAY_BUFFER,new Float32Array(points),gl.STATIC_DRAW);
                gl.vertexAttribPointer(a_position,2,gl.FLOAT,false,4*3,0);
                gl.vertexAttribPointer(pointsize,1,gl.FLOAT,false,4*3,2*4);
                gl.enableVertexAttribArray(a_position);
                gl.enableVertexAttribArray(pointsize);
                // gl.drawArrays(gl.POINTS,0,3);
                gl.drawArrays(gl.TRIANGLES,0, points.length/3 );
              }
              
              //gl.drawArrays(gl.POINTS,0,1);//放在循环外只能绘制一个点
            }
        };


        // var positionBuffer = gl.createBuffer();
        // gl.bindBuffer(gl.ARRAY_BUFFER,positionBuffer);
        // gl.bufferData(gl.ARRAY_BUFFER,new Float32Array([50,50,10.0,50,100,20.0,100,100,30.0]),gl.STATIC_DRAW);
        // gl.vertexAttribPointer(a_position,2,gl.FLOAT,false,4*3,0);
        // gl.vertexAttribPointer(pointsize,1,gl.FLOAT,false,4*3,2*4);
        // gl.enableVertexAttribArray(a_position);
        // gl.enableVertexAttribArray(pointsize);
        // // gl.drawArrays(gl.POINTS,0,3);
        // gl.drawArrays(gl.TRIANGLES,0,3);


        function randomColor(){
            var r = Math.random();
            var g = Math.random();
            var b = Math.random();
            var a = 0.5 + Math.random()*0.5;
            return {r,g,b,a};
        }

        bindEvent()

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

WebGL之绘制线段

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>绘制三角形</title>
</head>
<body>
    <canvas id="canvas" width="800" height="600"></canvas>
    <script type="notjs" id="vertex" >

        attribute vec2 a_position;
        attribute vec4 a_color;
        attribute float pointsize;
        uniform vec2 screenSize;
        varying vec4 v_color;
        void main(){
            float x = a_position.x * 2.0 / screenSize.x - 1.0;
            float y = 1.0 - ( a_position.y * 2.0 / screenSize.y);
            gl_Position = vec4(x, y, 0, 1);
            gl_PointSize = pointsize;
            v_color = a_color;
        }
    </script>
    <script type="notjs" id="fragment" >
        precision mediump float;
        varying vec4 v_color;
        void main(){
            gl_FragColor = v_color;
            
        }
    </script>
    <script>
        var canvas = document.getElementById("canvas");
        var gl = canvas.getContext("webgl");
        if(!gl){
            alert('浏览器不支持webgl')
        }
        // var  str = ''
        //创建着色器(两种着色器)
        function createShader(gl,type,source){
            var shader = gl.createShader(type);
            gl.shaderSource(shader,source);
            gl.compileShader(shader);
            var success= gl.getShaderParameter(shader,gl.COMPILE_STATUS);
            if(success){
                return shader;
            }
            console.log(gl.getShaderInfoLog(shader));
            // gl.deleteShader(shader);
        }

        var vetexStr = document.getElementById('vertex').innerText;
        var fragmentStr = document.getElementById('fragment').innerText;
        console.log(vetexStr,fragmentStr)
        //创建着色器程序
        var vertexShader = createShader(gl,gl.VERTEX_SHADER,vetexStr);
        var fragmentShader = createShader(gl,gl.FRAGMENT_SHADER,fragmentStr);

        
        function createProgram(gl,vertexShader,fragmentShader){
            //链接着色器程序
            var program = gl.createProgram();
            gl.attachShader(program,vertexShader);
            gl.attachShader(program,fragmentShader); 
            gl.linkProgram(program);

            var success= gl.getProgramParameter(program,gl.LINK_STATUS);
            if(success){
                return program;
            }
            
            console.log(success);
        }

        var program = createProgram(gl,vertexShader,fragmentShader);
        gl.useProgram(program); //使用着色器程序
        // gl.clearColor(0,0,1,1);
        // gl.clear(gl.COLOR_BUFFER_BIT); //清空画布
        

        var a_position = gl.getAttribLocation(program,'a_position'); //获取变量存储位置
        var pointsize = gl.getAttribLocation(program,'pointsize'); //获取变量存储位置
        var screenSize = gl.getUniformLocation(program,'screenSize'); //获取变量存储位置
        var a_color = gl.getAttribLocation(program,'a_color'); //获取变量存储位置
        gl.uniform2f(screenSize,canvas.width,canvas.height);
        gl.vertexAttrib4f(a_color,1,0,0,1);
        
        var positionBuffer = gl.createBuffer();
        gl.bindBuffer(gl.ARRAY_BUFFER,positionBuffer);

        function bindEvent(){
            var points = [];
            canvas.onmousedown = function (e){
            //   gl.clearColor(0,0,1,1);
              gl.clearColor(0,0,0,0);
              gl.clear(gl.COLOR_BUFFER_BIT); //清空画布
              var x = e.offsetX;
              var y = e.offsetY;
              var color = randomColor();
              points.push(x,y,10.0); //记录点击位置
            //   points.push({x,y,
            //     size:10.0
            //   }); //记录点击位置
              if(points.length % 3 == 0){
                gl.bufferData(gl.ARRAY_BUFFER,new Float32Array(points),gl.STATIC_DRAW);
                gl.vertexAttribPointer(a_position,2,gl.FLOAT,false,4*3,0);
                gl.vertexAttribPointer(pointsize,1,gl.FLOAT,false,4*3,2*4);
                gl.enableVertexAttribArray(a_position);
                gl.enableVertexAttribArray(pointsize);
                // gl.drawArrays(gl.POINTS,0,3);
                //改变gl.LINES 、gl.LINE_STRIP、gl.LINE_LOOP  可以绘制线段 、线条 、闭合线条
                // gl.drawArrays(gl.TRIANGLES,0, points.length/3 );
                // gl.drawArrays(gl.LINES,0, points.length/3 );
                // gl.drawArrays(gl.LINE_STRIP,0, points.length/3 );
                gl.drawArrays(gl.LINE_LOOP,0, points.length/3 );
              }
              
              //gl.drawArrays(gl.POINTS,0,1);//放在循环外只能绘制一个点
            }
        };


        // var positionBuffer = gl.createBuffer();
        // gl.bindBuffer(gl.ARRAY_BUFFER,positionBuffer);
        // gl.bufferData(gl.ARRAY_BUFFER,new Float32Array([50,50,10.0,50,100,20.0,100,100,30.0]),gl.STATIC_DRAW);
        // gl.vertexAttribPointer(a_position,2,gl.FLOAT,false,4*3,0);
        // gl.vertexAttribPointer(pointsize,1,gl.FLOAT,false,4*3,2*4);
        // gl.enableVertexAttribArray(a_position);
        // gl.enableVertexAttribArray(pointsize);
        // // gl.drawArrays(gl.POINTS,0,3);
        // gl.drawArrays(gl.TRIANGLES,0,3);


        function randomColor(){
            var r = Math.random();
            var g = Math.random();
            var b = Math.random();
            var a = 0.5 + Math.random()*0.5;
            return {r,g,b,a};
        }

        bindEvent()

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

WebGL之绘制矩形

索引缓冲区

绘制矩形的两种方法

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>绘制矩形</title>
</head>
<body>
    <canvas id="canvas" width="800" height="600"></canvas>
    <script type="notjs" id="vertex" >

        attribute vec2 a_position;
        attribute vec4 a_color;
        uniform vec2 screenSize;
        varying vec4 v_color;
        void main(){
            float x = a_position.x * 2.0 / screenSize.x - 1.0;
            float y = 1.0 - ( a_position.y * 2.0 / screenSize.y);
            gl_Position = vec4(x, y, 0, 1);
            gl_PointSize = 10.0;
            v_color = a_color;
        }
    </script>
    <script type="notjs" id="fragment" >
        precision mediump float;
        varying vec4 v_color;
        void main(){
            gl_FragColor = v_color;
            
        }
    </script>
    <script>
        var canvas = document.getElementById("canvas");
        var gl = canvas.getContext("webgl");
        if(!gl){
            alert('浏览器不支持webgl')
        }
        // var  str = ''
        //创建着色器(两种着色器)
        function createShader(gl,type,source){
            var shader = gl.createShader(type);
            gl.shaderSource(shader,source);
            gl.compileShader(shader);
            var success= gl.getShaderParameter(shader,gl.COMPILE_STATUS);
            if(success){
                return shader;
            }
            console.log(gl.getShaderInfoLog(shader));
            // gl.deleteShader(shader);
        }

        var vetexStr = document.getElementById('vertex').innerText;
        var fragmentStr = document.getElementById('fragment').innerText;
        console.log(vetexStr,fragmentStr)
        //创建着色器程序
        var vertexShader = createShader(gl,gl.VERTEX_SHADER,vetexStr);
        var fragmentShader = createShader(gl,gl.FRAGMENT_SHADER,fragmentStr);

        
        function createProgram(gl,vertexShader,fragmentShader){
            //链接着色器程序
            var program = gl.createProgram();
            gl.attachShader(program,vertexShader);
            gl.attachShader(program,fragmentShader); 
            gl.linkProgram(program);

            var success= gl.getProgramParameter(program,gl.LINK_STATUS);
            if(success){
                return program;
            }
            
            console.log(success);
        }

        var program = createProgram(gl,vertexShader,fragmentShader);
        gl.useProgram(program); //使用着色器程序
        // gl.clearColor(0,0,1,1);
        // gl.clear(gl.COLOR_BUFFER_BIT); //清空画布
        

        var a_position = gl.getAttribLocation(program,'a_position'); //获取变量存储位置
        var screenSize = gl.getUniformLocation(program,'screenSize'); //获取变量存储位置
        var a_color = gl.getAttribLocation(program,'a_color'); //获取变量存储位置
        gl.uniform2f(screenSize,canvas.width,canvas.height);
        // gl.vertexAttrib4f(a_color,1,0,0,1);
        
        var positionBuffer = gl.createBuffer();
        gl.bindBuffer(gl.ARRAY_BUFFER,positionBuffer);

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

        // function bindEvent(){
        //     var points = [];
        //     canvas.onmousedown = function (e){
        //     //   gl.clearColor(0,0,1,1);
        //       gl.clearColor(0,0,0,0);
        //       gl.clear(gl.COLOR_BUFFER_BIT); //清空画布
        //       var x = e.offsetX;
        //       var y = e.offsetY;
        //       var color = randomColor();
        //       points.push(x,y,10.0); //记录点击位置
        //     //   points.push({x,y,
        //     //     size:10.0
        //     //   }); //记录点击位置
        //       if(points.length % 3 == 0){
        //         gl.bufferData(gl.ARRAY_BUFFER,new Float32Array(points),gl.STATIC_DRAW);
        //         gl.vertexAttribPointer(a_position,2,gl.FLOAT,false,4*3,0);
        //         // gl.vertexAttribPointer(pointsize,1,gl.FLOAT,false,4*3,2*4);
        //         gl.enableVertexAttribArray(a_position);
        //         // gl.enableVertexAttribArray(pointsize);
        //         // gl.drawArrays(gl.POINTS,0,3);
        //         //改变gl.LINES 、gl.LINE_STRIP、gl.LINE_LOOP  可以绘制线段 、线条 、闭合线条
        //         // gl.drawArrays(gl.TRIANGLES,0, points.length/3 );
        //         // gl.drawArrays(gl.LINES,0, points.length/3 );
        //         // gl.drawArrays(gl.LINE_STRIP,0, points.length/3 );
        //         gl.drawArrays(gl.LINE_LOOP,0, points.length/3 );
        //       }
              
        //       //gl.drawArrays(gl.POINTS,0,1);//放在循环外只能绘制一个点
        //     }
        // };

        function draw(){
            gl.bufferData(gl.ARRAY_BUFFER,new Float32Array([
                50,50,1,0,0,
                50,100,0,1,0,
                150,100,0,0,1,

                150,50,1,1,0,
                
            ]),gl.STATIC_DRAW);

            gl.bufferData(gl.ELEMENT_ARRAY_BUFFER,new Uint16Array([
                0,1,2,
                2,3,0
            ]),gl.STATIC_DRAW);

            gl.vertexAttribPointer(a_position,2,gl.FLOAT,false, 4 * 5,0);
            gl.vertexAttribPointer(a_color,3,gl.FLOAT,false, 4*5, 4*2);
            gl.enableVertexAttribArray(a_position);
            gl.enableVertexAttribArray(a_color);
            gl.drawElements(gl.TRIANGLES,6,gl.UNSIGNED_SHORT,0);
            // gl.drawArrays(gl.TRIANGLES,0,6);
        }

        draw()

        // 绘制矩形的第二中方法
        // var positionBuffer = gl.createBuffer();
        // gl.bindBuffer(gl.ARRAY_BUFFER,positionBuffer);
        // gl.bufferData(gl.ARRAY_BUFFER,new Float32Array([50,50,10.0,50,100,20.0,100,100,30.0]),gl.STATIC_DRAW);
        // gl.vertexAttribPointer(a_position,2,gl.FLOAT,false,4*3,0);
        // gl.vertexAttribPointer(pointsize,1,gl.FLOAT,false,4*3,2*4);
        // gl.enableVertexAttribArray(a_position);
        // gl.enableVertexAttribArray(pointsize);
        // // gl.drawArrays(gl.POINTS,0,3);
        // gl.drawArrays(gl.TRIANGLES,0,3);


        function randomColor(){
            var r = Math.random();
            var g = Math.random();
            var b = Math.random();
            var a = 0.5 + Math.random()*0.5;
            return {r,g,b,a};
        }

        // bindEvent()

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

WebGL之绘制矩形二

利用三角形扇实现矩形

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>绘制矩形</title>
</head>
<body>
    <canvas id="canvas" width="800" height="600"></canvas>
    <script type="notjs" id="vertex" >

        attribute vec2 a_position;
        attribute vec4 a_color;
        uniform vec2 screenSize;
        varying vec4 v_color;
        void main(){
            float x = a_position.x * 2.0 / screenSize.x - 1.0;
            float y = 1.0 - ( a_position.y * 2.0 / screenSize.y);
            gl_Position = vec4(x, y, 0, 1);
            gl_PointSize = 10.0;
            v_color = a_color;
        }
    </script>
    <script type="notjs" id="fragment" >
        precision mediump float;
        varying vec4 v_color;
        void main(){
            gl_FragColor = v_color;
            
        }
    </script>
    <script>
        var canvas = document.getElementById("canvas");
        var gl = canvas.getContext("webgl");
        if(!gl){
            alert('浏览器不支持webgl')
        }
        // var  str = ''
        //创建着色器(两种着色器)
        function createShader(gl,type,source){
            var shader = gl.createShader(type);
            gl.shaderSource(shader,source);
            gl.compileShader(shader);
            var success= gl.getShaderParameter(shader,gl.COMPILE_STATUS);
            if(success){
                return shader;
            }
            console.log(gl.getShaderInfoLog(shader));
            // gl.deleteShader(shader);
        }

        var vetexStr = document.getElementById('vertex').innerText;
        var fragmentStr = document.getElementById('fragment').innerText;
        console.log(vetexStr,fragmentStr)
        //创建着色器程序
        var vertexShader = createShader(gl,gl.VERTEX_SHADER,vetexStr);
        var fragmentShader = createShader(gl,gl.FRAGMENT_SHADER,fragmentStr);

        
        function createProgram(gl,vertexShader,fragmentShader){
            //链接着色器程序
            var program = gl.createProgram();
            gl.attachShader(program,vertexShader);
            gl.attachShader(program,fragmentShader); 
            gl.linkProgram(program);

            var success= gl.getProgramParameter(program,gl.LINK_STATUS);
            if(success){
                return program;
            }
            
            console.log(success);
        }

        var program = createProgram(gl,vertexShader,fragmentShader);
        gl.useProgram(program); //使用着色器程序
        // gl.clearColor(0,0,1,1);
        // gl.clear(gl.COLOR_BUFFER_BIT); //清空画布
        

        var a_position = gl.getAttribLocation(program,'a_position'); //获取变量存储位置
        var screenSize = gl.getUniformLocation(program,'screenSize'); //获取变量存储位置
        var a_color = gl.getAttribLocation(program,'a_color'); //获取变量存储位置
        gl.uniform2f(screenSize,canvas.width,canvas.height);
        // gl.vertexAttrib4f(a_color,1,0,0,1);
        
        var positionBuffer = gl.createBuffer();
        gl.bindBuffer(gl.ARRAY_BUFFER,positionBuffer);

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

        // function bindEvent(){
        //     var points = [];
        //     canvas.onmousedown = function (e){
        //     //   gl.clearColor(0,0,1,1);
        //       gl.clearColor(0,0,0,0);
        //       gl.clear(gl.COLOR_BUFFER_BIT); //清空画布
        //       var x = e.offsetX;
        //       var y = e.offsetY;
        //       var color = randomColor();
        //       points.push(x,y,10.0); //记录点击位置
        //     //   points.push({x,y,
        //     //     size:10.0
        //     //   }); //记录点击位置
        //       if(points.length % 3 == 0){
        //         gl.bufferData(gl.ARRAY_BUFFER,new Float32Array(points),gl.STATIC_DRAW);
        //         gl.vertexAttribPointer(a_position,2,gl.FLOAT,false,4*3,0);
        //         // gl.vertexAttribPointer(pointsize,1,gl.FLOAT,false,4*3,2*4);
        //         gl.enableVertexAttribArray(a_position);
        //         // gl.enableVertexAttribArray(pointsize);
        //         // gl.drawArrays(gl.POINTS,0,3);
        //         //改变gl.LINES 、gl.LINE_STRIP、gl.LINE_LOOP  可以绘制线段 、线条 、闭合线条
        //         // gl.drawArrays(gl.TRIANGLES,0, points.length/3 );
        //         // gl.drawArrays(gl.LINES,0, points.length/3 );
        //         // gl.drawArrays(gl.LINE_STRIP,0, points.length/3 );
        //         gl.drawArrays(gl.LINE_LOOP,0, points.length/3 );
        //       }
              
        //       //gl.drawArrays(gl.POINTS,0,1);//放在循环外只能绘制一个点
        //     }
        // };

        function draw(){
            gl.bufferData(gl.ARRAY_BUFFER,new Float32Array([
                100,75,0,1,0,

                50,50,1,0,0,
                50,100,0,1,0,
                150,100,0,0,1,
                150,50,1,1,0,
                50,50,1,0,0,
                
            ]),gl.STATIC_DRAW);

            // gl.bufferData(gl.ELEMENT_ARRAY_BUFFER,new Uint16Array([
            //     0,1,2,
            //     2,3,0
            // ]),gl.STATIC_DRAW);

            gl.vertexAttribPointer(a_position,2,gl.FLOAT,false, 4 * 5,0);
            gl.vertexAttribPointer(a_color,3,gl.FLOAT,false, 4*5, 4*2);
            gl.enableVertexAttribArray(a_position);
            gl.enableVertexAttribArray(a_color);
            // gl.drawElements(gl.TRIANGLES,6,gl.UNSIGNED_SHORT,0);
            // gl.drawElements(gl.TRIANGLE_STRIP,6,gl.UNSIGNED_SHORT,0);
            // gl.drawElements(gl.TRIANGLE_FAN,6,gl.UNSIGNED_SHORT,0);
            // gl.drawArrays(gl.TRIANGLES,0,6);
            gl.drawArrays(gl.TRIANGLE_FAN,0,6);
        }

        draw()

        // var positionBuffer = gl.createBuffer();
        // gl.bindBuffer(gl.ARRAY_BUFFER,positionBuffer);
        // gl.bufferData(gl.ARRAY_BUFFER,new Float32Array([50,50,10.0,50,100,20.0,100,100,30.0]),gl.STATIC_DRAW);
        // gl.vertexAttribPointer(a_position,2,gl.FLOAT,false,4*3,0);
        // gl.vertexAttribPointer(pointsize,1,gl.FLOAT,false,4*3,2*4);
        // gl.enableVertexAttribArray(a_position);
        // gl.enableVertexAttribArray(pointsize);
        // // gl.drawArrays(gl.POINTS,0,3);
        // gl.drawArrays(gl.TRIANGLES,0,3);


        function randomColor(){
            var r = Math.random();
            var g = Math.random();
            var b = Math.random();
            var a = 0.5 + Math.random()*0.5;
            return {r,g,b,a};
        }

        // bindEvent()

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

WebGL之绘制圆

利用三角形 gl.TRIANGLE_FAN 模式绘制圆

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>绘制圆</title>
</head>
<body>
    <canvas id="canvas" width="800" height="600"></canvas>
    <script type="notjs" id="vertex" >

        attribute vec2 a_position;
        attribute vec4 a_color;
        uniform vec2 screenSize;
        varying vec4 v_color;
        void main(){
            float x = a_position.x * 2.0 / screenSize.x - 1.0;
            float y = 1.0 - ( a_position.y * 2.0 / screenSize.y);
            gl_Position = vec4(x, y, 0, 1);
            gl_PointSize = 10.0;
            v_color = a_color;
        }
    </script>
    <script type="notjs" id="fragment" >
        precision mediump float;
        varying vec4 v_color;
        void main(){
            gl_FragColor = v_color;
            
        }
    </script>
    <script>
        var canvas = document.getElementById("canvas");
        var gl = canvas.getContext("webgl");
        if(!gl){
            alert('浏览器不支持webgl')
        }
        // var  str = ''
        //创建着色器(两种着色器)
        function createShader(gl,type,source){
            var shader = gl.createShader(type);
            gl.shaderSource(shader,source);
            gl.compileShader(shader);
            var success= gl.getShaderParameter(shader,gl.COMPILE_STATUS);
            if(success){
                return shader;
            }
            console.log(gl.getShaderInfoLog(shader));
            // gl.deleteShader(shader);
        }

        var vetexStr = document.getElementById('vertex').innerText;
        var fragmentStr = document.getElementById('fragment').innerText;
        console.log(vetexStr,fragmentStr)
        //创建着色器程序
        var vertexShader = createShader(gl,gl.VERTEX_SHADER,vetexStr);
        var fragmentShader = createShader(gl,gl.FRAGMENT_SHADER,fragmentStr);

        
        function createProgram(gl,vertexShader,fragmentShader){
            //链接着色器程序
            var program = gl.createProgram();
            gl.attachShader(program,vertexShader);
            gl.attachShader(program,fragmentShader); 
            gl.linkProgram(program);

            var success= gl.getProgramParameter(program,gl.LINK_STATUS);
            if(success){
                return program;
            }
            
            console.log(success);
        }

        var program = createProgram(gl,vertexShader,fragmentShader);
        gl.useProgram(program); //使用着色器程序
        // gl.clearColor(0,0,1,1);
        // gl.clear(gl.COLOR_BUFFER_BIT); //清空画布
        

        var a_position = gl.getAttribLocation(program,'a_position'); //获取变量存储位置
        var screenSize = gl.getUniformLocation(program,'screenSize'); //获取变量存储位置
        var a_color = gl.getAttribLocation(program,'a_color'); //获取变量存储位置
        gl.uniform2f(screenSize,canvas.width,canvas.height);
        // gl.vertexAttrib4f(a_color,1,0,0,1);
        
        var positionBuffer = gl.createBuffer();
        gl.bindBuffer(gl.ARRAY_BUFFER,positionBuffer);

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


        function draw(){

            var positionData = circlePoints(100,100,50,100);

            // gl.bufferData(gl.ARRAY_BUFFER,new Float32Array([
            //     100,75,0,1,0,

            //     50,50,1,0,0,
            //     50,100,0,1,0,
            //     150,100,0,0,1,
            //     150,50,1,1,0,
            //     50,50,1,0,0,
                
            // ]),gl.STATIC_DRAW);

            gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(positionData) ,gl.STATIC_DRAW);


            // gl.bufferData(gl.ELEMENT_ARRAY_BUFFER,new Uint16Array([
            //     0,1,2,
            //     2,3,0
            // ]),gl.STATIC_DRAW);

            gl.vertexAttribPointer(a_position,2,gl.FLOAT,false, 4 * 5,0);
            gl.vertexAttribPointer(a_color,3,gl.FLOAT,false, 4*5, 4*2);
            gl.enableVertexAttribArray(a_position);
            gl.enableVertexAttribArray(a_color);
            // gl.drawElements(gl.TRIANGLES,6,gl.UNSIGNED_SHORT,0);
            // gl.drawElements(gl.TRIANGLE_STRIP,6,gl.UNSIGNED_SHORT,0);
            // gl.drawElements(gl.TRIANGLE_FAN,6,gl.UNSIGNED_SHORT,0);
            // gl.drawArrays(gl.TRIANGLES,0,6);
            // gl.drawArrays(gl.TRIANGLE_FAN,0,6);
            gl.drawArrays(gl.TRIANGLE_FAN,0,102);
        }


        function circlePoints(x,y,radius,n){
            var points = [x,y,1,0,0];
            var color = null;
            for(var i = 0;i <= n;i++){
                var angle = 2 * Math.PI / n;
                pointsx = radius * Math.cos(angle * i) + x;
                pointsy = radius * Math.sin(angle * i) + y;
                points.push(pointsx,pointsy,Math.random(),Math.random(),Math.random());
            }
            return points;
        }

        draw()  
    </script>
</body>
</html>
</body>
</html>

WebGL之绘制圆环

利用两个三角形来绘制圆环

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>绘制圆环</title>
</head>
<body>
    <canvas id="canvas" width="800" height="600"></canvas>
    <script type="notjs" id="vertex" >

        attribute vec2 a_position;
        attribute vec4 a_color;
        uniform vec2 screenSize;
        varying vec4 v_color;
        void main(){
            float x = a_position.x * 2.0 / screenSize.x - 1.0;
            float y = 1.0 - ( a_position.y * 2.0 / screenSize.y);
            gl_Position = vec4(x, y, 0, 1);
            gl_PointSize = 10.0;
            v_color = a_color;
        }
    </script>
    <script type="notjs" id="fragment" >
        precision mediump float;
        varying vec4 v_color;
        void main(){
            gl_FragColor = v_color;
            
        }
    </script>
    <script>
        var canvas = document.getElementById("canvas");
        var gl = canvas.getContext("webgl");
        if(!gl){
            alert('浏览器不支持webgl')
        }
        // var  str = ''
        //创建着色器(两种着色器)
        function createShader(gl,type,source){
            var shader = gl.createShader(type);
            gl.shaderSource(shader,source);
            gl.compileShader(shader);
            var success= gl.getShaderParameter(shader,gl.COMPILE_STATUS);
            if(success){
                return shader;
            }
            console.log(gl.getShaderInfoLog(shader));
            // gl.deleteShader(shader);
        }

        var vetexStr = document.getElementById('vertex').innerText;
        var fragmentStr = document.getElementById('fragment').innerText;
        console.log(vetexStr,fragmentStr)
        //创建着色器程序
        var vertexShader = createShader(gl,gl.VERTEX_SHADER,vetexStr);
        var fragmentShader = createShader(gl,gl.FRAGMENT_SHADER,fragmentStr);

        
        function createProgram(gl,vertexShader,fragmentShader){
            //链接着色器程序
            var program = gl.createProgram();
            gl.attachShader(program,vertexShader);
            gl.attachShader(program,fragmentShader); 
            gl.linkProgram(program);

            var success= gl.getProgramParameter(program,gl.LINK_STATUS);
            if(success){
                return program;
            }
            
            console.log(success);
        }

        var program = createProgram(gl,vertexShader,fragmentShader);
        gl.useProgram(program); //使用着色器程序
        // gl.clearColor(0,0,1,1);
        // gl.clear(gl.COLOR_BUFFER_BIT); //清空画布
        

        var a_position = gl.getAttribLocation(program,'a_position'); //获取变量存储位置
        var screenSize = gl.getUniformLocation(program,'screenSize'); //获取变量存储位置
        var a_color = gl.getAttribLocation(program,'a_color'); //获取变量存储位置
        gl.uniform2f(screenSize,canvas.width,canvas.height);
        // gl.vertexAttrib4f(a_color,1,0,0,1);
        
        var positionBuffer = gl.createBuffer();
        gl.bindBuffer(gl.ARRAY_BUFFER,positionBuffer);

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


        function draw(){

            // var positionData = circlePoints(100,100,50,100);
            var positionData = cirquePoints(100,100,100,50,100).positions;
            var indexData = cirquePoints(100,100,100,50,100).indices;

            // gl.bufferData(gl.ARRAY_BUFFER,new Float32Array([
            //     100,75,0,1,0,

            //     50,50,1,0,0,
            //     50,100,0,1,0,
            //     150,100,0,0,1,
            //     150,50,1,1,0,
            //     50,50,1,0,0,
                
            // ]),gl.STATIC_DRAW);

            gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(positionData) ,gl.STATIC_DRAW);


            gl.bufferData(gl.ELEMENT_ARRAY_BUFFER,new Uint16Array(indexData),gl.STATIC_DRAW);

            gl.vertexAttribPointer(a_position,2,gl.FLOAT,false, 4 * 5,0);
            gl.vertexAttribPointer(a_color,3,gl.FLOAT,false, 4*5, 4*2);
            gl.enableVertexAttribArray(a_position);
            gl.enableVertexAttribArray(a_color);
            gl.drawElements(gl.TRIANGLES,indexData.length,gl.UNSIGNED_SHORT,0);
            // gl.drawElements(gl.TRIANGLE_STRIP,6,gl.UNSIGNED_SHORT,0);
            // gl.drawElements(gl.TRIANGLE_FAN,6,gl.UNSIGNED_SHORT,0);
            // gl.drawArrays(gl.TRIANGLES,0,6);
            // gl.drawArrays(gl.TRIANGLE_FAN,0,6);
            // gl.drawArrays(gl.TRIANGLE_FAN,0,102);
        }


        // function circlePoints(x,y,radius,n){
        //     var points = [x,y,1,0,0];
        //     var color = null;
        //     for(var i = 0;i <= n;i++){
        //         var angle = 2 * Math.PI / n;
        //         pointsx = radius * Math.cos(angle * i) + x;
        //         pointsy = radius * Math.sin(angle * i) + y;
        //         points.push(pointsx,pointsy,Math.random(),Math.random(),Math.random());
        //     }
        //     return points;
        // }

        function cirquePoints(x,y,outerRadius,innerRadius,n){
                var positions = [];
                var indices = [];
                for(var i = 0;i <= n;i++){
                    var angle = 2 * Math.PI / n;
                    var outerX = outerRadius * Math.cos(angle * i) + x;
                    var outerY = outerRadius * Math.sin(angle * i) + y;
                    var innerX = innerRadius * Math.cos(angle * i) + x;
                    var innerY = innerRadius * Math.sin(angle * i) + y;
                    positions.push(innerX,innerY,Math.random(),Math.random(),Math.random()); 
                    positions.push(outerX,outerY,Math.random(),Math.random(),Math.random());

                    var v0 = i * 2;
                    var v1 = v0 + 1;
                    var v2 = v0 + 2;
                    var v3 = v0 + 3;
                    if(i == n ){
                         v2 = 0;
                         v3 = 1;
                    }
                    indices.push(v0,v1,v2,  v2,v1,v3);
                    
                }
                return {
                    positions,
                    indices
                }
        }

        draw()  
    </script>
</body>
</html>
</body>
</html>

利用三角形带来绘制圆环

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>绘制圆环</title>
</head>
<body>
    <canvas id="canvas" width="800" height="600"></canvas>
    <script type="notjs" id="vertex" >

        attribute vec2 a_position;
        attribute vec4 a_color;
        uniform vec2 screenSize;
        varying vec4 v_color;
        void main(){
            float x = a_position.x * 2.0 / screenSize.x - 1.0;
            float y = 1.0 - ( a_position.y * 2.0 / screenSize.y);
            gl_Position = vec4(x, y, 0, 1);
            gl_PointSize = 10.0;
            v_color = a_color;
        }
    </script>
    <script type="notjs" id="fragment" >
        precision mediump float;
        varying vec4 v_color;
        void main(){
            gl_FragColor = v_color;
            
        }
    </script>
    <script>
        var canvas = document.getElementById("canvas");
        var gl = canvas.getContext("webgl");
        if(!gl){
            alert('浏览器不支持webgl')
        }
        // var  str = ''
        //创建着色器(两种着色器)
        function createShader(gl,type,source){
            var shader = gl.createShader(type);
            gl.shaderSource(shader,source);
            gl.compileShader(shader);
            var success= gl.getShaderParameter(shader,gl.COMPILE_STATUS);
            if(success){
                return shader;
            }
            console.log(gl.getShaderInfoLog(shader));
            // gl.deleteShader(shader);
        }

        var vetexStr = document.getElementById('vertex').innerText;
        var fragmentStr = document.getElementById('fragment').innerText;
        console.log(vetexStr,fragmentStr)
        //创建着色器程序
        var vertexShader = createShader(gl,gl.VERTEX_SHADER,vetexStr);
        var fragmentShader = createShader(gl,gl.FRAGMENT_SHADER,fragmentStr);

        
        function createProgram(gl,vertexShader,fragmentShader){
            //链接着色器程序
            var program = gl.createProgram();
            gl.attachShader(program,vertexShader);
            gl.attachShader(program,fragmentShader); 
            gl.linkProgram(program);

            var success= gl.getProgramParameter(program,gl.LINK_STATUS);
            if(success){
                return program;
            }
            
            console.log(success);
        }

        var program = createProgram(gl,vertexShader,fragmentShader);
        gl.useProgram(program); //使用着色器程序
        // gl.clearColor(0,0,1,1);
        // gl.clear(gl.COLOR_BUFFER_BIT); //清空画布
        

        var a_position = gl.getAttribLocation(program,'a_position'); //获取变量存储位置
        var screenSize = gl.getUniformLocation(program,'screenSize'); //获取变量存储位置
        var a_color = gl.getAttribLocation(program,'a_color'); //获取变量存储位置
        gl.uniform2f(screenSize,canvas.width,canvas.height);
        // gl.vertexAttrib4f(a_color,1,0,0,1);
        
        var positionBuffer = gl.createBuffer();
        gl.bindBuffer(gl.ARRAY_BUFFER,positionBuffer);

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


        function draw(){

            // var positionData = circlePoints(100,100,50,100);
            var positionData = cirquePoints(100,100,100,50,100).positions;
            var indexData = cirquePoints(100,100,100,50,100).indices;

            // gl.bufferData(gl.ARRAY_BUFFER,new Float32Array([
            //     100,75,0,1,0,

            //     50,50,1,0,0,
            //     50,100,0,1,0,
            //     150,100,0,0,1,
            //     150,50,1,1,0,
            //     50,50,1,0,0,
                
            // ]),gl.STATIC_DRAW);

            gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(positionData) ,gl.STATIC_DRAW);


            gl.bufferData(gl.ELEMENT_ARRAY_BUFFER,new Uint16Array(indexData),gl.STATIC_DRAW);

            gl.vertexAttribPointer(a_position,2,gl.FLOAT,false, 4 * 5,0);
            gl.vertexAttribPointer(a_color,3,gl.FLOAT,false, 4*5, 4*2);
            gl.enableVertexAttribArray(a_position);
            gl.enableVertexAttribArray(a_color);
            gl.drawElements(gl.TRIANGLE_STRIP,indexData.length,gl.UNSIGNED_SHORT,0);
            // gl.drawElements(gl.TRIANGLE_STRIP,6,gl.UNSIGNED_SHORT,0);
            // gl.drawElements(gl.TRIANGLE_FAN,6,gl.UNSIGNED_SHORT,0);
            // gl.drawArrays(gl.TRIANGLES,0,6);
            // gl.drawArrays(gl.TRIANGLE_FAN,0,6);
            // gl.drawArrays(gl.TRIANGLE_FAN,0,102);
        }


        // function circlePoints(x,y,radius,n){
        //     var points = [x,y,1,0,0];
        //     var color = null;
        //     for(var i = 0;i <= n;i++){
        //         var angle = 2 * Math.PI / n;
        //         pointsx = radius * Math.cos(angle * i) + x;
        //         pointsy = radius * Math.sin(angle * i) + y;
        //         points.push(pointsx,pointsy,Math.random(),Math.random(),Math.random());
        //     }
        //     return points;
        // }

        function cirquePoints(x,y,outerRadius,innerRadius,n){
                var positions = [];
                var indices = [];
                for(var i = 0;i <= n;i++){
                    var angle = 2 * Math.PI / n;
                    var outerX = outerRadius * Math.cos(angle * i) + x;
                    var outerY = outerRadius * Math.sin(angle * i) + y;
                    var innerX = innerRadius * Math.cos(angle * i) + x;
                    var innerY = innerRadius * Math.sin(angle * i) + y;
                    positions.push(innerX,innerY,Math.random(),Math.random(),Math.random()); 
                    positions.push(outerX,outerY,Math.random(),Math.random(),Math.random());

                    var v0 = i * 2;
                    var v1 = v0 + 1;
                    var v2 = v0 + 2;
                    var v3 = v0 + 3;
                    if(i == n ){
                         v2 = 0;
                         v3 = 1;
                    }
                    indices.push(v0,v1,v2,v3);
                    
                }
                return {
                    positions,
                    indices
                }
        }

        draw()  
    </script>
</body>
</html>
</body>
</html>

WebGL之片元着色器绘图流程

WebGL纹理

vscode 中可以使用插件 WebGL Syntax Hint 来代码补全以及提示

矩形纹理案例

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>绘制矩形</title>
</head>
<body>
    <canvas id="canvas" width="800" height="600"></canvas>
    <!-- 将纹理坐标传递到顶点坐标系中 -->
    <script type="notjs" id="vertex" >
        /*
          a_position 顶点坐标
          a_TexCoord 纹理坐标
          screenSize canvas画布尺寸
          v_TexCoord 传递到片元着色器的纹理坐标
        */
        attribute vec2 a_position;
        attribute vec2 a_TexCoord ;
        uniform vec2 screenSize;
        varying vec2 v_TexCoord;
        void main(){
            /*
               坐标转换  将canvas坐标转换为webgl坐标
            */
            float x = a_position.x * 2.0 / screenSize.x - 1.0;
            float y = 1.0 - ( a_position.y * 2.0 / screenSize.y);
            gl_Position = vec4(x, y, 0, 1);
            gl_PointSize = 10.0;
            v_TexCoord = a_TexCoord;
        }
    </script>
    <script type="notjs" id="fragment" >
        /*
          v_TexCoord 片元着色器接收的纹理坐标
          u_Sampler 纹理图像源数据
        */
        precision mediump float;
        varying vec2 v_TexCoord;
        uniform sampler2D u_Sampler;
        void main(){
            /*
              texture2D  将纹理图像上指定位置(纹理坐标)纹素信息取出
            */
            gl_FragColor = texture2D(u_Sampler, v_TexCoord);
            
        }
    </script>
    <script>
        var canvas = document.getElementById("canvas");
        var gl = canvas.getContext("webgl");
        if(!gl){
            alert('浏览器不支持webgl')
        }
        // var  str = ''
        //创建着色器(两种着色器)
        function createShader(gl,type,source){
            var shader = gl.createShader(type);
            gl.shaderSource(shader,source);
            gl.compileShader(shader);
            var success= gl.getShaderParameter(shader,gl.COMPILE_STATUS);
            if(success){
                return shader;
            }
            console.log(gl.getShaderInfoLog(shader));
            // gl.deleteShader(shader);
        }

        var vetexStr = document.getElementById('vertex').innerText;
        var fragmentStr = document.getElementById('fragment').innerText;
        console.log(vetexStr,fragmentStr)
        //创建着色器程序
        var vertexShader = createShader(gl,gl.VERTEX_SHADER,vetexStr);
        var fragmentShader = createShader(gl,gl.FRAGMENT_SHADER,fragmentStr);

        
        function createProgram(gl,vertexShader,fragmentShader){
            //链接着色器程序
            var program = gl.createProgram();
            gl.attachShader(program,vertexShader);
            gl.attachShader(program,fragmentShader); 
            gl.linkProgram(program);

            var success= gl.getProgramParameter(program,gl.LINK_STATUS);
            if(success){
                return program;
            }
            
            console.log(success);
        }

        var program = createProgram(gl,vertexShader,fragmentShader);
        gl.useProgram(program); //使用着色器程序
       
        

        var a_position = gl.getAttribLocation(program,'a_position'); //获取变量存储位置
        var screenSize = gl.getUniformLocation(program,'screenSize'); //获取变量存储位置
        var a_TexCoord = gl.getAttribLocation(program,'a_TexCoord'); //获取变量存储位置
        var u_Sampler = gl.getUniformLocation(program,'u_Sampler'); //获取变量存储位置
        gl.uniform2f(screenSize,canvas.width,canvas.height);
        
        var positionBuffer = gl.createBuffer();
        gl.bindBuffer(gl.ARRAY_BUFFER,positionBuffer);

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

        var img = new Image();
        img.src = "./149291.jpg";
        var texture = gl.createTexture();
        img.onload = function(){
            //激活纹理单元
            gl.activeTexture(gl.TEXTURE0);
            //绑定纹理对象
            gl.bindTexture(gl.TEXTURE_2D,texture);
            gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_MAG_FILTER,gl.LINEAR);
            gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_MIN_FILTER,gl.LINEAR);
            gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_WRAP_S,gl.CLAMP_TO_EDGE);
            gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_WRAP_T,gl.CLAMP_TO_EDGE);
            //配置纹理图像
            gl.texImage2D(gl.TEXTURE_2D,0,gl.RGBA,gl.RGBA,gl.UNSIGNED_BYTE,img);
            gl.uniform1i(u_Sampler,0);
            draw();

        }

        function draw(){
            gl.bufferData(gl.ARRAY_BUFFER,new Float32Array([
               
                50,50,0,0,
                50,400,0,1,
                650,400,1,1,
                650,400,1,1,
                650,50,1,0,
                50,50,0,0,
                
            ]),gl.STATIC_DRAW);

            gl.vertexAttribPointer(a_position,2,gl.FLOAT,false, 4 * 4,0);
            // 为纹理坐标配置数据
            gl.vertexAttribPointer(a_TexCoord,2,gl.FLOAT,false, 4*4, 4*2);
            gl.enableVertexAttribArray(a_position);
            gl.enableVertexAttribArray(a_TexCoord);
            
            // gl.drawArrays(gl.TRIANGLE_FAN,0,6);
            gl.drawArrays(gl.TRIANGLES,0,6);
        }

        draw()
        function randomColor(){
            var r = Math.random();
            var g = Math.random();
            var b = Math.random();
            var a = 0.5 + Math.random()*0.5;
            return {r,g,b,a};
        }

        // bindEvent()

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

WebGL之数学向量

WebGL之数学矩阵

矩阵可以看看高等数学

WebGL之(矩阵变换)图像平移

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>绘制矩形</title>
</head>
<body>
    <canvas id="canvas" width="800" height="600"></canvas>
    <script type="notjs" id="vertex" >

        //如果在三维坐标系中会用vec4表示;
        /*
          在三维坐标系中  A(x,y,z)
          在齐次坐标系中我们会使用(x,y,z,w)来表示这个顶点的位置
                                (x,y,z,0)来表示向量     
        */
        attribute vec4 a_position;
        attribute vec4 a_color;
        uniform vec2 screenSize;
        // 用vec2表示平移矢量(-0.5,-0.5)
        uniform vec4 a_Translate
        uniform float Tx;
        uniform float Ty;
        varying vec4 v_color;
        void main(){
            gl_Position = vec4(a_position + a_Translate );
            v_color = a_color;
        }
    </script>
    <script type="notjs" id="fragment" >
        precision mediump float;
        varying vec4 v_color;
        void main(){
            gl_FragColor = v_color;
            
        }
    </script>
    <script>
        var canvas = document.getElementById("canvas");
        var gl = canvas.getContext("webgl");
        if(!gl){
            alert('浏览器不支持webgl')
        }
        // var  str = ''
        //创建着色器(两种着色器)
        function createShader(gl,type,source){
            var shader = gl.createShader(type);
            gl.shaderSource(shader,source);
            gl.compileShader(shader);
            var success= gl.getShaderParameter(shader,gl.COMPILE_STATUS);
            if(success){
                return shader;
            }
            console.log(gl.getShaderInfoLog(shader));
            // gl.deleteShader(shader);
        }

        var vetexStr = document.getElementById('vertex').innerText;
        var fragmentStr = document.getElementById('fragment').innerText;
        console.log(vetexStr,fragmentStr)
        //创建着色器程序
        var vertexShader = createShader(gl,gl.VERTEX_SHADER,vetexStr);
        var fragmentShader = createShader(gl,gl.FRAGMENT_SHADER,fragmentStr);

        
        function createProgram(gl,vertexShader,fragmentShader){
            //链接着色器程序
            var program = gl.createProgram();
            gl.attachShader(program,vertexShader);
            gl.attachShader(program,fragmentShader); 
            gl.linkProgram(program);

            var success= gl.getProgramParameter(program,gl.LINK_STATUS);
            if(success){
                return program;
            }
            
            console.log(success);
        }

        var program = createProgram(gl,vertexShader,fragmentShader);
        gl.useProgram(program); //使用着色器程序
        // gl.clearColor(0,0,1,1);
        // gl.clear(gl.COLOR_BUFFER_BIT); //清空画布
        

        var a_position = gl.getAttribLocation(program,'a_position'); //获取变量存储位置
        var screenSize = gl.getUniformLocation(program,'screenSize'); //获取变量存储位置
        var a_Translate = gl.getUniformLocation(program,'a_Translate'); //获取变量存储位置
        // var Ty = gl.getUniformLocation(program,'Ty'); //获取变量存储位置
        var a_color = gl.getAttribLocation(program,'a_color'); //获取变量存储位置
        //x轴上平移0.5  y轴上平移0.5
        gl.uniform4f(a_Translate,0.5,0.5,0,0)
        // gl.uniform1f(Ty,0.5)
        gl.uniform2f(screenSize,canvas.width,canvas.height);
        // gl.vertexAttrib4f(a_color,1,0,0,1);
        
        var positionBuffer = gl.createBuffer();
        gl.bindBuffer(gl.ARRAY_BUFFER,positionBuffer);

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

        // function bindEvent(){
        //     var points = [];
        //     canvas.onmousedown = function (e){
        //     //   gl.clearColor(0,0,1,1);
        //       gl.clearColor(0,0,0,0);
        //       gl.clear(gl.COLOR_BUFFER_BIT); //清空画布
        //       var x = e.offsetX;
        //       var y = e.offsetY;
        //       var color = randomColor();
        //       points.push(x,y,10.0); //记录点击位置
        //     //   points.push({x,y,
        //     //     size:10.0
        //     //   }); //记录点击位置
        //       if(points.length % 3 == 0){
        //         gl.bufferData(gl.ARRAY_BUFFER,new Float32Array(points),gl.STATIC_DRAW);
        //         gl.vertexAttribPointer(a_position,2,gl.FLOAT,false,4*3,0);
        //         // gl.vertexAttribPointer(pointsize,1,gl.FLOAT,false,4*3,2*4);
        //         gl.enableVertexAttribArray(a_position);
        //         // gl.enableVertexAttribArray(pointsize);
        //         // gl.drawArrays(gl.POINTS,0,3);
        //         //改变gl.LINES 、gl.LINE_STRIP、gl.LINE_LOOP  可以绘制线段 、线条 、闭合线条
        //         // gl.drawArrays(gl.TRIANGLES,0, points.length/3 );
        //         // gl.drawArrays(gl.LINES,0, points.length/3 );
        //         // gl.drawArrays(gl.LINE_STRIP,0, points.length/3 );
        //         gl.drawArrays(gl.LINE_LOOP,0, points.length/3 );
        //       }
              
        //       //gl.drawArrays(gl.POINTS,0,1);//放在循环外只能绘制一个点
        //     }
        // };

        function draw(){
            gl.bufferData(gl.ARRAY_BUFFER,new Float32Array([
                0,0,0,1,0,

                -0.5,0.5,1,0,0,
                0.5,0.5,0,1,0,
                0.5,-0.5,0,0,1,
                -0.5,-0.5,1,1,0,
                -0.5,0.5,1,0,0,
                
            ]),gl.STATIC_DRAW);

            // gl.bufferData(gl.ELEMENT_ARRAY_BUFFER,new Uint16Array([
            //     0,1,2,
            //     2,3,0
            // ]),gl.STATIC_DRAW);

            gl.vertexAttribPointer(a_position,2,gl.FLOAT,false, 4 * 5,0);
            gl.vertexAttribPointer(a_color,3,gl.FLOAT,false, 4*5, 4*2);
            gl.enableVertexAttribArray(a_position);
            gl.enableVertexAttribArray(a_color);
            // gl.drawElements(gl.TRIANGLES,6,gl.UNSIGNED_SHORT,0);
            // gl.drawElements(gl.TRIANGLE_STRIP,6,gl.UNSIGNED_SHORT,0);
            // gl.drawElements(gl.TRIANGLE_FAN,6,gl.UNSIGNED_SHORT,0);
            // gl.drawArrays(gl.TRIANGLES,0,6);
            gl.drawArrays(gl.TRIANGLE_FAN,0,6);
        }

        draw()

        // var positionBuffer = gl.createBuffer();
        // gl.bindBuffer(gl.ARRAY_BUFFER,positionBuffer);
        // gl.bufferData(gl.ARRAY_BUFFER,new Float32Array([50,50,10.0,50,100,20.0,100,100,30.0]),gl.STATIC_DRAW);
        // gl.vertexAttribPointer(a_position,2,gl.FLOAT,false,4*3,0);
        // gl.vertexAttribPointer(pointsize,1,gl.FLOAT,false,4*3,2*4);
        // gl.enableVertexAttribArray(a_position);
        // gl.enableVertexAttribArray(pointsize);
        // // gl.drawArrays(gl.POINTS,0,3);
        // gl.drawArrays(gl.TRIANGLES,0,3);


        function randomColor(){
            var r = Math.random();
            var g = Math.random();
            var b = Math.random();
            var a = 0.5 + Math.random()*0.5;
            return {r,g,b,a};
        }

        // bindEvent()

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

WebGL之(矩阵变换)旋转

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>绘制矩形平移</title>
</head>
<body>
    <canvas id="canvas" width="800" height="600"></canvas>
    <script type="notjs" id="vertex" >

        //如果在三维坐标系中会用vec4表示;
        /*
          在三维坐标系中  A(x,y,z)
          在齐次坐标系中我们会使用(x,y,z,w)来表示这个顶点的位置
                                (x,y,z,0)来表示向量     
        */
        attribute vec4 a_position;
        attribute vec4 a_color;
        uniform vec2 screenSize;
        // 用vec2表示平移矢量(-0.5,-0.5)
        uniform vec4 a_Translate;
        uniform float cosb , sinb;
        varying vec4 v_color;
        void main(){
            gl_Position.x = a_position.x * cosb - a_position.y * sinb;
            gl_Position.y = a_position.x * sinb + a_position.y * cosb;
            gl_Position.z = a_position.z ; 
            gl_Position.w = 1.0;
            v_color = a_color;
        }
    </script>
    <script type="notjs" id="fragment" >
        precision mediump float;
        varying vec4 v_color;
        void main(){
            gl_FragColor = v_color;
            
        }
    </script>
    <script>
        var canvas = document.getElementById("canvas");
        var gl = canvas.getContext("webgl");
        if(!gl){
            alert('浏览器不支持webgl')
        }
        // var  str = ''
        //创建着色器(两种着色器)
        function createShader(gl,type,source){
            var shader = gl.createShader(type);
            gl.shaderSource(shader,source);
            gl.compileShader(shader);
            var success= gl.getShaderParameter(shader,gl.COMPILE_STATUS);
            if(success){
                return shader;
            }
            console.log(gl.getShaderInfoLog(shader));
            // gl.deleteShader(shader);
        }

        var vetexStr = document.getElementById('vertex').innerText;
        var fragmentStr = document.getElementById('fragment').innerText;
        console.log(vetexStr,fragmentStr)
        //创建着色器程序
        var vertexShader = createShader(gl,gl.VERTEX_SHADER,vetexStr);
        var fragmentShader = createShader(gl,gl.FRAGMENT_SHADER,fragmentStr);

        
        function createProgram(gl,vertexShader,fragmentShader){
            //链接着色器程序
            var program = gl.createProgram();
            gl.attachShader(program,vertexShader);
            gl.attachShader(program,fragmentShader); 
            gl.linkProgram(program);

            var success= gl.getProgramParameter(program,gl.LINK_STATUS);
            if(success){
                return program;
            }
            
            console.log(success);
        }

        var program = createProgram(gl,vertexShader,fragmentShader);
        gl.useProgram(program); //使用着色器程序
        // gl.clearColor(0,0,1,1);
        // gl.clear(gl.COLOR_BUFFER_BIT); //清空画布
        

        var a_position = gl.getAttribLocation(program,'a_position'); //获取变量存储位置
        var screenSize = gl.getUniformLocation(program,'screenSize'); //获取变量存储位置
        var a_Translate = gl.getUniformLocation(program,'a_Translate'); //获取变量存储位置
        var u_cosb = gl.getUniformLocation(program,'cosb'); //获取变量存储位置
        var u_sinb = gl.getUniformLocation(program,'sinb'); //获取变量存储位置
        var deg = 30;
        var cosb = Math.cos(deg * Math.PI/180);
        var sinb = Math.sin(deg * Math.PI/180);
        console.log(cosb,sinb)
        gl.uniform1f(u_cosb,cosb);
        gl.uniform1f(u_sinb,sinb);
        // var Ty = gl.getUniformLocation(program,'Ty'); //获取变量存储位置
        var a_color = gl.getAttribLocation(program,'a_color'); //获取变量存储位置
        //x轴上平移0.5  y轴上平移0.5
        gl.uniform4f(a_Translate,0.5,0.5,0,0)
        // gl.uniform1f(Ty,0.5)
        gl.uniform2f(screenSize,canvas.width,canvas.height);
        // gl.vertexAttrib4f(a_color,1,0,0,1);
        
        var positionBuffer = gl.createBuffer();
        gl.bindBuffer(gl.ARRAY_BUFFER,positionBuffer);

        var indexBuffer = gl.createBuffer();
        gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER,indexBuffer);
        function draw(){
            gl.bufferData(gl.ARRAY_BUFFER,new Float32Array([
                0,0,0, 0, 1,0,

                -0.5,0.5,0,  1,0,0,
                0.5,0.5,0,   0,1,0,
                0.5,-0.5,0,  0,0,1,
                -0.5,-0.5,0, 1,1,0,
                -0.5,0.5,0,  1,0,0,
                
            ]),gl.STATIC_DRAW);
            gl.vertexAttribPointer(a_position,3,gl.FLOAT,false, 4 * 6,0);
            gl.vertexAttribPointer(a_color,3,gl.FLOAT,false, 4*6, 4*3);
            gl.enableVertexAttribArray(a_position);
            gl.enableVertexAttribArray(a_color);
            // gl.drawElements(gl.TRIANGLES,6,gl.UNSIGNED_SHORT,0);
            // gl.drawElements(gl.TRIANGLE_STRIP,6,gl.UNSIGNED_SHORT,0);
            // gl.drawElements(gl.TRIANGLE_FAN,6,gl.UNSIGNED_SHORT,0);
            // gl.drawArrays(gl.TRIANGLES,0,6);
            gl.drawArrays(gl.TRIANGLE_FAN,0,6);
        }

        draw()
        function randomColor(){
            var r = Math.random();
            var g = Math.random();
            var b = Math.random();
            var a = 0.5 + Math.random()*0.5;
            return {r,g,b,a};
        }

        // bindEvent()

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

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>绘制矩形平移</title>
</head>
<body>
    <canvas id="canvas" width="800" height="600"></canvas>
    <script type="notjs" id="vertex" >

        //如果在三维坐标系中会用vec4表示;
        /*
          在三维坐标系中  A(x,y,z)
          在齐次坐标系中我们会使用(x,y,z,w)来表示这个顶点的位置
                                (x,y,z,0)来表示向量     
        */
        attribute vec3 a_position;
        attribute vec4 a_color;
        uniform vec2 screenSize;
        // 用vec2表示平移矢量(-0.5,-0.5)
        // uniform vec4 a_Translate;
        // uniform float cosb , sinb;
        /*
            用矩阵的方式  申明旋转矩阵
        */
        uniform mat3 rotateMatrix;
        varying vec4 v_color;
        void main(){
           /* gl_Position.x = a_position.x * cosb - a_position.y * sinb;
            gl_Position.y = a_position.x * sinb + a_position.y * cosb;
            gl_Position.z = a_position.z ; 
            gl_Position.w = 1.0;

           */

           gl_Position = vec4(rotateMatrix * a_position,1);
            v_color = a_color;
        }
    </script>
    <script type="notjs" id="fragment" >
        precision mediump float;
        varying vec4 v_color;
        void main(){
            gl_FragColor = v_color;
            
        }
    </script>
    <script>
        var canvas = document.getElementById("canvas");
        var gl = canvas.getContext("webgl");
        if(!gl){
            alert('浏览器不支持webgl')
        }
        // var  str = ''
        //创建着色器(两种着色器)
        function createShader(gl,type,source){
            var shader = gl.createShader(type);
            gl.shaderSource(shader,source);
            gl.compileShader(shader);
            var success= gl.getShaderParameter(shader,gl.COMPILE_STATUS);
            if(success){
                return shader;
            }
            // console.log(gl.getShaderInfoLog(shader));
            // gl.deleteShader(shader);
        }

        var vetexStr = document.getElementById('vertex').innerText;
        var fragmentStr = document.getElementById('fragment').innerText;
        console.log(vetexStr,fragmentStr)
        //创建着色器程序
        var vertexShader = createShader(gl,gl.VERTEX_SHADER,vetexStr);
        var fragmentShader = createShader(gl,gl.FRAGMENT_SHADER,fragmentStr);

        
        function createProgram(gl,vertexShader,fragmentShader){
            //链接着色器程序
            var program = gl.createProgram();
            gl.attachShader(program,vertexShader);
            gl.attachShader(program,fragmentShader); 
            gl.linkProgram(program);

            var success= gl.getProgramParameter(program,gl.LINK_STATUS);
            if(success){
                return program;
            }
            
            console.log(success);
        }

        var program = createProgram(gl,vertexShader,fragmentShader);
        gl.useProgram(program); //使用着色器程序
        // gl.clearColor(0,0,1,1);
        // gl.clear(gl.COLOR_BUFFER_BIT); //清空画布
        

        var a_position = gl.getAttribLocation(program,'a_position'); //获取变量存储位置
        var screenSize = gl.getUniformLocation(program,'screenSize'); //获取变量存储位置
        // var a_Translate = gl.getUniformLocation(program,'a_Translate'); //获取变量存储位置
        // var u_cosb = gl.getUniformLocation(program,'cosb'); //获取变量存储位置
        // var u_sinb = gl.getUniformLocation(program,'sinb'); //获取变量存储位置
        var rotateMatrix = gl.getUniformLocation(program,'rotateMatrix'); //获取变量存储位置
        var deg = 30;
        var cosb = Math.cos(deg * Math.PI/180);
        var sinb = Math.sin(deg * Math.PI/180);
        // console.log(cosb,sinb)
        // gl.uniform1f(u_cosb,cosb);
        // gl.uniform1f(u_sinb,sinb);
        // var Ty = gl.getUniformLocation(program,'Ty'); //获取变量存储位置
        var a_color = gl.getAttribLocation(program,'a_color'); //获取变量存储位置
        //x轴上平移0.5  y轴上平移0.5
        gl.uniformMatrix3fv(rotateMatrix,false,new Float32Array([
            cosb,sinb,0,
            -sinb,cosb,0,
            0,0,1
        ]));
        // gl.uniform4f(a_Translate,0.5,0.5,0,0)
        // gl.uniform1f(Ty,0.5)
        gl.uniform2f(screenSize,canvas.width,canvas.height);
        // gl.vertexAttrib4f(a_color,1,0,0,1);
        
        var positionBuffer = gl.createBuffer();
        gl.bindBuffer(gl.ARRAY_BUFFER,positionBuffer);

        var indexBuffer = gl.createBuffer();
        gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER,indexBuffer);
        function draw(){
            gl.bufferData(gl.ARRAY_BUFFER,new Float32Array([
                0,0,0, 0, 1,0,

                -0.5,0.5,0,  1,0,0,
                0.5,0.5,0,   0,1,0,
                0.5,-0.5,0,  0,0,1,
                -0.5,-0.5,0, 1,1,0,
                -0.5,0.5,0,  1,0,0,
                
            ]),gl.STATIC_DRAW);
            gl.vertexAttribPointer(a_position,3,gl.FLOAT,false, 4 * 6,0);
            gl.vertexAttribPointer(a_color,3,gl.FLOAT,false, 4*6, 4*3);
            gl.enableVertexAttribArray(a_position);
            gl.enableVertexAttribArray(a_color);
            // gl.drawElements(gl.TRIANGLES,6,gl.UNSIGNED_SHORT,0);
            // gl.drawElements(gl.TRIANGLE_STRIP,6,gl.UNSIGNED_SHORT,0);
            // gl.drawElements(gl.TRIANGLE_FAN,6,gl.UNSIGNED_SHORT,0);
            // gl.drawArrays(gl.TRIANGLES,0,6);
            gl.drawArrays(gl.TRIANGLE_FAN,0,6);
        }

        draw()
        function randomColor(){
            var r = Math.random();
            var g = Math.random();
            var b = Math.random();
            var a = 0.5 + Math.random()*0.5;
            return {r,g,b,a};
        }

        // bindEvent()

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

WebGL之(变换矩阵)缩放

WebGL之复合运算

先平移再旋转

WebGL坐标系统

01 模型坐标

02 世界坐标系

03 观察坐标系(视图坐标系)

正射投影 展示的形状是不变的

透视投影 会根据相机的距离改变物体的局部大小

04 裁剪坐标系 y轴向上 X轴向右 Z轴垂直平面向里

05 NDC坐标系

06 屏幕坐标

WebGL之立方体

视点:观察者所在的位置;

视线:从视点出发沿着观察方向的视线

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>绘制立方体</title>
    
</head>
<body>
     
    <canvas id="canvas" width="800" height="600"></canvas>
    <script src="./cuon-matrix.js" ></script>  
    <script type="notjs" id="vertex" >
        attribute vec3 a_position;
        attribute vec4 a_color;
        uniform vec2 screenSize;
        varying vec4 v_color;
        uniform mat4 u_Matrix;
        void main(){
            gl_Position = u_Matrix * vec4(a_position, 1);
            gl_PointSize = 10.0;
            v_color = a_color;
        }
    </script>
    <script type="notjs" id="fragment" >
        precision mediump float;
        varying vec4 v_color;
        void main(){
            gl_FragColor = v_color;    
        }
    </script>
    <script>
        var canvas = document.getElementById("canvas");
        var gl = canvas.getContext("webgl");
        if(!gl){
            alert('浏览器不支持webgl')
        }
        // var  str = ''
        //创建着色器(两种着色器)
        function createShader(gl,type,source){
            var shader = gl.createShader(type);
            gl.shaderSource(shader,source);
            gl.compileShader(shader);
            var success= gl.getShaderParameter(shader,gl.COMPILE_STATUS);
            if(success){
                return shader;
            }
            console.log(gl.getShaderInfoLog(shader));
            // gl.deleteShader(shader);
        }

        var vetexStr = document.getElementById('vertex').innerText;
        var fragmentStr = document.getElementById('fragment').innerText;
        console.log(vetexStr,fragmentStr)
        //创建着色器程序
        var vertexShader = createShader(gl,gl.VERTEX_SHADER,vetexStr);
        var fragmentShader = createShader(gl,gl.FRAGMENT_SHADER,fragmentStr);

        
        function createProgram(gl,vertexShader,fragmentShader){
            //链接着色器程序
            var program = gl.createProgram();
            gl.attachShader(program,vertexShader);
            gl.attachShader(program,fragmentShader); 
            gl.linkProgram(program);

            var success= gl.getProgramParameter(program,gl.LINK_STATUS);
            if(success){
                return program;
            }
            
            console.log(success);
        }

        var program = createProgram(gl,vertexShader,fragmentShader);
        gl.useProgram(program); //使用着色器程序
        // gl.clearColor(0,0,1,1);
        // gl.clear(gl.COLOR_BUFFER_BIT); //清空画布
        

        var a_position = gl.getAttribLocation(program,'a_position'); //获取变量存储位置
        var screenSize = gl.getUniformLocation(program,'screenSize'); //获取变量存储位置
        var a_color = gl.getAttribLocation(program,'a_color'); //获取变量存储位置

        var u_Matrix = gl.getUniformLocation(program,'u_Matrix'); //获取变量存储位置



        gl.uniform2f(screenSize,canvas.width,canvas.height);
        // gl.vertexAttrib4f(a_color,1,0,0,1);
        
        var positionBuffer = gl.createBuffer();
        gl.bindBuffer(gl.ARRAY_BUFFER,positionBuffer);

        var indexBuffer = gl.createBuffer();
        gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER,indexBuffer);
        gl.enable(gl.DEPTH_TEST);// 深度检测 看有没有超过webgl系统的大小
        var deg = 0;
        function rotate(){
            deg++
            var viewMatrix = new Matrix4();
            viewMatrix.setOrtho(-3,3,-3,3,100,-100);
            var modelMatrix = new Matrix4();
            modelMatrix.setRotate(deg,1,1,0);
            var matrix =viewMatrix.multiply(modelMatrix);
            gl.uniformMatrix4fv(u_Matrix, false, matrix.elements);
            draw();
            requestAnimationFrame(rotate)
        }
        rotate(deg);
        
        // setInterval(()=>{
        //         deg++;
        //         rotate(deg);
        // },100)

        // function bindEvent(){
        //     var points = [];
        //     canvas.onmousedown = function (e){
        //     //   gl.clearColor(0,0,1,1);
        //       gl.clearColor(0,0,0,0);
        //       gl.clear(gl.COLOR_BUFFER_BIT); //清空画布
        //       var x = e.offsetX;
        //       var y = e.offsetY;
        //       var color = randomColor();
        //       points.push(x,y,10.0); //记录点击位置
        //     //   points.push({x,y,
        //     //     size:10.0
        //     //   }); //记录点击位置
        //       if(points.length % 3 == 0){
        //         gl.bufferData(gl.ARRAY_BUFFER,new Float32Array(points),gl.STATIC_DRAW);
        //         gl.vertexAttribPointer(a_position,2,gl.FLOAT,false,4*3,0);
        //         // gl.vertexAttribPointer(pointsize,1,gl.FLOAT,false,4*3,2*4);
        //         gl.enableVertexAttribArray(a_position);
        //         // gl.enableVertexAttribArray(pointsize);
        //         // gl.drawArrays(gl.POINTS,0,3);
        //         //改变gl.LINES 、gl.LINE_STRIP、gl.LINE_LOOP  可以绘制线段 、线条 、闭合线条
        //         // gl.drawArrays(gl.TRIANGLES,0, points.length/3 );
        //         // gl.drawArrays(gl.LINES,0, points.length/3 );
        //         // gl.drawArrays(gl.LINE_STRIP,0, points.length/3 );
        //         gl.drawArrays(gl.LINE_LOOP,0, points.length/3 );
        //       }
              
        //       //gl.drawArrays(gl.POINTS,0,1);//放在循环外只能绘制一个点
        //     }
        // };

        function draw(){
            gl.bufferData(gl.ARRAY_BUFFER,new Float32Array([
                // 前面
                -0.5,0.5,-0.5,1,0,0,
                -0.5,-0.5,-0.5,1,0,0,
                0.5,-0.5,-0.5,1,0,0,
                0.5,0.5,-0.5,1,0,0,

                // 后面
                -0.5,0.5,0.5,1,1,0,
                -0.5,-0.5,0.5,1,1,0,
                0.5,-0.5,0.5,1,1,0,
                0.5,0.5,0.5,1,1,0,

                //左面
                -0.5,0.5,-0.5,0,1,0,
                -0.5,0.5,0.5,0,1,0,
                -0.5,-0.5,0.5,0,1,0,
                -0.5,-0.5,-0.5,0,1,0,

                //右面
                0.5,0.5,-0.5,0,1,0,
                0.5,0.5,0.5,0,1,0,
                0.5,-0.5,0.5,0,1,0,
                0.5,-0.5,-0.5,0,1,0,

                //上面
                -0.5,0.5,-0.5,1,0,1,
                0.5,0.5,-0.5,1,0,1,
                0.5,0.5,0.5,1,0,1,
                -0.5,0.5,0.5,1,0,1,
                
                //下面
                -0.5,-0.5,-0.5,1,0,1,
                0.5,-0.5,-0.5,1,0,1,
                0.5,-0.5,0.5,1,0,1,
                -0.5,-0.5,0.5,1,0,1,
                

            ]),gl.STATIC_DRAW);

            gl.bufferData(gl.ELEMENT_ARRAY_BUFFER,new Uint16Array([
                0,1,2,
                2,3,0,

                4,5,6,
                6,7,4,

                8,9,10,
                10,11,8,

                12,13,14,
                14,15,12,

                16,17,18,
                18,19,16,

                20,21,22,
                22,23,20,



            ]),gl.STATIC_DRAW);

            gl.vertexAttribPointer(a_position,3,gl.FLOAT,false, 4 * 6,0);
            gl.vertexAttribPointer(a_color,3,gl.FLOAT,false, 4*5, 4*2);
            gl.enableVertexAttribArray(a_position);
            gl.enableVertexAttribArray(a_color);
            gl.drawElements(gl.TRIANGLES,36,gl.UNSIGNED_SHORT,0);
            // gl.drawElements(gl.TRIANGLE_STRIP,6,gl.UNSIGNED_SHORT,0);
            // gl.drawElements(gl.TRIANGLE_FAN,6,gl.UNSIGNED_SHORT,0);
            // gl.drawArrays(gl.TRIANGLES,0,6);
            // gl.drawArrays(gl.TRIANGLE_FAN,0,6);
        }

        draw()

        // var positionBuffer = gl.createBuffer();
        // gl.bindBuffer(gl.ARRAY_BUFFER,positionBuffer);
        // gl.bufferData(gl.ARRAY_BUFFER,new Float32Array([50,50,10.0,50,100,20.0,100,100,30.0]),gl.STATIC_DRAW);
        // gl.vertexAttribPointer(a_position,2,gl.FLOAT,false,4*3,0);
        // gl.vertexAttribPointer(pointsize,1,gl.FLOAT,false,4*3,2*4);
        // gl.enableVertexAttribArray(a_position);
        // gl.enableVertexAttribArray(pointsize);
        // // gl.drawArrays(gl.POINTS,0,3);
        // gl.drawArrays(gl.TRIANGLES,0,3);


        function randomColor(){
            var r = Math.random();
            var g = Math.random();
            var b = Math.random();
            var a = 0.5 + Math.random()*0.5;
            return {r,g,b,a};
        }

        // bindEvent()

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

WebGL之球体