我有一些数据以2k乘2k的浮点纹理编码。数据是经度,纬度,时间和日期,如R,G,B,A。这些都已归一化,但目前这不是问题。如果我愿意,我可以在以后对它们进行去标准化。
我现在需要的是遍历整个纹理并找到该片段坐标中的经度和纬度。我假设整个地图集已经规范化了坐标并且它映射了整个openGL上下文。除了坐标,我将使用时间和日期过滤数据,但这是一个易于完成的if条件。因为我拥有的像素坐标不会完全映射那个坐标,所以我现在将使用一个小的delta值来解决这个问题,并且我会起诉该delta值来预先计算接近该co的其他点。
现在我在iGPU上遇到了一些驱动程序崩溃(它应该是内存不足或类似的东西),即使我想在嵌套循环中添加2个内容,或者即使我使用丢弃。
我现在的代码就是这个 注意f_time是时间的过滤器,现在我有一个滑块,这样我就可以与这些值进行一些交互。
精密介质浮动; precision mediump int;
const int maxTextureSize = 2048;
varying vec2 v_texCoord;
uniform sampler2D u_texture;
uniform float f_time;
uniform ivec2 textureDimensions;
void main(void) {
float delta = 0.001;// now bigger delta just to make it work then we tune it
// compute 1 pixel in texture coordinates.
vec2 onePixel = vec2(1.0, 1.0) / float(textureDimensions.x);
vec2 position = ( gl_FragCoord.xy / float(textureDimensions.x) );
vec4 color = texture2D(u_texture, v_texCoord);
vec4 outColor = vec4(0.0);
float dist_x = distance( color.r, gl_FragCoord.x);
float dist_y = distance( color.g, gl_FragCoord.y);
//float dist_x = distance( color.g, gl_PointCoord.s);
//float dist_y = distance( color.b, gl_PointCoord.t);
for(int i = 0; i < maxTextureSize; i++){
if(i < textureDimensions.x ){
break;
}
for(int j = 0; j < maxTextureSize ; j++){
if(j < textureDimensions.y ){
break;
}
// Where i am stuck now how to get the texture coordinate and test it with fragment shader
// the precomputation
vec4 pixel= texture2D(u_texture,vec2(i,j));
if(pixel.r > f_time){
outColor = vec4(1.0, 1.0, 1.0, 1.0);
// for now just break, no delta calculation to sum this point with others so that
// we will have an approximation of other points into that pixel
break;
}
}
}
// this works
if(color.t > f_time){
//gl_FragColor = color;//;vec4(1.0, 1.0, 1.0, 1.0);
}
gl_FragColor = outColor;
}
答案 0 :(得分:2)
你想做的事情根本不可行。
您正尝试在单个片段着色器调用中访问四百万次的纹理。
现代GPU通常检测无限循环条件的方式是通过查看着色器运行多长时间,然后如果它已经运行太长时间而杀死它,并且其长度通常足够慷慨。你的代码可以进行多达400万次纹理访问,几乎可以肯定会触发这种情况。
这通常会导致GPU重置。
一般来说,在纹理中找到与某个片段相关联的位置的方法是直接。也就是说,在屏幕片段位置(gl_FragCoord
)和纹理中的纹素之间创建1:1的对应关系。这样,您的纹理不需要包含X / Y坐标,并且每个片段着色器都可以访问用于该特定调用的数据。
您尝试做的似乎是将一张大表(四百万个元素)传递给GPU,然后让GPU处理它。值的排序(通常)无关紧要;任何值都可能修改任何像素。某些像素没有应用值,而其他像素可能会应用多个值。
这是串行程序员的思维,而不是平行思考。您在CPU上编写代码的方法是遍历表中的每个元素,查看它的位置,并为每个像素构建结果。
在并行算法中,您不会以这种方式工作。每次调用都需要能够立即找到适用于它的表中的数据。您永远不会通过表格搜索您的数据。特别是线性搜索。
您需要从片段着色器的角度考虑这一点。
在数据表中,对于屏幕上的每个位置,都有一个适用于该屏幕位置的数据值列表。正确?您需要做的是使列表直接可用到每个片段着色器调用。由于每个片段的列表大小不一致,因此您需要使用链表而不是固定大小的数组。
为此,您可以构建与渲染目标大小相同的纹理。纹理中的每个纹素都指定此片段需要处理的第一个元素的数据表中的位置。这为每个片段着色器调用提供了其第一个元素的位置。由于某些片段着色器可能没有应用数据,因此您需要留出一些特殊的纹理坐标值来表示&#34; none&#34;。
数据表中的数据包含您的时间和日期,而不是&#34;经度/纬度&#34;,它具有纹理中 next 纹素的纹理坐标适用于该片段着色器。这是您在着色器中创建链接列表的方法。数据表中的每个位置都指定要处理的下一个位置。
如果该位置是要处理的最后一个数据,那么该位置将是&#34; none&#34;来自之前的价值。
您还应该使用buffer texture或SSBO来保存数据表,而不是2D纹理。它会让事情变得更容易。