ユニフォーム変数

uniform.png

概要

ユニフォーム変数は、頂点シェーダからもフラグメントシェーダからも参照可能な、
constグローバル変数である。

ユニフォーム変数は、シェーダの中で初期化してはいけない。
シェーダの外側(つまりcpp側)からのみ値をセットすることができる。
シェーダプログラムの中で途中で値を書き換えることもできない。
なぜなら、
頂点シェーダ、やフラグメントシェーダは並列に動くプログラムだから、
(頂点シェーダは各頂点ごとに並列、フラグメントシェーダは各ピクセルごとに並列)
ひとつのリソースを参照にすることは
デッドロックになったりして危険なこと。
だから、最初に値をセットしてから頂点シェーダやフラグメントシェーダからいじることはできなくなっている。

ユニフォーム変数はあんまり頻繁に値が更新されることは想定していない。
(私は平気で毎フレームユニフォーム変数の値を書き換えたりしょっちゅうするけど、いいのかなぁ、、)
せいぜい1プリミティブにつき1回だけ値が変化する程度が良い使い方らしい。
ユニフォーム変数は
1シェーダプログラムにつき、1個のグローバル変数として確保されている。
だから、頂点シェーダで宣言したユニフォーム変数はフラグメントシェーダでも使っていいってこと

使用上の注意

uniform int xxxx;

みたいにして定義をしていても、その変数がシェーダコード内で使われていないと、
glGetUniformLocation()時にエラーになる。
たとえ使っているつもりでも、最終的にgl_FragColorに反映されていないなら、取得できない!ようになっている。
賢いなぁ。

例えば

uniform float uniMiffy;
void main(){
....
}

使う手順

GLuint uniLoc=glGetUniformLocation(program,"ユニフォーム変数の名前")//glLinkProgramよりも後に行う!!
 glUniform**(uniLoc,渡す値);//glUseProgram(program)より後に使う。

glUniformの値が、1フレームごとに渡さなくてもいいような値なら、一時的にglUseProgram(program)して、そのあとglUseProgram(0)すればいい。

glUseProgram(gProgram);
    glUniform1f(gCubeSizeLoc,gCubeSize);
    glUseProgram(0);

アクティブなユニフォーム変数の数を確認する

int name;
        glGetProgramiv(_program,GL_ACTIVE_UNIFORMS,&name);
        printf("GL_ACTIVE_UNIFORMS:%d\n",name);

ユニフォーム変数の使っても良い最大文字数

int name;
    glGetProgramiv(gProgram,GL_ACTIVE_UNIFORM_MAX_LENGTH,&name);
    printf("ユニフォーム変数の使っても良い最大文字数=%d\n",name);

glGetUniformLocation

存在しない名前を取得しようとすると、-1が返ってくる。
locationが-1のままglUniformしたらどうなるのか?
glGetErrorには引っかからないようになってる。
ようは、無視されるってこと

Bibliography

を使ったらどうなるのか?
getGLErrorには引っかからないようにはなってる

遭遇したエラー

中身を渡したはずのユニフォーム変数がいつも0になってる

ユニフォーム変数はglUseProgramの後に、渡さないと(glUniformしないと)だめ。
もし、ユニフォーム変数の中身を渡してなくてもエラーにはならないが、初期値の0のままでことが進む。

GL_INVALID_OPERATION error generated. Wrong component type or count.

uniform vec3 uColor;

にdoubleで値を渡そうとしたらえらーになった
glUniform4d(colorLocation,165.0/255.0f,217.0/255.0,221.0/255.0,1.0);//doubleで値を渡すとエラー!
glUniform4f(colorLocation,165.0/255.0f,217.0/255.0,221.0/255.0,1.0);//floatならばok

shader

サポートサイト Wikidot.com shader