• WebGL-四之二


          前几次对图形图形内部多是 以纯色填充,但是现实中已经有许多好的图片了我们没必要一点点画,这一章就是将图片以纹理的形式加载到片元中,主要过程如下,首先是定义点的坐标的attribute变量用于在javascript中 赋值,接下来定义varying 的vec2的变量用于将纹理坐标从顶点着色器传给片元着色器 在片元着色器中定义取样器左右存储纹理图像和相关参数,接下来就是为各个变量赋值,赋值方法与前面一直,先是创建缓冲区,绑定矩阵,写入数据,获取变量存储地址,再就是写入缓冲区数据,最后激活变量,这样就为顶点坐标和纹理坐标赋值了,最后是对取样器赋值 取样器是uniform的 先创建纹理对象,获取取样器地址,获取图像对象,设置图像Y轴反转,因为无法对纹理对象直接操作所以指定纹理单员,激活单元,将纹理对象和纹理单元绑定,配置纹理参数,配置纹理图像,最后取样器赋值,然后画图形。

        

        接下来是代码:

    <!DOCTYPE html>
    <html>
      <head>
        <title>TexturedQuad.html</title>
        
        <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
        <meta http-equiv="description" content="this is my page">
        <meta http-equiv="content-type" content="text/html; charset=UTF-8">
        
        <!--<link rel="stylesheet" type="text/css" href="./styles.css">-->
        <script src="js/cuon-matrix.js"></script>
        <script src="js/cuon-utils.js"></script>
        <script src="js/webgl-debug.js"></script>
        <script src="js/webgl-utils.js"></script>
        <script type="text/javascript">
            var VSHADER_SOURCE=//定点着色器
            'attribute vec4 a_Position; '+//定义vec4的变量 并且声明该变量是attribute型的
            'attribute float a_PointSize; '+
            'attribute vec2 a_TextCoord; '+
            'varying vec2 v_TextCoord; '+
            'void main(){ '+
            'gl_Position=a_Position; '+//将attribute的变量赋值给内部
            'gl_PointSize=a_PointSize; '+
            'v_TextCoord=a_TextCoord; '+//将数据传给片元着色器
            '} ';

            var FSHADER_SOURCE=//片元着色器
            'precision mediump float; ' +
            'uniform sampler2D u_Sampler; '+
            'varying vec2 v_TextCoord; '+
            'void main(){ '+
            'gl_FragColor=texture2D(u_Sampler,v_TextCoord); '+//
            '} ';
            
            function main(){
                var canvas=document.getElementById("webgl");
                
                var gl=getWebGLContext(canvas);
                if(!gl){
                    console.log("gl load fail!");
                    return;
                }
                
                if(!initShaders(gl,VSHADER_SOURCE,FSHADER_SOURCE)){//初始化着色器
                    console.log("fail init shader()!");
                    return ;
                }

                var n=initVertexBuffers(gl);//将顶点坐标和纹理坐标赋值
                if(n<0){
                    console.log("failed to set the positions of the vertices");
                    return;
                }
                gl.clearColor(0.0, 0.0, 1.0, 1.0);
                initTextures(gl,n);
                
                 
            }
            function initVertexBuffers(gl){
                    var verticesTextCoords=new Float32Array([
                    -0.5,0.5,2,-0.3,1.7,
                    -0.5,-0.5,2,-0.3,-0.2,
                    0.5,0.5,2,1.7,1.7,
                    0.5,-0.5,2,1.7,-0.2,
                    ]);//类型化数组

                    var n=4;//点的个数
                    
                    var vertexTexcoordBuffer=gl.createBuffer();//在webGL中创建缓冲区
                    if(!vertexTexcoordBuffer){
                        console.log("failed to create the buffer object!");
                        return -1;
                    }
                    
                    gl.bindBuffer(gl.ARRAY_BUFFER,vertexTexcoordBuffer);//将缓冲区与ARRAY_BUFFER绑定就是指定了缓冲区的用途
                    gl.bufferData(gl.ARRAY_BUFFER,verticesTextCoords,gl.STATIC_DRAW);//往缓冲区写数据 STATIC_DRAW对缓冲区优化   将顶点坐标和纹理坐标放进缓冲区
                    
                    var FSize=verticesTextCoords.BYTES_PER_ELEMENT;//数组中每个元素的字节大小
                    //alert(FSize);
                    //设置顶点坐标 从缓冲区取出坐标
                    var a_Position=gl.getAttribLocation(gl.program,'a_Position');
                    gl.vertexAttribPointer(a_Position,2,gl.FLOAT,false,5*FSize,0);//将缓冲区的数据传入分配给attribute对象 2是定点的分量个数   3*FSize表示相邻两个顶点间相距的字节数也可以理解为每隔3*FSize字节取俩值 是这些 0表示它的其实 偏移量就是从哪开始的 
                    gl.enableVertexAttribArray(a_Position);//开启attribute变量

                    //将纹理坐标分配给webgl
                    var a_TextCoord=gl.getAttribLocation(gl.program,'a_TextCoord');
                    gl.vertexAttribPointer(a_TextCoord,2,gl.FLOAT,false,5*FSize,3*FSize);
                    gl.enableVertexAttribArray(a_TextCoord);
                    
                    //设置点的大小
                    var a_PointSize=gl.getAttribLocation(gl.program,'a_PointSize');
                    gl.vertexAttribPointer(a_PointSize,1,gl.FLOAT,false,5*FSize,2*FSize);
                    gl.enableVertexAttribArray(a_PointSize);
                    return n;
                }
                function initTextures(gl,n){
                    //alert(n);
                    var texture=gl.createTexture();//创建纹理对象 用来管理纹理
                    if(!texture){
                        console.log("failed to texture");
                        return false;
                    }

                    //u_Sampler是用来存储纹理的
                    var u_Sampler=gl.getUniformLocation(gl.program,'u_Sampler');
                    if(!u_Sampler){
                        console.log("failed to u_Sampler");
                        return false;
                    }
                    //加载图片创建图片对象异步加载图片加载完后调用loadTexture函数 未完成前也继续执行下面的代码
                    var image=new Image();
                    
                    image.onload=function(){
                        loadTexture(gl,n,texture,u_Sampler,image);//将纹理单元的图像以及参数传给取样器
                    };
                    image.src="image/sky.jpg";
                    return true;
                }

                function loadTexture(gl,n,texture,u_Sampler,image){
                    //alert(image.height);
                    gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL,1);//对图像进行Y轴反转
                    gl.activeTexture(gl.TEXTURE0);//开启0号单元
                    //console.log(gl.activeTexture(gl.TEXTURE0));
                    gl.bindTexture(gl.TEXTURE_2D,texture);//将纹理对象绑定到纹理单元中 因为没法直接操作纹理对象但是可以操作纹理单元
                    gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_MIN_FILTER,gl.LINEAR);//配置纹理的参数
                    gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_WRAP_S,gl.CLAMP_TO_EDGE);//在X轴上不足会自动填充
                    gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_WRAP_T,gl.MIRRORED_REPEAT);//在y轴上不足的灰自动tian
                    gl.texImage2D(gl.TEXTURE_2D,0,gl.RGB,gl.RGB,gl.UNSIGNED_BYTE,image);//配置纹理图像
                    gl.uniform1i(u_Sampler,0);//将0单元的纹理传给纹理取样器
                    
                    gl.clear(gl.COLOR_BUFFER_BIT);
                    gl.drawArrays(gl.TRIANGLE_STRIP,0,n);
                }
        </script>
      </head>
      
      <body onload="main()">
           <canvas id="webgl" width="600" height="400"></canvas>
      </body>
    </html>

  • 相关阅读:
    适配器和外观模式
    命令模式
    单件模式
    工厂模式
    装饰者模式
    观察者模式(发布--订阅模式)
    设计模式之策略模式
    C#学习笔记15
    C#学习笔记14
    lucky的时光助理-2017.02
  • 原文地址:https://www.cnblogs.com/yizhuceyonghuming/p/5860634.html
Copyright © 2020-2023  润新知