Q: OpenGL book

Вот смотрю я на профили исполнения RawDigger и вижу, что на отрисовку пиксельного буфера там уходит заметное время. Особенно заметное, если картинка здоровая, а кроме перерисовки - ничего не происходит (скажем, каналы RAW переключаются).

Решение, казалось бы, очевидное: загнать это самое RAW в виде текстуры в видеокарту и рисовать дальше уже средствами видеокарты же. Пиксельные шейдеры и все такое. Короче, OpenGL.

Разглядывание (несколько дней на даче сидел и разглядывал) всяких простых OpenGL-ных примеров навело меня на очевидную мысль - я нихрена в этом не понимаю совсем. А пора бы уже.

Отсюда вопрос: какую книжку "OpenGL для чайников за 21 день" вы бы мне посоветовали? На басурманском бегло читаю, наверное надежнее читать исходник, а не перевод.

От OpenGL мне, по большому счету, нужно банальное 2D: показ двумерной картинки, с зумированием (и показ участка), может быть наложение в 2D нескольких слоев с регулируемой прозрачностью. Идеальным был бы tutorial именно в этом вот духе.

Comments

А RawDigger - оно на Qt?
Если Qt, то тогда оно на виджетах или GraphicsView?
Там можно подсунуть QGLWidget в качестве вьюпорта и тогда активный контекст будет opengl и пиксмапы будут с буфером в текстуре для отрисовки.
Можно и самому поизвращаться с загрузкой картинок в текстуру и отрисовкой через QGLWidget::drawTexture .

http://qt-project.org/doc/qt-4.8/qtopengl.html
Просто с opengl для каждой платформы всё разное (glx, wgl, agl, egl) и меня лично ломает писать сетап код.

qt5 вроде полностью на opengl и работает с тяжелой графикой быстрее, но оно пока даже не бета.

Да, оно на Qt и естественно я на все эти setViewport смотрел.

А потом задумался, а хрен ли собственно, вот та же самая отрисовка одного из каналов (R-G-B-G2) - это банальное копирование одной компоненты в остальные. Ну так и пусть это видеокарта делает, у нее мозги больше.

Ну да.
Только пусть Qt этим всем управляет - чтобы не возиться напрямую с gl кодом.

Ну да, пусть qt.

Но вот все эти пассы, которые в QGLWidget происходят - я хочу понимать что там написано, а не каким-то чудом скомпоновать кусок работающего кода, не понимая что делаю.

Могу дать туториал по opengl es 2.0 .
Там практически всё, что не относится к EGL и созданию контекста, будет работать на десктопе.
Заодно с переносимостью будет получше ;)

Я тут налабал темплейт https://github.com/dubik/OpenGLTemplate/ . Там еще есть бранч с шейдером. А вот мега книжка по шейдерам http://www.amazon.com/Shaders-Programmers-Artists-Premier-Development/dp... есть в электронном виде. Шейдеры лучше в рендермонкей делать, ну если простые то можно и в коде.

Книжку спиратил, спасибо.
Но она 2004-го года, я так подозреваю, что с тех пор наука шагнула очень далеко вперед.

А темплейт - я на даче примерно такой же написал (копипастом из qt-шных примеров) и понял, что не понимаю базы.

> Но она 2004-го года, я так подозреваю, что с тех пор наука шагнула очень далеко вперед.
Я бы не сказал. Ну то есть наука конечно шагнула, но той книжки хватит что бы сделать вполне приличный движек.

А что именно не понятно? Обычно после описания проблемы, и решение как то сразу приходит.
Там немножко все запутанно из за того что:
В OpenGL до шейдеров был фиксированный pipeline. То есть надо было задавать матрицы преобразования координат вершин через спец комманды https://github.com/dubik/OpenGLTemplate/blob/shaders/glwindow.cpp#L40 потом загружая геометрию в в драйвер https://github.com/dubik/OpenGLTemplate/blob/shaders/glwindow.cpp#L52 оно тупо перемножалось. Цвет и текстурка бралась из других спец комманд https://github.com/dubik/OpenGLTemplate/blob/shaders/glwindow.cpp#L51. К тому же есть комманды которые включают освещение.

После того как появились геометрические шейдеры, это можно делать в коде шейдера, без спец комманд. То есть матрицу можно передать геометрическому шейдеру в виде аттрибута и он уже будет перемножать ее (и не только) с геометрией https://github.com/dubik/OpenGLTemplate/blob/shaders/shaders/solidColor....
после того как отрабатывает геометрический шейдер, запускаются пиксельные. Карта растеризует треугольник и для каждого пикселя вызывает main https://github.com/dubik/OpenGLTemplate/blob/shaders/shaders/solidColor....
самая засада тут понять какие переменные входят в шейдер а какие выходят. Меня в свое время это жутко бесило. При линковке шейдеров, компилятор или драйвер хитрожопо выясняют могут ли они выходные аттрибуты одного соединить со входными аттрибутами другого. К тому же есть встроенные выходные аттрибуты типа gl_FragColor. Это цвет выходного пикселя. Кстати в этом случае освещение надо считать самому. В книжке написано как именно, но идея в том что передаеш координаты лампочки в геом шейдер и он может посчитать светимость в каждой вершине, потом он передаст эти аттрибуды в пиксельный шейдер. Пиксельный шейдер можно просто проинтерполировать или посчитать свет уже в каждом пикселе.

