使用ATLAS在具有WebGL的三角形上绘制精灵会因邻居精灵而导致错误的结果

时间:2014-03-07 02:19:50

标签: javascript opengl webgl shader

我有一个大的2048x2048图像,带有4096个32x32精灵。也就是说,一个64x64的32x32图像表。我用三角形画它们。每个触发器必须切割纹理的正确部分。它可以正常工作,除了面的 之外,引擎正在从工作表上的邻居精灵访问像素,从而产生噪音。注意兽人下面的像素:

notice the noise pixels below the character

它们来自工作表下方的精灵。我正在使用以下计算来削减面积:

顶点着色器:

// position of each pixel of this face on texture
varying vec2 pix_pos;

// pos_in_sheet holds the position of the sprite on the sheet
// considering it is a 64x64 sheet, it is on the range vec2(0..63, 0..63)
vec2 pos_in_sheet = vec2(floor(mod(sprid,texture_cols)), floor(sprid/texture_cols));

// `vec2 vertex` indicates which of the 4 vertex in the quad this is:
// vec2(-1.0,-1.0)|vec2(-1.0,1.0)|vec2(1.0,-1.0)|vec2(1.0,1.0)

// inside main() I calculate the bounding quad that contains the sprite
pix_pos = vec3(
    ((pos_in_sheet.x+(vertex.x+1.0)/2.0)/64.0), //64 = rows in texture 
    ((pos_in_sheet.y+(-vertex.y+1.0)/2.0)/64.0));

这是片段着色器:

varying vec3 pix_pos;
uniform sampler2D sampler;
void main(void){
    vec4 col = texture2D(sampler,vec2(pix_pos.x,pix_pos.y));
    gl_FragColor = vec4(col.x,col.y,col.z,1.0);
}

我检查了我的计算,看起来很好。那么什么可能导致片段着色器访问其自己的切割区域之外的精灵?

1 个答案:

答案 0 :(得分:2)

这可能由于线性插值而发生,因为每个texture2D()可以从纹理中获取4个像素,并根据这4个像素和一些权重返回结果。通过数学代码很难解决这个问题,因为浮动操作很难处理。

可以产生此问题的另一件事是纹理mipmap(如果你使用它们)。通常,较低的mipmap级别是使用某种过滤技术创建的,该过滤技术将4个像素合并为一个。具有高对比度的相邻像素可能会产生此类伪影。

解决方法是在精灵之间填充。通常在2到4个像素的空白空间(通常是黑色rgba< 0,0,0,0>)应该解决问题。所以每个精灵都有32x32像素,在地图集中需要34x34像素。精灵周围的2像素边框必须是精灵中最近像素的颜色(在您的情况下是透明的)。这减少了您可以在地图集中使用的精灵数量