То, что вы можете попробовать, это «уменьшить» текстуру до значительно меньшего размера и вернуться к ЦП (что должно быть дешевле с точки зрения производительности). Например, вы можете разбить текстуру на квадраты N на N (где N предпочтительно равно степени двойки), а затем визуализировать квад «весь экран» в текстуру 1024 / N на 1024 / N с помощью фрагментного шейдера, который суммирует число красных пикселей в соответствующем квадрате:
sampler2D texture;
void main(void) {
vec2 offset = N * gl_FragCoord.xy;
int cnt = 0;
for (float x = 0.; x < float(N); x += 1) {
for(float y = 0.; y < float(N); y += 1) {
if (texture2D(texture, (offset + vec2(x, y)) / 1024.) == vec4(1, 0, 0, 1)) {
cnt += 1;
}
}
}
gl_FragColor = vec4((cnt % 256) / 255., ((cnt / 256) % 256) / 255., /* ... */);
}
Также помните, что readPixels
синхронно ожидает, пока GPU завершится со всеми ранее выполненными отрисовками текстуры. Так что может быть полезно иметь две текстуры,
в каждом кадре один отображается, а другой читается из. В следующем кадре вы меняете их местами. Это несколько задержит получение нужных данных, но должно устранить некоторые зависания.