GLSL Sampler2D平铺问题

时间:2017-10-10 10:52:21

标签: three.js glsl

所以我目前正在开发一个后处理着色器,它采用8个纹理并在屏幕上以类似方式显示它们。有8个瓷砖,出现在2行4中。在大多数情况下,我已经得到了我需要工作的东西,但是我遇到了一个具有坐标精度的小问题。请看下面的图片:

enter image description here

正如你可以看到它的大部分工作,在每个瓷砖的外部x和y极值上有一些纹理的轻微包裹。毫无疑问,这是导致这个问题的数学原因。

这基本上是GLSL片段着色器的代码:

uniform sampler2D tDiffuse;
uniform sampler2D tDiffuse2;
uniform sampler2D tDiffuse3;
uniform sampler2D tDiffuse4;
uniform sampler2D tDiffuse5;
uniform sampler2D tDiffuse6;
uniform sampler2D tDiffuse7;
uniform sampler2D tDiffuse8;
varying vec2 vUv;

vec4 getPixelColor(vec2 coord) {

    //Output color
    vec4 color = vec4(.0, .0, .0, .0);

    //Obtain the division point between tiles
    float xDiv = 1.0 / 4.0;
    float yDiv = 1.0 / 2.0;

    //Which tile is it?
    int tileX = int(floor(coord.x / xDiv));
    int tileY = int(floor(coord.y / yDiv));

    float x = (coord.x - (float(tileX) * xDiv)) * 4.0;
    float y = (coord.y - (float(tileY) * yDiv)) * 2.0;
    vec2 tileCoord = vec2(x, y);

    //Set the current sample to the desired texture
    if (tileX == 0 && tileY == 1) color = texture2D(tDiffuse, tileCoord);
    if (tileX == 1 && tileY == 1) color = texture2D(tDiffuse2, tileCoord);
    if (tileX == 2 && tileY == 1) color = texture2D(tDiffuse3, tileCoord);
    if (tileX == 3 && tileY == 1) color = texture2D(tDiffuse4, tileCoord);
    if (tileX == 0 && tileY == 0) color = texture2D(tDiffuse5, tileCoord);
    if (tileX == 1 && tileY == 0) color = texture2D(tDiffuse6, tileCoord);
    if (tileX == 2 && tileY == 0) color = texture2D(tDiffuse7, tileCoord);
    if (tileX == 3 && tileY == 0) color = texture2D(tDiffuse8, tileCoord);

    return color;
}

void main() {

    //Output color
    vec4 color = vec4(.0, .0, .0, .0); 
    color = getPixelColor(vUv);

    //Output to render
    gl_FragColor = color;
}

为方便起见,我提供了我在Google云端硬盘上使用的4个纹理贴图:(https://drive.google.com/open?id=0B5BRDQX6tFRqRmFKRE5PNFJkYTg)。

非常感谢任何帮助:)

修改1:

我忘了提到我使用THREE.js作为WebGL组件。在一些反馈之后,我使用了纹理的包裹设置,但问题仍然存在。

1 个答案:

答案 0 :(得分:0)

您可以使用gl.texParameteri来设置纹理包装参数。

请参阅Khronos OpenGL ES 2.0 documentation of glTexParameteri

  

GL_CLAMP_TO_EDGE使坐标被限制在范围为[1/(2*N), 1 − 1/(2*N)]的范围内,其中N是夹紧方向上纹理的大小。

gl.texParameter(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
gl.texParameter(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);

在three.js中,纹理包装参数可以设置如下(参见TextureTexture Constants):

var texture = new THREE.TextureLoader().load( textureFileName );
texture.wrapS = THREE.ClampToEdgeWrapping;
texture.wrapT = THREE.ClampToEdgeWrapping; 

这意味着传递给texture2D的纹理坐标会被钳制,如果它们小于0.0或大于1.0。事实上, ux)坐标被限制为[0.5/width, (width-0.5)/width]vy)坐标被限制为[0.5/height, (hight-0.5)/height]


您的着色器代码可以简化为:

vec2 tile      = floor(coord.xy * vec2(4.0, 2.0));
vec2 tileCoord = coord.xy * vec2(4.0, 2.0) - tile;

int tileX = int(tile.x);
int tileY = int(tile.y);