Кстати еще про входные аттрибуты. В геометрическом шейдере
varying vec4 vColor;

void main(void)
{
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
vColor = gl_Color;
}

gl_ModelViewProjectionMatrix - это встроенный аттрибут, в который запихнулась матрица после вот этого
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45, (GLdouble)w / (GLdouble)h, -10, 10);
glMatrixMode(GL_MODELVIEW);

gl_Color - это то что приходит из glColor3f(1.0f, 0.0f, 0.0f);

В opengl обычно более одного способа сделать одно и тоже, можно задавать геометрию одним массивом. Но glVertex и glColor самый простой и самый медленный с точки зрения производительности способ.

Мне непонятна именно целостная картина.

Т.е. почти про каждую строчку кода в Qt-шных примерах - я понимаю что она делает.

А вот почему делается именно это и в таком порядке - не понимаю.

Соответственно, и вопрос задать не могу т.к. надо знать половину ответа.

Ясно.
Есть треугольник в каких то координатах например как в моем темплейте -1..1. Его надо нарисовать. Что бы понять где рисовать нужно преобразовать координаты треугольника в экранные координаты. Для этого нужно собрать матрицу. В матрица представлены: перемещение, вращение, увеличение. То есть умножая вектор на матрицу мы преобразовывает одни координаты в другие. Есть еще перспектива, она тоже всовывается в матрицу. Про перспективу лучше картинку посмотреть.

Каждый фрейм в опенгл начинается с очистки буферов - glClear. Буфера бывают разные, есть экранный буфер, есть стенсил буфер, есть буфер глубины и т.д. Как минимум нужен экранный буфер. Он опять таки хитрожопо мапится на окошко в виндовз или там линуксе. QT это лучше сделает.
Дальше начинаем рисовать. У нас есть геометрия: вершины треугольника, цвет в каждой вершине, и например координаты текстуры для каждой вершины. Вызывая glColor и glVertex мы засылаем данные в драйвер. Драйвер строит разные буфера которые потом отдаст карте. Карта начинает это все считать когда вызывает glSwapBuffers.

С каждой вершиной ассоциируется пакет аттрибутов: цвет, текстурные координаты и т.д. Это все передается геометрическому шейдеру. В шейдере как я уже говорил как минимум перемножается матрица проекции 3д координаты вершины в экранные координаты. После чего карта растеризует треугольник и вызывает пиксельный шейдер. Пиксельный шейдер должен вернуть цвет, именно его и положит карта в графическую память.

Еще больше запутался? :)

Да, еще больше запутался.

Потому что у меня нет треугольников. У меня есть прямоугольник, некую область из которого (тоже прямоугольную) надо показать в окошке. Всех этих ужасов с вращением - мне не надо вовсе.

Я вот книжку почитаю - будет легче.

Да, и про науку.
Я вот так вот подозреваю, что если ориентироваться только на видеокарты выпущенные в 2007-м году и позже, то многие вещи внезапно станут сильно проще.

Для тех целей которые описаны в посте хватит самой примитивной карты того же 2004 года. Я точно не помню, но шейдеры 2.0 делают то что написано и даже больше. Вот в книжке как раз описаны карточки и версии шейдеров, которые стали проще в использовании (появился си подобный язык). Другое дело что если надо соединить это все с opencl. Тогда надо смотреть.

Ну я скорее к тому, что на 2.x может быть можно смело забить и смотреть на 3.x (а может и 4.x).

C OpenCL в том что мне надо в дальнейшем (не сейчас) - все тоже банально, OpenCL генерирует текстуру, OpenGL - натягивает на экран.

Про науку я имел в виду вот что примерно:

Why would we want to use the OpenGL Core profile? Well, for a start OpenGL 3.0 deprecated much of the old fixed-functionality pipeline entry points. Yes, at present these are still available when using the Compatibility profile in order to keep old applications working. However, many of these deprecated functions encourage poor or out-dated practises. For example it is much more efficient to use vertex arrays or even better vertex buffer objects to send geometry to the OpenGL pipeline than the old glVertex family of functions. The same is true for all other per-vertex attributes too (e.g. normals, texture coordinates, colours etc.).

Отсюда: http://qt-project.org/wiki/How_to_use_OpenGL_Core_Profile_with_Qt

В том смысле, что старые практики могут быть просто неудобными и незачем ими и париться.

