【WebGL初学系列之四】纹理三角

nbcoders.com地址:http://nbcoders.com/webgl-chu-xue-xi-lie-zhi-si-ai.html

 前面已经给三角形添加了颜色,为了让其更加丰富多彩,我们这里继续向它添加纹理图片。在实际的应用当中,纹理的添加也比直接绘制颜色要多得多,因为添加纹理就可以让很多形状看起来更加逼真了,好吧,废话少说了,还是接着写。

一:添加纹理

   首先来看,我们要给三角形添加纹理,所以我们必须要先创建纹理。创建纹理首先得创建一个WebGL的纹理对象,然后将要显示的纹理绑定到纹理对象中。这里创建一个纹理的对象使用WebGL的createTexture()函数进行创建吗,返回一个纹理对象,紧接着用bindTexture将纹理对象进行绑定,最后,将数据拷贝到纹理。这里使用的WebGL API为 void texImage2D(GLenum target, GLint level, GLenum internalformat,GLenum format, GLenum type, HTMLImageElement image),具体函数的参数细节这里不多说了,可以去查查API。此函数的作用是将内存中的图片数据拷贝到纹理存储器中。代码如下:

                //创建一个纹理对象区间
                textObj = webgl.createTexture();
                //绑定文理对象
                webgl.bindTexture(webgl.TEXTURE_2D, textObj);
                //获得html中的原始图片
                var img = document.getElementById("texImg");
                //将图片数据拷贝到纹理中
                webgl.texImage2D(webgl.TEXTURE_2D, 0, webgl.RGB, webgl.RGB, webgl.UNSIGNED_BYTE, img);

二:渲染纹理

    接下来,就是需要看纹理是如何使用和渲染出来的。
    来看看,Shader程序如何编写。要将三角形绘制纹理,首先我们得对片段着色器进行处理,片段着色器中添加一个Uniform变量对纹理对象进行访问。通过uniform变量对其进行访问,需要知道uniform变量的关联索引。uniform变量管理索引由程序在链接时自动生成,我们通过getUniformLocation函数进行获取其索引。
    sampleTexIndex = canvas.getUniformLocation(shaderProgramObject, "sTexture");
    三角形要绘制纹理的位置当然由定点着色器决定,所以需要一个定点着色器算好后,通过varying变量传入片段着色器。但是纹理和渲染又不同,纹理坐标是左上角是(0,0)点右下角是(1, 1)点。设纹理坐标为(x1,y1),渲染坐标为(x2,y2),计算公式如下:
    x1= (x2 + 1.0)/2.0;
    y1= 1.0 - (y2 + 1.0)/2.0;
    所以,最后着色器的代码如下

       <script id="shader-vs" type="x-shader/x-vertex">
            attribute vec3 v3Position;
            varying vec2 vTexCood;
            void main()
            {
                vTexCood = vec2((v3Position.x+1.0)/2.0, 1.0-(v3Position.y+1.0)/2.0);
                gl_Position = vec4(v3Position, 1.0);
            }
        </script>
           
        <script id ="shader-fs" type ="x-shader/x-fragment">
            #ifdef GL_FRAGMENT_PRECISION_HIGH
                precision highp float;
            #else
                precision mediump float;
            #endif
            varying vec2 vTexCood;
            uniform sampler2D sTexture;
            void main()
            {
                gl_FragColor = texture2D(sTexture, vTexCood);
               // gl_FragColor = vec4(1.0,1.0,1.0, 1.0);
            }
        </script> 

    图像数据在纹理存储器中,在使用之前,要给其打上一个标示符。在片段着色器中通过整个纹理标识进行访问。当上标识之前必须激活标识。纹理单元为TEXTURE0,TEXTURE1,TEXTURE2...等等。纹理单元的数量还是有一定的限制,必须在getParameter(MAX_TEXTURE_IMAGE_UNITS)的返回值范围之内。
                //激活纹理标示0
                webgl.activeTexture(webgl.TEXTURE0);
                webgl.bindTexture(webgl.texImage2D, textObj);
                webgl.uniform1i(sampleTexIndex, 0);
 
