本サイトでは、アフィリエイト広告およびGoogleアドセンスを利用しています。

GLSLのシェーダーリフレクション

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

OpenGLプログラミング
すらりんをフォローする
すらりん日記
タイトルとURLをコピーしました