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

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

OpenGL (GLSL) のユニフォームブロックでのシェーダーリフレクションを試してみました。
ここで使った vertexShader, fragment shaderは以下のようなものです。

// vertex shader
#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 LightBlock {
  Light uLight;
};
uniform ModelMeshBlock {
  ModelMesh uModelMesh;
};

// 略

// fragment shader
#version 410 core

in VS_Out {
  vec4 Color;
  vec3 Normal;
  vec2 UV0;
} PSIn;

out vec4 out_color0;

uniform sampler2D gSampler0;
uniform samplerCube gSampler1;

// 略

これらのシェーダーについて情報を出してみるとこのような感じになりました。
まずはシェーダーユニフォームの一覧.

Shader uniform(s) ----
uniformIndex=0 : loc=0, "cameraPosition" type=vec3, size=1
uniformIndex=1 : loc=1, "gSampler0" type=sampler2D, size=1
uniformIndex=2 : loc=2, "gSampler1" type=samplerCUBE, size=1
uniformIndex=3 : loc=3, "matProjection" type=mat4, size=1
uniformIndex=4 : loc=4, "matView" type=mat4, size=1
uniformIndex=5 : loc=-1, "uLight.color" type=vec4, size=1
uniformIndex=6 : loc=-1, "uLight.direction" type=vec3, size=1
uniformIndex=7 : loc=-1, "uModelMesh.matWorld" type=mat4, size=1
uniformIndex=8 : loc=-1, "uModelMesh.material.diffuse" type=vec4, size=1
uniformIndex=9 : loc=-1, "uModelMesh.material.specularColor" type=vec3, size=1
uniformIndex=10 : loc=-1, "uModelMesh.vUser[0]" type=vec4, size=4

ユニフォームブロックの中身のメンバには、ロケーションIDは振られていないことが確認できます。ユニフォームのインデックスは振られており、情報はこちら軽油で取得できるようです。
そして、ユニフォームブロックに関して情報を取得してみます。

0: LightBlock
  blockDataSize = 32
  0 > uniformIndexInBlock=5 : "uLight.color" offset=  0,type=vec4
  1 > uniformIndexInBlock=6 : "uLight.direction" offset= 16,type=vec3
1: ModelMeshBlock
  blockDataSize = 160
  0 > uniformIndexInBlock=7 : "uModelMesh.matWorld" offset= 32,type=mat4
  1 > uniformIndexInBlock=8 : "uModelMesh.material.diffuse" offset=  0,type=vec4
  2 > uniformIndexInBlock=9 : "uModelMesh.material.specularColor" offset= 16,type=vec3
  3 > uniformIndexInBlock=10 : "uModelMesh.vUser[0]" offset= 96,type=vec4

ユニフォームブロック内でのシェーダー定数のオフセットが取得できました。
ユニフォームブロック内に構造体を配置しても、従来のシェーダー定数の場合と変わらないような名前でオフセットやデータ型を取得できることがわかります。

std140 とかレイアウト指定をしない場合、シェーダーによって(環境によって?)定数の位置が変わりそうです。
そのため、UBOを複数のシェーダーで使い回すのは難しそうです。この場合結局定数毎に書き込む位置を見てバッファ内のデータ更新という手続きをとるので、あまりUBOによる描画効率化に繋がらないように感じます。

ユニフォームブロック内の定数であっても GL_ACTIVE_UNIFORMS にて有効なユニフォーム変数としてカウントされていることに少々驚きました。ただしユニフォームブロック内の変数名からは有効なロケーションが取得できません。ユニフォームブロック内の変数についてはロケーション=-1となっているようです。

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