三:完整代码 最后,给出完整代码
  <html>
 <head>
        <script type="text/javascript" src="../Js/InitWebGL.js"></script>
        <script id="shader-vs" type="x-shader/x-vertex">
            attribute vec3 v3Position;
            varying vec2 vTexCood;
            void main()
            {
                vTexCood = vec2((v3Position.x+1.0)/2.0, 1.0-(v3Position.y+1.0)/2.0);
                gl_Position = vec4(v3Position, 1.0);
            }
        </script>
 
        <script id ="shader-fs" type ="x-shader/x-fragment">
            #ifdef GL_FRAGMENT_PRECISION_HIGH
                precision highp float;
            #else
                precision mediump float;
            #endif
            varying vec2 vTexCood;
            uniform sampler2D sTexture;
            void main()
            {
                gl_FragColor = texture2D(sTexture, vTexCood);
               // gl_FragColor = vec4(1.0,1.0,1.0, 1.0);
            }
        </script>
 
        <script>
            var v3PositionIndex = 0;
            var sampleTexIndex = -1;
            var triangleBuffer = null;
            var triangleBuffer = null;
            var textObj = null;
 
            function initData(webgl)
            {
                //顶点坐标
                var jsArrayData = [
                     0.0, 1.0, 0.0,
                    -1.0, 0.0, -1.0,
                     1.0, 0.0, 0.0
                ]
 
                //创建一个webgl能够访问的缓冲
                triangleBuffer = webgl.createBuffer();
                //绑定buffer
                webgl.bindBuffer(webgl.ARRAY_BUFFER, triangleBuffer);
                //将js数据拷贝到buffer上
                webgl.bufferData(webgl.ARRAY_BUFFER, new Float32Array(jsArrayData), webgl.STATIC_DRAW);
 
                //创建一个纹理对象区间
                textObj = webgl.createTexture();
                //绑定文理对象
                webgl.bindTexture(webgl.TEXTURE_2D, textObj);
                //获得html中的原始图片
                var img = document.getElementById("texImg");
                //将图片数据拷贝到纹理中
                webgl.texImage2D(webgl.TEXTURE_2D, 0, webgl.RGB, webgl.RGB, webgl.UNSIGNED_BYTE, img);
 
            }
 
            function renderScene(webgl)
            {
                //清空屏幕
                webgl.clearColor(0.0, 0.0, 0.0, 1.0);
                webgl.clear(webgl.COLOR_BUFFER_BIT);
 
                //绑定顶点数据
                webgl.bindBuffer(webgl.ARRAY_BUFFER, triangleBuffer);
                //启动开关
                webgl.enableVertexAttribArray(v3PositionIndex);
                //制定数据索引原则
                webgl.vertexAttribPointer(v3PositionIndex, 3, webgl.FLOAT, false, 0, 0);
 
                //插值计算
                webgl.texParameteri(webgl.TEXTURE_2D, webgl.TEXTURE_MIN_FILTER, webgl.NEAREST);
                webgl.texParameteri(webgl.TEXTURE_2D, webgl.TEXTURE_MAG_FILTER, webgl.NEAREST);
                webgl.texParameteri(webgl.TEXTURE_2D, webgl.TEXTURE_WRAP_S, webgl.CLAMP_TO_EDGE);
                webgl.texParameteri(webgl.TEXTURE_2D, webgl.TEXTURE_WRAP_T, webgl.CLAMP_TO_EDGE);
 
                //激活纹理标示0
                webgl.activeTexture(webgl.TEXTURE0);
                webgl.bindTexture(webgl.texImage2D, textObj);
                webgl.uniform1i(sampleTexIndex, 0);
 
                //绘制数据
                webgl.drawArrays(webgl.TRIANGLES, 0, 3);
            }
 
            function init()
            {
                //获取webgl canvas
                var canvas = initCanvas("webglCanvas");
 
                //初始化shader程序
                var bind1 = [v3PositionIndex, "v3Position"];
                var bindData = new Array();
                bindData.push(bind1);
                var shaderProgramObject = initShaders(canvas, "shader-vs", "shader-fs", bindData);
 
                //获取Uniform变量在链接时生成的索引
                sampleTexIndex = canvas.getUniformLocation(shaderProgramObject, "sTexture");
                canvas.useProgram(shaderProgramObject);
 
                //初始化顶点数据
                initData(canvas);
 
                //渲染场景
                renderScene(canvas);
            }
        </script>
 </head>
 <body onload ="init()">
  <canvas id="webglCanvas" style="border:1px solid red" width="600" height="600"></canvas>
        <img id = "texImg" src="../Img/1.jpg" width="600" height="600"><img/>
 </body>
</html>>
四:效果展示

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值