• 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;
        varying vec2 v_TexCoord;
        void main(){
            gl_FragColor = texture2D(u_Sampler,v_TexCoord);
        }
    `;
    
    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();
    
            //读取u_Sampler存储位置
            var u_Sampler = gl.getUniformLocation(gl.program,'u_Sampler');
    
            var image = new Image();
    
            image.onload = function(){
                loadTexture(gl,n,texture,u_Sampler,image);
            }
    
            image.src = '../image/demo.jpg';
    
            return true;
        }
    
        //加载纹理
        function loadTexture(gl,n,texture,u_Sampler,image){
            //对问题图像进行y轴反转
            gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL,1);
            //开启0号纹理单元
            gl.activeTexture(gl.TEXTURE0);
            //向target绑定纹理对象
            gl.bindTexture(gl.TEXTURE_2D,texture);
            //配置纹理参数
            gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
    
            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);
            //将0号纹理传递给着色器
            gl.uniform1i(u_Sampler,0);
    
            gl.clear(gl.COLOR_BUFFER_BIT);   // Clear <canvas>
    
              gl.drawArrays(gl.TRIANGLE_STRIP, 0, n); 
    
        }
    }
    main();

    注意:

    ①每个顶点着色器数据(-0.5, 0.5, 0.0, 1.0)前两个表示webgl的坐标系,后两个表示纹理坐标系;

    ②顶点着色器需要传入两个参数数据源a_Position、a_TexCoord,分别代表webgl顶点坐标和纹理坐标;

    ③对于纹理坐标,无论是顶点坐标系输入输出(a_TexCoord,v_TexCoord)还是片元着色器用于输入的v_TexCoord类型都是vec2,是二维的,别搞错了

    ④对于片元着色器uniform sampler2D u_Sampler;该变量的数据传递和以往不同,将纹理全部处理完毕之后,通过如下方法传递该纹理到片元着色器

    gl.uniform1i(u_Sampler,0);

    ⑤因为加载纹理可能是异步的,所以渲染方法必须在加载纹理结束(配置完纹理并数据传递完毕)之后

    //将0号纹理传递给着色器
            gl.uniform1i(u_Sampler,0);
    
            gl.clear(gl.COLOR_BUFFER_BIT);   // Clear <canvas>
    
            gl.drawArrays(gl.TRIANGLE_STRIP, 0, n); 

     ⑥图片尺寸非2的幂次方问题相关配置,文中也已经给出

  • 相关阅读:
    [日志]“著名”炒股实用口诀
    Taven教授:解决失眠的好办法
    [日志]挂在树上的茶壶
    [日志]教你把脉知生男生女
    [日志]看了很多次的十句话
    [健康]国家制定公布甲型流感中药方市民可食用预防
    初学者如何开发出高质量J2EE系统
    学老中医的顺口溜防病
    [健康]巧用药茶疗慢性咽炎
    [日志]说一个人长的丑!如何说?
  • 原文地址:https://www.cnblogs.com/eco-just/p/10680575.html
Copyright © 2020-2023  润新知