2011-05-15 71 views
4

可以说我有搞清楚一个相当复杂的frag着色器到底有多少光进入每个像素从我的Java程序中传递值到GLSL:使用LWJGL

//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等parame各种材料形成。此外,当子弹等有影响时,这些参数会发生变化。 我的问题是:如何将变量从我的java传递到着色器语言,而不重新生成整个着色器并重新编译它(这会很慢)。理想情况下,我绘制的每个四边形都希望更新着色器参数。

回答

5

你需要看看the GLSL Specs中的“制服”。

基本上,它是着色器变量的存储限定符,表示它将从着色器外侧(即CPU侧)设置,并且更改频率比输入更少(每个几何体批次最多一次,而不是每个顶点一次) 。这个变量存在于整个程序的范围内(即顶点着色器+片段着色器+可选的几何图形和镶嵌着色器);如果要在顶点着色器和片段着色器中使用它,则需要在两者中声明它,但只需在客户端代码中将其设置一次即可。

为了实际设置变量,您需要在程序处于活动状态时查询制服的位置(按名称)。只要程序没有重新编译,这个位置就是稳定的,所以你可以缓存并重用它,如果你想要的话。只要程序没有重新编译,您设置的值也会保持不变。

例如,设置一个浮点数(这是OpenGL 3 +;我不确定语法在该级别下是否完全相同)。

在你的shader:

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,这是更复杂一点(很多变体来设置整数,浮点数组,矩阵等)。

+0

我无法使这些功能正常工作。我尝试'ARBShaderObjects.glUseProgram',它不起作用。如果它们不在lwjgl的ARbShaderObjects类中,那么它们在哪里? – 2011-05-15 20:57:49

+0

哦,我得到它的工作。您使用GL20类,并将这些命令应用于着色器,而不是碎片着色器。 – 2011-05-15 22:13:48

+0

我不能说lwjgl的细节(我主要使用OpenGL与Python),但我正在修改我的帖子,以澄清,制服应用于一个完整的程序,而不是一个着色器。 – 2011-05-16 08:08:02