当前位置: 首页 > article >正文

【WebGL】纹理

背景

记录下纹理相关容易忘记的地方

texImage2D

根据数据源不同,有多个重载函数

上传 HTML 元素(图片、视频、Canvas 等)
gl.texImage2D(target, level, internalformat, format, type, source);

参数说明:

  • target: 目标纹理类型(如 gl.TEXTURE_2D)。
  • level: Mipmap 级别(通常为 0)。
  • internalformat: 纹理的内部格式(如 gl.RGBA)。
  • format: 数据的格式(如 gl.RGBA)。
  • type: 数据类型(如 gl.UNSIGNED_BYTE)。
  • source: HTML 元素(如 HTMLImageElement, HTMLCanvasElement, HTMLVideoElement, 或 ImageBitmap)
const image = new Image();
image.onload = () => {
  gl.bindTexture(gl.TEXTURE_2D, texture);
  gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image);
};
image.src = 'texture.png';
上传 TypedArray 数据
gl.texImage2D(target, level, internalformat, width, height, border, format, type, pixels);

参数说明:

  • target: 目标纹理类型(如 gl.TEXTURE_2D)。
  • level: Mipmap 级别(通常为 0)。
  • internalformat: 纹理的内部格式(如 gl.RGBA)。
  • width: 纹理的宽度。
  • height: 纹理的高度。
  • border: 边框大小(在 WebGL 中必须为 0)。
  • format: 数据的格式(如 gl.RGBA)。
  • type: 数据类型(如 gl.UNSIGNED_BYTE)。
  • pixels: 包含像素数据的 TypedArray(如 Uint8Array, Float32Array 等)或 null。
const width = 256;
const height = 256;
const data = new Uint8Array(width * height * 4); // RGBA 数据

gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, width, height, 0, gl.RGBA, gl.UNSIGNED_BYTE, data);

activeTexture

gl.activeTexture(textureUnit);
  • textureUnit:指定要激活的纹理单元。
    通常为 gl.TEXTURE0 到 gl.TEXTURE31,表示可以同时激活的 32 个纹理单元之一。
    gl.TEXTURE0 是默认的活动纹理单元。意思你不执行这行代码,默认也是gl.TEXTURE0被激活的

完整案例

在这里插入图片描述

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>WebGL Textured Triangle</title>
  <style>
    canvas {
      display: block;
      margin: auto;
      background: #000;
    }
  </style>
