webgl 添加 texture

85 阅读1分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第1天,点击查看活动详情

上次写了在《webgl中实现三角形》,我们这次修改一下为它加上texture

分析

先分析想为三角形上texture,我们需要做什么

  1. 请求图片资源,拿到图片的数据
  2. 修改着色器
  3. 将图片的坐标与三角形的坐标匹配
  4. 绑定纹理坐标与绘制

请求图片资源,拿到图片的数据

我们可以创建img标签,赋值上url 通过onLoad判断是否请求完


  function initTextures({ gl, n, src }) {
    var texture = gl.createTexture();
    var u_sampler = gl.getUniformLocation(gl.program, "u_image");
    var image = new Image();
    image.onload = function () {
      loadTexture({ gl, n, texture, u_sampler, image });
    };
    image.src = src;
    return true;
  }
  

修改着色器

我们需要将uv坐标从顶点着色器中提供到片段着色器,所以需要声明两个变量a_textCoord、v_textCoord,直接将a_textCoord赋值给v_textCoord就行了,这样这个会传到片段着色器中,而片段着色器中我们声明纹理,并且从纹理坐标读取到正确的映射

const vertexCode = `
   attribute vec4 a_position;
   attribute vec2 a_textCoord;
   varying vec2 v_textCoord;

   void main(){
    gl_Position = a_position;
    v_textCoord = a_textCoord;
  }
  `;
  const fragmentCode = `
  precision mediump float;
  varying vec2 v_textCoord;
  uniform sampler2D u_image;
  void main(){

    gl_FragColor = texture2D(u_image, v_textCoord);
  }

`;

将图片的坐标与三角形的坐标匹配

texture的坐标是从左上角开始的,Y向下,X向左

 const aTextCoordLocation = gl.getAttribLocation(gl.program, "a_textCoord");
 gl.vertexAttribPointer(
   aTextCoordLocation,
   2,
   gl.FLOAT,
   false,
   FSIZE * 4,
   FSIZE * 2
);

绑定纹理坐标与如何绘制

先将创建的texture绑定到上下文中,然后声明越界的如何处理,最后绘制即可

function loadTexture({ gl, n, texture, u_sampler, image }) {
    gl.bindTexture(gl.TEXTURE_2D, texture);
    
    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.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
    
    gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, gl.RGB, gl.UNSIGNED_BYTE, image);

    gl.clear(gl.COLOR_BUFFER_BIT); 

    gl.drawArrays(gl.TRIANGLE_STRIP, 0, n); 
  }

最后绘制即可。