Простая структура для шейдеров OpenGL в C / C ++

Я просто хотел попробовать некоторые шейдеры на плоском изображении. Оказывается, что написание программы на C, которая просто берет изображение в виде текстуры и применяется, скажем, гауссовское размытие, поскольку fragmentарный шейдер на нем не так прост: вы должны инициализировать OpenGL, которые похожи на 100 строк кода, затем понимание GLBuffers и т. д. Также для связи с системой окон, нужно использовать GLUT, который является еще одним фреймворком.

Оказывается, что композитор Fx Nvidia приятно играть с шейдерами. Но мне все же хотелось бы иметь простую программу на C или C ++, которая просто применяет данный шейдер fragmentа к изображению и отображает результат. Есть ли у кого-нибудь пример или есть frameworks?

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

Это (в основном) оставляет код для компиляции, ссылки и использования шейдеров. Я написал небольшой class, который мне удобен для этой цели:

class shader_prog { GLuint vertex_shader, fragment_shader, prog; template  GLuint compile(GLuint type, char const *(&source)[N]) { GLuint shader = glCreateShader(type); glShaderSource(shader, N, source, NULL); glCompileShader(shader); GLint compiled; glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled); if (!compiled) { GLint length; glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &length); std::string log(length, ' '); glGetShaderInfoLog(shader, length, &length, &log[0]); throw std::logic_error(log); return false; } return shader; } public: template  shader_prog(GLchar const *(&v_source)[N], GLchar const *(&f_source)[M]) { vertex_shader = compile(GL_VERTEX_SHADER, v_source); fragment_shader = compile(GL_FRAGMENT_SHADER, f_source); prog = glCreateProgram(); glAttachShader(prog, vertex_shader); glAttachShader(prog, fragment_shader); glLinkProgram(prog); } operator GLuint() { return prog; } void operator()() { glUseProgram(prog); } ~shader_prog() { glDeleteProgram(prog); glDeleteShader(vertex_shader); glDeleteShader(fragment_shader); } }; 

Для простой демонстрации несколько «проходных» шейдеров (просто имитируйте конвейер с фиксированной функциональностью):

 const GLchar *vertex_shader[] = { "void main(void) {\n", " gl_Position = ftransform();\n", " gl_FrontColor = gl_Color;\n", "}" }; const GLchar *color_shader[] = { "void main() {\n", " gl_FragColor = gl_Color;\n", "}" }; 

Который вы бы использовали что-то вроде:

 void draw() { // compile and link the specified shaders: static shader_prog prog(vertex_shader, color_shader); // Use the compiled shaders: prog(); // Draw something: glBegin(GL_TRIANGLES); glColor3f(0.0f, 0.0f, 1.0f); glVertex3f(-1.0f, 0.0f, -1.0f); glColor3f(0.0f, 1.0f, 0.0f); glVertex3f(1.0f, 0.0f, -1.0f); glColor3f(1.0f, 0.0f, 0.0f); glVertex3d(0.0, -1.0, -1.0); glEnd(); } 

Если вы собираетесь использовать, например, несколько различных шейдеров fragmentов во время рисования вашей сцены, вы просто определяете статический объект для каждого, а затем выполняете prog1(); , prog2(); и т. д., только перед тем, как рисовать объекты, которые вы хотите затенять с каждым шейдером. Например,

 void draw() { static shader_prog wall_shader("wall_vertex", "wall_frag"); static shader_prog skin_shader("skin_vertex", "skin_frag"); wall_shader(); draw_walls(); skin_shader(); draw_skin(); } 

Изменить: Поскольку @rotoglup совершенно правильно указывает, это использование static переменных задерживает разрушение до тех пор, пока контекст OpenGL не будет уничтожен, поэтому, когда деструкторы пытаются использовать glDeleteProgram / glDeleteShader , результаты непредсказуемы (в лучшем случае).

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

Чтобы избежать обеих проблем, вы, как правило, хотите создать свои шейдерные объекты как члены экземпляра classа, чье жизненное время, в свою очередь, привязано к времени жизни того, что будет затеняться:

 class some_character_type { shader_prog skin_shader; public: // ... }; 

Это будет скомпилировать / связать программу шейдеров один раз, когда вы создадите символ этого типа, и уничтожьте его, когда вы уничтожите этот символ.

Конечно, в некоторых случаях это не совсем желательно. Например, рассмотрим 3D-версию древних игр «убить множество целей», таких как Galaga или Centipede. Для подобных игр вы создаете и уничтожаете множество практически идентичных целей относительно быстро. Учитывая большое количество практически идентичных целей, вы, вероятно, захотите использовать что-то вроде shared_ptr чтобы создать один экземпляр шейдера, который делится между всеми экземплярами определенного целевого типа. Учитывая, что вы повторно используете одни и те же типы целей много раз, вам может понадобиться немного больше, чем это, поэтому вы сохраняете одни и те же шейдеры во всей игре, а не только при отображении определенного типа цели.

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

Я был в аналогичной позиции примерно полтора года назад. Я быстро нашел простой учебник и исходный код для использования GLSL .. но мне приходилось работать с GLUT и GLEW, и я думаю, что в итоге я собрал хотя бы один из них. Поскольку я использовал Windows (и Windows – это нестандартный частный случай, который редко обрабатывается открытыми проектами), это также связано с нелепым процессом, когда я должен был вручную копировать и вставлять файлы DLL и заголовки в некоторые общие местах. Это всегда боль, и я потерял хороший кусок в моей жизни, делая что-то вроде этого, но я протащил процесс, как указано, и это получилось в конце, как это обычно бывает.

Во всяком случае, наиболее удобный пример шейдера с использованием GLSL, который я могу найти прямо сейчас, – это http://www.lighthouse3d.com/opengl/glsl/index.php?minimal

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

Мне жаль, что он использует GLUT и GLEW. Если вы получите лучший ответ на этот вопрос, я тоже стану мгновенным поклонником того, что сайт предлагает код. Удачи.

Этот учебник может быть полезен (обратите внимание, что он содержит материал GLSL помимо старого материала Cg).

Обратите внимание, что я бы подумал о том, чтобы писать шейдеры для реализации неграфических объектов типа GPGPU, которые в наши дни являются устаревшим. OpenCL или CUDA, очевидно, способ пойти в будущем.

Хотя это не ваша цель, вы можете получить что-то из образца шейдера OpenGL ES 2.0 от Noel Llopis: http://www.mobileorchard.com/getting-started-with-opengl-es-20-on-the-iphone-3gs/

  • как включить вертикальную синхронизацию в opengl?
  • Почему GL разделяет `gl_Position` на W для вас, а не позволяет вам сделать это самостоятельно?
  • Как отключить или обойти ускорение аппаратной графики (Prism) в JavaFX
  • Как составить матрицу вращения с удобочитаемыми углами с нуля?
  • Как получить библиотеку / заголовки GL?
  • Система координат OpenGL левая или правая?
  • Почему java-приложение врезается в gdb, но работает нормально в реальной жизни?
  • Создание нормальной карты с карты высоты?
  • Как скомпилировать для Windows на Linux с gcc / g ++?
  • Что означает «немедленный режим» в OpenGL?
  • Как рисовать текст с помощью GLUT / OpenGL на C ++?
  • Давайте будем гением компьютера.