图形渲染之纹理贴图

本文详细介绍了在WebGL中如何处理2D纹理,包括创建WebGLTexture对象、绑定纹理、载入图像数据并上传到GPU,以及设置纹理参数。重点讲述了由于WebGL与HTML DOM Image对象坐标系的不同,需要通过gl.texImage2D()方法上传纹理,并通过gl.pixelStorei()方法处理纹理坐标翻转问题。最后,讨论了如何在缓冲中定义纹理坐标以便在绘制时使用。
摘要由CSDN通过智能技术生成

载入2D纹理

WebGL中最常见的纹理格式就是2D纹理,2D纹理的最基本形式就是使用单幅图像作为纹理。为了把2D纹理应用于几何对象,首先需要载入纹理。就是将普通图像文件的纹理载入到纹理对象中,然后将这幅图像作为2D纹理的输入数据。图像文件可以是PNG、JPEG或GIF格式。

创建WebGLTexture对象

在WebGL中使用纹理的第一个步骤是为每个纹理创建一个WebGLTexture对象。创建纹理对象要使用下面的代码:
var texture = gl.createTexture()
WebGLTexture是个容器对象,它可以作为纹理的引用,通过它访问与此纹理有关的处理参数。
还有个方法可以显式地删除一个WebGLTexture对象。例如,如果要删除一个名为Texture的纹理对象,则可以使用以下的代码:
gl.deleteTexture(texture);
注意,当结束使用纹理时,并不需要调用gl.deleteTexture()方法。JavaScript垃圾收集在销毁WebGLTexture对象时会自动删除相应的纹理对象。这个方法只是给用户提供更灵活的控制权,控制何时销毁纹理对象。

绑定纹理

对新创建的纹理对象做任何操作之前,首先需要把它绑定为当前纹理对象。例如为了把一个名为texture的纹理对象绑定为一个2D纹理对象,要用下面的代码:
gl.bindTexture(gl.TEXTURE_2D, texture);
调用gl.bindTexture()可告诉WebGL,这就是从现在起需要操作的纹理对象。这个方法与WebGLTexture纹理对象的关系就如同gl.bindBuffer()方法WebGLBuffer缓冲对象的关系。

载入图像数据

绑定了纹理对象后,我们就可以把图像数据载入纹理对象中,即把纹理数据传到GPU(或GPU可以访问的内存)。把纹理数据上传给GPU要使用gl.texlmage2D()方法,我们等会详细介绍,这个方法可以接受各种不同格式的纹理数据,但是当纹理是普通图像文件(PNG、GIF或JPEG)时,则它通常可以接受一个HTML DOM类型Image对象。因此,在调用gl.texlmage2D()方法之前,需要把数据保存在一个image对象中。
一个Image对象是由HTML文档中的标记显式创建得到的元素。但是调用下面的函数也可以显创建一个image对象:
image = new Image();
新建的Image对象是一个空对象,还没有载入任何图像数据。为了把图像数据载入image对象中,需要把Image对象的src属性设置为需要载入图像的URL。只要把图像的URL赋给这个src属性,系统就会按异步方式载入这个图像。
为了知道图像何时载入结束,可以使用onload事件。当图像载入结束时会立刻引发这个事件。下面这个代码创建一个Image对象,并载入图像数据:

function setupTexture() {
   
    myTexture = gl.createTexture();
    myTexture.image = new Image();
    myTexture.image.onload = function () {
   
        textureFinishedLoading(myTexture)
    }

    myTexture.image.src = "webgl.gif";
}

载入图像且onload事件触发匿名函数时,调用textureFinishedLoading()函数把处理过程转入下个步骤。在下个步骤中把图像数据上传给GPU。
在用JavaScript代码把图像数据载入一个Image对象时,一个常用的方法是把onload事件处理程序赋给Image对象。当我们想把一个Image对象作为WebGL中某个纹理的输入数据时,就是使用这种方法。
注意:纹理大小必须是2的n次方。在学习如何载入图像数据时,必须知道图像可接受的大小。开发人员经常选择宽度和高度都是2的n次方的图像(即图像的宽度和高度为1、2、4、8、16、32、64、128等值)。采用这种方法的理由之一是老式的GPU只支持纹理的宽度和高度都是2的n次方。桌面OpenGL 2.0及之后的版本实际上可以支持非2的n次方(NPOT)的纹理。在OpenGL ES2.0和WebGL中,允许使用NPOT纹理,但是存在以下限制:

  1. 如果使用NPOT纹理,则不能使用Mip映射贴图。
  2. 唯一允许使用的纹理包装模式是gl.CLAMP_TO_EDGE。

将纹理上传到GPU

为了把纹理上传到GPU,需要调用gl.texImage2D()方法。这个方法有多个不同的版本,
它们各有不同的参数,具体用法取决于用作纹理的数据类型。主要的3个原型如下所示:

void texImage2D(GLenum target, GLint level, GLenum internalformat, GLenum format, GLenum type, HTMLImageElement image) /* May throw DOMException */

void texImage2D(GLenum target, GLint level, GLenum internalformat, GLenum format, GLenum type, HTMLCanvasElement canvas) /* May throw DOMException */

void texImage2D(GLenum target, GLint level, GLenum internalformat, GLenum format, GLenum type, HTMLVideoElement video) /* May throw DOMException */ 

对于第一个版本,纹理数据是一个HTML DOM类型的image对象。第二个版本接受一个HTML5画布元素作为纹理的输入数据。最后一个版本接受一个视频元素作为纹理的输入数据。
接受HTML Image对象的版本可能会是我们最经常使用的方法。为了将Image对象上传到GPU,要像下面的代码那样调用gl.texImage2D()方法:

gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, texture.image);

第1个参数表示目标是一个2D纹理,第2个参数指定了Mip映射级别,这里必须把这个参数设置为0。
第3个参数表示内部格式,第4个参数表示格式,在WebGL中,这两个参数必须相同。在本例中,用gl.RGBA表示此纹理的每个纹素都有红、绿、蓝和alpha通道

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值