zoukankan      html  css  js  c++  java
  • 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);配置好参数后将纹理传递给对应的纹理单元

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

    效果:

  • 相关阅读:
    都在谈零信任,网络安全和零信任架构的核心是什么?
    盘点:区块链有望被主流接纳的四个场景
    同态加密:密码学的下一个黄金时代
    浅谈人工智能应对数字化转型挑战的5个领域
    2021年7项物联网预测
    15分钟=1年!当人工智能遇到材料学……
    人工智能推理的演进
    保护加密货币资产的7种优秀做法
    ES6语法 Promise Iterator
    css阴影框
  • 原文地址:https://www.cnblogs.com/eco-just/p/10686419.html
Copyright © 2011-2022 走看看