[WebGL入门]二十七,多纹理

注:文章译自http://wgld.org/,原作者杉本雅広(doxas),文章中如果有我的额外说明,我会加上[lufy:],另外,鄙人webgl研究还不够深入,一些专业词语,如果翻译有误,欢迎大家指正。



本次的demo的运行结果


使用多个纹理

上次介绍了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

http://wgld.org/s/sample_015/


转载请注明:转自lufy_legend的博客http://blog.csdn.net/lufy_legend

猜你喜欢

转载自blog.csdn.net/lufy_Legend/article/details/40250697