4

各ピクセルにどれだけの光が入るかを把握するためのかなり複雑なフラグシェーダーがあるとしましょう。

//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からシェーダー言語に変数を渡すにはどうすればよいですか(遅いでしょう)。理想的には、描画するすべてのクワッドでシェーダーパラメーターを更新したいと思います。

4

1 に答える 1

5

GLSL仕様の「ユニフォーム」を確認する必要があります。

基本的に、これはシェーダー変数のストレージ修飾子であり、シェーダーの外部(つまりCPU側)から設定され、入力よりも頻繁に変更されないことを示します(頂点ごとではなく、ジオメトリバッチごとに最大1回)。

この変数は、プログラム全体のスコープに存在します(つまり、頂点シェーダー+フラグメントシェーダー+オプションのジオメトリおよびテッセレーションシェーダー)。たとえば、頂点シェーダーとフラグメントシェーダーで使用する場合は、両方で宣言する必要がありますが、クライアント側のコードで1回だけ設定する必要があります。

実際に変数を設定するには、プログラムがアクティブなときにユニフォームの場所を(名前で)照会する必要があります。この場所は、プログラムが再コンパイルされない限り安定しているため、必要に応じてキャッシュして再利用できます。プログラムが再コンパイルされない限り、設定した値も保持されます。

たとえば、単一のフロートを設定するには(これは、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(int、float、配列、行列などを設定するための多くのバリアント)のリファレンスです。

于 2011-05-15T20:14:02.653 に答える