1

作者:心叶
时间:2018-05-14 10:14

接着前面的文章开始学习,前面我们画了一个点,不过点的位置、大小和颜色都是在着色器中写死的,这一次,我们通过js代码传递给着色器。

传递位置

着色器

由于现在的点是传递进去的,不是写死的,应该是一个变量,因此我们修改成如下:

<!-- 顶点着色器 -->
<script type='x-shader/x-vertex' id='shader-vs'>
    attribute vec4 a_Position;
    void main(){
        gl_Position=a_Position;
        gl_PointSize=100.0;
    }
</script>

其中attribute代表的是不同顶点的不同信息,后面还会看见uniform代表所有顶点一致的处理信息,而varying是顶点着色器和片段着色器桥梁,二者间传递数据。一句话,这三个就是标明变量的地位。

不过需要注意的是,attribute只可以在顶点着色器中使用。

再看vec4这是一种类型,表示四个浮点数,这里声明类型。

我们定义了一个变量,返回赋值给位置,因此下一步,我们需要给这个变量赋值。

给着色器中定义的变量传递数据

只有二步:1.获取变量的存储位置;2.传递数据。直接看代码(代码是在绘制点前一步添加,下同):

// 获取attribute变量的存储位置
var a_Position = gl.getAttribLocation(glProgram, 'a_Position');
// 传递位置
gl.vertexAttrib3f(a_Position, 0.0, 0.0, 0.0);

其中vertexAttrib3f代表的是传递三给float类型的数据,变量的4个float,最后一个会自动补为1.0,当然还有vertexAttrib1f等类似的方法。

这样,位置就是传递进去的了,是活的了。

传递大小

着色器

还是一样,我们需要把原本写死的大小用定义为一个变量,赋值:

<!-- 顶点着色器 -->
<script type='x-shader/x-vertex' id='shader-vs'>
    attribute vec4 a_Position;
    attribute float a_PointSize;
    void main(){
        gl_Position=a_Position;
        gl_PointSize=a_PointSize;
    }
</script>

给着色器中定义的变量传递数据

//【传递点的大小】
var a_PointSize=gl.getAttribLocation(glProgram,'a_PointSize');
gl.vertexAttrib1f(a_PointSize,30.0);

传递颜色

着色器

<!-- 片段着色器 -->
<script type='x-shader/x-fragment' id='shader-fs'>
    precision mediump float;
    uniform vec4 u_FragColor;
    void main(){
        gl_FragColor=u_FragColor;
    }
</script>

由于attribute值可以用在顶点着色器,因此这里定义使用uniform。

【precision mediump float;】这句话是修改精度的,必须有,除了mediump这种中等的精度,还有lowp和highp。

给着色器中定义的变量传递数据

 // 【传递点的颜色】
var u_FragColor=gl.getUniformLocation(glProgram,'u_FragColor');
gl.uniform4f(u_FragColor,1.0,0.0,0.0,1.0);

由于变量的性质改变了,因此获取变量的存储位置和传递数据的方法也要使用对应api,不过大体差不多。

结束语

到这里,我们就实现了数据从着色器写死到传递进去了,一步步来,先实践,到一定时候了,有了感觉再聊聊设计和原理。

共勉!


心叶
304 声望114 粉丝

我还惊讶地意识到, 在我生命中有很多时刻, 每当我遇到一个遥不可及、令人害怕的情境,并感到惊慌失措时, 我都能够应付——因为我回想起了很久以前自己上过的那一课。