在一个顶点中,我给pointSize赋予一个大于1的值。说15。 在片段中,我想在15x15正方形内选择一个点:
vec2 sprite = gl_PointCoord;
if (sprite.s == (9. )/15.0 ) discard ;
gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);
但是,如果Size不是2的幂,那将不起作用。
(如果大小为16,那么(sprite.s == a / 16。)其中a在1..16中:完美!)
是实现我的目标的一种方法,其中大小不是2的幂?
编辑:我知道具有大小纹理的解决方案:PointSize * PointSize
gl_FragColor = texture2D(tex, gl_PointCoord);
但不适合动态更改
编辑7月26日:
首先,我不明白为什么使用webgl2而不是webgl更容易读取浮动纹理。就我而言,我做一个ext = gl.getExtension(“ OES_texture_float”);而gl.readpixel使用相同的语法。
然后,可以肯定的是我什么都不懂,但是我尝试对正确居中的2x2像素尝试s = 0.25和s = 0.75的解决方案,但这似乎不起作用。 另一方面,值0.5和1.0为我提供了正确的显示(请参见小提琴1)
(小提琴1)https://jsfiddle.net/3u26rpf0/274/
实际上,为了准确显示任何大小的顶点(例如SIZE),我使用以下公式:
float size = 13.0;
float nby = floor ((size) /2.0);
float nbx = floor ((size-1.0) /2.0);
//
// <nby> pixels CENTER <nbx> pixels
//
// if size is odd nbx == nby
// if size is even nbx == nby +1
vec2 off = 2. * vec2 (nbx, nby) / canvasSize;
vec2 p = -1. + (2. * (a_position.xy * size) + 1.) / canvasSize + off;
gl_Position vec4 = (p, 0.0,1.0);
gl_PointSize = size;
答案 0 :(得分:1)
用浮点数检查精确值通常不是一个好主意。检查范围
sprite.s > ??? && sprite.s < ???
或者更好地考虑使用蒙版纹理或比硬编码的if语句更灵活的东西。
否则,在WebGL中,像素由其中心引用。因此,如果您在像素边界上绘制2x2点,则这些值应为.s
的{{1}}值。
gl_PointCoord
如果您将其画出像素边界,则取决于情况
+-----+-----+
| .25 | .75 |
| | |
+-----+-----+
| .25 | .75 |
| | |
+-----+-----+
它仍将仅绘制4个像素(最接近该点所在的4个像素),但它将选择不同的gl_PointCoords,就好像它可以绘制小数像素一样。如果我们使++=====++=====++======++
|| || || ||
|| +------+------+ ||
|| | | | ||
++==| | |===++
|| | | | ||
|| +------+------+ ||
|| | | | ||
++==| | |===++
|| | | | ||
|| +------+------+ ||
|| || || ||
++=====++=====++======++
偏移,使得我们的点超出了0.25像素,则它仍将与像素对齐时绘制完全相同的4像素,因为偏移量.25不足以将其移出绘制相同的4像素,因此我们可以猜测是将gl_Position
偏移-.25像素(在我们的示例中是2x2点,偏移量是.125,因此(.25--.125)= .125和(.75-.125)=。 675。
我们可以通过使用WebGL2将WebGL写入浮点纹理中来测试WebGL的用途(因为更容易从WebGL2中读取浮点像素)
gl_PointCoord
function main() {
const gl = document.createElement("canvas").getContext("webgl2");
if (!gl) {
return alert("need WebGL2");
}
const ext = gl.getExtension("EXT_color_buffer_float");
if (!ext) {
return alert("need EXT_color_buffer_float");
}
const vs = `
uniform vec4 position;
void main() {
gl_PointSize = 2.0;
gl_Position = position;
}
`;
const fs = `
precision mediump float;
void main() {
gl_FragColor = vec4(gl_PointCoord.xy, 0, 1);
}
`;
const programInfo = twgl.createProgramInfo(gl, [vs, fs]);
const width = 2;
const height = 2;
// creates a 2x2 float texture and attaches it to a framebuffer
const fbi = twgl.createFramebufferInfo(gl, [
{ internalFormat: gl.RGBA32F, minMag: gl.NEAREST, },
], width, height);
// binds the framebuffer and set the viewport
twgl.bindFramebufferInfo(gl, fbi);
gl.useProgram(programInfo.program);
test([0, 0, 0, 1]);
test([.25, .25, 0, 1]);
function test(position) {
twgl.setUniforms(programInfo, {position});
gl.drawArrays(gl.POINTS, 0, 1);
const pixels = new Float32Array(width * height * 4);
gl.readPixels(0, 0, 2, 2, gl.RGBA, gl.FLOAT, pixels);
console.log('gl_PointCoord.s at position:', position.join(', '));
for (y = 0; y < height; ++y) {
const s = [];
for (x = 0; x < width; ++x) {
s.push(pixels[(y * height + x) * 4]);
}
console.log(`y${y}:`, s.join(', '));
}
}
}
main();
<script src="https://twgljs.org/dist/4.x/twgl.min.js"></script>
的公式位于the spec section 3.3
因此,从2个像素宽度的点开始,一个点从0个像素边界上绘制了0.25个像素
gl_PointCoord
这是我从上面的示例中获得的值。
drawing a 2x2 at .25,.25 (slightly off center)
// first pixel
// this value is constant for all pixels. It is the unmodified
// **WINDOW** coordinate of the **vertex** (not the pixel)
xw = 1.25
// this is the integer pixel coordinate
xf = 0
// gl_PointSize
size = 2
s = 1 / 2 + (xf + 1 / 2 - xw) / size
s = .5 + (0 + .5 - 1.25) / 2
s = .5 + (-.75) / 2
s = .5 + (-.375)
s = .125
是顶点的窗口x坐标。换句话说,xw
是基于我们将xw
设置为如此的
gl_Position
或更具体地说
xw = (gl_Position.x / gl_Position.w * .5 + .5) * canvas.width
在xw = (gl_Position.x / gl_Position.w * .5 + .5) * viewportWidth + viewportX
和viewportX
设置为viewportWidth
的情况下,默认大小与画布相同。