【发布时间】:2021-01-21 09:05:56
【问题描述】:
我在 Firefox 中看到红色形状的边框周围有一些白色像素:
这是R附近区域的放大图。
我的期望
我得到了什么
但是片段着色器代码基本上只是检查一些条件,如果为真则写入一个红色像素,如果为假则从背景图像中写入信息。没有实施抗锯齿。所以我想知道,这些人工制品是从哪里来的?
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, ["vs", "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,
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,
u_resolution: [glCtx.canvas.width, glCtx.canvas.height]
});
}
cntrl.add(pmtrs, "ir", 0, 1).onChange(finsh);
cntrl.add(pmtrs, "or", 0, 1).onChange(finsh);
cntrl.add(pmtrs, "rt", 0, 3).onChange(finsh);
cntrl.add(pmtrs, "br", 0, 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, 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, v_texcoord + vec2(0, -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, 0.0, 1.0);
} else {
float tf = texture(u_original, v_texcoord).a;
f_color = vec4(1.0 - tf, 1.0 - tf, 1.0 - tf, 1.0);
}
}
</script>
【问题讨论】:
-
如果在
fs_warp着色器中将float tf = texture(u_original, v_texcoord).a;移动到if之前,有什么变化吗? -
是的,这行得通!感谢顺便说一句编辑我的问题!你知道为什么这确实有效吗?
-
没问题。我最初没有理解这个问题,因为原始屏幕截图中的工件太小了????。直到几天后,我再看一遍,才注意到那些小灰点。
标签: glsl antialiasing webgl2 visual-glitch