А, теперь понял. Opengl 3.0 не значит, что в нем появились шейдеры (к примеру). Шейдеры появились по второй версии OpenGL. Но API (если рассуждать на уровне 2 треугольников и текстуры) с тех времен не менялся. Как то путано я все написал. Вообщем если якобы использовать 3.0 то это не значит что оно не взлетит на 2.0 или 2.1. Просто они выбрасывают старые ф-ции, но новые были добавлены хрен знает когда.
Имеет смысл не использовать glVertex например, а засовывать геометрию VBO (vertex buffer object). Просто при разработке (поменял местами строчки, закомментил, скомпилировал) с массивами сложнее будет. И имхо старые практики как раз удобнее, но они не такие эффективные в плане производительности.

Мне вот тоже хочется, в порядке самообразования.
Что-то все туториалы что нагугливались - не собирались сходу на линуксе (в смысле примеры от них не собирались).

Qt-шные - на макоси успешно собираются, как и на винде.

Линукс меня слабо интересует пока.

OpenGL SuperBible вполне сгодится. На самом деле, поскольку я лет 7 назад проходил той же самой дорогой, то могу сказать что сгодится любая, с хорошим рейтингом на амазоне и более-менее up to date (ну чтоб как минимум 2.1 покрывала). И тебе из нее надо 10%.

Потому что тебе реально надо засетапить ортогональную проекцию, засетапить mapping mode (уже забыл какой), и нарисовать простейший шейдер (скопировав из любого примера). Без шейдера тоже можно, но на самом деле удобнее прям с нуля с ним, потому что все равно понадобится. Когда я этим занимался, грузить текстуры надо было каким-нибудь расширением, а не штатными средствами, штатные средства по скорости работы напоминали *dst++ = *src++; Наверняка за прошедшее время эти расширения уже в сам стандарт загнали. Через расширения гигабайт в секунду с диска на телевизор я загонял уже тогда. Еще вопрос - tiling, опять же тогда, максимальный размер текстуры (у нвидии) был 4096. Поскольку мне для кино больше было и не надо, я и не парился, а фотачки бывают заметно побольше. Это тоже понятно - рисуешь не один прямоугольник, а два-четыре-сколько надо и настраиваешь текстурные координаты так, чтобы они "продолжались" поперек этих прямоугольников.

Там вся суть геометрических трансформаций вырождается в простые линейные пересчеты (поскольку проекция ортогональная) - геометрические координаты прямоугольничка пересчитываются в тексели (текстурные координаты), которые фрагментный процессор пересчитывает в реальные пиксели. Поэтому пан и зум - бесплатные (просто циферки в пайплайне меняешь).

Про tiling - это ловкое замечание. У меня на нвидиевской карте 65kx65k лимит (как минимум, такие текстуры в CUDA), но наверное надежнее забиться на тайлинг.

А вот с версиями этого добра - я не вполне понимаю. Наверное, в 2012-м году можно считать, что везде есть OpenGL 3.x?

Про версии - э. 2.х или 3.х в твоем (моем) случае никак не влияет на сетап геометрии (который и в 1.4 был такой же), но влияет на выбор расширений для загрузки текстуры и на возможности шейдера. А это от карты зависит, а не от версии ICD. И размеры текстуры тоже, я не знаю на какую аудиторию ты целишься и в какой момент будешь делать фоллбек на рисование руками. К сожалению, у OpenGL нету нормальных капсов, как у DirectX и у текущего сетапа не спросишь что он умеет. Ну то есть конечно люди нашли способы, но они э.

На самом деле, наверное центральный сакральный нолидж, который ты почерпнешь из книжки относительно твоей задачи - это тот факт что фрагментный шейдер когда делает выборку из текстуры по полученной "сверху" (от геометрии) координате, то он делает не выборку, а интерполяцию. Всегда. Просто когда у тебя все совсем 1:1, то интерполяция попадает точно в тексели. Из-за этого удобно делать лукап таблицы и сложно иногда отлаживать, когда например ошибся в расчетах (ошибки глазом почти не будет видно).

Общая моя идея в том, что OpenGL есть сейчас везде и fallback делать не надо. Посмотрим, конечно...

А сакральный нолидж про текстуры мне и так известен - в CUDA текстуры ведут себя так же.

Не знаю на сколько поможет (сам не пробовал), но гугла на запрос "OpenGL 3.0 for dummies" выдала вот такое:

http://sites.google.com/site/opengltutorialsbyaks/introduction-to-opengl...

ж-)

Видел, естественно, но не проникся.

Сейчас этого добра наделали мульен всякого (OpenACC, да и вообще PGI старается), но я в коммунизм не верю, не получится писать эффективно на GPU не задумываясь о тамошней архитектуре.

"Камера Leica M Monochrom удовлетворяет самых взыскательных пользователей, предоставляя в их распоряжение гистограмму RAW-данных для полного контроля тонального набора снимка. В отличие от обычной гистограммы, гистограмма RAW-данных отображает истинные данные, записанные сенсором камеры."

http://www.leica-camera.ru/leica/content/photography/m_system/m_monochrom/

Во как. И фильтры смывать не надо. Всего-то $8K.

Еще у Лейки S2 гистограмма в RAW. Тоже недорого.