看起来像抗锯齿故障的白色像素 6 次纹理访问

问题描述

我在 Firefox 中看到红色形状的边框周围有一些白色像素:

这是 R 附近区域的放大图。

我的期望

good

我得到了什么

enter image description here

但是片段着色器代码基本上只是检查一些条件,如果为真则写入一个红色像素,如果为假则从背景图像中写入信息。没有实现抗锯齿。所以我想知道,这些人工制品是从哪里来的?

twgl.setDefaults({ attribPrefix: "a_" });
const bdrSz = 50;
const cntrl = new dat.GUI();
const glCtx = twgl.getContext(document.createElement("canvas"));
const imgLc =
  "https://upload.wikimedia.org/wikipedia/commons/8/85/BlackRock_wordmark.svg";
// const imgLc =
//   "https://upload.wikimedia.org/wikipedia/commons/8/8e/Panasonic_logo_%28Blue%29.svg";
const pmtrs = { ir: 0.3,or: 0.4,rt: 2,br: 0.1,ri: 10 };
const width = 1200;
let buffr;
let dmnsn;
let pgInf = {
  blr: twgl.createProgramInfo(glCtx,["vs","fs_blur"]),wrp: twgl.createProgramInfo(glCtx,"fs_warp"])
};
let qBInf = twgl.primitives.createXYQuadBufferInfo(glCtx);
let imgTx;
function nrmlz(arr) {
  let sum = arr.reduce((v,w) => v + w[0] * w[1],0);
  return arr.map((v) => v[0] / sum);
}
function rendr(fbi,pi,u) {
  twgl.bindFramebufferInfo(glCtx,fbi);
  twgl.drawObjectList(glCtx,[
    {
      programInfo: pi,bufferInfo: qBInf,uniforms: u
    }
  ]);
}
function prepr() {
  let img = new Image();
  img.crossOrigin = "Anonymous";
  img.src = imgLc;
  img.onload = function () {
    let ctx = document.createElement("canvas").getContext("2d");
    ctx.canvas.width = glCtx.canvas.width = width;
    ctx.canvas.height = glCtx.canvas.height =
      (img.height * (width - 2 * bdrSz)) / img.width + 2 * bdrSz;
    buffr = twgl.createFramebufferInfo(
      glCtx,[
        {
          internalFormat: glCtx.R32F
        }
      ],ctx.canvas.width,ctx.canvas.height
    );
    document.body.append(glCtx.canvas);
    ctx.drawImage(
      img,bdrSz,ctx.canvas.width - 2 * bdrSz,ctx.canvas.height - 2 * bdrSz
    );
    imgTx = twgl.createTexture(glCtx,{ flipY: 1,src: ctx.canvas });
    compt();
  };
}
function compt() {
  let bra = Math.max(2,Math.floor(pmtrs.br * glCtx.canvas.height));
  let knl = twgl.createTexture(glCtx,{
    height: bra,internalFormat: glCtx.R32F,src: nrmlz(
      Array(bra)
        .fill()
        .map((_,i) =>
          Array(bra)
            .fill()
            .map((_,j) => [
              Math.exp(-((i / bra) ** 2 + (j / bra) ** 2)),i == 0 && j == 0 ? 1 : i == j || i == 0 || j == 0 ? 4 : 8
            ])
        )
        .flat()
    ),width: bra
  });
  rendr(buffr,pgInf.blr,{
    u_kernel: knl,u_radius: bra,u_resolution: [glCtx.canvas.width,glCtx.canvas.height],u_texture: imgTx
  });
  finsh();
}
function finsh() {
  rendr(null,pgInf.wrp,{
    u_blurred: buffr.attachments[0],u_original: imgTx,u_innerRadius: pmtrs.ir,u_outerRadius: pmtrs.or,u_ratio: pmtrs.rt,u_refIndex: pmtrs.ri,glCtx.canvas.height]
  });
}
cntrl.add(pmtrs,"ir",1).onChange(finsh);
cntrl.add(pmtrs,"or","rt",3).onChange(finsh);
cntrl.add(pmtrs,"br",0.1).onChange(compt);
cntrl.add(pmtrs,"ri",-10,10).onChange(finsh);
prepr();
<script src="https://cdnjs.cloudflare.com/ajax/libs/dat-gui/0.7.7/dat.gui.min.js"></script>
<script src="https://twgljs.org/dist/4.x/twgl-full.min.js"></script>
<script id="vs" type="x-shader/x-vertex">
  #version 300 es
  in vec4 a_position;
  in vec2 a_texcoord;
    
  out vec2 v_texcoord;

  void main() {
    v_texcoord = a_texcoord;
    gl_Position = a_position;
  }
</script>
<script id="fs_blur" type="x-shader/x-fragment">
  #version 300 es
  precision highp float;

  in vec2 v_texcoord;

  uniform sampler2D u_kernel;
  uniform int u_radius;
  uniform vec2 u_resolution;
  uniform sampler2D u_texture;

  out vec4 f_color;

  void main() {
    float sum = 0.0;
    for(int i = -u_radius + 1; i < u_radius; i++) {
      for(int j = -u_radius + 1; j < u_radius; j++) {
        sum += texture(u_kernel,vec2(abs(i),abs(j)) / float(u_radius)).r *
          texture(u_texture,v_texcoord + vec2(i,j) / u_resolution).a;
      }
    }
    f_color = vec4(sum,1.0,1.0);
  }
</script> 
<script id="fs_warp" type="x-shader/x-fragment">
  #version 300 es
  precision highp float;

  in vec2 v_texcoord;

  uniform sampler2D u_blurred;
  uniform sampler2D u_original;
  uniform float u_innerRadius;
  uniform float u_outerRadius;
  uniform float u_ratio;
  uniform float u_refIndex;
  uniform vec2 u_resolution;

  out vec4 f_color;

  void main() {
    vec2 ref = v_texcoord + u_refIndex * (
      texture(u_blurred,v_texcoord + vec2(0,1) / u_resolution).r -
      texture(u_blurred,-1) / u_resolution).r +
      texture(u_blurred,v_texcoord + vec2(1,0) / u_resolution).r -
      texture(u_blurred,v_texcoord + vec2(-1,0) / u_resolution).r
    );
    float len = length(2.0 * (ref - 0.5) / vec2(u_ratio,1));
    if(u_innerRadius < len && len < u_outerRadius) {
      f_color = vec4(1.0,0.0,1.0);
    } else {
      float tf = texture(u_original,v_texcoord).a;
      f_color = vec4(1.0 - tf,1.0 - tf,1.0);
    }
  }
</script> 

解决方法

所以 AFAIK 的问题是您不能在条件中使用纹理查找,否则它们会破坏您的变量

来自the GLSL ES 1.0 spec附录 A

6 次纹理访问

在非均匀条件块的主体内访问 mip 映射纹理会给出未定义的 价值。非一致条件块是在编译时无法确定其执行的块 时间

the GLSL ES 3.0 spec第 8.8 节

某些纹理函数(非“Lod”和非“Grad”版本)可能需要隐式导数。 隐式 导数在非统一控制流中未定义和顶点纹理提取。

换句话说,您需要在 fs_warp 着色器中移动此行

float tf = texture(u_original,v_texcoord).a;

if 语句之外。

不幸的是,它是否会得到糟糕的结果取决于 GPU,所以如果你不走运,你不会遇到这个问题,但你的一些用户会。幸运的是,您遇到了这个问题,因此您可以解决它。

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...