所以我目前正在开发一个后处理着色器,它采用8个纹理并在屏幕上以类似方式显示它们。有8个瓷砖,出现在2行4中。在大多数情况下,我已经得到了我需要工作的东西,但是我遇到了一个具有坐标精度的小问题。请看下面的图片:
正如你可以看到它的大部分工作,在每个瓷砖的外部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组件。在一些反馈之后,我使用了纹理的包裹设置,但问题仍然存在。
答案 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中,纹理包装参数可以设置如下(参见Texture和Texture Constants):
var texture = new THREE.TextureLoader().load( textureFileName );
texture.wrapS = THREE.ClampToEdgeWrapping;
texture.wrapT = THREE.ClampToEdgeWrapping;
这意味着传递给texture2D
的纹理坐标会被钳制,如果它们小于0.0或大于1.0。事实上,
u
(x
)坐标被限制为[0.5/width, (width-0.5)/width]
,v
(y
)坐标被限制为[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);