Передача значений из моей Java-программы в GLSL с использованием lwjgl - PullRequest
4 голосов
/ 15 мая 2011

Допустим, у меня довольно сложный фрагментный шейдер для определения того, сколько света идет на каждый пиксель:

//shaders/screen.frag
varying vec4 vertColor; //unlit color
float intensity = 1.0; //lighting intensity.

//parameters vary from material to material:
float roughness_rms; //root-mean-square roughness (um).
float peak_angle; //how steep peaks are on average.
/* more parameters */

void main(){
    /* complex shader code to calculate intensity */
    gl_FragColor = intensity*vertColor; //set the light strength
}

Вот как я инициализирую шейдеры:

//something.java
import <needed crap>
int shader, fragShader;
shader=ARBShaderObjects.glCreateProgramObjectARB();
fragShader=createFragShader("shaders/screen.frag");
ARBShaderObjects.glAttachObjectARB(shader, fragShader);
ARBShaderObjects.glLinkProgramARB(shader);
ARBShaderObjects.glValidateProgramARB(shader);

И как я их использую:

//something.java
ARBShaderObjects.glUseProgramObjectARB(shader);
GL11.glBegin(GL11.GL_QUADS);
//etc.

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

1 Ответ

5 голосов
/ 16 мая 2011

Вам нужно взглянуть на "Униформу" в спецификации GLSL .

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

Эта переменная существует в рамках всей программы (то есть вершинный шейдер + фрагментный шейдер + дополнительные геометрические и тесселяционные шейдеры); если вы хотите использовать его, скажем, в вершинном шейдере и фрагментном шейдере, вам нужно объявить его в обоих, но вам нужно будет установить его только один раз в своем клиентском коде.

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

Например, для установки одного плавающего числа (это OpenGL 3+; я не уверен, что синтаксис точно такой же ниже этого уровня).

В вашем шейдере:

uniform float my_value;

В вашем клиентском коде:

glUseProgram(program_id);
GLint my_value_loc = glGetUniformLocation(program_id, "my_value");
glUniform1f(my_value_loc, 1.0);
glUseProgram(0);

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

...