GLSLいじりの過程で、シェーダーリフレクションっぽいことをやってみたのでその調査結果です。
OpenGLでは別に他のライブラリに依存することなく、シェーダーリフレクションの機能を持っています。普段ではuniform変数のロケーション情報を名前から取得しているかと思いますが、その延長上でいろいろな情報をとれるようになっています。
そこで次のようなシェーダープログラム(抜粋)で、どのように情報がとれてくるか試してみました。
// vertexShader
#version 410 core
layout( location=0 ) in vec3 inPosition;
layout( location=1 ) in vec3 inNormal;
layout( location=2) in vec2 inTexcoord;
uniform mat4 matProjection;
uniform mat4 matView;
uniform vec3 cameraPosition;
struct Material {
vec4 diffuse;
vec3 specularColor;
};
struct Light {
vec4 color;
vec3 direction;
};
struct ModelMesh {
Material material;
mat4 matWorld;
vec4 vUser[4];
};
uniform Light uLight;
uniform ModelMesh uModelMesh;
out VS_Out {
vec4 Color;
vec2 UV0;
vec3 Normal;
} Out;
void main() {
// 略
}
// fragmentShader
#version 410 core
in VS_Out {
vec4 Color;
vec3 Normal;
vec2 UV0;
} PSIn;
out vec4 out_color0;
uniform sampler2D gSampler0;
uniform samplerCube gSampler1;
void main() {
// 略
}
結果はこんな感じでした。ドライバの状態によっては別の結果を返してきそうな気配も・・・。AMDやIntelで試してみたいところです。
NVIDIA 331.65 のドライバの結果。
Shader uniform(s) ----
loc=0 : "cameraPosition" type=vec3, size=1
loc=1 : "gSampler0" type=sampler2D, size=1
loc=2 : "gSampler1" type=samplerCUBE, size=1
loc=3 : "matProjection" type=mat4, size=1
loc=4 : "matView" type=mat4, size=1
loc=5 : "uLight.color" type=vec4, size=1
loc=6 : "uLight.direction" type=vec3, size=1
loc=7 : "uModelMesh.matWorld" type=mat4, size=1
loc=8 : "uModelMesh.material.diffuse" type=vec4, size=1
loc=9 : "uModelMesh.material.specularColor" type=vec3, size=1
loc=10 : "uModelMesh.vUser[0]" type=vec4, size=4
ここからわかることは、次のような感じかと。
- 配列の場合には [0] とか付加されて返ってくる. (NVIDIAの場合限定かも?)
- サイズとして配列のサイズ(長さ)が返ってくる
- 構造体メンバの場合は、構造体変数名が間に挟まっている
- 構造体だからといって、1つのuniform location に集約されるわけではない
GLSLは構造体使えるから、お?とおもっていたのですが、実際のところは内部のメンバに対して1つずつロケーションが与えられているようです。
次回には、Uniform Blockでのリフレクションのチェックをしてみたいと思います。