Array ( )
Вход:




Главная | OpenGL | GLSL | AI | Сеть | Примеры | Библиотека

GLSL: Коммуникация OGL-GLSL: Uniform переменные






Значение переменных Uniform может изменятся только примитивами, то есть не могут быть изменены
между glBegin() & glEnd(). Это значит, что этот тип переменных не может быть использован,
например, для хранения аттрибутов вершин. Эти переменные подходят для хранения констант,
относящихся к примитиву, кадру, даже ко всей сцене. Uniform-переменные могут быть прочитаны
(но не перезаписаны) обоими шейдерами, вершинным и пикселным.

Первое, что вы должны сделать - это получить адрес переменной в памяти. Учтите, что
эта информация доступна только после прилинковки шейдера, то есть сначала нужен
вызов (для OpenGL 2.0) glUSeProgram, или (для расширений ARB) glUSeProgramObjectARB.


Синтаксис и OpenGL 2.0 и расширений ARB при работе с переменными очень прост.
Для перехода от ARB к OGL 2.0 просто отбросьте префикс ARB от функции.


Функция получения адреса переменной в памяти в синтаксисе OpenGL 2.0:
GLint glGetUniformLocation(GLuint program, const char *name);

// Параметры:

//    program - дескриптор программы
//    name - имя переменной


И используя ARB
GLint glGetUniformLocationARB(GLhandleARB program, const char *name);

// Параметры:

//    program - дескриптор программы
//    name - имя переменной



Возвращаемое значение - адрес в памяти искомой переменной, которой затем можно присваивать
значения. Существует семейство функций для установки переменных, их применение зависит от
типа данных переменной. Функции для OpenGL 2.0:
void glUniform1f(GLint location, GLfloat v0);
void glUniform2f(GLint location, GLfloat v0, GLfloat v1);
void glUniform3f(GLint location, GLfloat v0, GLfloat v1, GLfloat v2);
void glUniform4f(GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);

// или

GLint glUniform{1,2,3,4}fv(GLint location, GLsizei count, GLfloat *v);

// Параметры:

//    location - предварительно найденный адрес памяти
//    v0,v1,v2,v3 - float-значения.
//    count - число элементов в массиве
//    v - массив float-ов.



Используя шейдерные расширения ARB:
void glUniform1fARB(GLint location, GLfloat v0);
void glUniform2fARB(GLint location, GLfloat v0, GLfloat v1);
void glUniform3fARB(GLint location, GLfloat v0, GLfloat v1, GLfloat v2);
void glUniform4fARB(GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);

// или

GLint glUniform{1,2,3,4}fvARB(GLint location, GLsizei count, GLfloat *v);

// Параметры:

//    location - предварительно найденный адрес памяти
//    v0,v1,v2,v3 - float-значения.
//    count - число элементов в массиве
//    v - массив float-ов.


Подобный же список функций доступен и для целых чисел, int, при этом "f" заменяется на "i".
Функций для передачи bool не существует. Используйте 0 вместо false и что угодно вместо true.


Матрицы - тоже доступный тип данных.
OpenGL 2.0:
GLint glUniformMatrix{2,3,4}fv(GLint location, GLsizei count, GLboolean transpose, GLfloat *v);

// Параметры:

//    location - предварительно найденный адрес памяти
//    count - количество матриц в массиве.
//    transpose - Определяет тип матрицы. 0/1 для горизонтальной/вертикальной
//    v - массив float-ов.


Расширения ARB:
GLint glUniformMatrix{2,3,4}fvARB(GLint location, GLsizei count, GLboolean transpose, GLfloat *v);

// Параметры:

//    location - предварительно найденный адрес памяти
//    count - количество матриц в массиве.
//    transpose - Определяет тип матрицы. 0/1 для горизонтальной/вертикальной
//    v - массив float-ов.



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




А теперь немного кода. Предположим, будет использоватся шейдер со следующими переменными:
    uniform float specIntensity;
    uniform vec4 specColor;
    uniform float t[2];
    uniform vec4 colors[3];



В приложении OpenGL 2.0 присвоение им кода будет выглядеть так:
    GLint loc1,loc2,loc3,loc4;
    float specIntensity = 0.98;
    float sc[4] = {0.8,0.8,0.8,1.0};
    float threshold[2] = {0.5,0.25};
    float colors[12] = {0.4,0.4,0.8,1.0,
                  0.2,0.2,0.4,1.0,
                  0.1,0.1,0.1,1.0};

    loc1 = glGetUniformLocation(p,"specIntensity");
    glUniform1f(loc1,specIntensity);

    loc2 = glGetUniformLocation(p,"specColor");
    glUniform4fv(loc2,1,sc);

    loc3 = glGetUniformLocation(p,"t");
    glUniform1fv(loc3,2,threshold);

    loc4 = glGetUniformLocation(p,"colors");
    glUniform4fv(loc4,3,colors);



В приложении с шейдерными расширениями ARB это будет выглядеть так:
    GLint loc1,loc2,loc3,loc4;
    float specIntensity = 0.98;
    float sc[4] = {0.8,0.8,0.8,1.0};
    float threshold[2] = {0.5,0.25};
    float colors[12] = {0.4,0.4,0.8,1.0,
                  0.2,0.2,0.4,1.0,
                  0.1,0.1,0.1,1.0};

    loc1 = glGetUniformLocationARB(p,"specIntensity");
    glUniform1fARB(loc1,specIntensity);

    loc2 = glGetUniformLocationARB(p,"specColor");
    glUniform4fvARB(loc2,1,sc);

    loc3 = glGetUniformLocationARB(p,"t");
    glUniform1fvARB(loc3,2,threshold);

    loc4 = glGetUniformLocationARB(p,"colors");
    glUniform4fvARB(loc4,3,colors);



Исходные коды работающих примеров:
[a=http://masandilov.ru/coding/sources/glutglsl2_2.0.zip:a]OpenGL 2.0
[a=http://masandilov.ru/coding/sources/glutglsl2.zip:a]Расширения ARB


Ещё одна интересная возможность GLSL - передача адреса переменной, находящейся внутри массива.
Например, возможно получить адрес переменной t[1]. Следующий пример это продемонстрирует:
    loct0 = glGetUniformLocation(p,"t[0]");
    glUniform1f(loct0,threshold[0]);

    loct1 = glGetUniformLocation(p,"t[1]");
    glUniform1f(loct1,threshold[1]);


Функция для расширения ARB точно такая же - просто добавьте префикс ARB в имя функции.









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

Войдите, чтобы оставить комментарий:












Яндекс.Метрика
 Яндекс цитирования.