webGl shader的学习记录(二)js 与(glsl语言) OpenGL ES之间如何进行交互?及其如何在js中对vertexShader与fragmentShader进行赋值

 再上一个的章节之中我们知道,着色的书写分两个着色器(顶点着色器与片元着色器),从而结合成为一个可以使用的单独使用的着色器的程序。

下面我们将会接触到的是,如何使用js 与(glsl语言) OpenGL ES之间进行交互。

在了解两者之间如何通讯的时候,我们需要了解一些定义。这些定义出来的数据,可以是的glsl与js进行交互。

attribute变量: attribute变量是只能在vertexShader中使用的变量。(它不能在fragment shader中声明attribute变量,也不能被fragment shader中使用)如:顶点坐标,法线,纹理坐标,顶点颜色等。

uniform变量:uniform变量一般用来表示:变换矩阵,材质,光照参数和颜色等信息。fragmentShader就是这个定义的

既可以在顶点着色器中定义,也可以在片元着色器中定义。

varying变量 :可以简单的理解为可以是的vertexShader与fragmentShader之间进行交互,因此varying变量在vertexShader和fragment shader二者之间的声明必须是一致的

上面的三个定义的变量,你可以去看下 webgl一些变量 这个文章中会有例子

下面我们就看一下:如何是的js 与 glsl之间进行交互

你需要先看下最下面的代码,这个就是我们今天学习使用到的例子

js 与(glsl语言) OpenGL ES之间如何进行交互

我们看下 vextexShader 的定义

    //设置浮点数精度为中等精度
    precision mediump float;
    //接收点在 canvas 坐标系上的坐标 (x, y)
    attribute vec2 a_Position;
    //接收 canvas 的宽高尺寸
    attribute vec2 a_Screen_Size;
    void main(){
        //start 将屏幕坐标系转化为裁剪坐标(裁剪坐标系)
       vec2 position = (a_Position / a_Screen_Size) * 2.0 - 1.0;
       position = position * vec2(1.0, -1.0);
       gl_Position = vec4(position, 0, 1);
       //end 将屏幕坐标系转化为裁剪坐标(裁剪坐标系)
       //声明要绘制的点的大小。
       gl_PointSize = 10.0;
    }

我们看了上面的代码,就会发现在mian() 函数中 gl_Position与gl_PointSize 被赋予了值,而gl_Position更是被变量赋值。我想你大概明白些了,既然被变量赋值了,那我们直接修改变量,不就达到了对webgl(gl_Position直接决定webgl中显示出来的图形的坐标)的赋值了交互更改了吗!

我们看到下面的代码直接进行的gl_Position的数据修改。你会发现是attribute型的

    //接收点在 canvas 坐标系上的坐标 (x, y)
    attribute vec2 a_Position;
    //接收 canvas 的宽高尺寸
    attribute vec2 a_Screen_Size;

我们再来看看在js中 有下面的代码。

如果你并不懂 getAttribLoaction 这个api的意思(点击它,你的疑问会得到解决)

 //找到顶点做着色器程序中的变量 a_Position
    //getAttribLocation(program: WebGLProgram, name: string): GLint;
    //getAttribLocation通过这个方法取到相关Attribute的相关参数
    let a_Position = gl.getAttribLocation(program,'a_Position');
    //找到顶点做着色器程序中的变量 a_Screen_Size
    //getAttribLocation通过这个方法取到相关Attribute的相关参数
    let a_Screen_Size = gl.getAttribLocation(program,'a_Screen_Size');
    console.log(a_Position,a_Screen_Size);
    //找到片元着色器的变量 u_colo;
    let u_Clolor = gl.getUniformLocation(program,'u_Color');
    //为顶点着色器中的 a_Screen_Size 传递 canvas 的宽高信息
    //通过这个指令传递相传递相关参数a_Screen_Size
    gl.vertexAttrib2f(a_Screen_Size,canvas.width,canvas.height);
    this.clearcanvas();
    let points = [];

上面的代码中,你会发现,js通过getAttribLoaction这个API去访问了vertexShader与fragmentShader的上面我们定义的变量 a_Position, a_Screen_Size;

这样我们就可以js中访问了。通我们可以通过在js中的取到的webgl的相关变量。对这些变量进行赋值,就达到了交互的目的了,既然我们取到了相关的变量,那我们又如何在js中对glsl的代码进行赋值呢?这就是我们下面的问题了

js中对vertexShader与fragmentShader进行赋值

自然是webgl给我们提供了API进行使用了,啊哈哈哈,不需要我们自己从头轮子

下面是两个AIP 这两个API分贝对应了相关的变量修改的方法。

WebGLRenderingContext.vertexAttrib[1234]f[v]()(点击我前去查看) 是 WebGL API 的方法,可以为顶点attibute变量赋值。

The WebGLRenderingContext.uniform[1234][fi][v]()(点击我前去查看) 是 WebGL API的方法,可以为片元uniform比那辆赋值

上面API具体是使用 1234的后缀中的哪一个,这取决你定义的这个定义了的类型 float=1 vuc2=2 vuc3=3 vuc4=4。 

例如 a_Screen_Size

 attribute vec2 a_Screen_Size;

 我们之前在tertexShader中定义的是 vec2的类型,所以我们使用的是vertexAttrib2f的API第一个是参数,后边相关赋值的内容

​​​​​​​ gl.vertexAttrib2f(a_Screen_Size,canvas.width,canvas.height);