</head>
<body>
  <canvas id="webgl-canvas" width="800" height="600"></canvas>

  <script>
    const vertexShaderSource = `
      attribute vec2 aPosition;
      attribute vec2 aTexCoord;
      varying vec2 vTexCoord;
      void main() {
          gl_Position = vec4(aPosition, 0.0, 1.0);
          vTexCoord = aTexCoord; // Pass texture coordinates to the fragment shader
      }
    `;

    const fragmentShaderSource = `
      precision mediump float;
      varying vec2 vTexCoord;
      uniform sampler2D uTexture;
      void main() {
          gl_FragColor = texture2D(uTexture, vTexCoord); // Sample the texture
      }
    `;

    function createShader(gl, type, source) {
      const shader = gl.createShader(type);
      gl.shaderSource(shader, source);
      gl.compileShader(shader);
      if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
        console.error('Shader compile error:', gl.getShaderInfoLog(shader));
        gl.deleteShader(shader);
        return null;
      }
      return shader;
    }

    function createProgram(gl, vertexShader, fragmentShader) {
      const program = gl.createProgram();
      gl.attachShader(program, vertexShader);
      gl.attachShader(program, fragmentShader);
      gl.linkProgram(program);
      if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
        console.error('Program link error:', gl.getProgramInfoLog(program));
        gl.deleteProgram(program);
        return null;
      }
      return program;
    }

    function initWebGL() {
      const canvas = document.getElementById('webgl-canvas');
      const gl = canvas.getContext('webgl2');
      if (!gl) {
        console.error('WebGL not supported');
        return;
      }

      // Compile shaders and link program
      const vertexShader = createShader(gl, gl.VERTEX_SHADER, vertexShaderSource);
      const fragmentShader = createShader(gl, gl.FRAGMENT_SHADER, fragmentShaderSource);
      const program = createProgram(gl, vertexShader, fragmentShader);

      // Triangle vertices and texture coordinates
      const vertices = new Float32Array([
        // Positions    // Texture coordinates
         0.0,  0.5,     0.5, 1.0,   // Top vertex
        -0.5, -0.5,     0.0, 0.0,   // Bottom-left vertex
         0.5, -0.5,     1.0, 0.0    // Bottom-right vertex
      ]);

      // Set up buffers
      const vao = gl.createVertexArray();
      gl.bindVertexArray(vao);

      const vbo = gl.createBuffer();
      gl.bindBuffer(gl.ARRAY_BUFFER, vbo);
      gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);

      const aPosition = gl.getAttribLocation(program, 'aPosition');
      gl.vertexAttribPointer(aPosition, 2, gl.FLOAT, false, 4 * Float32Array.BYTES_PER_ELEMENT, 0);
      gl.enableVertexAttribArray(aPosition);

      const aTexCoord = gl.getAttribLocation(program, 'aTexCoord');
      gl.vertexAttribPointer(aTexCoord, 2, gl.FLOAT, false, 4 * Float32Array.BYTES_PER_ELEMENT, 2 * Float32Array.BYTES_PER_ELEMENT);
      gl.enableVertexAttribArray(aTexCoord);

      // Load texture
      const texture = gl.createTexture();
      const image = new Image();
      image.crossOrigin = 'anonymous'; // Allow cross-origin for external images
      image.src = 'https://webglfundamentals.org/webgl/resources/leaves.jpg'; // Replace with your texture image URL
      image.onload = () => {
        gl.bindTexture(gl.TEXTURE_2D, texture);
        gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image);

        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
        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);

        render(); // Start rendering after the texture is loaded
      };

      function render() {
        gl.clearColor(0.0, 0.0, 0.0, 1.0);
        gl.clear(gl.COLOR_BUFFER_BIT);

        gl.useProgram(program);
        gl.bindVertexArray(vao);

        //gl.activeTexture(gl.TEXTURE0);
        //gl.bindTexture(gl.TEXTURE_2D, texture);
        gl.uniform1i(gl.getUniformLocation(program, 'uTexture'), 0);

        gl.drawArrays(gl.TRIANGLES, 0, 3);

        // Request the next frame
        requestAnimationFrame(render);
      }
    }

    initWebGL();
  </script>
</body>
</html>


http://www.kler.cn/a/523837.html

相关文章:

  • mybatis(134/134)完结
  • Helm Chart 实战指南
  • 2501,20个窗口常用操作
  • 万物皆有联系:驼鸟和布什
  • Ubuntu介绍、与centos的区别、基于VMware安装Ubuntu Server 22.04、配置远程连接、安装jdk+Tomcat
  • 【HarmonyOS之旅】基于ArkTS开发(三) -> 兼容JS的类Web开发(三)
  • 【某大厂一面】java深拷贝和浅拷贝的区别
  • 顶刊JFR|ROLO-SLAM:首个针对不平坦路面的车载Lidar SLAM系统
  • 基于Python的智慧物业管理系统
  • aws sagemaker api 获取/删除 endpoints
  • ResNeSt: Split-Attention Networks论文学习笔记
  • MATLAB基础应用精讲-【数模应用】DBSCAN算法(附MATLAB、R语言和python代码实现)(二)
  • 54.数字翻译成字符串的可能性|Marscode AI刷题
  • Next.js 14 TS 中使用jwt 和 App Router 进行管理
  • 基于 NodeJs 一个后端接口的创建过程及其规范 -- 【elpis全栈项目】
  • oracle比较一下统计信息差异吧
  • Vue 响应式渲染 - 列表布局和v-html
  • 【2024年华为OD机试】(C卷,200分)- 推荐多样性 (JavaScriptJava PythonC/C++)
  • kaggle-ISIC 2024 - 使用 3D-TBP 检测皮肤癌-学习笔记
  • go 循环处理无限极数据
  • 【llm对话系统】大模型 RAG 之回答生成:融合检索信息,生成精准答案
  • HTML表单深度解析:GET 和 POST 提交方法
  • linux监控脚本+自动触发邮件发送
  • 【AI】【本地部署】OpenWebUI的升级并移植旧有用户信息
  • 面向对象编程 vs 面向过程编程
  • React第二十七章(Suspense)