You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在WebGL着色器中为每个像素获取position属性

如何在WebGL中为每个像素提供独立的vec3位置值

你需要利用WebGL的**顶点属性(attribute)和插值变量(varying)**来实现每个像素获取独立的位置值,核心逻辑是:给每个顶点传入不同的vec3位置,通过varying让WebGL在光栅化时自动为每个像素插值计算出对应的位置值。

具体修改步骤:

  1. 更新顶点数据
    你当前的coords是2D顶点坐标,需要扩展为3D位置数据。比如给四边形四个顶点设置不同的z值,或根据需求定义每个顶点的vec3位置:

    // 示例:四个顶点的3D位置(x,y,z)
    this.coords = new Float32Array([
      -1.0, -1.0, 0.0,  // 左下角
       1.0, -1.0, 0.0,  // 右下角
       1.0,  1.0, 0.5,  // 右上角
      -1.0,  1.0, 0.5   // 左上角
    ]);
    
  2. 修改绘制代码中的属性配置
    在draw函数中,新增对3D位置属性的绑定和配置(需提前通过gl.getAttribLocation获取positionAttrib的位置):

    draw(gl) {
      gl.useProgram(this.prog);
    
      // 绑定并设置3D位置属性
      gl.bindBuffer(gl.ARRAY_BUFFER, this.coordsBuffer);
      gl.bufferData(gl.ARRAY_BUFFER, this.coords, gl.STREAM_DRAW);
      // 第二个参数设为3,对应vec3类型
      gl.vertexAttribPointer(this.positionAttrib, 3, gl.FLOAT, false, 0, 0);
      gl.enableVertexAttribArray(this.positionAttrib);
    
      // 原有uniform配置保持不变
      gl.uniform2fv(this.inTexCoordUni, this.inTexCoord);
      gl.uniform1f(this.rotationUni, this.rotation);
      gl.uniform2fv(this.dimensionsUni, this.dimensions);
      gl.uniform1f(this.borderWidthUni, this.borderWidth);
      gl.uniform2fv(this.positionUni, this.position);
      
      gl.drawArrays(gl.TRIANGLE_FAN, 0, 4);
    }
    
  3. 修改顶点着色器
    添加3D位置的attribute和用于插值的varying变量,将顶点位置传递给片元着色器:

    precision mediump float;
    
    uniform vec2 position1;
    uniform vec2 textureSize_;
    uniform vec2 inTexCoord;
    uniform float rotation;
    varying vec2 texCoord;
    varying vec2 center;
    // 新增:3D位置属性
    attribute vec3 position;
    // 新增:用于插值的varying变量
    varying vec3 vPosition;
    
    attribute vec2 coords1;
    
    void main() {
      gl_Position = vec4(coords1, 0.0, 1.0);
    
      // 传递顶点位置给varying,WebGL会自动为每个像素插值
      vPosition = position;
    
      // 原有逻辑保持不变
      float inX = (inTexCoord.x/textureSize_.x);
      float inY = (inTexCoord.y/textureSize_.y);
    
      float x = position1.x*2.5/textureSize_.x+inX;
      float y = position1.y*2.5/textureSize_.y+inY;
          
      float s = sin(rotation);
      float c = cos(rotation);
    
      float dX = x - inX;
      float dY = y - inY;
          
      float newX = inX + c * dX - s * dY;
      float newY = inY + s * dX + c * dY;
    
      center.x = inTexCoord.x/textureSize_.x;
      center.y = inTexCoord.y/textureSize_.y;
      texCoord.x = newX;
      texCoord.y = newY;
    }
    
  4. 修改片元着色器
    接收插值后的varying变量,此时每个像素都能获取到独立的vec3位置值:

    precision mediump float;
    
    uniform vec2 textureSize_;
    uniform sampler2D texture1;
    uniform vec2 dimensions;
    uniform float borderWidth;
    varying vec2 texCoord;
    varying vec2 center;
    // 新增:接收插值后的3D位置
    varying vec3 vPosition;
    
    void main() {
      // 现在vPosition就是当前像素的3D位置值(基于顶点插值计算)
      // 可直接使用该值,比如调整颜色:gl_FragColor.r = vPosition.z;
    
      // 原有逻辑保持不变
      float dx = texCoord.x - center.x;
      float dy = texCoord.y - center.y;
      float dist = sqrt(dx * dx + dy * dy);
      float radius = (dimensions.x*2.5/textureSize_.x)/2.0-0.003;
      if(dist > radius)
        discard;
      else if(dist > radius-borderWidth)
        gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);
      else
        gl_FragColor = vec4(texture2D(texture1, texCoord).rgb, 1.0);
    }
    

关键原理说明:

  • attribute:每个顶点对应一个独立值,你给四边形的四个顶点传入不同的vec3位置,顶点着色器会逐个处理这些值。
  • varying:顶点着色器输出的varying变量会在WebGL光栅化阶段自动进行插值计算,最终片元着色器中的每个像素都会得到基于周围顶点位置平滑过渡的数值,实现每个像素拥有独立的position值。
  • 你之前的误解:uniform是全局统一值,但attribute是每个顶点独立值,结合varying的插值就能让每个像素获得不同的结果。

内容的提问来源于stack exchange,提问作者aa bb

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.21 14:06:18