Выборка текстур в открытом GL

#c #opengl

Вопрос:

мне нужно получить цвет в определенной координате из текстуры. Есть 2 способа, которыми я могу это сделать: получить и просмотреть необработанные данные png или путем выборки моей сгенерированной текстуры opengl. Можно ли попробовать текстуру opengl, чтобы получить цвет (RGBA) в заданной координате UV или XY? Если да, то как?

Ответ №1:

У меня в голове не укладывается, что у тебя есть варианты

  1. Извлеките всю текстуру с помощью glGetTexImage() и проверьте интересующий вас текстель.
  2. Нарисуйте интересующий вас текстель (например, путем визуализации примитива GL_POINTS), затем возьмите пиксель, в котором вы его отрисовали, из буфера кадров с помощью glReadPixels.
  3. Держите копию текстурного изображения под рукой и не включайте в него OpenGL.

Варианты 1 и 2 ужасно неэффективны (хотя вы могли бы несколько ускорить 2, используя объекты пиксельного буфера и выполняя копирование асинхронно). Так что мой любимый, безусловно, вариант 3.

Редактировать: Если у вас есть GL_APPLE_client_storage расширение (т. Е. вы находитесь на Mac или iPhone), тогда это вариант 4, который по большому счету является победителем.

Комментарии:

1. Однако, за пределами варианта 2, вам нужен метод выборки на основе текстовых записей, что является трудной частью-это описано в моем ответе.

2. Насколько я понял, на плакате спрашивалось, как реализовать часть «getTexel» в вашем примере, а не как реплицировать фильтрацию (что зависит от того, какую фильтрацию он все равно хочет реплицировать).

3. Я вроде как спрашивал о части getTexel, но он прав, что 1 и 2 слишком медленные, особенно учитывая, что я работаю на мобильном устройстве. Спасибо 🙂

4. Мобильное устройство? Это, случайно, не iPhone? См.Обновленный ответ.

5. действительно, было бы неплохо, спасибо за совет… хотя в этом случае действительно оказывается, что данные могут быть предварительно обработаны как необработанные данные изображения до создания текстуры OpenGL.

Ответ №2:

Самый эффективный способ, который я нашел для этого, — это получить доступ к данным текстуры (вы все равно должны декодировать наш PNG, чтобы превратить его в текстуру) и самостоятельно интерполировать между текселями. Предполагая, что ваши текстовые записи равны [0,1], умножьте texwidth u и texheight v, а затем используйте это, чтобы найти положение на текстуре. Если это целые числа, просто используйте пиксель напрямую, в противном случае используйте части int, чтобы найти граничащие пиксели и интерполировать между ними на основе дробных частей.

Вот для него какой-то HLSL-подобный psuedocode. Должно быть достаточно ясно:

 float3 sample(float2 coord, texture tex) {
    float x = tex.w * coord.x; // Get X coord in texture
    int ix = (int) x; // Get X coord as whole number
    float y = tex.h * coord.y;
    int iy = (int) y;

    float3 x1 = getTexel(ix, iy); // Get top-left pixel
    float3 x2 = getTexel(ix 1, iy); // Get top-right pixel
    float3 y1 = getTexel(ix, iy 1); // Get bottom-left pixel
    float3 y2 = getTexel(ix 1, iy 1); // Get bottom-right pixel

    float3 top = interpolate(x1, x2, frac(x)); // Interpolate between top two pixels based on the fractional part of the X coord
    float3 bottom = interpolate(y1, y2, frac(x)); // Interpolate between bottom two pixels

    return interpolate(top, bottom, frac(y)); // Interpolate between top and bottom based on fractional Y coord
}
 

Ответ №3:

Как предположили другие, считывание текстуры из VRAM ужасно неэффективно, и его следует избегать, как чумы, если вы хотя бы отдаленно заинтересованы в производительности.

Два работоспособных решения, насколько я знаю:

  1. Держите копию пиксельных данных под рукой (однако тратьте память впустую).
  2. Сделайте это с помощью шейдера