webGl shader的学习记录(三):怎么样去画出来一个三角形

 在这章节中我们需要绘制一个静态的三角形

首先我们依旧是现需要写两个顶点着色器的素材与顶点做色器的素材。

就是下面这段代码 

   //顶点着色器
    let vertexShaderSource = `
        precision mediump float;
        attribute vec2 a_Position;
        void main(){
            gl_Position = vec4(a_Position,0,1);
        }
    `
    //片元着色器
    let fragmentShaderSource =`
        precision mediump float;
        uniform vec4 u_Color;
        void main(){
            vec4 color = u_Color/vec4(255,255,255,1);
            gl_FragColor = color;
        }
    `

如果你并不太理解上面的内容是什么意思的话,可以去看这一章,你会大概的明白是什么意思

下面就是老生常谈的代码了,

然后我们需要创建一个canvas同时将glsl的代码使用取来,创建一个着色器的程序就是下面的代码

        let canvas = document.getElementById('canvas');
        canvas.width = window.innerWidth;
        canvas.height = window.innerHeight;
        //创建顶点着色器的代码
        let vertexShader = gl.createShader(gl.VERTEX_SHADER);
        gl.shaderSource(vertexShader,vertexShaderSource);
        gl.compileShader(vertexShader);
        //创建片片元着色器的代码
        let fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
        gl.shaderSource(fragmentShader,fragmentShaderSource);
        gl.compileShader(fragmentShader);

        //合并代码组成一个完成可用的着色器代码
        let program = gl.createProgram();
        gl.attachShader(program,vertexShader);
        gl.attachShader(program,fragmentShader);
        gl.linkProgram(program);
        //选择使用这个着色器
        gl.useProgram(program);
  
    
 

下面就是本章的最重要的代码了,就是如何绘制一个三角形。

在webgl中绘制三角形的方法不同于上两章的点绘制。webgl个给我们提供专门使用的API

第一步我们需要创建一个三角形的三个顶点坐标是多少,下面的代码就是顶点1(x1,y1)顶点2(x2,y2) 顶点3(x3.y3)

//var positions = [x1,y1, x2,y2, x3,y3]
var positions = [1,0, 0,1, 0,0];//先默认的设置三个顶点 两两一对

第二步就是创建一个缓冲区,我知道你可能看见这个词语并不太理解,你可以理解是数据处理(数据池)这个意思,

   let buffer = gl.createBuffer();//创建一个缓冲区

创建好了之后我们就要告诉webGl,我们刚刚使用的缓冲区设置为当前的我们使用的缓冲区,否则的话,他定不知道要使用这个

 gl.bindBuffer(gl.ARRAY_BUFFER,buffer);//将上面的缓冲区设置为当前使用的缓冲区

既然webGl知道使用那个缓冲区了,那么我们就在这个缓冲区中填入相关的数据,这样我们才能使用嘛。(或许你会想,为什么我们不直接使用呢,反而是使用这样的方法。感觉变的麻烦了。在js与glsl交互中这样的设置与低层也是有很大的关系,你先继续往下看,后面会有一个专门API来使用这个缓冲区中的数值)

gl.bufferData(gl.ARRAY_BUFFER,new Float32Array(positions),gl.STATIC_DRAW);//将我们使用的数据,放入到缓冲区中

注意,着色器程序中的变量需要强类型数据,所以我们在往缓冲区写数据的时候,JS 的弱类型数组一定要用类型化数组转化一下。上面的 new Float32Array(positions),目的就是将 JavaScript 中的弱类型数组转化为强类型数组。

下面就是我们将自己需要处理的变量从着色器中取出来

  //下面我们处理的是 读取之前放进去的缓存区中的数据
    let a_Position = gl.getAttribLocation(program,'a_Position');
    //我们需要告诉 WebGL 如何从之前创建的缓冲区中获取数据,并且传递给顶点着色器中的 a_Position 属性
    gl.enableVertexAttribArray(a_Position);

API的解释是:glVertexAttribPointer 指定了渲染时索引值为 index 的顶点属性数组的数据格式和位置

前面处理的是,如何将数据放进缓冲区中,下面就是如何缓冲区中的数据使用起来

  //每次取两个数据
    let size = 2;
    //每个数据的类型是32位浮点型
    let type = gl.FLOAT;
    //不需要归一化数据
    let normalize = false;
    // 每次迭代运行需要移动数据数 * 每个数据所占内存 到下一个数据开始点。
    let stride = 0;
    // 从缓冲起始位置开始读取
    let offset = 0;
    // 将 a_Position 变量获取数据的缓冲区指向当前绑定的 buffer。
    gl.vertexAttribPointer(a_Position, size, type, normalize, stride, offset)

 另外一个关键的API就是 vertexAttribPointer 这个就是专门处理,我们刚刚放进去的相关数据,相信你看完这个api 就能明白的差不错了。

