Легкая платформа для Программ построения теней OpenGL в C/C++

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

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

31
задан Nils 8 May 2010 в 17:50
поделиться

4 ответа

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

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

class shader_prog {
    GLuint vertex_shader, fragment_shader, prog;

    template <int N>
    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 <int N, int M>
    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();
}

Если вы собираетесь использовать, например, несколько различных шейдеров фрагментов в процессе рисования вашей сцены, вы просто определяете статический объект для каждого, а затем выполняете 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();
}

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

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

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

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

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

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

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

55
ответ дан 27 November 2019 в 22:07
поделиться

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

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

Это не " • Специально измените текстуру по своему усмотрению ... но по моему опыту, как только вы получите такой код, компиляция и запуск будут более приятными, и вы быстро добьетесь прогресса и сможете при необходимости склеить части из других руководств. Могу сказать, что как только я запустил пример, я использовал ту же структуру, чтобы быстро решить множество проблем дома и на работе.

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

4
ответ дан 27 November 2019 в 22:07
поделиться

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

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

2
ответ дан 27 November 2019 в 22:07
поделиться

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

1
ответ дан 27 November 2019 в 22:07
поделиться