【发布时间】:2019-09-11 16:05:32
【问题描述】:
我终于开始努力学习如何编写着色器,并且我对它们的工作原理有了相当不错的掌握。问题是,我无法检索结构制服的制服位置。现在我知道你必须查询每个内部成员的位置,我正在这样做,而且我还知道如果 GL 确定制服不会影响最终输出,它会被优化掉(老实说不是一点点坏事)。
问题是,它没有找到用于影响片段着色器输出的制服。
在我的着色器类中,我有一个名为“GetAndStoreUniformLocation”的函数(我喜欢对名称进行描述 - 确保清楚该函数的作用)!这个函数只是抓取给定统一名称的位置并将其推送到地图中,因此我不必在每一帧都继续查询 OpenGL 的位置(我不确定这可能或可能不会有多么好的优化......在这个阶段它是相当实验性的)。此功能适用于所有标准类型的制服。
问题(TL;DR):
为什么我不能从着色器中检索“材质”制服成员的位置?它不应该被优化掉,我将“material.*”(其中 * 是成员名称)传递给 glGetUniformLocation()。
我觉得我可能遗漏了一些明显的东西,但我已经在 OpenGL 文档和其他人的帖子上搜索了类似问题,到目前为止,没有提供任何有用的东西,只有优化删除的建议制服,但是,我怀疑是这种情况,因为它正在输出中使用。
我已经尝试在加载、编译和链接着色器后直接调用 glGetUniformLocation(),用于矩阵制服(成功)和材质。*制服(失败)。
代码
加载着色器后,我激活它以便访问统一位置,然后调用:
v_primaryShader.GetAndStoreUniformLocation("material.ambient");
v_primaryShader.GetAndStoreUniformLocation("material.diffuse");
v_primaryShader.GetAndStoreUniformLocation("material.specular");
Shader::GetAndStoreUniformLocation(const GLchar* uniformName)
void Shader::GetAndStoreUniformLocation(const GLchar* uniformName)
{
GLint location = glGetUniformLocation(this->v_programID, uniformName);
if (location != -1)
{
v_uniformLocations.insert(std::pair<const GLchar*, GLint>(uniformName, location));
Debug::LogDebug("Uniform stored for shader '" + v_name + "': name: '" + std::string(uniformName) + "', location: '" + std::to_string(location) + "'");
return;
}
ThrowException("Shader>GetAndStoreUniformLocation: Could not find uniform '" + std::string(uniformName) + "' in shader '" + this->v_name + "'.");
}
着色器::调试(无效)
void Shader::Debug(void) const
{
GLint i;
GLint count;
GLint size;
GLenum type;
const GLsizei bufSize = 25;
GLchar name[bufSize];
GLsizei length;
Debug::LogDebug("Debugging shader '" + this->v_name + "':");
glGetProgramiv(this->v_programID, GL_ACTIVE_ATTRIBUTES, &count);
Debug::LogDebug(" - Attributes (" + std::to_string(count) + " in total; numbers do not correspond to locations!): ");
for (i = 0; i < count; i++)
{
glGetActiveAttrib(this->v_programID, (GLuint)i, bufSize, &length, &size, &type, name);
int location = glGetAttribLocation(this->v_programID, name);
Debug::LogDebug(" - Attribute " + std::to_string(i) + " = name: '" + name + "', location: " + std::to_string(location) + ", type: " + TypeToString(type));
}
glGetProgramiv(this->v_programID, GL_ACTIVE_UNIFORMS, &count);
Debug::LogDebug(" - Uniforms (" + std::to_string(count) + " in total; numbers do not correspond to locations!): ");
for (i = 0; i < count; i++)
{
glGetActiveUniform(this->v_programID, (GLuint)i, bufSize, &length, &size, &type, name);
int location = glGetUniformLocation(this->v_programID, name);
Debug::LogDebug(" - Uniform " + std::to_string(i) + " = name: '" + name + "', location: " + std::to_string(location) + ", type: " + TypeToString(type));
}
}
片段着色器 (GLSL):
#version 440
struct Material
{
vec3 ambient;
vec3 diffuse;
vec3 specular;
//sampler2D diffuse_texture;
//sampler2D specular_texture;
};
in vec3 pass_position;
in vec3 pass_normal;
in vec2 pass_uv;
uniform Material material;
uniform sampler2D texture0; // TODO: remove later
uniform vec3 light_position;
uniform vec3 camera_position;
out vec4 result;
void main(void)
{
// Ambient light
vec3 _ambient_final = material.ambient;
// Diffuse light
vec3 _position_to_light_directional_vector = normalize(light_position - pass_position);
float _diffuse_dot_product = clamp(dot(_position_to_light_directional_vector, pass_normal), 0, 1);
vec3 _diffuse_final = material.diffuse * _diffuse_dot_product;
// Specular light
vec3 _light_to_position_directional_vector = normalize(light_position - pass_position);
vec3 _reflect_directional_vector = normalize(reflect(_light_to_position_directional_vector, normalize(pass_normal)));
vec3 _position_to_view_directional_vector = normalize(pass_position - camera_position);
float _specular_constant = pow(max(dot(_position_to_view_directional_vector, _reflect_directional_vector), 0), 70); // final number = smoothness
vec3 _specular_final = material.specular * _specular_constant;
// Attenuation (todo)
// Final light (todo)
result = texture(texture0, pass_uv) * (vec4(_ambient_final, 1.F) + vec4(_diffuse_final, 1.F) + vec4(_specular_final, 1.F));
}
结果(错误)
Shader 类还有一个 Debug() 函数,可以打印所有属性和制服。我得到的输出是:
(call to v_primaryShader.Debug() )
[ DEBUG ] Debugging shader 'primary':
[ DEBUG ] - Attributes (3 in total; numbers do not correspond to locations!):
[ DEBUG ] - Attribute 0 = name: 'vertex_normal', location: 1, type: vec3
[ DEBUG ] - Attribute 1 = name: 'vertex_position', location: 0, type: vec3
[ DEBUG ] - Attribute 2 = name: 'vertex_uv', location: 2, type: vec2
[ DEBUG ] - Uniforms (6 in total; numbers do not correspond to locations!):
[ DEBUG ] - Uniform 0 = name: 'camera_position', location: 0, type: vec3
[ DEBUG ] - Uniform 1 = name: 'light_position', location: 1, type: vec3
[ DEBUG ] - Uniform 2 = name: 'model_matrix', location: 2, type: mat4
[ DEBUG ] - Uniform 3 = name: 'projection_matrix', location: 3, type: mat4
[ DEBUG ] - Uniform 4 = name: 'texture0', location: 4, type: sampler2D
[ DEBUG ] - Uniform 5 = name: 'view_matrix', location: 5, type: mat4
(calls to v_primaryShader.GetAndStoreUniformLocation() )
[ DEBUG ] Uniform stored for shader 'primary': name: 'model_matrix', location: '2'
[ DEBUG ] Uniform stored for shader 'primary': name: 'view_matrix', location: '5'
[ DEBUG ] Uniform stored for shader 'primary': name: 'projection_matrix', location: '3'
[ DEBUG ] Uniform stored for shader 'primary': name: 'light_position', location: '1'
[ DEBUG ] Uniform stored for shader 'primary': name: 'camera_position', location: '0'
[ CRITICAL ] Exception during phase 'LOAD'
[ CRITICAL ] Shader>GetAndStoreUniformLocation: Could not find uniform 'material.ambient' in shader 'primary'.
,所以它肯定让所有其他制服都很好。但是“材料”无处可见,但是,正如您从着色器代码中看到的那样,“材料”结构的内部成员被用于照明,用于颜色的最终输出。是的,我完全知道代码可能不正确,或者没有优化......但是当我放下样板时,我只需要在里面放一堆东西就可以让它在基本的水平上工作。照明一直在工作,直到制作结构(之前,我只是使用硬编码值)
【问题讨论】:
-
制服的名字似乎是正确的。您可以内省程序。使用
n = glGetProgramiv(program, GL_ACTIVE_UNIFORMS)和for(i=0; i<n; ++i) glGetActiveUniform(program, i, ... )获取所有现役制服。分别见glGetActiveUniformglGetProgramiv。 -
是的,抱歉我忘了提,这就是我的 Shader Debug() 函数所做的(控制台日志中的第一组输出)
-
我想你在
GetAndStoreUniformLocation之前打电话给glUseProgram对吧? -
@Ripi2 程序不一定是当前安装的程序,查询活动程序资源的资源索引。 (如果您想通过
glUnifrom*更改制服的值,这将是必要的)。 -
你确定你已经编译了那个片段着色器吗?您是否错误地读取了另一个状态较早的文件?