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でのリフレクションのチェックをしてみたいと思います。