当前位置:首页 >百科 >一起学 WebGL:绘制图片 制图我是起学前端西瓜哥

一起学 WebGL:绘制图片 制图我是起学前端西瓜哥

2024-06-28 16:39:42 [百科] 来源:避面尹邢网

一起学 WebGL:绘制图片

作者:前端西瓜哥 开发 前端 纹理映射会根据纹理图像,起学将光栅化后的制图每个片元(像素点)设置对应颜色值。这些像素也称为 纹素(Texels,起学 Texture Elements)。

大家好,制图我是起学前端西瓜哥。之前讲解了如何用 WebGL 绘制红色三角形,制图今天西瓜哥带大家来学习如何将图片绘制到画布上的起学技术:纹理映射(texture mapping)。

一起学 WebGL:绘制图片 制图我是起学前端西瓜哥

纹理映射会根据纹理图像,制图将光栅化后的起学每个片元(像素点)设置对应颜色值。这些像素也称为 纹素(texels,制图 texture elements)。

一起学 WebGL:绘制图片 制图我是起学前端西瓜哥

纹理坐标

纹理图像的起学坐标系统是二维的,为和世界坐标的制图 x、y 区分,起学WebGL 对应使用 s、制图t 来表示。起学

一起学 WebGL:绘制图片 制图我是起学前端西瓜哥

目前纹理坐标更常用的命名是 uv。因为历史原因,WebGL 还是用的 st。

图片

和世界坐标系类似,宽高使用的是一个比例值,即真实像素位置除以宽高后得到的比例。

着色器

const vertexShaderSrc = `attribute vec4 a_Position;attribute vec2 a_TexCoord;varying vec2 v_TexCoord;void main() {  gl_Position = a_Position; v_TexCoord = a_TexCoord;}`;const fragmentShaderSrc = `precision highp float;uniform sampler2D u_Sampler;varying vec2 v_TexCoord;void main() {   gl_FragColor = texture2D(u_Sampler, v_TexCoord);}`;

相比绘制单色三角形,我们在顶点着色器加了 a_TexCoord,记录顶点对应的纹理坐标,因为纹理坐标只有两个维度,所以用的 vec2 属性。

并命名一个 v_TexCoord 的 varying 变量,用于将 a_TexCoord 的值传递给片元着色器。

片元着色器,声明了一个接收同名 v_TexCoord 变量 接收传过来的纹理坐标。

u_Sampler 是 sampler2D 类型,是一个二维纹理采样器,指定着色器提取颜色的纹理对象。texture2D(u_Sampler, v_TexCoord) 表示从 u_Sampler 纹理采样器中的某个位置中取出颜色。

传入顶点数据

将顶点位置和纹理位置对应好,放在一个缓冲区中,并设置读取规则。

先读第一个点的位置,然后是第一个点对应的纹理坐标。然后第二个点...

// 顶点坐标,纹理坐标const verticesTexCoords = 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,]);const FSIZE = verticesTexCoords.BYTES_PER_ELEMENT;// 创建缓存对象const verticesTexBuffer = gl.createBuffer();// 绑定缓存对象到上下文gl.bindBuffer(gl.ARRAY_BUFFER, verticesTexBuffer);// 向缓存区写入数据gl.bufferData(gl.ARRAY_BUFFER, verticesTexCoords, gl.STATIC_DRAW);// 获取 a_Position 变量地址const a_Position = gl.getAttribLocation(gl.program, 'a_Position');// 将缓冲区对象分配给 a_Position 变量gl.vertexAttribPointer(a_Position, 2, gl.FLOAT, false, FSIZE * 4, 0);// 允许访问缓存区gl.enableVertexAttribArray(a_Position);// 传入纹理坐标位置信息const a_TexCoord = gl.getAttribLocation(gl.program, 'a_TexCoord');gl.vertexAttribPointer(a_TexCoord, 2, gl.FLOAT, false, FSIZE * 4, FSIZE * 2);gl.enableVertexAttribArray(a_TexCoord);

纹理对象与图片绑定

/***** 纹理对象 *****/const texture = gl.createTexture(); // 创建纹理对象const u_Sampler = gl.getUniformLocation(gl.program, 'u_Sampler'); // 获取 u_Sampler 地址const img = new Image();img.onload = () => {   gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, 1); // 翻转纹理图像的 y 轴  gl.activeTexture(gl.TEXTURE0); // 开启 0 号纹理单元  gl.bindTexture(gl.TEXTURE_2D, texture); // 将我们的纹理对象绑定到 gl.TEXTURE_2D,类似绑定缓冲区对象  // 配置纹理参数  // 这里表示在 “绘制范围小于纹理尺寸” 时,使用 “加权平均” 算法缩小  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);    // 将纹理图像分配给纹理对象  gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, gl.RGB, gl.UNSIGNED_BYTE, img);  // 使用 0 号纹理单元  gl.uniform1i(u_Sampler, 0);  /

(责任编辑:娱乐)

    推荐文章
    热点阅读