#c #opengl
Вопрос:
мне нужно получить цвет в определенной координате из текстуры. Есть 2 способа, которыми я могу это сделать: получить и просмотреть необработанные данные png или путем выборки моей сгенерированной текстуры opengl. Можно ли попробовать текстуру opengl, чтобы получить цвет (RGBA) в заданной координате UV или XY? Если да, то как?
Ответ №1:
У меня в голове не укладывается, что у тебя есть варианты
- Извлеките всю текстуру с помощью glGetTexImage() и проверьте интересующий вас текстель.
- Нарисуйте интересующий вас текстель (например, путем визуализации примитива GL_POINTS), затем возьмите пиксель, в котором вы его отрисовали, из буфера кадров с помощью glReadPixels.
- Держите копию текстурного изображения под рукой и не включайте в него 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 ужасно неэффективно, и его следует избегать, как чумы, если вы хотя бы отдаленно заинтересованы в производительности.
Два работоспособных решения, насколько я знаю:
- Держите копию пиксельных данных под рукой (однако тратьте память впустую).
- Сделайте это с помощью шейдера