我的应用程序是用Javascript + Three.js / WebGL + GLSL编写的。我有200条曲线,每条曲线由85个点组成。要为曲线设置动画,我添加一个新点并删除最后一个。
所以我制作了一个positions
着色器,用于将新位置存储到纹理(1)和lines
着色器上,该着色器将所有曲线的位置写入另一个纹理(2)。
目标是将纹理用作数组:我知道一行的第一个和最后一个索引,因此我需要将这些索引转换为uv
坐标。
我使用FBOHelper来调试FBO。
1)此1D纹理包含每条曲线的新点(总共200个):positionTexture
2)这些是200条曲线,所有点都是一个接一个:linesTexture
黑色部分是这里的BUG。那些纹素不应该是黑色的。
它是如何工作的:在每一帧,着色器为positionTexture
中的每一行查找新点并相应地更新linesTextures
,并使用for
循环:
#define LINES_COUNT = 200
#define LINE_POINTS = 85 // with 100 it works!!!
// Then in main()
vec2 uv = gl_FragCoord.xy / resolution.xy;
for (float i = 0.0; i < LINES_COUNT; i += 1.0) {
float startIdx = i * LINE_POINTS; // line start index
float endIdx = beginIdx + LINE_POINTS - 1.0; // line end index
vec2 lastCell = getUVfromIndex(endIdx); // last uv coordinate reserved for current line
if (match(lastCell, uv)) {
pos = texture2D( positionTexture, vec2((i / LINES_COUNT) + minFloat, 0.0)).xyz;
} else if (index >= startIdx && index < endIdx) {
pos = texture2D( lineTexture, getNextUV(uv) ).xyz;
}
}
这很有效,但是当我有很多行(150+)时,它有点小问题:可能是一个精确问题。我不确定我写的用于查找纹理的函数是否正确。我编写了像getNextUV(uv)
这样的函数来从下一个索引(转换为uv坐标)获取值并复制到前一个。或者match(xy, uv)
知道当前片段是否是我想要的纹素。
我虽然可以简单地使用经典公式:
index = uv.y * width + uv.x
但它比那更复杂。例如match()
:
// Wether a point XY is within a UV coordinate
float size = 132.0; // width and height of texture
float unit = 1.0 / size;
float minFloat = unit / size;
bool match(vec2 point, vec2 uv) {
vec2 p = point;
float x = floor(p.x / unit) * unit;
float y = floor(p.y / unit) * unit;
return x <= uv.x && x + unit > uv.x && y <= uv.y && y + unit > uv.y;
}
或getUVfromIndex()
:
vec2 getUVfromIndex(float index) {
float row = floor(index / size); // Example: 83.56 / 10 = 8
float col = index - (row * size); // Example: 83.56 - (8 * 10) = 3.56
col = col / size + minFloat; // u = 0.357
row = row / size + minFloat; // v = 0.81
return vec2(col, row);
}
有人可以通过从uv
值获取index
坐标来解释在纹理中查找值的最有效方法是什么?
答案 0 :(得分:2)
纹理坐标来自像素的边缘而不是中心,因此计算UV坐标的公式需要
u = (xPixelCoord + .5) / widthOfTextureInPixels;
v = (yPixelCoord + .5) / heightOfTextureInPixels;
所以我猜你想要getUVfromIndex
uniform vec2 sizeOfTexture; // allow texture to be any size
vec2 getUVfromIndex(float index) {
float widthOfTexture = sizeOfTexture.x;
float col = mod(index, widthOfTexture);
float row = floor(index / widthOfTexture);
return (vec2(col, row) + .5) / sizeOfTexture;
}
或者,based on some other experience with math issues in shaders您可能需要捏造索引
uniform vec2 sizeOfTexture; // allow texture to be any size
vec2 getUVfromIndex(float index) {
float fudgedIndex = index + 0.1;
float widthOfTexture = sizeOfTexture.x;
float col = mod(fudgedIndex, widthOfTexture);
float row = floor(fudgedIndex / widthOfTexture);
return (vec2(col, row) + .5) / sizeOfTexture;
}
如果您使用的是WebGL2,则可以使用texelFetch
获取整数像素坐标以获取纹理中的值