总要有人来改变世界的,为什么不能是你呢

WebGL编程指南案例解析之纹理叠加

var vShader = `
    attribute vec4 a_Position;
    attribute vec2 a_TexCoord;
    varying vec2 v_TexCoord;
    void main(){
        gl_Position = a_Position;
        v_TexCoord = a_TexCoord;
    }
`;

var fShader = `
    //设定默认精度
    #ifdef GL_ES
    precision mediump float;
    #endif
    uniform sampler2D u_Sampler;
    uniform sampler2D u_Sampler1;
    varying vec2 v_TexCoord;
    void main(){
        vec4 color  = texture2D(u_Sampler,v_TexCoord);
        vec4 color1 = texture2D(u_Sampler1,v_TexCoord);
         gl_FragColor = color * color1;
    }
`;

function main(){
    //获取canvas元素
    var canvas = document.getElementById('webgl');

    //获取webgl上下文
    var gl = getWebGLContext(canvas);

    if(!gl){
        console.log('Failed to get the rendering context for WebGL!');
        return;
    }
    //初始化着色器
    if(!initShaders(gl,vShader,fShader)){
        console.log('Failed to initialize shaders.');
        return;
    }
    var n = initVertexBuffers(gl);
    if(n < 0){
        console.log('Failed to set the positions of the vertices!');
        return;
    }
    if(!initTextures(gl,n)){
        console.log('Failed to initialize textures.');
        return;
    }


    //用指定颜色填充webgl容器,就是设置背景
    gl.clearColor(0.4, 0.5, 0.0, 1.0);


    function initVertexBuffers(gl){
        var verticesTex =  new Float32Array([
            -0.5, 0.5, 0.0, 1.0,
            -0.5,-0.5, 0.0, 0.0,
             0.5, 0.5, 1.0, 1.0,
             0.5,-0.5, 1.0, 0.0
        ]);
        var n = 4;//点的个数
        //创建缓冲区对象
        var vertexTexBuffer = gl.createBuffer();
        if(!vertexTexBuffer){
            console.log('Failed to create the buffer object!');
            return -1;
        }
        //将数据添加到缓冲区(绑定在缓冲区对象上)
        gl.bindBuffer(gl.ARRAY_BUFFER,vertexTexBuffer);
        gl.bufferData(gl.ARRAY_BUFFER,verticesTex,gl.STATIC_DRAW);
        var fsize = verticesTex.BYTES_PER_ELEMENT;

        //获取shaderProgram中attribute变量‘a_Position’的地址
        var a_Position = gl.getAttribLocation(gl.program,'a_Position');
        if (a_Position < 0) {
            console.log('Failed to get the storage location of a_Position');
            return -1;
        }
        //将缓冲区对象分配给a_Position变量并开启访问
        gl.vertexAttribPointer(a_Position,2,gl.FLOAT,false,fsize * 4,0);
        gl.enableVertexAttribArray(a_Position);


        var a_TexCoord = gl.getAttribLocation(gl.program,'a_TexCoord');
        if (a_TexCoord < 0) {
            console.log('Failed to get the storage location of a_TexCoord');
            return -1;
        }
        //将缓冲区对象分配给a_TexCoord变量并开启访问
        gl.vertexAttribPointer(a_TexCoord,2,gl.FLOAT,false,fsize * 4,fsize * 2);
        gl.enableVertexAttribArray(a_TexCoord);

        return n;
    }


    //初始化纹理图片,通过image传入
    function initTextures(){
        //创建纹理对象
        var texture = gl.createTexture();
        var texture1 = gl.createTexture();

        //读取u_Sampler存储位置
        var u_Sampler = gl.getUniformLocation(gl.program,'u_Sampler');
        var u_Sampler1 = gl.getUniformLocation(gl.program,'u_Sampler1');

        var image = new Image(),image1 = new Image;

        image.onload = function(){
            loadTexture(gl,n,texture,u_Sampler,image,0);
        }
        image1.onload = function(){
            loadTexture(gl,n,texture1,u_Sampler1,image1,1);
        }

        image.src = '../image/sky.JPG';
        image1.src = '../image/circle.gif';

        return true;
    }
    var flag = false,flag1= false;
    //加载纹理
    function loadTexture(gl,n,texture,u_Sampler,image,index){
        //对问题图像进行y轴反转
        gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL,1);
        //开启纹理单元
        if(index ==0){
            gl.activeTexture(gl.TEXTURE0);
            flag = true;
        }else{
            gl.activeTexture(gl.TEXTURE1);
            flag1 = true;
        }
        //向target绑定纹理对象
        gl.bindTexture(gl.TEXTURE_2D,texture);
        //配置纹理参数
        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);

        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
        //处理图片像素非2的幂次方的配置
        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);

        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);

        //配置纹理图像
        gl.texImage2D(gl.TEXTURE_2D,0,gl.RGB,gl.RGB,gl.UNSIGNED_BYTE,image);

        //将纹理传递给着色器
        gl.uniform1i(u_Sampler,index);

        if(flag && flag1){
            gl.clear(gl.COLOR_BUFFER_BIT);   // Clear <canvas>
              gl.drawArrays(gl.TRIANGLE_STRIP, 0, n); 
        }

    }
}


main();

相对于之前的为正方形添加单个纹理来说,多了一些变化,文中已经用红字标出:

①片元着色器中新增一个取样器,并且main方法输出的颜色是这两个取色器颜色的乘积;

②用两个纹理对象来加载纹理,并且启用不同的纹理单元(gl.TEXTURE0、gl.TEXTURE1);配置好参数后将纹理传递给对应的纹理单元

③在两个纹理都激活之后才开始绘图

效果:

 

posted @ 2019-04-10 21:48  桔子桑  阅读(880)  评论(0编辑  收藏  举报