[WebGL入门]二十七,多纹理
注:文章译自http://wgld.org/,原作者杉本雅広(doxas),文章中如果有我的额外说明,我会加上[lufy:],另外,鄙人webgl研究还不够深入,一些专业词语,如果翻译有误,欢迎大家指正。
使用多个纹理
上次介绍了WebGL中的纹理的使用方法。简单的实现了将纹理贴到四边形中,果然是使用图片数据的话比较灵活吧。那么,这次来说说使用多个纹理来合成图像的方法,学习了这个方法之后可以再一个多边形中使用多个纹理。
为了同时使用多个纹理,先来想想一下需要做些什么呢?
上次已经简单的基础了,WebGL中管理纹理的方法是纹理单位,灵活使用这个纹理单位的话,就能实现多纹理的渲染了。
这次的demo使用下面两个图片。
>第一张
>第二张
下面就使用这两张图片来实现多纹理渲染。
着色器的修改
首先来看一下着色器的修改吧。为了渲染多纹理,着色器一侧需要准备多个uniform变量,用来接收多个纹理单位,但是,这次多边形的纹理坐标只需要一个,无论第一个纹理还是第二个纹理都一样,需要变更的代码如下。
>片段着色器的代码修改
precision mediump float; uniform sampler2D texture0; uniform sampler2D texture1; varying vec4 vColor; varying vec2 vTextureCoord; void main(void){ vec4 smpColor0 = texture2D(texture0, vTextureCoord); vec4 smpColor1 = texture2D(texture1, vTextureCoord); gl_FragColor = vColor * smpColor0 * smpColor1; }如上,接收纹理情报的sampler2D型uniform变量一共有两个,所做的处理和之前类似或者说一样。
使用GLSL的内置函数texture2D来获取纹理的情报,使用顶点颜色和两个纹理颜色计算出最终的输出的颜色。
这次只需要修改片段着色器,顶点着色器没有做任何改动。
javascript的修改
接着是javascript的代码修改,在这里需要向新追加的uniform变量中传入正确的纹理数据。
首先,固定的,uniformLocation的获取。
>uniformLocation的获取部分
// uniformLocationを配列に取得 var uniLocation = new Array(); uniLocation[0] = gl.getUniformLocation(prg, ‘mvpMatrix‘); uniLocation[1] = gl.getUniformLocation(prg, ‘texture0‘); uniLocation[2] = gl.getUniformLocation(prg, ‘texture1‘);这里很简单,纯粹的从着色器中获取uniformLocation。
接着,准备纹理对象,这个还是使用自制的create_texture函数。
>纹理对象的生成部分
// テクスチャ用変数の宣言と生成 var texture0 = null, texture1 = null; create_texture(‘texture0.png‘, 0); create_texture(‘texture1.png‘, 1);为了使用多个纹理,需要修改一下create_texture函数,来接收纹理单位的编号。
>create_texture函数
function create_texture(source, number){ // イメージオブジェクトの生成 var img = new Image(); // データのオンロードをトリガーにする img.onload = function(){ // テクスチャオブジェクトの生成 var tex = gl.createTexture(); // テクスチャをバインドする gl.bindTexture(gl.TEXTURE_2D, tex); // テクスチャへイメージを適用 gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, img); // ミップマップを生成 gl.generateMipmap(gl.TEXTURE_2D); // テクスチャのバインドを無効化 gl.bindTexture(gl.TEXTURE_2D, null); // 生成したテクスチャを変数に代入 switch(number){ case 0: texture0 = tex; break; case 1: texture1 = tex; break; default: break; }; } // イメージオブジェクトのソースを指定 img.src = source;第二个参数用来接收纹理单位的编号,来确定生成的纹理对象要赋值给谁。其他地方和之前一样,没有变化。
那么,持续循环部分的地方要添加向着色器中添加纹理的处理。
>持续循环中的处理
// テクスチャユニットを指定してバインドし登録する gl.activeTexture(gl.TEXTURE0); gl.bindTexture(gl.TEXTURE_2D, texture0); gl.uniform1i(uniLocation[1], 0); // テクスチャユニットを指定してバインドし登録する gl.activeTexture(gl.TEXTURE1); gl.bindTexture(gl.TEXTURE_2D, texture1); gl.uniform1i(uniLocation[2], 1);这里的重点是,纹理单位的有效化,纹理对象的绑定,以及向着色器中设定单位编号是一个组合。
另外,activeTexture函数中指定的纹理单位的编号和uniform1i函数的第二个参数中指定的整数值必须是一致的。其他的没有变化,使用合适的坐标变换矩阵的话,就能够在多边形中绘制合成状态的纹理了,是不是出奇的简单啊?
总结
多纹理进行渲染的时候应该注意的是,指定正确的纹理单位进行数据的处理,这就足够了。
其他的细节,主要是activeTexture函数和uniform1i函数的使用方法,这几个不出错的话,之后就可以在着色器一侧使用自己喜欢的图片了。
这次只是单纯的在着色器中将两个纹理数据进行相乘运算,然后各个纹理数据分别进行处理,就可以进行完全不一样的渲染,没有使用固定渲染管道,而是使用GLSL中的程序员自定义着色器,这一点很刺激吧。
可运行demo的连接在最下面。
下次,详细介绍一下关于纹理的参数。使用多纹理绘图的demo
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。