【问题标题】:Shader uniform either improperly optimised away or not being found着色器均匀要么优化不当,要么找不到
【发布时间】: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&lt;n; ++i) glGetActiveUniform(program, i, ... ) 获取所有现役制服。分别见glGetActiveUniformglGetProgramiv
  • 是的,抱歉我忘了提,这就是我的 Shader Debug() 函数所做的(控制台日志中的第一组输出)
  • 我想你在GetAndStoreUniformLocation 之前打电话给glUseProgram 对吧?
  • @Ripi2 程序不一定是当前安装的程序,查询活动程序资源的资源索引。 (如果您想通过glUnifrom* 更改制服的值,这将是必要的)。
  • 你确定你已经编译了那个片段着色器吗?您是否错误地读取了另一个状态较早的文件?

标签: c++ opengl


【解决方案1】:

事实证明,问题在于 IDE 已删除将资产(着色器、纹理等)复制到构建目录的批处理文件,并且没有迹象表明这已经发生,也没有任何真正的原因。我已经把文件放回去了,现在它可以工作了。 我可能实际上应该检查构建目录中的着色器文件以确保它是最新的,但我没有想到(如果我更聪明的话,它肯定应该有) ,但在我的困惑和沮丧中,我正在寻找代码中的错误。

绝对是一个意外的结果,但我很高兴这意味着代码/驱动程序没有错误。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-06
    • 2017-07-03
    • 2017-11-30
    • 2020-11-04
    相关资源
    最近更新 更多