最后就是画出来这个三角形的API了

    //绘制图元设置为三角形
    let primitiveType = gl.TRIANGLES;
    this.clearScene();//设置背景
    //从顶点数组的开始位置取顶点数据
    let offset1 = 0;
    //因为我们要绘制三个点,所以执行三次顶点绘制操作。
    let count = 3;
    gl.drawArrays(primitiveType, offset1, count);

希望可以帮助到你

前面处理的使用

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<canvas id="canvas"></canvas>
<script>
    //顶点着色器
    let vertexShaderSource = `
        precision mediump float;
        attribute vec2 a_Position;
        void main(){
            gl_Position = vec4(a_Position,0,1);
        }
    `
    //片元着色器
    let fragmentShaderSource =`
        precision mediump float;
        uniform vec4 u_Color;
        void main(){
            vec4 color = u_Color/vec4(255,255,255,1);
            gl_FragColor = color;
        }
    `
    let canvas = document.getElementById('canvas');
    canvas.width = window.innerWidth;
    canvas.height = window.innerHeight;
    let gl = canvas.getContext('webgl');
    //三角形的三个.
    var positions = [1,0, 0,1, 0,0];
    //取到这个着色器的程序
    let program =  this.initWebGlInfo(gl);
    //取到顶点着色器中的 顶点变量
    let a_Position = gl.getAttribLocation(program,'a_Position');
    //因为一次要传递多个数据 使用之前的方法是不可以的 所以我们可以创建一个缓冲区
    let buffer = gl.createBuffer();
    gl.bindBuffer(gl.ARRAY_BUFFER,buffer);//绑定缓冲区
    //往缓冲区之内写入数据
    gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(positions),gl.STATIC_DRAW);
    //我们需要告诉 WebGL 如何从之前创建的缓冲区中获取数据,并且传递给顶点着色器中的 a_Position 属性
    gl.enableVertexAttribArray(a_Position);

    //每次取两个数据
    let size = 2;
    //每个数据的类型是32位浮点型
    let type = gl.FLOAT;
    //不需要归一化数据
    let normalize = false;
    // 每次迭代运行需要移动数据数 * 每个数据所占内存 到下一个数据开始点。
    let stride = 0;
    // 从缓冲起始位置开始读取
    let offset = 0;
    // 将 a_Position 变量获取数据的缓冲区指向当前绑定的 buffer。
    gl.vertexAttribPointer(
        a_Position, size, type, normalize, stride, offset)
    //绘制图元设置为三角形
    let primitiveType = gl.TRIANGLES;
    //清除屏幕的色调
    //处理片元着色器
    let u_Color = gl.getUniformLocation(program,'u_Color');//取到片元着色器的变量
    gl.uniform4f(u_Color,this.randomColor().r,this.randomColor().g,this.randomColor().b,this.randomColor().a);//设置颜色

    this.clearScene();//设置背景
    //从顶点数组的开始位置取顶点数据
    let offset1 = 0;
    //因为我们要绘制三个点,所以执行三次顶点绘制操作。
    let count = 3;
    gl.drawArrays(primitiveType, offset1, count);

    //初始化相关的状态
    function initWebGlInfo(gl) {
        let vertexShader = gl.createShader(gl.VERTEX_SHADER);
        gl.shaderSource(vertexShader,vertexShaderSource);
        gl.compileShader(vertexShader);

        let fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
        gl.shaderSource(fragmentShader,fragmentShaderSource);
        gl.compileShader(fragmentShader);


        let program = gl.createProgram();
        gl.attachShader(program,vertexShader);
        gl.attachShader(program,fragmentShader);
        gl.linkProgram(program);

        gl.useProgram(program);
        return program;
    }

    //清除屏幕的颜色
    function clearScene(){
        gl.clearColor(0.0,0.0,0.0,1);
        gl.clear(gl.COLOR_BUFFER_BIT);
    }


    //随机取到相关的颜色
    function randomColor() {
        return {
            r: Math.random() * 255,
            g: Math.random() * 255,
            b: Math.random() * 255,
            a: Math.random() * 1
        };
    }




</script>
</body>
</html>
发布了65 篇原创文章 · 获赞 18 · 访问量 11万+

猜你喜欢

转载自blog.csdn.net/huhudeni/article/details/101022301