像点画一样重复纹理

时间:2014-06-05 12:04:19

标签: opengl-es textures webgl

我使用正交投影。

我有两个三角形创建一个长四边形。 在这个四边形上我放了一个纹理,在路上重复他自己。

世界变焦总是由用户改变 - 并使四边形长度相应地变短或变长。高度在着色器中计算,因此它始终具有相同的大小(以像素为单位)。

我的问题是我希望纹理根据它的真实(像素大小)和四边形的长度重复。换句话说,纹理将始终具有相同的大小(像素),并且它将通过或多或少取决于四边形长度重复它来填充四边形。

轮换很重要。

例如 我的纹理是enter image description here

我已添加到我的顶点 - 纹理坐标,现在重复20次 如下所示enter image description here 因为它被缩小了太多,我们看到纹理被挤压了。

现在我放大并且纹理拉伸。它总是重复20次。 enter image description here

我确定我必须使用frag着色器中的纹理坐标,但是没有看到解决方案。或者对我的问题有更好的解决方案。

---- ADDITION ----

通过以下方式解决: 计算当前缩放中的重复S值(即添加顶点)并将地图宽度(以世界值为单位)作为属性发送。每次绘制我都会将当前地图宽度发送为统一,以便计算比例。

但我对此解决方案不满意。

2 个答案:

答案 0 :(得分:0)

一般解决方案是包括纹理矩阵。所以你的顶点着色器可能看起来像

attribute vec4 a_position;
attribute vec2 a_texcoord;

varying vec2 v_texcoord;

uniform mat4 u_matrix;
uniform mat4 u_texMatrix;

void main() {
  gl_Position = u_matrix * a_position;
  v_texcoord = (u_texMatrix * v_texcoord).xy;
}

现在您可以设置纹理矩阵以根据需要缩放纹理坐标。如果您的纹理坐标在纹理上从0到1,并且您的图案宽度为16像素,那么如果您要绘制100像素长的线条,则需要100/16作为X比例。

var pixelsLong = 100;
var pixelsTall = 8;
var textureWidth = 16;
var textureHeight = 16;

var xScale = pixelsLong / textureWidth;
var yScale = pixelsTall / textureHeight;

var texMatrix = [
  xScale, 0, 0, 0,
  0, yScale, 0, 0,
  0, 0, 1, 0,
  0, 0, 0, 1,
];

gl.uniformMatrix4fv(texMatrixLocation, false, texMatrix);

这似乎会起作用。因为您使用矩阵,您还可以轻松地偏移或旋转纹理。见matrix math

答案 1 :(得分:0)

好的,找到了一种方法,可以使用着色器中的最小属性和最少代码来实现。

做一次:

  • 计算每行的重复次数,因为我的世界和我的屏幕在我的世界中是1:1 - 1是1像素。 LineDistance(InWorldUnits)/picWidth(inScreenUnits)
  • 保存为属性。

每次抽奖:

  • 计算尺度 - 世界到屏幕 - WorldWidth/ScreenWidth
  • 设置为统一
  • 绘制缓冲区

在frag shader中

  • 只需将此比例与repeat属性相乘。

效果很好,看起来很棒。也支持调整窗口大小。