让我们说我有一个相当复杂的碎片着色器,用于确定每个像素有多少光线:
//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代码用各种材料计算roughness_rms和其他参数。此外,当子弹等受到撞击时,这些参数会发生变化。 我的问题是:如何在不重新生成整个着色器并重新编译它的情况下将变量从我的java传递到着色器语言(这会很慢)。理想情况下,我绘制的每个四边形我都想更新着色器参数。
答案 0 :(得分:5)
您需要查看the GLSL Specs中的“制服”。
基本上,它是着色器变量的存储限定符,表示它将从着色器外部(即CPU端)设置,并且变化频率低于输入(每个几何批次最多一次,而不是每个顶点一次)。
此变量存在于整个程序的范围内(即顶点着色器+片段着色器+可选几何和曲面细分着色器);如果你想在顶点着色器和片段着色器中使用它,你需要在两者中声明它,但你只需要在客户端代码中设置它一次。
为了实际设置变量,您需要在程序处于活动状态时查询统一的位置(按名称)。只要程序没有重新编译,此位置就是稳定的,因此您可以缓存它并在需要时重复使用它。只要不重新编译程序,您设置的值也会保持不变。
例如,设置一个浮点数(这是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的引用,它稍微复杂一些(设置整数,浮点数,数组,矩阵等的变量很多)。