我正在openGL中使用一个四元组和一个纹理图集实现2d视差滚动。
我使用以下公式(偏移量为1.0/层数,因此为0.2):
它几乎可以完美地工作,但在某些偏移处,循环点处的接缝是可见的。(看中间墙上的裂缝,它揭示了城堡和背后的海洋。)
我的算法是:
在每个片段上,计算偏移*i处纹理中的位置;如果颜色是透明的,则移动到偏移*(i+1)等。当遇到纯色时停止。同样,偏移量为1.0/(层数),此处为0.2。
在上面的图像中,我的算法似乎是在正确纹理位置的左侧或右侧对空间进行采样,因此它遇到了一种透明的颜色,这是错误的。
我已经尝试了很多方法来进行错误更正,包括在执行mods之前乘以1000.0,然后进行除法、钳制到特定范围等等,但我还没有找到一致的解决方案。此外,这个问题不一定仅仅是浮点不准确造成的。
是否有一种执行计算的方法来确保纹理部分完美循环--也许以某种不寻常的方式使用FRCT和floor?(我发现了这个讨论,但无法完全理解,因为OP和公认的答案都没有解释许多变量的含义:
parallax offsets with texture atlas?
它利用了压裂和地面,但这种方法可能不兼容。很难说。)
在这种情况下,以下是我的顶点和片段着色器代码的相关摘录(删除了不相关的部分--使用
precision highp float
):
// vertex shader
void main(void)
{
gl_Position = u_matrix * vec4(a_position, 1.0);
v_uv = vec2(a_uv.x * u_offset_layers_x, a_uv.y);
v_position_cam = u_position_cam; // set the camera position to an out variable
}
// fragment shader
void main(void)
{
vec4 texel;
// each successive layer scrolls more slowly
float rate = 0.65;
// iterate through each layer and sample until the alpha is not 0
// since I get tears every so often, I might have rounding errors that end up sampling part of a previous or successive texture by mistake
for (int i = 0; i < u_count_layers; ++i) {
// I use multiplications and divisions by 1000.0 in an attempt to reduce the error, but I don't think it works at all
// the camera position offsets the parallax layer
float sample_coord = v_uv.x + ((v_position_cam.x * 1000.0 * rate) / 1000.0);
// the y offset seems fine
float off_y = (-v_position_cam.y * rate * rate * rate);
off_y = max(off_y, 0.0);
// offset by i layers, add that offset to (the sampled coordinate * offset per layer) % offset per layer
texel = vec4(texture(tex0, vec2(
(float(i) * u_offset_layers_x) + mod(sample_coord * 1000.0, u_offset_layers_x * 1000.0) / 1000.0,
v_uv.y + off_y))
);
// if the alpha is not 0, then don't sample the layers behind it (a texel has an alpha of 0.0 or 1.0)
if (texel.a != 0.0) {
break;
}
// reduce the scroll speed for the next layer
rate *= rate;
}
// output the color
color = vec4(texel.rgb, texel.a);
}
**
我要补充一点,我可以很容易地使用
GL_REPEAT
在映射到5个四边形的5个单独纹理上(或重新绑定制服并重新渲染相同的四边形),但我希望着色器在一个纹理和一个四边形上工作,以创建着色器效果和纹理过渡,在渲染到单个四边形时最容易实现。此外,减少制服的数量也是好事。此外,我对这个问题背后的工程感兴趣,并且正在使用这种方法来应对挑战。我感觉自己很接近,但我找不到接缝/偏移问题的文档/解决方案。
禁用GL\u REPEAT和使用GL\u CLAMP\u TO\u EDGE似乎不起作用,但不可否认,如果我使用这样的图集,GL\u REPEAT是不必要的。
提前感谢您的帮助。
编辑:如果单纹理方法不起作用,一次绑定5-10个重复纹理并使用类似的算法,但依赖GL\u REPEAT而不是mod,会不会很糟糕?我认为这可能会产生较差的性能,但我可能错了。在未来,我想过渡两个多层背景之间使用平滑的步骤。这就是为什么我更喜欢单四边形方法。此外,如果我能做到这一点,那么我可以有更多的层。
编辑2:我注意到这个屏幕截图中“砌砖”上缺少一条垂直的黑线,所以我认为这里发生的是采样/插值有时会在像素完美的水平上失败,这是有道理的。有没有办法避免这种情况?