WebGL 纹理颜色原理

站长手记 作者: 2024-08-28 03:40:02
WebGL绘制图像时,往着色器中传入颜色信息就可以给图形绘制出相应的颜色,现在已经知道顶点着色器和片段着色器一起决定着向颜色缓冲区写入颜色信息并最终呈现出来,那么这个过程是什么样

导语

颜色缓冲区

图形装配

// 顶点着色器
const VSHADER_SOURCE =
 `attribute vec4 a_Position;
  void main() {
    gl_Position = a_Position;
  }`;

// 片段着色器
const FSHADER_SOURCE =
 `void main() {
    gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
  }`;

光栅化

// 顶点着色器
const VSHADER_SOURCE =
 `attribute vec4 a_Position;
  attribute vec4 a_Color;
  varying vec4 v_Color;
  void main() {
    gl_Position = a_Position;
    v_Color = a_Color;
  }`;

// 片段着色器
const FSHADER_SOURCE =
 `varying vec4 v_Color;
  void main() {
    gl_FragColor = v_Color;
  }`;

纹理贴图

  • 加载好需要的纹理图像
  • 设置纹理坐标
  • 对纹理进行配置
  • 片段着色器抽出纹素并赋值给片元
function main() {
  const canvas = document.getElementById('webgl');

  const webgl = getWebGLContext(canvas);
  webgl.images = {};

  // 初始化之前先加载图片
  loadImage([
    `src/images/0.jpeg`,
  ], webgl).then((gl) => {
    if (!initShaders(gl, VSHADER_SOURCE, FSHADER_SOURCE)) {
      console.log('Failed to intialize shaders.');
      return;
    }

    gl.clearColor(0, 0, 0, 1);
    gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);

    const n = initVertexBuffers(gl);
    initTextures(gl, n, 0);
  });
}
function initVertexBuffers(gl) {
  // 顶点坐标和纹理图像坐标
  const vertices = new Float32Array([
    -0.3, 0.7, 0.0, 0.0, 1.0,
   -0.3, -0.7, 0.0, 0.0, 0.0,
    0.3, 0.7, 0.0, 1.0, 1.0,
    0.3, -0.7, 0.0, 1.0, 0.0,
  ]);

  const FSIZE = vertices.BYTES_PER_ELEMENT;

  const vertexBuffer = gl.createBuffer();

  gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
  gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);

  const a_Position = gl.getAttribLocation(gl.program, 'a_Position');
  const a_TexCoord = gl.getAttribLocation(gl.program, 'a_TexCoord');

  gl.vertexAttribPointer(a_Position, 3, gl.FLOAT, false, FSIZE * 5, 0);
  gl.enableVertexAttribArray(a_Position);

  gl.vertexAttribPointer(a_TexCoord, 2, gl.FLOAT, false, FSIZE * 5, FSIZE * 3);
  gl.enableVertexAttribArray(a_TexCoord);

  return 4;
}
function initTextures(gl, n, index) {
  // 创建纹理对象
  const texture = gl.createTexture();
  const u_Sampler = gl.getUniformLocation(gl.program, 'u_Sampler');
  const image = gl.images[index];

  // WebGL纹理坐标中的纵轴方向和PNG,JPG等图片容器的Y轴方向是反的,所以先反转Y轴
  gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, 1);

  // 激活纹理单元,开启index号纹理单元
  gl.activeTexture(gl[`TEXTURE${index}`]);

  // 绑定纹理对象
  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.LINEAR);

  // 将纹理图像分配给纹理对象
  gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image);

  // 将纹理单元编号传给着色器
  gl.uniform1i(u_Sampler, index);

  // 绘制
  gl.drawArrays(gl.TRIANGLE_STRIP, 0, n);
}
  • 伸展(gl.TEXTURE_MAX_FILTER): 绘制图形比纹理图像大的时候怎么取纹素,默认值gl.LINEAR
  • 收缩(gl.TEXTURE_MIN_FILTER): 绘制图形比纹理图像小的时候怎么取纹素, 默认值gl.NEAREST_MIP_LINEAR
  • 水平填充(gl.TEXTURE_WRAP_S): 定义绘制图形水平方向如何填充,默认值gl.REPEAT
  • 垂直填充(gl.TEXTURE_WRAP_T): 定义绘制图形垂直方向如何填充,默认值gl.REPEAT
const VSHADER_SOURCE =
 `attribute vec4 a_Position;
  attribute vec2 a_TexCoord;
  varying vec2 v_TexCoord;
  void main() {
    gl_Position = a_Position;
    v_TexCoord = a_TexCoord;
  }`;

const FSHADER_SOURCE =
 `precision mediump float;
  uniform sampler2D u_Sampler;
  varying vec2 v_TexCoord;
  void main() {
    gl_FragColor = texture2D(u_Sampler, v_TexCoord);
  }`;

多纹理实现

本文由云+社区发表,作者:ivweb qcyhust
原创声明
本站部分文章基于互联网的整理,我们会把真正“有用/优质”的文章整理提供给各位开发者。本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
本文链接:http://www.jiecseo.com/news/show_69910.html
WebG WebGL绘制图像