我正在绘制填充有在着色器中重复的纹理的线条。如下图
该线是单点 - 我在顶点着色器中扩展每个顶点,并进行一些计算,无论我们的缩放比例如何,该计算始终具有相同的像素宽度。
我正在创建三角形,并在它们上在 X 轴上重复绘制纹理。所以线的宽度始终是图像的高度。
用户可以随心所欲地放大,并且形状会随着缩放的变化而变大或变小。虽然纹理节省了它的大小,但意味着有更多的重复。
当用户放大很多时,我开始得到奇怪的结果,我猜是由于浮动溢出。
缩放:1
缩放2
我的着色器:
顶点着色器
uniform float factor;
attribute vec2 texCoords;
varying vec2 vTexCoords;
attribute vec4 texAtlas;
varying vec4 vTexAtlas;
uniform vec4 uPixelWolrdScale;
attribute vec2 outlineOffset;
void main() {
vTexCoords = texCoords;
vTexAtlas = texAtlas;
gl_Position = LIGHTGLgl_ModelViewProjectionMatrix * (LIGHTGLgl_Vertex + uWorldOffset) + vec4((outlineOffset.xy) * uPixelWolrdScale.zw, 0,0);
}
uPixelWolrdScale 是 vec4,其中 xy = worldScale.xy / ScreenSize.xy,zw = 2/ ScreenSize.xy。
我使用
zw
来偏移线的宽度
以及用于在片段着色器中重复纹理的 xy
precision highp float;
uniform float factor;
uniform vec4 color;
varying vec2 vTexCoords;
uniform vec4 uPixelWolrdScale;
uniform sampler2D sampler;
varying vec4 vTexAtlas;
void main() {
// Here is the problem i guess
vec2 vexelPos = fract(vec2((vTexCoords.s) / (uPixelWolrdScale.x * factor), vTexCoords.t));
vexelPos = vTexAtlas.xy + vexelPos * vTexAtlas.zw;
gl_FragColor = texture2D(sampler, vexelPos);
gl_FragColor *= color;
}
vTexCoords.s
是世界和屏幕单位相同时的重复次数。没有变焦。
当
(vTexCoords.s) / (uPixelWolrdScale.x * factor)
溢出时,还有其他方法可以重复纹理吗?
-----已编辑------
尝试通过使用
mod()
而不是 fract()
来改变我的方法来实现重复。
经过几轮之后,我已经成功做到了这一点,作为我问题的解决方案,但它仍然在某些缩放中开始出现异常。
基本思想是使用同质值来重复纹理,并在纹理大小和模量的帮助下进行额外的计算变化。
在我的顶点着色器中
我添加了属性并改变了
attribute vec4 startVertex;
varying float vVertex;
...
// Same calculation i did to the gl_Vertex I do here to the attribute
vec4 coordToRemove = LIGHTGLgl_ModelViewProjectionMatrix * (startVertex + uWorldOffset) + vec4((outlineOffset.xy) * uPixelWolrdScale.zw, 0,0);
vVertex = gl_Position.x - coordToRemove.x;
我希望我的变化从 0 开始并一直插值到第二个齐次位置。所以我添加了第一个顶点值作为两个顶点的属性 -
coordForVar
- 所以当第一个顶点到达这里时 vVertex
将是 0。而第二个 vVertex
将是差异。
在我的片段着色器中
varying float vVertex;
...
float hmgSize = 1. / 32.; // Getting the size in homogeneous - For now 32px, later uniform/attribute
vec2 vexelPos = vec2(mod(vVertex, hmgSize) / hmgSize, vTexCoords.t);
vexelPos = vTexAtlas.xy + vexelPos * vTexAtlas.zw;
在纹理坐标中使用 fract 和 mod 可能会通过 mipmapping 做出奇怪的事情,请确保您的纹理对 min 和 mag 过滤器使用最近过滤,然后从那里开始
编辑:
无论纹理的内容是什么,texture2D 只是真正查找 0 到 1 之间的纹理坐标。整数部分用于重复,但使用它会降低查找精度。使用 fract 或 mod 进行重复而不是整数部分可能会导致 mipmap 查找中出现 1px 不连续性;但如果你是阿尔塔斯,无论如何你都会遇到这个问题。
因此,您在查找图集时,纹理坐标应该是 0..1 的一小部分的范围
例如,如果您有 16x16 图像,则范围为 0.0625。例如X 中的第三个纹理是 0.125 到 0.1875。
您想要处理纹理坐标之外的重复,然后将值转换为该范围。
编辑:
当放大而不是使几何体长一百万个单位时,但只显示它的百万分之一;这只会导致精确战斗,请调整您的几何屏幕尺寸;那么您应该拥有所需的所有精度。
例如,在进行透视计算后,您的几何图形 x,y 坐标将位于屏幕空间中,并且仅显示在 -1,-1 到 1,1 框中的位置。此时,您可以相交并修剪(或丢弃/忽略)几何体,以便 x,y 位于该框中,然后将纹理设置为与应有的屏幕重复次数匹配的纹理。这意味着它不需要百万分之一的精度。