好了,到了这里我相信你大概是知道了怎么在js中对着色器进行相关的处理了。然后好好体味下代码是怎么处理的。希望可以帮助到你

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

<script type="shader-source" id="vertexShader">
    //设置浮点数精度为中等精度
    precision mediump float;
    //接收点在 canvas 坐标系上的坐标 (x, y)
    attribute vec2 a_Position;
    //接收 canvas 的宽高尺寸
    attribute vec2 a_Screen_Size;
    void main(){
        //start 将屏幕坐标系转化为裁剪坐标(裁剪坐标系)
       vec2 position = (a_Position / a_Screen_Size) * 2.0 - 1.0;
       position = position * vec2(1.0, -1.0);
       gl_Position = vec4(position, 0, 1);
       //end 将屏幕坐标系转化为裁剪坐标(裁剪坐标系)
       //声明要绘制的点的大小。
       gl_PointSize = 10.0;
    }
</script>

<script type="shader-source" id="fragmentShader">

    //设置浮点数精度为中等精度
    precision mediump float;
    //接收 JavaScript 传过来的颜色值(RGBA)。
    uniform vec4 u_Color;
    void main(){
        //将普通的颜色表示转化为 WebGL 需要的表示方式,即将【0-255】转化到【0,1】之间。
       vec4 color = u_Color / vec4(255, 255, 255, 1);
       gl_FragColor = color;
    }
</script>


<!--<script type="shader-source" id="vertexShader">-->
    <!--void main(){-->
        <!--//声明顶点位置-->
        <!--gl_Position = vec4(0.0, 0.0, 0.0 ,1.0);-->
        <!--//声明要绘制的点的大小-->
        <!--gl_PointSize = 10.0;-->
    <!--}-->
<!--</script>-->


<!--<script type="shader-source" id="fragmentShader">-->
    <!--void main(){-->
        <!--//设置像素颜色为红点-->
        <!--gl_FragColor = vec4(1.0,0.0,0.0,1.0);-->
    <!--}-->
<!--</script>-->

<canvas id="canvas"></canvas>

<script>
    function randomColor() {
        return {
            r: Math.random() * 255,
            g: Math.random() * 255,
            b: Math.random() * 255,
            a: Math.random() * 1
        };
    }



    let canvas = document.getElementById('canvas');
    canvas.width = window.innerWidth;
    canvas.height = window.innerHeight;
    let gl = canvas.getContext('webgl');
    //顶点着色器
    let vertexShaderSource = document.querySelector('#vertexShader').innerHTML;
    let vertexShader = gl.createShader(gl.VERTEX_SHADER);
    gl.shaderSource(vertexShader,vertexShaderSource);
    gl.compileShader(vertexShader);

    //片元着色器
    let fragmentShaderSource = document.querySelector('#fragmentShader').innerHTML;
    let fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
    gl.shaderSource(fragmentShader,fragmentShaderSource);
    gl.compileShader(fragmentShader);
    //着色器程序
    //创建着色器程序WebGLProgram
    let program = gl.createProgram();//WebGLProgram
    gl.attachShader(program,vertexShader);//将顶点定点着色器挂靠在program上
    gl.attachShader(program,fragmentShader);//将片元着色器挂靠在program上
    gl.linkProgram(program);
    gl.useProgram(program);//选择使用这个程序WebGLProgram

    //设置清空画布使用的颜色




    //找到顶点做着色器程序中的变量 a_Position
    //getAttribLocation(program: WebGLProgram, name: string): GLint;
    //getAttribLocation通过这个方法取到相关Attribute的相关参数
    let a_Position = gl.getAttribLocation(program,'a_Position');
    //找到顶点做着色器程序中的变量 a_Screen_Size
    //getAttribLocation通过这个方法取到相关Attribute的相关参数
    let a_Screen_Size = gl.getAttribLocation(program,'a_Screen_Size');
    console.log(a_Position,a_Screen_Size);
    //找到片元着色器的变量 u_colo;
    let u_Clolor = gl.getUniformLocation(program,'u_Color');
    //为顶点着色器中的 a_Screen_Size 传递 canvas 的宽高信息
    //通过这个指令传递相传递相关参数a_Screen_Size
    gl.vertexAttrib2f(a_Screen_Size,canvas.width,canvas.height);
    this.clearcanvas();
    let points = [];
    canvas.addEventListener('click',e =>{
        let x = e.pageX;
        let y = e.pageY;
        //取到随机的颜色
        let color = randomColor();
        //放入数组之中
        points.push({x,y,color});

        this.clearcanvas();
        for (let i = 0;i<points.length;i++ ){
            let color = points[i].color;
            //为片元着色器中的 u_Color 传递随机颜色
            gl.uniform4f(u_Clolor,color.r,color.g,color.b,color.a);
            //为定点着色器传递传递坐标
            gl.vertexAttrib2f(a_Position,points[i].x,points[i].y);
            //描绘出来点
            gl.drawArrays(gl.POINTS,0,1);

        }

    })


    //的到相关参数使用get开头然后找到数据类型就能摘找到
    //通过上面修改相关参数  我们总结出来有个用法 修改相应的采纳数 就是用相应参数的类型 去修改



    //清除屏幕渲染背景
    function clearcanvas(){
        //设置清屏后的背景颜色
        gl.clearColor(0,0,0,1);
        //使用缓存中设设置好的颜色 就是上面这个颜色
        gl.clear(gl.COLOR_BUFFER_BIT);
    }
</script>



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

猜你喜欢

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