-1glGetUniformLocation (...)
が返される原因を突き止めようとして盲目的に手探りすることがよくあるので、GLSL プログラムごとにすべてのユニフォームを列挙するために使用する修正済みコードを共有することにしました。私は実際にマップ構造を使用して列挙型を文字列名に変換しますが、それは必要以上に複雑になります。
人間が読める型を出力するためのユーティリティ構造 (GLSL 430 まで):
struct glsl_type_set {
GLenum type;
const char* name;
}
type_set [] = {
GL_INVALID_ENUM, "invalid",
GL_FLOAT, "float",
GL_FLOAT_VEC2, "vec2",
GL_FLOAT_VEC3, "vec3",
GL_FLOAT_VEC4, "vec4",
GL_DOUBLE, "double",
GL_DOUBLE_VEC2, "dvec2",
GL_DOUBLE_VEC3, "dvec3",
GL_DOUBLE_VEC4, "dvec4",
GL_INT, "int",
GL_INT_VEC2, "ivec2",
GL_INT_VEC3, "ivec3",
GL_INT_VEC4, "ivec4",
GL_UNSIGNED_INT, "unsigned int",
GL_UNSIGNED_INT_VEC2, "uvec2",
GL_UNSIGNED_INT_VEC3, "uvec3",
GL_UNSIGNED_INT_VEC4, "uvec4",
GL_BOOL, "bool",
GL_BOOL_VEC2, "bvec2",
GL_BOOL_VEC3, "bvec3",
GL_BOOL_VEC4, "bvec4",
GL_FLOAT_MAT2, "mat2",
GL_FLOAT_MAT3, "mat3",
GL_FLOAT_MAT4, "mat4",
GL_FLOAT_MAT2x3, "mat2x3",
GL_FLOAT_MAT2x4, "mat2x4",
GL_FLOAT_MAT3x2, "mat3x2",
GL_FLOAT_MAT3x4, "mat3x4",
GL_FLOAT_MAT4x2, "mat4x2",
GL_FLOAT_MAT4x3, "mat4x3",
GL_DOUBLE_MAT2, "dmat2",
GL_DOUBLE_MAT3, "dmat3",
GL_DOUBLE_MAT4, "dmat4",
GL_DOUBLE_MAT2x3, "dmat2x3",
GL_DOUBLE_MAT2x4, "dmat2x4",
GL_DOUBLE_MAT3x2, "dmat3x2",
GL_DOUBLE_MAT3x4, "dmat3x4",
GL_DOUBLE_MAT4x2, "dmat4x2",
GL_DOUBLE_MAT4x3, "dmat4x3",
GL_SAMPLER_1D, "sampler1D",
GL_SAMPLER_2D, "sampler2D",
GL_SAMPLER_3D, "sampler3D",
GL_SAMPLER_CUBE, "samplerCube",
GL_SAMPLER_1D_SHADOW, "sampler1DShadow",
GL_SAMPLER_2D_SHADOW, "sampler2DShadow",
GL_SAMPLER_1D_ARRAY, "sampler1DArray",
GL_SAMPLER_2D_ARRAY, "sampler2DArray",
GL_SAMPLER_1D_ARRAY_SHADOW, "sampler1DArrayShadow",
GL_SAMPLER_2D_ARRAY_SHADOW, "sampler2DArrayShadow",
GL_SAMPLER_2D_MULTISAMPLE, "sampler2DMS",
GL_SAMPLER_2D_MULTISAMPLE_ARRAY, "sampler2DMSArray",
GL_SAMPLER_CUBE_SHADOW, "samplerCubeShadow",
GL_SAMPLER_BUFFER, "samplerBuffer",
GL_SAMPLER_2D_RECT, "sampler2DRect",
GL_SAMPLER_2D_RECT_SHADOW, "sampler2DRectShadow",
GL_INT_SAMPLER_1D, "isampler1D",
GL_INT_SAMPLER_2D, "isampler2D",
GL_INT_SAMPLER_3D, "isampler3D",
GL_INT_SAMPLER_CUBE, "isamplerCube",
GL_INT_SAMPLER_1D_ARRAY, "isampler1DArray",
GL_INT_SAMPLER_2D_ARRAY, "isampler2DArray",
GL_INT_SAMPLER_2D_MULTISAMPLE, "isampler2DMS",
GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY, "isampler2DMSArray",
GL_INT_SAMPLER_BUFFER, "isamplerBuffer",
GL_INT_SAMPLER_2D_RECT, "isampler2DRect",
GL_UNSIGNED_INT_SAMPLER_1D, "usampler1D",
GL_UNSIGNED_INT_SAMPLER_2D, "usampler2D",
GL_UNSIGNED_INT_SAMPLER_3D, "usampler3D",
GL_UNSIGNED_INT_SAMPLER_CUBE, "usamplerCube",
GL_UNSIGNED_INT_SAMPLER_1D_ARRAY, "usampler2DArray",
GL_UNSIGNED_INT_SAMPLER_2D_ARRAY, "usampler2DArray",
GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE, "usampler2DMS",
GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY, "usampler2DMSArray",
GL_UNSIGNED_INT_SAMPLER_BUFFER, "usamplerBuffer",
GL_UNSIGNED_INT_SAMPLER_2D_RECT, "usampler2DRect",
GL_IMAGE_1D, "image1D",
GL_IMAGE_2D, "image2D",
GL_IMAGE_3D, "image3D",
GL_IMAGE_2D_RECT, "image2DRect",
GL_IMAGE_CUBE, "imageCube",
GL_IMAGE_BUFFER, "imageBuffer",
GL_IMAGE_1D_ARRAY, "image1DArray",
GL_IMAGE_2D_ARRAY, "image2DArray",
GL_IMAGE_2D_MULTISAMPLE, "image2DMS",
GL_IMAGE_2D_MULTISAMPLE_ARRAY, "image2DMSArray",
GL_INT_IMAGE_1D, "iimage1D",
GL_INT_IMAGE_2D, "iimage2D",
GL_INT_IMAGE_3D, "iimage3D",
GL_INT_IMAGE_2D_RECT, "iimage2DRect",
GL_INT_IMAGE_CUBE, "iimageCube",
GL_INT_IMAGE_BUFFER, "iimageBuffer",
GL_INT_IMAGE_1D_ARRAY, "iimage1DArray",
GL_INT_IMAGE_2D_ARRAY, "iimage2DArray",
GL_INT_IMAGE_2D_MULTISAMPLE, "iimage2DMS",
GL_INT_IMAGE_2D_MULTISAMPLE_ARRAY, "iimage2DMSArray",
GL_UNSIGNED_INT_IMAGE_1D, "uimage1D",
GL_UNSIGNED_INT_IMAGE_2D, "uimage2D",
GL_UNSIGNED_INT_IMAGE_3D, "uimage3D",
GL_UNSIGNED_INT_IMAGE_2D_RECT, "uimage2DRect",
GL_UNSIGNED_INT_IMAGE_CUBE, "uimageCube",
GL_UNSIGNED_INT_IMAGE_BUFFER, "uimageBuffer",
GL_UNSIGNED_INT_IMAGE_1D_ARRAY, "uimage1DArray",
GL_UNSIGNED_INT_IMAGE_2D_ARRAY, "uimage2DArray",
GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE, "uimage2DMS",
GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE_ARRAY, "uimage2DMSArray",
GL_UNSIGNED_INT_ATOMIC_COUNTER, "atomic_uint"
};
プログラム内のすべてのACTIVEユニフォームを列挙するコード:
void
eTB_GLSL__print_uniforms (GLuint program)
{
GLint uniform_count;
glGetProgramiv (program, GL_ACTIVE_UNIFORMS, &uniform_count);
GLchar name [256];
for (GLint i = 0; i < uniform_count; i++) {
memset (name, '\0', 256);
GLint size;
GLenum type;
glGetActiveUniform (program, i, 255, NULL, &size, &type, name);
GLint location = glGetUniformLocation (program, name);
for (int j = 0; j < sizeof (type_set) / sizeof (glsl_type_set); j++) {
if (type_set [j].type != type)
continue;
const char* type_name = type_set [j].name;
if (size > 1)
printf ( "Uniform %d (loc=%d):\t%20s %-20s <Size: %d>\n",
i, location, type_name, name, size );
else
printf ( "Uniform %d (loc=%d):\t%20s %-20s\n",
i, location, type_name, name );
break;
}
if (i == (uniform_count - 1))
printf ("\n");
}
}
サンプル出力 (AMD):
Uniform 0 (loc=0): float buffer_res_x
Uniform 1 (loc=1): float buffer_res_y
Uniform 2 (loc=2): float buffer_scale
Uniform 3 (loc=3): mat4 camera_matrix
Uniform 4 (loc=4): bool fxaa
Uniform 5 (loc=5): vec3 light_colors <Size: 128>
Uniform 6 (loc=133): vec3 light_pos <Size: 128>
Uniform 7 (loc=261): mat4 modelview_mat
Uniform 8 (loc=262): int num_lights
Uniform 9 (loc=263): sampler2D depth_buffer
Uniform 10 (loc=264): sampler2D diffuse_buffer
Uniform 11 (loc=265): sampler2D normal_buffer
Uniform 12 (loc=266): samplerCube shadow_buffer <Size: 10>
サンプル出力 (NV):
Uniform 0 (loc=0): float buffer_res_x
Uniform 1 (loc=1): float buffer_res_y
Uniform 2 (loc=2): float buffer_scale
Uniform 3 (loc=3): mat4 camera_matrix
Uniform 4 (loc=4): bool fxaa
Uniform 5 (loc=5): vec3 light_colors[0] <Size: 128>
Uniform 6 (loc=133): vec3 light_pos[0] <Size: 128>
Uniform 7 (loc=261): mat4 modelview_mat
Uniform 8 (loc=262): int num_lights
Uniform 9 (loc=263): sampler2D depth_buffer
Uniform 10 (loc=264): sampler2D diffuse_buffer
Uniform 11 (loc=265): sampler2D normal_buffer
Uniform 12 (loc=266): samplerCube shadow_buffer[0] <Size: 10>
私がこの特定のシェーダーを選択したのは、配列の統一名を報告するときに NV と AMD がどのように異なるかを示す最初のシェーダーであり、特に特別なことは何もないためです。NV は常に[0]
表記を使用し、AMD は使用しません (ただし、新しいドライバーは使用する傾向があります)。<Size: X> で示される範囲内であれば、個々の均一な位置を照会できます。つまり、ドライバーはそれらをname[0]
またはとして列挙しますが、いずれかの実装でまたはname
の均一な場所を照会することは技術的に有効です。name
name[0]
私は次の3つのことを見ることに非常に興味があります。
- AMD ハードウェアにリンクした後の出力
- NV ハードウェアにリンクした後の出力
- あなたのフルシェーダー
この3つがあれば、実際の答えが可能になるはずです。
アップデート
シェーダーの記述方法が原因で、GLSL コンパイラーが使用法を判断するのに苦労していると思います。これを確認するには、以下を置き換えてみてください。
vec3 computeLight(int light_index){
Light light = lights[light_index];
if(light.position == vec4(0.0)) { return vec3(0.0);}
if(light.position.w == 0.0 ) {return directionLight(light);}
if(light.cutoff == 0) {return pointLight(light);}
return reflectionLight(light);
}
[...]
vec3 lighting = vec3(0.);
for(int i = 0; i < lights_no; i++) {
lighting += computeLight(i);
}
次のようなもっと醜いものを使用します。
vec3 lighting = vec3(0.0);
for(int i = 0; i < lights_no; i++) {
Light light = lights [i];
if (light.position != vec4 (0.0)) {
if (light.position.w == 0.0)
lighting += directionLight(light);
else if (light.cutoff == 0.0)
lighting += pointLight(light);
else
lighting += reflectionLight (light);
}
}
}